[performance] temporarily cache account status counts to reduce no. account counts (#2620)

* temporarily cache account status counts to reduce no. account counts

* whoops, forgot to initAccountCounts()

* use already fetched cache capacity value

* make cache a ptr type

* whoops, use count instead of just select

* fix to correctly use the transaction

* properly wrap that tx 😇

* correctly wrap both tx types

* outline retryOnBusy() to allow the fast path to be inlined

* return err on context cancelled

* remove unnecessary storage of context in stmt, fix Exec and Query interface implementations

* shutup linter
This commit is contained in:
kim 2024-02-12 11:52:12 +00:00 committed by GitHub
commit ede8f43635
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 199 additions and 38 deletions

View file

@ -532,20 +532,56 @@ func (a *accountDB) GetAccountFaves(ctx context.Context, accountID string) ([]*g
}
func (a *accountDB) CountAccountStatuses(ctx context.Context, accountID string) (int, error) {
return a.db.
NewSelect().
TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")).
Where("? = ?", bun.Ident("status.account_id"), accountID).
Count(ctx)
counts, err := a.getAccountStatusCounts(ctx, accountID)
return counts.Statuses, err
}
func (a *accountDB) CountAccountPinned(ctx context.Context, accountID string) (int, error) {
return a.db.
NewSelect().
TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")).
Where("? = ?", bun.Ident("status.account_id"), accountID).
Where("? IS NOT NULL", bun.Ident("status.pinned_at")).
Count(ctx)
counts, err := a.getAccountStatusCounts(ctx, accountID)
return counts.Pinned, err
}
func (a *accountDB) getAccountStatusCounts(ctx context.Context, accountID string) (struct {
Statuses int
Pinned int
}, error) {
// Check for an already cached copy of account status counts.
counts, ok := a.state.Caches.GTS.AccountCounts.Get(accountID)
if ok {
return counts, nil
}
if err := a.db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
var err error
// Scan database for account statuses.
counts.Statuses, err = tx.NewSelect().
Table("statuses").
Where("? = ?", bun.Ident("account_id"), accountID).
Count(ctx)
if err != nil {
return err
}
// Scan database for pinned statuses.
counts.Pinned, err = tx.NewSelect().
Table("statuses").
Where("? = ?", bun.Ident("account_id"), accountID).
Where("? IS NOT NULL", bun.Ident("pinned_at")).
Count(ctx)
if err != nil {
return err
}
return nil
}); err != nil {
return counts, err
}
// Store this account counts result in the cache.
a.state.Caches.GTS.AccountCounts.Set(accountID, counts)
return counts, nil
}
func (a *accountDB) GetAccountStatuses(ctx context.Context, accountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, mediaOnly bool, publicOnly bool) ([]*gtsmodel.Status, error) {