[bugfix] updated pinned counts on status delete (#3188)

* include pinned status when incrementing / decrementing status counts

* remove the pinned increment on status creation

* code comments

* microoptimize decr
This commit is contained in:
kim 2024-08-11 09:23:36 +00:00 committed by GitHub
parent 4a3ece0c6c
commit 865b3aeaac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 36 additions and 28 deletions

View File

@ -251,10 +251,7 @@ func (p *clientAPI) CreateStatus(ctx context.Context, cMsg *messages.FromClientA
// If pending approval is true then status must // If pending approval is true then status must
// reply to a status (either one of ours or a // reply to a status (either one of ours or a
// remote) that requires approval for the reply. // remote) that requires approval for the reply.
pendingApproval := util.PtrOrValue( pendingApproval := util.PtrOrZero(status.PendingApproval)
status.PendingApproval,
false,
)
switch { switch {
case pendingApproval && !status.PreApproved: case pendingApproval && !status.PreApproved:
@ -816,7 +813,7 @@ func (p *clientAPI) UndoAnnounce(ctx context.Context, cMsg *messages.FromClientA
} }
// Update stats for the origin account. // Update stats for the origin account.
if err := p.utils.decrementStatusesCount(ctx, cMsg.Origin); err != nil { if err := p.utils.decrementStatusesCount(ctx, cMsg.Origin, status); err != nil {
log.Errorf(ctx, "error updating account stats: %v", err) log.Errorf(ctx, "error updating account stats: %v", err)
} }
@ -873,7 +870,7 @@ func (p *clientAPI) DeleteStatus(ctx context.Context, cMsg *messages.FromClientA
} }
// Update stats for the origin account. // Update stats for the origin account.
if err := p.utils.decrementStatusesCount(ctx, cMsg.Origin); err != nil { if err := p.utils.decrementStatusesCount(ctx, cMsg.Origin, status); err != nil {
log.Errorf(ctx, "error updating account stats: %v", err) log.Errorf(ctx, "error updating account stats: %v", err)
} }

View File

@ -845,7 +845,7 @@ func (p *fediAPI) DeleteStatus(ctx context.Context, fMsg *messages.FromFediAPI)
} }
// Update stats for the remote account. // Update stats for the remote account.
if err := p.utils.decrementStatusesCount(ctx, fMsg.Requesting); err != nil { if err := p.utils.decrementStatusesCount(ctx, fMsg.Requesting, status); err != nil {
log.Errorf(ctx, "error updating account stats: %v", err) log.Errorf(ctx, "error updating account stats: %v", err)
} }

View File

@ -256,17 +256,17 @@ func (u *utils) incrementStatusesCount(
unlock := u.state.ProcessingLocks.Lock(account.URI) unlock := u.state.ProcessingLocks.Lock(account.URI)
defer unlock() defer unlock()
// Populate stats. // Ensure account stats are populated.
if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil { if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil {
return gtserror.Newf("db error getting account stats: %w", err) return gtserror.Newf("db error getting account stats: %w", err)
} }
// Update stats by incrementing status // Update status meta for account.
// count by one and setting last posted.
*account.Stats.StatusesCount++ *account.Stats.StatusesCount++
account.Stats.LastStatusAt = status.CreatedAt account.Stats.LastStatusAt = status.CreatedAt
if err := u.state.DB.UpdateAccountStats(
ctx, // Update details in the database for stats.
if err := u.state.DB.UpdateAccountStats(ctx,
account.Stats, account.Stats,
"statuses_count", "statuses_count",
"last_status_at", "last_status_at",
@ -280,28 +280,30 @@ func (u *utils) incrementStatusesCount(
func (u *utils) decrementStatusesCount( func (u *utils) decrementStatusesCount(
ctx context.Context, ctx context.Context,
account *gtsmodel.Account, account *gtsmodel.Account,
status *gtsmodel.Status,
) error { ) error {
// Lock on this account since we're changing stats. // Lock on this account since we're changing stats.
unlock := u.state.ProcessingLocks.Lock(account.URI) unlock := u.state.ProcessingLocks.Lock(account.URI)
defer unlock() defer unlock()
// Populate stats. // Ensure account stats are populated.
if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil { if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil {
return gtserror.Newf("db error getting account stats: %w", err) return gtserror.Newf("db error getting account stats: %w", err)
} }
// Update stats by decrementing // Update status meta for account (safely checking for zero value).
// status count by one. *account.Stats.StatusesCount = util.Decr(*account.Stats.StatusesCount)
//
// Clamp to 0 to avoid funny business. if !status.PinnedAt.IsZero() {
*account.Stats.StatusesCount-- // Update status pinned count for account (safely checking for zero value).
if *account.Stats.StatusesCount < 0 { *account.Stats.StatusesPinnedCount = util.Decr(*account.Stats.StatusesPinnedCount)
*account.Stats.StatusesCount = 0
} }
if err := u.state.DB.UpdateAccountStats(
ctx, // Update details in the database for stats.
if err := u.state.DB.UpdateAccountStats(ctx,
account.Stats, account.Stats,
"statuses_count", "statuses_count",
"statuses_pinned_count",
); err != nil { ); err != nil {
return gtserror.Newf("db error updating account stats: %w", err) return gtserror.Newf("db error updating account stats: %w", err)
} }
@ -317,7 +319,7 @@ func (u *utils) incrementFollowersCount(
unlock := u.state.ProcessingLocks.Lock(account.URI) unlock := u.state.ProcessingLocks.Lock(account.URI)
defer unlock() defer unlock()
// Populate stats. // Ensure account stats are populated.
if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil { if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil {
return gtserror.Newf("db error getting account stats: %w", err) return gtserror.Newf("db error getting account stats: %w", err)
} }
@ -344,7 +346,7 @@ func (u *utils) decrementFollowersCount(
unlock := u.state.ProcessingLocks.Lock(account.URI) unlock := u.state.ProcessingLocks.Lock(account.URI)
defer unlock() defer unlock()
// Populate stats. // Ensure account stats are populated.
if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil { if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil {
return gtserror.Newf("db error getting account stats: %w", err) return gtserror.Newf("db error getting account stats: %w", err)
} }
@ -376,7 +378,7 @@ func (u *utils) incrementFollowingCount(
unlock := u.state.ProcessingLocks.Lock(account.URI) unlock := u.state.ProcessingLocks.Lock(account.URI)
defer unlock() defer unlock()
// Populate stats. // Ensure account stats are populated.
if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil { if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil {
return gtserror.Newf("db error getting account stats: %w", err) return gtserror.Newf("db error getting account stats: %w", err)
} }
@ -403,7 +405,7 @@ func (u *utils) decrementFollowingCount(
unlock := u.state.ProcessingLocks.Lock(account.URI) unlock := u.state.ProcessingLocks.Lock(account.URI)
defer unlock() defer unlock()
// Populate stats. // Ensure account stats are populated.
if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil { if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil {
return gtserror.Newf("db error getting account stats: %w", err) return gtserror.Newf("db error getting account stats: %w", err)
} }
@ -435,7 +437,7 @@ func (u *utils) incrementFollowRequestsCount(
unlock := u.state.ProcessingLocks.Lock(account.URI) unlock := u.state.ProcessingLocks.Lock(account.URI)
defer unlock() defer unlock()
// Populate stats. // Ensure account stats are populated.
if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil { if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil {
return gtserror.Newf("db error getting account stats: %w", err) return gtserror.Newf("db error getting account stats: %w", err)
} }
@ -462,7 +464,7 @@ func (u *utils) decrementFollowRequestsCount(
unlock := u.state.ProcessingLocks.Lock(account.URI) unlock := u.state.ProcessingLocks.Lock(account.URI)
defer unlock() defer unlock()
// Populate stats. // Ensure account stats are populated.
if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil { if err := u.state.DB.PopulateAccountStats(ctx, account); err != nil {
return gtserror.Newf("db error getting account stats: %w", err) return gtserror.Newf("db error getting account stats: %w", err)
} }

View File

@ -23,6 +23,15 @@ type Number interface {
~uintptr | ~float32 | ~float64 ~uintptr | ~float32 | ~float64
} }
// Decr performs a safe decrement of
// n, clamping minimum value at zero.
func Decr[N Number](n N) N {
if n <= 0 {
return 0
}
return n - 1
}
// Div performs a safe division of // Div performs a safe division of
// n1 and n2, checking for zero n2. In the // n1 and n2, checking for zero n2. In the
// case of zero n2, zero is returned. // case of zero n2, zero is returned.