Files
GoToSocial/internal/federation/federatingdb/db.go
kim 3cff4b2d7d [chore] various federatingdb tweaks (#4178)
after seeing a potential reported federating worker lockup i decided to start digging into the federatingdb code. this PR encompasses:
- removes one of our last unused interface types `federatingdb.DB{}`, replacing it with a struct type `*federatingdb.DB{}`
- in `transport.dereferenceLocal()` differentiates between an unsupported lookup type and ErrNoEntries to reduce unnecessary calls, and reduce potential lockups that may occur while trying to call our own endpoints that then call `federatingdb.Lock()`
- removes a bunch of the locks on follow state changes since the DB already synchronizes that
- removes the unnecessary `pub.Clock{}` struct field and type passed to the transport controller

frankly it would be great if we could remove the locking in `federatingdb.Lock()` and instead handle it ourselves as it gets very confusing trying to figure out what functions will have locks held. but i guess that's one for when we move further away from the go-fed/activity/pub package usage.

Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4178
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
2025-05-15 09:40:48 +00:00

100 lines
3.2 KiB
Go

// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package federatingdb
import (
"context"
"net/url"
"code.superseriousbusiness.org/activity/pub"
"code.superseriousbusiness.org/activity/streams/vocab"
"code.superseriousbusiness.org/gotosocial/internal/ap"
"code.superseriousbusiness.org/gotosocial/internal/filter/interaction"
"code.superseriousbusiness.org/gotosocial/internal/filter/spam"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/state"
"code.superseriousbusiness.org/gotosocial/internal/typeutils"
"codeberg.org/gruf/go-cache/v3/simple"
)
// Check our type's
// interface conformity.
var _ interface {
// Default
// functionality.
pub.Database
// Federating protocol overridden callback functionality.
Like(context.Context, vocab.ActivityStreamsLike) error
Block(context.Context, vocab.ActivityStreamsBlock) error
Follow(context.Context, vocab.ActivityStreamsFollow) error
Undo(context.Context, vocab.ActivityStreamsUndo) error
Accept(context.Context, vocab.ActivityStreamsAccept) error
Reject(context.Context, vocab.ActivityStreamsReject) error
Announce(context.Context, vocab.ActivityStreamsAnnounce) error
Move(context.Context, vocab.ActivityStreamsMove) error
Flag(context.Context, vocab.ActivityStreamsFlag) error
/*
Extra/convenience functionality.
*/
GetAccept(ctx context.Context, acceptIRI *url.URL) (vocab.ActivityStreamsAccept, error)
} = &DB{}
// DB uses the given state interface to
// implement the go-fed pub.Database interface.
type DB struct {
state *state.State
converter *typeutils.Converter
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
// interface, using the given state and filters.
func New(
state *state.State,
converter *typeutils.Converter,
visFilter *visibility.Filter,
intFilter *interaction.Filter,
spamFilter *spam.Filter,
) *DB {
fdb := DB{
state: state,
converter: converter,
visFilter: visFilter,
intFilter: intFilter,
spamFilter: spamFilter,
}
fdb.activityIDs.Init(0, 2048)
return &fdb
}
// storeActivityID stores an entry in the .activityIDs cache for this
// type's JSON-LD ID, for later checks in Exist() to mark it as seen.
func (f *DB) storeActivityID(asType vocab.Type) {
f.activityIDs.Set(ap.GetJSONLDId(asType).String(), struct{}{})
}