[feature] support canceling scheduled tasks, some federation API performance improvements (#2329)

This commit is contained in:
kim
2023-11-04 20:21:20 +00:00
committed by GitHub
parent 314dda196e
commit 41435a6c4e
23 changed files with 993 additions and 487 deletions

View File

@ -32,6 +32,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/messages"
"github.com/superseriousbusiness/gotosocial/internal/processing/account"
"github.com/superseriousbusiness/gotosocial/internal/state"
"github.com/superseriousbusiness/gotosocial/internal/util"
)
// fediAPI wraps processing functions
@ -142,27 +143,22 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg messages.FromFe
}
}
return nil
return gtserror.Newf("unhandled: %s %s", fMsg.APActivityType, fMsg.APObjectType)
}
func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) error {
var (
status *gtsmodel.Status
err error
// Check the federatorMsg for either an already dereferenced
// and converted status pinned to the message, or a forwarded
// AP IRI that we still need to deref.
forwarded = (fMsg.GTSModel == nil)
)
if forwarded {
// Model was not set, deref with IRI.
if fMsg.APObjectModel == nil /* i.e. forwarded */ {
// Model was not set, deref with IRI (this is a forward).
// This will also cause the status to be inserted into the db.
status, err = p.statusFromAPIRI(ctx, fMsg)
} else {
// Model is set, ensure we have the most up-to-date model.
status, err = p.statusFromGTSModel(ctx, fMsg)
status, err = p.statusFromAPModel(ctx, fMsg)
}
if err != nil {
@ -188,19 +184,10 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
}
}
// Ensure status ancestors dereferenced. We need at least the
// immediate parent (if present) to ascertain timelineability.
if err := p.federate.DereferenceStatusAncestors(
ctx,
fMsg.ReceivingAccount.Username,
status,
); err != nil {
return err
}
if status.InReplyToID != "" {
// Interaction counts changed on the replied status;
// uncache the prepared version from all timelines.
// Interaction counts changed on the replied status; uncache the
// prepared version from all timelines. The status dereferencer
// functions will ensure necessary ancestors exist before this point.
p.surface.invalidateStatusFromTimelines(ctx, status.InReplyToID)
}
@ -211,23 +198,31 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
return nil
}
func (p *fediAPI) statusFromGTSModel(ctx context.Context, fMsg messages.FromFediAPI) (*gtsmodel.Status, error) {
// There should be a status pinned to the message:
// we've already checked to ensure this is not nil.
status, ok := fMsg.GTSModel.(*gtsmodel.Status)
func (p *fediAPI) statusFromAPModel(ctx context.Context, fMsg messages.FromFediAPI) (*gtsmodel.Status, error) {
// AP statusable representation MUST have been set.
statusable, ok := fMsg.APObjectModel.(ap.Statusable)
if !ok {
err := gtserror.New("Note was not parseable as *gtsmodel.Status")
return nil, err
return nil, gtserror.Newf("cannot cast %T -> ap.Statusable", fMsg.APObjectModel)
}
// AP statusable representation may have also
// been set on message (no problem if not).
statusable, _ := fMsg.APObjectModel.(ap.Statusable)
// Status may have been set (no problem if not).
status, _ := fMsg.GTSModel.(*gtsmodel.Status)
// Call refresh on status to update
// it (deref remote) if necessary.
var err error
status, _, err = p.federate.RefreshStatus(
if status == nil {
// No status was set, create a bare-bones
// model for the deferencer to flesh-out,
// this indicates it is a new (to us) status.
status = &gtsmodel.Status{
// if coming in here status will ALWAYS be remote.
Local: util.Ptr(false),
URI: ap.GetJSONLDId(statusable).String(),
}
}
// Call refresh on status to either update existing
// model, or parse + insert status from statusable data.
status, _, err := p.federate.RefreshStatus(
ctx,
fMsg.ReceivingAccount.Username,
status,
@ -235,7 +230,7 @@ func (p *fediAPI) statusFromGTSModel(ctx context.Context, fMsg messages.FromFedi
false, // Don't force refresh.
)
if err != nil {
return nil, gtserror.Newf("%w", err)
return nil, gtserror.Newf("error refreshing status: %w", err)
}
return status, nil
@ -245,11 +240,8 @@ func (p *fediAPI) statusFromAPIRI(ctx context.Context, fMsg messages.FromFediAPI
// There should be a status IRI pinned to
// the federatorMsg for us to dereference.
if fMsg.APIri == nil {
err := gtserror.New(
"status was not pinned to federatorMsg, " +
"and neither was an IRI for us to dereference",
)
return nil, err
const text = "neither APObjectModel nor APIri set"
return nil, gtserror.New(text)
}
// Get the status + ensure we have
@ -260,7 +252,7 @@ func (p *fediAPI) statusFromAPIRI(ctx context.Context, fMsg messages.FromFediAPI
fMsg.APIri,
)
if err != nil {
return nil, gtserror.Newf("%w", err)
return nil, gtserror.Newf("error getting status by uri %s: %w", fMsg.APIri, err)
}
return status, nil
@ -337,7 +329,9 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg messages.FromFediAPI)
return gtserror.Newf("%T not parseable as *gtsmodel.Status", fMsg.GTSModel)
}
// Dereference status that this status boosts.
// Dereference status that this boosts, note
// that this will handle dereferencing the status
// ancestors / descendants where appropriate.
if err := p.federate.DereferenceAnnounce(
ctx,
status,
@ -358,15 +352,6 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg messages.FromFediAPI)
return gtserror.Newf("db error inserting status: %w", err)
}
// Ensure boosted status ancestors dereferenced. We need at least
// the immediate parent (if present) to ascertain timelineability.
if err := p.federate.DereferenceStatusAncestors(ctx,
fMsg.ReceivingAccount.Username,
status.BoostOf,
); err != nil {
return err
}
// Timeline and notify the announce.
if err := p.surface.timelineAndNotifyStatus(ctx, status); err != nil {
return gtserror.Newf("error timelining status: %w", err)
@ -526,23 +511,25 @@ func (p *fediAPI) UpdateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
}
// Cast the updated ActivityPub statusable object .
apStatus, ok := fMsg.APObjectModel.(ap.Statusable)
if !ok {
return gtserror.Newf("cannot cast %T -> ap.Statusable", fMsg.APObjectModel)
}
apStatus, _ := fMsg.APObjectModel.(ap.Statusable)
// Fetch up-to-date attach status attachments, etc.
_, _, err := p.federate.RefreshStatus(
_, statusable, err := p.federate.RefreshStatus(
ctx,
fMsg.ReceivingAccount.Username,
existing,
apStatus,
false,
true,
)
if err != nil {
return gtserror.Newf("error refreshing updated status: %w", err)
}
if statusable != nil {
// Status representation was refetched, uncache from timelines.
p.surface.invalidateStatusFromTimelines(ctx, existing.ID)
}
return nil
}