diff options
author | 2023-06-11 11:18:44 +0200 | |
---|---|---|
committer | 2023-06-11 10:18:44 +0100 | |
commit | 5e2897e35cd2bea889fa37a2a857f4dcc076dafc (patch) | |
tree | b1ac6203ffa20f5fff1c460fed942854a6e5c6bd /internal/processing/status | |
parent | [docs] Revamp the installation guide (#1877) (diff) | |
download | gotosocial-5e2897e35cd2bea889fa37a2a857f4dcc076dafc.tar.xz |
[bugfix] Invalidate timeline entries for status when stats change (#1879)
Diffstat (limited to 'internal/processing/status')
-rw-r--r-- | internal/processing/status/bookmark.go | 14 | ||||
-rw-r--r-- | internal/processing/status/common.go | 37 | ||||
-rw-r--r-- | internal/processing/status/pin.go | 26 |
3 files changed, 68 insertions, 9 deletions
diff --git a/internal/processing/status/bookmark.go b/internal/processing/status/bookmark.go index ea386b183..64e3fc1fd 100644 --- a/internal/processing/status/bookmark.go +++ b/internal/processing/status/bookmark.go @@ -53,7 +53,12 @@ func (p *Processor) BookmarkCreate(ctx context.Context, requestingAccount *gtsmo } if err := p.state.DB.PutStatusBookmark(ctx, gtsBookmark); err != nil { - err = fmt.Errorf("BookmarkCreate: error putting bookmark in database: %w", err) + err = gtserror.Newf("error putting bookmark in database: %w", err) + return nil, gtserror.NewErrorInternalError(err) + } + + if err := p.invalidateStatus(ctx, requestingAccount.ID, targetStatusID); err != nil { + err = gtserror.Newf("error invalidating status from timelines: %w", err) return nil, gtserror.NewErrorInternalError(err) } @@ -74,7 +79,12 @@ func (p *Processor) BookmarkRemove(ctx context.Context, requestingAccount *gtsmo // We have a bookmark to remove. if err := p.state.DB.DeleteStatusBookmark(ctx, existingBookmarkID); err != nil { - err = fmt.Errorf("BookmarkRemove: error removing status bookmark: %w", err) + err = gtserror.Newf("error removing status bookmark: %w", err) + return nil, gtserror.NewErrorInternalError(err) + } + + if err := p.invalidateStatus(ctx, requestingAccount.ID, targetStatusID); err != nil { + err = gtserror.Newf("error invalidating status from timelines: %w", err) return nil, gtserror.NewErrorInternalError(err) } diff --git a/internal/processing/status/common.go b/internal/processing/status/common.go index 1c08a1e65..e557563f3 100644 --- a/internal/processing/status/common.go +++ b/internal/processing/status/common.go @@ -21,15 +21,17 @@ import ( "context" "fmt" + "codeberg.org/gruf/go-kv" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/log" ) func (p *Processor) apiStatus(ctx context.Context, targetStatus *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*apimodel.Status, gtserror.WithCode) { apiStatus, err := p.tc.StatusToAPIStatus(ctx, targetStatus, requestingAccount) if err != nil { - err = fmt.Errorf("error converting status %s to frontend representation: %w", targetStatus.ID, err) + err = gtserror.Newf("error converting status %s to frontend representation: %w", targetStatus.ID, err) return nil, gtserror.NewErrorInternalError(err) } @@ -66,3 +68,36 @@ func (p *Processor) getVisibleStatus(ctx context.Context, requestingAccount *gts return targetStatus, nil } + +// invalidateStatus is a shortcut function for invalidating the prepared/cached +// representation one status in the home timeline and all list timelines of the +// given accountID. It should only be called in cases where a status update +// does *not* need to be passed into the processor via the worker queue, since +// such invalidation will, in that case, be handled by the processor instead. +func (p *Processor) invalidateStatus(ctx context.Context, accountID string, statusID string) error { + // Get lists first + bail if this fails. + lists, err := p.state.DB.GetListsForAccountID(ctx, accountID) + if err != nil { + return gtserror.Newf("db error getting lists for account %s: %w", accountID, err) + } + + l := log.WithContext(ctx).WithFields(kv.Fields{ + {"accountID", accountID}, + {"statusID", statusID}, + }...) + + // Unprepare item from home + list timelines, just log + // if something goes wrong since this is not a showstopper. + + if err := p.state.Timelines.Home.UnprepareItem(ctx, accountID, statusID); err != nil { + l.Errorf("error unpreparing item from home timeline: %v", err) + } + + for _, list := range lists { + if err := p.state.Timelines.List.UnprepareItem(ctx, list.ID, statusID); err != nil { + l.Errorf("error unpreparing item from list timeline %s: %v", list.ID, err) + } + } + + return nil +} diff --git a/internal/processing/status/pin.go b/internal/processing/status/pin.go index 1e7dc40e8..c5981b699 100644 --- a/internal/processing/status/pin.go +++ b/internal/processing/status/pin.go @@ -95,7 +95,13 @@ func (p *Processor) PinCreate(ctx context.Context, requestingAccount *gtsmodel.A targetStatus.PinnedAt = time.Now() if err := p.state.DB.UpdateStatus(ctx, targetStatus, "pinned_at"); err != nil { - return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error pinning status: %w", err)) + err = gtserror.Newf("db error pinning status: %w", err) + return nil, gtserror.NewErrorInternalError(err) + } + + if err := p.invalidateStatus(ctx, requestingAccount.ID, targetStatusID); err != nil { + err = gtserror.Newf("error invalidating status from timelines: %w", err) + return nil, gtserror.NewErrorInternalError(err) } return p.apiStatus(ctx, targetStatus, requestingAccount) @@ -118,11 +124,19 @@ func (p *Processor) PinRemove(ctx context.Context, requestingAccount *gtsmodel.A return nil, errWithCode } - if !targetStatus.PinnedAt.IsZero() { - targetStatus.PinnedAt = time.Time{} - if err := p.state.DB.UpdateStatus(ctx, targetStatus, "pinned_at"); err != nil { - return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error unpinning status: %w", err)) - } + if targetStatus.PinnedAt.IsZero() { + return p.apiStatus(ctx, targetStatus, requestingAccount) + } + + targetStatus.PinnedAt = time.Time{} + if err := p.state.DB.UpdateStatus(ctx, targetStatus, "pinned_at"); err != nil { + err = gtserror.Newf("db error unpinning status: %w", err) + return nil, gtserror.NewErrorInternalError(err) + } + + if err := p.invalidateStatus(ctx, requestingAccount.ID, targetStatusID); err != nil { + err = gtserror.Newf("error invalidating status from timelines: %w", err) + return nil, gtserror.NewErrorInternalError(err) } return p.apiStatus(ctx, targetStatus, requestingAccount) |