mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 22:42:24 -05:00 
			
		
		
		
	[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:
		
					parent
					
						
							
								4a3ece0c6c
							
						
					
				
			
			
				commit
				
					
						865b3aeaac
					
				
			
		
					 4 changed files with 36 additions and 28 deletions
				
			
		|  | @ -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) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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. | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue