diff --git a/internal/cache/cache.go b/internal/cache/cache.go index 5554445b2..68a31f11e 100644 --- a/internal/cache/cache.go +++ b/internal/cache/cache.go @@ -47,6 +47,11 @@ type Caches struct { // Webfinger provides access to the webfinger URL cache. Webfinger *ttl.Cache[string, string] // TTL=24hr, sweep=5min + // TTL cache of statuses -> filterable text fields. + // To ensure up-to-date fields, cache is keyed as: + // `[status.ID][status.UpdatedAt.Unix()]` + StatusesFilterableFields *ttl.Cache[string, []string] + // prevent pass-by-value. _ nocopy } @@ -109,6 +114,7 @@ func (c *Caches) Init() { c.initUserMuteIDs() c.initWebfinger() c.initVisibility() + c.initStatusesFilterableFields() } // Start will start any caches that require a background @@ -204,3 +210,12 @@ func (c *Caches) initWebfinger() { 24*time.Hour, ) } + +func (c *Caches) initStatusesFilterableFields() { + c.Webfinger = new(ttl.Cache[string, string]) + c.Webfinger.Init( + 0, + 512, + 1*time.Hour, + ) +} diff --git a/internal/typeutils/converter.go b/internal/typeutils/converter.go index 97d661a5d..311839dc0 100644 --- a/internal/typeutils/converter.go +++ b/internal/typeutils/converter.go @@ -19,12 +19,9 @@ package typeutils import ( "sync" - "time" - "codeberg.org/gruf/go-cache/v3" "github.com/superseriousbusiness/gotosocial/internal/filter/interaction" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility" - "github.com/superseriousbusiness/gotosocial/internal/log" "github.com/superseriousbusiness/gotosocial/internal/state" ) @@ -34,25 +31,13 @@ type Converter struct { randAvatars sync.Map visFilter *visibility.Filter intFilter *interaction.Filter - - // TTL cache of statuses -> filterable text fields. - // To ensure up-to-date fields, cache is keyed as: - // [status.ID][status.UpdatedAt.Unix()]` - statusesFilterableFields cache.TTLCache[string, []string] } func NewConverter(state *state.State) *Converter { - statusHashesToFilterableText := cache.NewTTL[string, []string](0, 512, 0) - statusHashesToFilterableText.SetTTL(time.Hour, true) - if !statusHashesToFilterableText.Start(time.Minute) { - log.Panic(nil, "failed to start statusHashesToFilterableText cache") - } - return &Converter{ - state: state, - defaultAvatars: populateDefaultAvatars(), - visFilter: visibility.NewFilter(state), - intFilter: interaction.NewFilter(state), - statusesFilterableFields: statusHashesToFilterableText, + state: state, + defaultAvatars: populateDefaultAvatars(), + visFilter: visibility.NewFilter(state), + intFilter: interaction.NewFilter(state), } } diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index 58797e790..fe49766fa 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "slices" + "strconv" "strings" "time" @@ -941,15 +942,16 @@ func (c *Converter) statusToAPIFilterResults( // Key this status based on ID + last updated time, // to ensure we always filter on latest version. - statusKey := fmt.Sprintf("%s%d", s.ID, s.UpdatedAt.Unix()) + statusKey := s.ID + strconv.FormatInt(s.UpdatedAt.Unix(), 10) // Check if we have filterable fields cached for this status. - fields, stored := c.statusesFilterableFields.Get(statusKey) + cache := c.state.Caches.StatusesFilterableFields + fields, stored := cache.Get(statusKey) if !stored { // We don't have filterable fields // cached, calculate + cache now. fields = filterableFields(s) - c.statusesFilterableFields.Set(statusKey, fields) + cache.Set(statusKey, fields) } // Record all matching warn filters and the reasons they matched.