[performance] retry db queries on busy errors (#2025)

* catch SQLITE_BUSY errors, wrap bun.DB to use our own busy retrier, remove unnecessary db.Error type

Signed-off-by: kim <grufwub@gmail.com>

* remove dead code

Signed-off-by: kim <grufwub@gmail.com>

* remove more dead code, add missing error arguments

Signed-off-by: kim <grufwub@gmail.com>

* update sqlite to use maxOpenConns()

Signed-off-by: kim <grufwub@gmail.com>

* add uncommitted changes

Signed-off-by: kim <grufwub@gmail.com>

* use direct calls-through for the ConnIface to make sure we don't double query hook

Signed-off-by: kim <grufwub@gmail.com>

* expose underlying bun.DB better

Signed-off-by: kim <grufwub@gmail.com>

* retry on the correct busy error

Signed-off-by: kim <grufwub@gmail.com>

* use longer possible maxRetries for db retry-backoff

Signed-off-by: kim <grufwub@gmail.com>

* remove the note regarding max-open-conns only applying to postgres

Signed-off-by: kim <grufwub@gmail.com>

* improved code commenting

Signed-off-by: kim <grufwub@gmail.com>

* remove unnecessary infof call (just use info)

Signed-off-by: kim <grufwub@gmail.com>

* rename DBConn to WrappedDB to better follow sql package name conventions

Signed-off-by: kim <grufwub@gmail.com>

* update test error string checks

Signed-off-by: kim <grufwub@gmail.com>

* shush linter

Signed-off-by: kim <grufwub@gmail.com>

* update backoff logic to be more transparent

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
This commit is contained in:
kim 2023-07-25 09:34:05 +01:00 committed by GitHub
commit 5f3e095717
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 1050 additions and 898 deletions

View file

@ -35,7 +35,7 @@ func (r *relationshipDB) GetFollowRequestByID(ctx context.Context, id string) (*
ctx,
"ID",
func(followReq *gtsmodel.FollowRequest) error {
return r.conn.NewSelect().
return r.db.NewSelect().
Model(followReq).
Where("? = ?", bun.Ident("id"), id).
Scan(ctx)
@ -49,7 +49,7 @@ func (r *relationshipDB) GetFollowRequestByURI(ctx context.Context, uri string)
ctx,
"URI",
func(followReq *gtsmodel.FollowRequest) error {
return r.conn.NewSelect().
return r.db.NewSelect().
Model(followReq).
Where("? = ?", bun.Ident("uri"), uri).
Scan(ctx)
@ -63,7 +63,7 @@ func (r *relationshipDB) GetFollowRequest(ctx context.Context, sourceAccountID s
ctx,
"AccountID.TargetAccountID",
func(followReq *gtsmodel.FollowRequest) error {
return r.conn.NewSelect().
return r.db.NewSelect().
Model(followReq).
Where("? = ?", bun.Ident("account_id"), sourceAccountID).
Where("? = ?", bun.Ident("target_account_id"), targetAccountID).
@ -93,7 +93,7 @@ func (r *relationshipDB) GetFollowRequestsByIDs(ctx context.Context, ids []strin
return followReqs, nil
}
func (r *relationshipDB) IsFollowRequested(ctx context.Context, sourceAccountID string, targetAccountID string) (bool, db.Error) {
func (r *relationshipDB) IsFollowRequested(ctx context.Context, sourceAccountID string, targetAccountID string) (bool, error) {
followReq, err := r.GetFollowRequest(
gtscontext.SetBarebones(ctx),
sourceAccountID,
@ -112,7 +112,7 @@ func (r *relationshipDB) getFollowRequest(ctx context.Context, lookup string, db
// Not cached! Perform database query
if err := dbQuery(&followReq); err != nil {
return nil, r.conn.ProcessError(err)
return nil, r.db.ProcessError(err)
}
return &followReq, nil
@ -150,8 +150,8 @@ func (r *relationshipDB) getFollowRequest(ctx context.Context, lookup string, db
func (r *relationshipDB) PutFollowRequest(ctx context.Context, follow *gtsmodel.FollowRequest) error {
return r.state.Caches.GTS.FollowRequest().Store(follow, func() error {
_, err := r.conn.NewInsert().Model(follow).Exec(ctx)
return r.conn.ProcessError(err)
_, err := r.db.NewInsert().Model(follow).Exec(ctx)
return r.db.ProcessError(err)
})
}
@ -163,19 +163,19 @@ func (r *relationshipDB) UpdateFollowRequest(ctx context.Context, followRequest
}
return r.state.Caches.GTS.FollowRequest().Store(followRequest, func() error {
if _, err := r.conn.NewUpdate().
if _, err := r.db.NewUpdate().
Model(followRequest).
Where("? = ?", bun.Ident("follow_request.id"), followRequest.ID).
Column(columns...).
Exec(ctx); err != nil {
return r.conn.ProcessError(err)
return r.db.ProcessError(err)
}
return nil
})
}
func (r *relationshipDB) AcceptFollowRequest(ctx context.Context, sourceAccountID string, targetAccountID string) (*gtsmodel.Follow, db.Error) {
func (r *relationshipDB) AcceptFollowRequest(ctx context.Context, sourceAccountID string, targetAccountID string) (*gtsmodel.Follow, error) {
// Get original follow request.
followReq, err := r.GetFollowRequest(ctx, sourceAccountID, targetAccountID)
if err != nil {
@ -198,12 +198,12 @@ func (r *relationshipDB) AcceptFollowRequest(ctx context.Context, sourceAccountI
if err := r.state.Caches.GTS.Follow().Store(follow, func() error {
// If the follow already exists, just
// replace the URI with the new one.
_, err := r.conn.
_, err := r.db.
NewInsert().
Model(follow).
On("CONFLICT (?,?) DO UPDATE set ? = ?", bun.Ident("account_id"), bun.Ident("target_account_id"), bun.Ident("uri"), follow.URI).
Exec(ctx)
return r.conn.ProcessError(err)
return r.db.ProcessError(err)
}); err != nil {
return nil, err
}
@ -212,12 +212,12 @@ func (r *relationshipDB) AcceptFollowRequest(ctx context.Context, sourceAccountI
defer r.state.Caches.GTS.FollowRequest().Invalidate("ID", followReq.ID)
// Delete original follow request.
if _, err := r.conn.
if _, err := r.db.
NewDelete().
Table("follow_requests").
Where("? = ?", bun.Ident("id"), followReq.ID).
Exec(ctx); err != nil {
return nil, r.conn.ProcessError(err)
return nil, r.db.ProcessError(err)
}
// Delete original follow request notification
@ -230,7 +230,7 @@ func (r *relationshipDB) AcceptFollowRequest(ctx context.Context, sourceAccountI
return follow, nil
}
func (r *relationshipDB) RejectFollowRequest(ctx context.Context, sourceAccountID string, targetAccountID string) db.Error {
func (r *relationshipDB) RejectFollowRequest(ctx context.Context, sourceAccountID string, targetAccountID string) error {
// Delete follow request first.
if err := r.DeleteFollowRequest(ctx, sourceAccountID, targetAccountID); err != nil {
return err
@ -262,11 +262,11 @@ func (r *relationshipDB) DeleteFollowRequest(ctx context.Context, sourceAccountI
}
// Finally delete followreq from DB.
_, err = r.conn.NewDelete().
_, err = r.db.NewDelete().
Table("follow_requests").
Where("? = ?", bun.Ident("id"), follow.ID).
Exec(ctx)
return r.conn.ProcessError(err)
return r.db.ProcessError(err)
}
func (r *relationshipDB) DeleteFollowRequestByID(ctx context.Context, id string) error {
@ -285,11 +285,11 @@ func (r *relationshipDB) DeleteFollowRequestByID(ctx context.Context, id string)
}
// Finally delete followreq from DB.
_, err = r.conn.NewDelete().
_, err = r.db.NewDelete().
Table("follow_requests").
Where("? = ?", bun.Ident("id"), id).
Exec(ctx)
return r.conn.ProcessError(err)
return r.db.ProcessError(err)
}
func (r *relationshipDB) DeleteFollowRequestByURI(ctx context.Context, uri string) error {
@ -308,18 +308,18 @@ func (r *relationshipDB) DeleteFollowRequestByURI(ctx context.Context, uri strin
}
// Finally delete followreq from DB.
_, err = r.conn.NewDelete().
_, err = r.db.NewDelete().
Table("follow_requests").
Where("? = ?", bun.Ident("uri"), uri).
Exec(ctx)
return r.conn.ProcessError(err)
return r.db.ProcessError(err)
}
func (r *relationshipDB) DeleteAccountFollowRequests(ctx context.Context, accountID string) error {
var followReqIDs []string
// Get full list of IDs.
if _, err := r.conn.
if _, err := r.db.
NewSelect().
Column("id").
Table("follow_requestss").
@ -330,7 +330,7 @@ func (r *relationshipDB) DeleteAccountFollowRequests(ctx context.Context, accoun
accountID,
).
Exec(ctx, &followReqIDs); err != nil {
return r.conn.ProcessError(err)
return r.db.ProcessError(err)
}
defer func() {
@ -351,9 +351,9 @@ func (r *relationshipDB) DeleteAccountFollowRequests(ctx context.Context, accoun
}
// Finally delete all from DB.
_, err := r.conn.NewDelete().
_, err := r.db.NewDelete().
Table("follow_requests").
Where("? IN (?)", bun.Ident("id"), bun.In(followReqIDs)).
Exec(ctx)
return r.conn.ProcessError(err)
return r.db.ProcessError(err)
}