Skip to content

Commit

Permalink
[performance] reduce InboxForward->Create calls by partially implemen…
Browse files Browse the repository at this point in the history
…ting Exists() (#3647)

* alphabetical reordering

* keep a cache of activity IDs we have handled creates for

* reduce number of inbox forwarding create calls by partially implementing Exists()

* increase cache size, since all we're storing is string keys
  • Loading branch information
NyaaaWhatsUpDoc authored Jan 22, 2025
1 parent 5c0514e commit 0a99901
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 23 deletions.
28 changes: 14 additions & 14 deletions internal/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,18 @@ type Caches struct {
// the block []headerfilter.Filter cache.
BlockHeaderFilters headerfilter.Cache

// 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]

// Visibility provides access to the item visibility
// cache. (used by the visibility filter).
Visibility VisibilityCache

// 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
}
Expand Down Expand Up @@ -203,6 +203,15 @@ func (c *Caches) Sweep(threshold float64) {
c.Visibility.Trim(threshold)
}

func (c *Caches) initStatusesFilterableFields() {
c.StatusesFilterableFields = new(ttl.Cache[string, []string])
c.StatusesFilterableFields.Init(
0,
512,
1*time.Hour,
)
}

func (c *Caches) initWebfinger() {
// Calculate maximum cache size.
cap := calculateCacheMax(
Expand All @@ -219,12 +228,3 @@ func (c *Caches) initWebfinger() {
24*time.Hour,
)
}

func (c *Caches) initStatusesFilterableFields() {
c.StatusesFilterableFields = new(ttl.Cache[string, []string])
c.StatusesFilterableFields.Init(
0,
512,
1*time.Hour,
)
}
4 changes: 4 additions & 0 deletions internal/federation/federatingdb/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
return nil
}

// Cache entry for this create activity ID for later
// checks in the Exist() function if we see it again.
f.activityIDs.Set(ap.GetJSONLDId(asType).String(), struct{}{})

switch name := asType.GetTypeName(); name {
case ap.ActivityBlock:
// BLOCK SOMETHING
Expand Down
6 changes: 6 additions & 0 deletions internal/federation/federatingdb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"context"
"net/url"

"codeberg.org/gruf/go-cache/v3/simple"
"github.com/superseriousbusiness/activity/pub"
"github.com/superseriousbusiness/activity/streams/vocab"
"github.com/superseriousbusiness/gotosocial/internal/filter/interaction"
Expand Down Expand Up @@ -61,6 +62,10 @@ type federatingDB struct {
visFilter *visibility.Filter
intFilter *interaction.Filter
spamFilter *spam.Filter

// tracks Activity IDs we have handled creates for,
// for use in the Exists() function during forwarding.
activityIDs simple.Cache[string, struct{}]
}

// New returns a DB that satisfies the pub.Database
Expand All @@ -79,5 +84,6 @@ func New(
intFilter: intFilter,
spamFilter: spamFilter,
}
fdb.activityIDs.Init(0, 2048)
return &fdb
}
10 changes: 3 additions & 7 deletions internal/federation/federatingdb/exists.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@ import (
"net/url"
)

// Exists returns true if the database has an entry for the specified
// id. It may not be owned by this application instance.
//
// The library makes this call only after acquiring a lock first.
//
// Implementation note: this just straight up isn't implemented, and doesn't *really* need to be either.
// Exists is an implementation of pub.Database{}.Exists(), optimized specifically for
// the only usecase in which go-fed/activity/pub actually calls it. Do not use otherwise!
func (f *federatingDB) Exists(ctx context.Context, id *url.URL) (exists bool, err error) {
return false, nil
return f.activityIDs.Has(id.String()), nil
}
2 changes: 1 addition & 1 deletion internal/federation/federator.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
var _ interface {
pub.CommonBehavior
pub.FederatingProtocol
} = &Federator{}
} = (*Federator)(nil)

type Federator struct {
db db.DB
Expand Down
2 changes: 1 addition & 1 deletion internal/federation/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import (
// Note that the library will not maintain a long-lived pointer to the
// returned Transport so that any private credentials are able to be
// garbage collected.
func (f *Federator) NewTransport(ctx context.Context, actorBoxIRI *url.URL, gofedAgent string) (pub.Transport, error) {
func (f *Federator) NewTransport(ctx context.Context, actorBoxIRI *url.URL, _ string) (pub.Transport, error) {
var username string
var err error

Expand Down

0 comments on commit 0a99901

Please sign in to comment.