gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

gts.go (14120B)


      1 // GoToSocial
      2 // Copyright (C) GoToSocial Authors admin@gotosocial.org
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 //
      5 // This program is free software: you can redistribute it and/or modify
      6 // it under the terms of the GNU Affero General Public License as published by
      7 // the Free Software Foundation, either version 3 of the License, or
      8 // (at your option) any later version.
      9 //
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU Affero General Public License for more details.
     14 //
     15 // You should have received a copy of the GNU Affero General Public License
     16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 package cache
     19 
     20 import (
     21 	"codeberg.org/gruf/go-cache/v3/result"
     22 	"codeberg.org/gruf/go-cache/v3/ttl"
     23 	"github.com/superseriousbusiness/gotosocial/internal/cache/domain"
     24 	"github.com/superseriousbusiness/gotosocial/internal/config"
     25 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     26 )
     27 
     28 type GTSCaches struct {
     29 	account *result.Cache[*gtsmodel.Account]
     30 	block   *result.Cache[*gtsmodel.Block]
     31 	// TODO: maybe should be moved out of here since it's
     32 	// not actually doing anything with gtsmodel.DomainBlock.
     33 	domainBlock   *domain.BlockCache
     34 	emoji         *result.Cache[*gtsmodel.Emoji]
     35 	emojiCategory *result.Cache[*gtsmodel.EmojiCategory]
     36 	follow        *result.Cache[*gtsmodel.Follow]
     37 	followRequest *result.Cache[*gtsmodel.FollowRequest]
     38 	list          *result.Cache[*gtsmodel.List]
     39 	listEntry     *result.Cache[*gtsmodel.ListEntry]
     40 	media         *result.Cache[*gtsmodel.MediaAttachment]
     41 	mention       *result.Cache[*gtsmodel.Mention]
     42 	notification  *result.Cache[*gtsmodel.Notification]
     43 	report        *result.Cache[*gtsmodel.Report]
     44 	status        *result.Cache[*gtsmodel.Status]
     45 	statusFave    *result.Cache[*gtsmodel.StatusFave]
     46 	tombstone     *result.Cache[*gtsmodel.Tombstone]
     47 	user          *result.Cache[*gtsmodel.User]
     48 	// TODO: move out of GTS caches since not using database models.
     49 	webfinger *ttl.Cache[string, string]
     50 }
     51 
     52 // Init will initialize all the gtsmodel caches in this collection.
     53 // NOTE: the cache MUST NOT be in use anywhere, this is not thread-safe.
     54 func (c *GTSCaches) Init() {
     55 	c.initAccount()
     56 	c.initBlock()
     57 	c.initDomainBlock()
     58 	c.initEmoji()
     59 	c.initEmojiCategory()
     60 	c.initFollow()
     61 	c.initFollowRequest()
     62 	c.initList()
     63 	c.initListEntry()
     64 	c.initMedia()
     65 	c.initMention()
     66 	c.initNotification()
     67 	c.initReport()
     68 	c.initStatus()
     69 	c.initStatusFave()
     70 	c.initTombstone()
     71 	c.initUser()
     72 	c.initWebfinger()
     73 }
     74 
     75 // Start will attempt to start all of the gtsmodel caches, or panic.
     76 func (c *GTSCaches) Start() {
     77 	tryStart(c.account, config.GetCacheGTSAccountSweepFreq())
     78 	tryStart(c.block, config.GetCacheGTSBlockSweepFreq())
     79 	tryStart(c.emoji, config.GetCacheGTSEmojiSweepFreq())
     80 	tryStart(c.emojiCategory, config.GetCacheGTSEmojiCategorySweepFreq())
     81 	tryStart(c.follow, config.GetCacheGTSFollowSweepFreq())
     82 	tryStart(c.followRequest, config.GetCacheGTSFollowRequestSweepFreq())
     83 	tryStart(c.list, config.GetCacheGTSListSweepFreq())
     84 	tryStart(c.listEntry, config.GetCacheGTSListEntrySweepFreq())
     85 	tryStart(c.media, config.GetCacheGTSMediaSweepFreq())
     86 	tryStart(c.mention, config.GetCacheGTSMentionSweepFreq())
     87 	tryStart(c.notification, config.GetCacheGTSNotificationSweepFreq())
     88 	tryStart(c.report, config.GetCacheGTSReportSweepFreq())
     89 	tryStart(c.status, config.GetCacheGTSStatusSweepFreq())
     90 	tryStart(c.statusFave, config.GetCacheGTSStatusFaveSweepFreq())
     91 	tryStart(c.tombstone, config.GetCacheGTSTombstoneSweepFreq())
     92 	tryStart(c.user, config.GetCacheGTSUserSweepFreq())
     93 	tryUntil("starting *gtsmodel.Webfinger cache", 5, func() bool {
     94 		if sweep := config.GetCacheGTSWebfingerSweepFreq(); sweep > 0 {
     95 			return c.webfinger.Start(sweep)
     96 		}
     97 		return true
     98 	})
     99 }
    100 
    101 // Stop will attempt to stop all of the gtsmodel caches, or panic.
    102 func (c *GTSCaches) Stop() {
    103 	tryStop(c.account, config.GetCacheGTSAccountSweepFreq())
    104 	tryStop(c.block, config.GetCacheGTSBlockSweepFreq())
    105 	tryStop(c.emoji, config.GetCacheGTSEmojiSweepFreq())
    106 	tryStop(c.emojiCategory, config.GetCacheGTSEmojiCategorySweepFreq())
    107 	tryStop(c.follow, config.GetCacheGTSFollowSweepFreq())
    108 	tryStop(c.followRequest, config.GetCacheGTSFollowRequestSweepFreq())
    109 	tryStop(c.list, config.GetCacheGTSListSweepFreq())
    110 	tryStop(c.listEntry, config.GetCacheGTSListEntrySweepFreq())
    111 	tryStop(c.media, config.GetCacheGTSMediaSweepFreq())
    112 	tryStop(c.mention, config.GetCacheGTSNotificationSweepFreq())
    113 	tryStop(c.notification, config.GetCacheGTSNotificationSweepFreq())
    114 	tryStop(c.report, config.GetCacheGTSReportSweepFreq())
    115 	tryStop(c.status, config.GetCacheGTSStatusSweepFreq())
    116 	tryStop(c.statusFave, config.GetCacheGTSStatusFaveSweepFreq())
    117 	tryStop(c.tombstone, config.GetCacheGTSTombstoneSweepFreq())
    118 	tryStop(c.user, config.GetCacheGTSUserSweepFreq())
    119 	tryUntil("stopping *gtsmodel.Webfinger cache", 5, c.webfinger.Stop)
    120 }
    121 
    122 // Account provides access to the gtsmodel Account database cache.
    123 func (c *GTSCaches) Account() *result.Cache[*gtsmodel.Account] {
    124 	return c.account
    125 }
    126 
    127 // Block provides access to the gtsmodel Block (account) database cache.
    128 func (c *GTSCaches) Block() *result.Cache[*gtsmodel.Block] {
    129 	return c.block
    130 }
    131 
    132 // DomainBlock provides access to the domain block database cache.
    133 func (c *GTSCaches) DomainBlock() *domain.BlockCache {
    134 	return c.domainBlock
    135 }
    136 
    137 // Emoji provides access to the gtsmodel Emoji database cache.
    138 func (c *GTSCaches) Emoji() *result.Cache[*gtsmodel.Emoji] {
    139 	return c.emoji
    140 }
    141 
    142 // EmojiCategory provides access to the gtsmodel EmojiCategory database cache.
    143 func (c *GTSCaches) EmojiCategory() *result.Cache[*gtsmodel.EmojiCategory] {
    144 	return c.emojiCategory
    145 }
    146 
    147 // Follow provides access to the gtsmodel Follow database cache.
    148 func (c *GTSCaches) Follow() *result.Cache[*gtsmodel.Follow] {
    149 	return c.follow
    150 }
    151 
    152 // FollowRequest provides access to the gtsmodel FollowRequest database cache.
    153 func (c *GTSCaches) FollowRequest() *result.Cache[*gtsmodel.FollowRequest] {
    154 	return c.followRequest
    155 }
    156 
    157 // List provides access to the gtsmodel List database cache.
    158 func (c *GTSCaches) List() *result.Cache[*gtsmodel.List] {
    159 	return c.list
    160 }
    161 
    162 // ListEntry provides access to the gtsmodel ListEntry database cache.
    163 func (c *GTSCaches) ListEntry() *result.Cache[*gtsmodel.ListEntry] {
    164 	return c.listEntry
    165 }
    166 
    167 // Media provides access to the gtsmodel Media database cache.
    168 func (c *GTSCaches) Media() *result.Cache[*gtsmodel.MediaAttachment] {
    169 	return c.media
    170 }
    171 
    172 // Mention provides access to the gtsmodel Mention database cache.
    173 func (c *GTSCaches) Mention() *result.Cache[*gtsmodel.Mention] {
    174 	return c.mention
    175 }
    176 
    177 // Notification provides access to the gtsmodel Notification database cache.
    178 func (c *GTSCaches) Notification() *result.Cache[*gtsmodel.Notification] {
    179 	return c.notification
    180 }
    181 
    182 // Report provides access to the gtsmodel Report database cache.
    183 func (c *GTSCaches) Report() *result.Cache[*gtsmodel.Report] {
    184 	return c.report
    185 }
    186 
    187 // Status provides access to the gtsmodel Status database cache.
    188 func (c *GTSCaches) Status() *result.Cache[*gtsmodel.Status] {
    189 	return c.status
    190 }
    191 
    192 // StatusFave provides access to the gtsmodel StatusFave database cache.
    193 func (c *GTSCaches) StatusFave() *result.Cache[*gtsmodel.StatusFave] {
    194 	return c.statusFave
    195 }
    196 
    197 // Tombstone provides access to the gtsmodel Tombstone database cache.
    198 func (c *GTSCaches) Tombstone() *result.Cache[*gtsmodel.Tombstone] {
    199 	return c.tombstone
    200 }
    201 
    202 // User provides access to the gtsmodel User database cache.
    203 func (c *GTSCaches) User() *result.Cache[*gtsmodel.User] {
    204 	return c.user
    205 }
    206 
    207 // Webfinger provides access to the webfinger URL cache.
    208 func (c *GTSCaches) Webfinger() *ttl.Cache[string, string] {
    209 	return c.webfinger
    210 }
    211 
    212 func (c *GTSCaches) initAccount() {
    213 	c.account = result.New([]result.Lookup{
    214 		{Name: "ID"},
    215 		{Name: "URI"},
    216 		{Name: "URL"},
    217 		{Name: "Username.Domain"},
    218 		{Name: "PublicKeyURI"},
    219 		{Name: "InboxURI"},
    220 		{Name: "OutboxURI"},
    221 		{Name: "FollowersURI"},
    222 		{Name: "FollowingURI"},
    223 	}, func(a1 *gtsmodel.Account) *gtsmodel.Account {
    224 		a2 := new(gtsmodel.Account)
    225 		*a2 = *a1
    226 		return a2
    227 	}, config.GetCacheGTSAccountMaxSize())
    228 	c.account.SetTTL(config.GetCacheGTSAccountTTL(), true)
    229 	c.account.IgnoreErrors(ignoreErrors)
    230 }
    231 
    232 func (c *GTSCaches) initBlock() {
    233 	c.block = result.New([]result.Lookup{
    234 		{Name: "ID"},
    235 		{Name: "URI"},
    236 		{Name: "AccountID.TargetAccountID"},
    237 	}, func(b1 *gtsmodel.Block) *gtsmodel.Block {
    238 		b2 := new(gtsmodel.Block)
    239 		*b2 = *b1
    240 		return b2
    241 	}, config.GetCacheGTSBlockMaxSize())
    242 	c.block.SetTTL(config.GetCacheGTSBlockTTL(), true)
    243 	c.block.IgnoreErrors(ignoreErrors)
    244 }
    245 
    246 func (c *GTSCaches) initDomainBlock() {
    247 	c.domainBlock = new(domain.BlockCache)
    248 }
    249 
    250 func (c *GTSCaches) initEmoji() {
    251 	c.emoji = result.New([]result.Lookup{
    252 		{Name: "ID"},
    253 		{Name: "URI"},
    254 		{Name: "Shortcode.Domain"},
    255 		{Name: "ImageStaticURL"},
    256 	}, func(e1 *gtsmodel.Emoji) *gtsmodel.Emoji {
    257 		e2 := new(gtsmodel.Emoji)
    258 		*e2 = *e1
    259 		return e2
    260 	}, config.GetCacheGTSEmojiMaxSize())
    261 	c.emoji.SetTTL(config.GetCacheGTSEmojiTTL(), true)
    262 	c.emoji.IgnoreErrors(ignoreErrors)
    263 }
    264 
    265 func (c *GTSCaches) initEmojiCategory() {
    266 	c.emojiCategory = result.New([]result.Lookup{
    267 		{Name: "ID"},
    268 		{Name: "Name"},
    269 	}, func(c1 *gtsmodel.EmojiCategory) *gtsmodel.EmojiCategory {
    270 		c2 := new(gtsmodel.EmojiCategory)
    271 		*c2 = *c1
    272 		return c2
    273 	}, config.GetCacheGTSEmojiCategoryMaxSize())
    274 	c.emojiCategory.SetTTL(config.GetCacheGTSEmojiCategoryTTL(), true)
    275 	c.emojiCategory.IgnoreErrors(ignoreErrors)
    276 }
    277 
    278 func (c *GTSCaches) initFollow() {
    279 	c.follow = result.New([]result.Lookup{
    280 		{Name: "ID"},
    281 		{Name: "URI"},
    282 		{Name: "AccountID.TargetAccountID"},
    283 	}, func(f1 *gtsmodel.Follow) *gtsmodel.Follow {
    284 		f2 := new(gtsmodel.Follow)
    285 		*f2 = *f1
    286 		return f2
    287 	}, config.GetCacheGTSFollowMaxSize())
    288 	c.follow.SetTTL(config.GetCacheGTSFollowTTL(), true)
    289 }
    290 
    291 func (c *GTSCaches) initFollowRequest() {
    292 	c.followRequest = result.New([]result.Lookup{
    293 		{Name: "ID"},
    294 		{Name: "URI"},
    295 		{Name: "AccountID.TargetAccountID"},
    296 	}, func(f1 *gtsmodel.FollowRequest) *gtsmodel.FollowRequest {
    297 		f2 := new(gtsmodel.FollowRequest)
    298 		*f2 = *f1
    299 		return f2
    300 	}, config.GetCacheGTSFollowRequestMaxSize())
    301 	c.followRequest.SetTTL(config.GetCacheGTSFollowRequestTTL(), true)
    302 }
    303 
    304 func (c *GTSCaches) initList() {
    305 	c.list = result.New([]result.Lookup{
    306 		{Name: "ID"},
    307 	}, func(l1 *gtsmodel.List) *gtsmodel.List {
    308 		l2 := new(gtsmodel.List)
    309 		*l2 = *l1
    310 		return l2
    311 	}, config.GetCacheGTSListMaxSize())
    312 	c.list.SetTTL(config.GetCacheGTSListTTL(), true)
    313 	c.list.IgnoreErrors(ignoreErrors)
    314 }
    315 
    316 func (c *GTSCaches) initListEntry() {
    317 	c.listEntry = result.New([]result.Lookup{
    318 		{Name: "ID"},
    319 	}, func(l1 *gtsmodel.ListEntry) *gtsmodel.ListEntry {
    320 		l2 := new(gtsmodel.ListEntry)
    321 		*l2 = *l1
    322 		return l2
    323 	}, config.GetCacheGTSListEntryMaxSize())
    324 	c.list.SetTTL(config.GetCacheGTSListEntryTTL(), true)
    325 	c.list.IgnoreErrors(ignoreErrors)
    326 }
    327 
    328 func (c *GTSCaches) initMedia() {
    329 	c.media = result.New([]result.Lookup{
    330 		{Name: "ID"},
    331 	}, func(m1 *gtsmodel.MediaAttachment) *gtsmodel.MediaAttachment {
    332 		m2 := new(gtsmodel.MediaAttachment)
    333 		*m2 = *m1
    334 		return m2
    335 	}, config.GetCacheGTSMediaMaxSize())
    336 	c.media.SetTTL(config.GetCacheGTSMediaTTL(), true)
    337 	c.media.IgnoreErrors(ignoreErrors)
    338 }
    339 
    340 func (c *GTSCaches) initMention() {
    341 	c.mention = result.New([]result.Lookup{
    342 		{Name: "ID"},
    343 	}, func(m1 *gtsmodel.Mention) *gtsmodel.Mention {
    344 		m2 := new(gtsmodel.Mention)
    345 		*m2 = *m1
    346 		return m2
    347 	}, config.GetCacheGTSMentionMaxSize())
    348 	c.mention.SetTTL(config.GetCacheGTSMentionTTL(), true)
    349 	c.mention.IgnoreErrors(ignoreErrors)
    350 }
    351 
    352 func (c *GTSCaches) initNotification() {
    353 	c.notification = result.New([]result.Lookup{
    354 		{Name: "ID"},
    355 		{Name: "NotificationType.TargetAccountID.OriginAccountID.StatusID"},
    356 	}, func(n1 *gtsmodel.Notification) *gtsmodel.Notification {
    357 		n2 := new(gtsmodel.Notification)
    358 		*n2 = *n1
    359 		return n2
    360 	}, config.GetCacheGTSNotificationMaxSize())
    361 	c.notification.SetTTL(config.GetCacheGTSNotificationTTL(), true)
    362 	c.notification.IgnoreErrors(ignoreErrors)
    363 }
    364 
    365 func (c *GTSCaches) initReport() {
    366 	c.report = result.New([]result.Lookup{
    367 		{Name: "ID"},
    368 	}, func(r1 *gtsmodel.Report) *gtsmodel.Report {
    369 		r2 := new(gtsmodel.Report)
    370 		*r2 = *r1
    371 		return r2
    372 	}, config.GetCacheGTSReportMaxSize())
    373 	c.report.SetTTL(config.GetCacheGTSReportTTL(), true)
    374 	c.report.IgnoreErrors(ignoreErrors)
    375 }
    376 
    377 func (c *GTSCaches) initStatus() {
    378 	c.status = result.New([]result.Lookup{
    379 		{Name: "ID"},
    380 		{Name: "URI"},
    381 		{Name: "URL"},
    382 	}, func(s1 *gtsmodel.Status) *gtsmodel.Status {
    383 		s2 := new(gtsmodel.Status)
    384 		*s2 = *s1
    385 		return s2
    386 	}, config.GetCacheGTSStatusMaxSize())
    387 	c.status.SetTTL(config.GetCacheGTSStatusTTL(), true)
    388 	c.status.IgnoreErrors(ignoreErrors)
    389 }
    390 
    391 func (c *GTSCaches) initStatusFave() {
    392 	c.statusFave = result.New([]result.Lookup{
    393 		{Name: "ID"},
    394 		{Name: "AccountID.StatusID"},
    395 	}, func(f1 *gtsmodel.StatusFave) *gtsmodel.StatusFave {
    396 		f2 := new(gtsmodel.StatusFave)
    397 		*f2 = *f1
    398 		return f2
    399 	}, config.GetCacheGTSStatusFaveMaxSize())
    400 	c.status.SetTTL(config.GetCacheGTSStatusFaveTTL(), true)
    401 	c.status.IgnoreErrors(ignoreErrors)
    402 }
    403 
    404 func (c *GTSCaches) initTombstone() {
    405 	c.tombstone = result.New([]result.Lookup{
    406 		{Name: "ID"},
    407 		{Name: "URI"},
    408 	}, func(t1 *gtsmodel.Tombstone) *gtsmodel.Tombstone {
    409 		t2 := new(gtsmodel.Tombstone)
    410 		*t2 = *t1
    411 		return t2
    412 	}, config.GetCacheGTSTombstoneMaxSize())
    413 	c.tombstone.SetTTL(config.GetCacheGTSTombstoneTTL(), true)
    414 	c.tombstone.IgnoreErrors(ignoreErrors)
    415 }
    416 
    417 func (c *GTSCaches) initUser() {
    418 	c.user = result.New([]result.Lookup{
    419 		{Name: "ID"},
    420 		{Name: "AccountID"},
    421 		{Name: "Email"},
    422 		{Name: "ConfirmationToken"},
    423 		{Name: "ExternalID"},
    424 	}, func(u1 *gtsmodel.User) *gtsmodel.User {
    425 		u2 := new(gtsmodel.User)
    426 		*u2 = *u1
    427 		return u2
    428 	}, config.GetCacheGTSUserMaxSize())
    429 	c.user.SetTTL(config.GetCacheGTSUserTTL(), true)
    430 	c.user.IgnoreErrors(ignoreErrors)
    431 }
    432 
    433 func (c *GTSCaches) initWebfinger() {
    434 	c.webfinger = ttl.New[string, string](
    435 		0,
    436 		config.GetCacheGTSWebfingerMaxSize(),
    437 		config.GetCacheGTSWebfingerTTL())
    438 }