mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 13:42:24 -05:00
[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:
parent
9eff0d46e4
commit
5f3e095717
53 changed files with 1050 additions and 898 deletions
|
|
@ -44,21 +44,21 @@ import (
|
|||
const rsaKeyBits = 2048
|
||||
|
||||
type adminDB struct {
|
||||
conn *DBConn
|
||||
db *WrappedDB
|
||||
state *state.State
|
||||
}
|
||||
|
||||
func (a *adminDB) IsUsernameAvailable(ctx context.Context, username string) (bool, db.Error) {
|
||||
q := a.conn.
|
||||
func (a *adminDB) IsUsernameAvailable(ctx context.Context, username string) (bool, error) {
|
||||
q := a.db.
|
||||
NewSelect().
|
||||
TableExpr("? AS ?", bun.Ident("accounts"), bun.Ident("account")).
|
||||
Column("account.id").
|
||||
Where("? = ?", bun.Ident("account.username"), username).
|
||||
Where("? IS NULL", bun.Ident("account.domain"))
|
||||
return a.conn.NotExists(ctx, q)
|
||||
return a.db.NotExists(ctx, q)
|
||||
}
|
||||
|
||||
func (a *adminDB) IsEmailAvailable(ctx context.Context, email string) (bool, db.Error) {
|
||||
func (a *adminDB) IsEmailAvailable(ctx context.Context, email string) (bool, error) {
|
||||
// parse the domain from the email
|
||||
m, err := mail.ParseAddress(email)
|
||||
if err != nil {
|
||||
|
|
@ -67,12 +67,12 @@ func (a *adminDB) IsEmailAvailable(ctx context.Context, email string) (bool, db.
|
|||
domain := strings.Split(m.Address, "@")[1] // domain will always be the second part after @
|
||||
|
||||
// check if the email domain is blocked
|
||||
emailDomainBlockedQ := a.conn.
|
||||
emailDomainBlockedQ := a.db.
|
||||
NewSelect().
|
||||
TableExpr("? AS ?", bun.Ident("email_domain_blocks"), bun.Ident("email_domain_block")).
|
||||
Column("email_domain_block.id").
|
||||
Where("? = ?", bun.Ident("email_domain_block.domain"), domain)
|
||||
emailDomainBlocked, err := a.conn.Exists(ctx, emailDomainBlockedQ)
|
||||
emailDomainBlocked, err := a.db.Exists(ctx, emailDomainBlockedQ)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
@ -81,16 +81,16 @@ func (a *adminDB) IsEmailAvailable(ctx context.Context, email string) (bool, db.
|
|||
}
|
||||
|
||||
// check if this email is associated with a user already
|
||||
q := a.conn.
|
||||
q := a.db.
|
||||
NewSelect().
|
||||
TableExpr("? AS ?", bun.Ident("users"), bun.Ident("user")).
|
||||
Column("user.id").
|
||||
Where("? = ?", bun.Ident("user.email"), email).
|
||||
WhereOr("? = ?", bun.Ident("user.unconfirmed_email"), email)
|
||||
return a.conn.NotExists(ctx, q)
|
||||
return a.db.NotExists(ctx, q)
|
||||
}
|
||||
|
||||
func (a *adminDB) NewSignup(ctx context.Context, newSignup gtsmodel.NewSignup) (*gtsmodel.User, db.Error) {
|
||||
func (a *adminDB) NewSignup(ctx context.Context, newSignup gtsmodel.NewSignup) (*gtsmodel.User, error) {
|
||||
// If something went wrong previously while doing a new
|
||||
// sign up with this username, we might already have an
|
||||
// account, so check first.
|
||||
|
|
@ -220,17 +220,17 @@ func (a *adminDB) NewSignup(ctx context.Context, newSignup gtsmodel.NewSignup) (
|
|||
return user, nil
|
||||
}
|
||||
|
||||
func (a *adminDB) CreateInstanceAccount(ctx context.Context) db.Error {
|
||||
func (a *adminDB) CreateInstanceAccount(ctx context.Context) error {
|
||||
username := config.GetHost()
|
||||
|
||||
q := a.conn.
|
||||
q := a.db.
|
||||
NewSelect().
|
||||
TableExpr("? AS ?", bun.Ident("accounts"), bun.Ident("account")).
|
||||
Column("account.id").
|
||||
Where("? = ?", bun.Ident("account.username"), username).
|
||||
Where("? IS NULL", bun.Ident("account.domain"))
|
||||
|
||||
exists, err := a.conn.Exists(ctx, q)
|
||||
exists, err := a.db.Exists(ctx, q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -277,18 +277,18 @@ func (a *adminDB) CreateInstanceAccount(ctx context.Context) db.Error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *adminDB) CreateInstanceInstance(ctx context.Context) db.Error {
|
||||
func (a *adminDB) CreateInstanceInstance(ctx context.Context) error {
|
||||
protocol := config.GetProtocol()
|
||||
host := config.GetHost()
|
||||
|
||||
// check if instance entry already exists
|
||||
q := a.conn.
|
||||
q := a.db.
|
||||
NewSelect().
|
||||
Column("instance.id").
|
||||
TableExpr("? AS ?", bun.Ident("instances"), bun.Ident("instance")).
|
||||
Where("? = ?", bun.Ident("instance.domain"), host)
|
||||
|
||||
exists, err := a.conn.Exists(ctx, q)
|
||||
exists, err := a.db.Exists(ctx, q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -309,13 +309,13 @@ func (a *adminDB) CreateInstanceInstance(ctx context.Context) db.Error {
|
|||
URI: fmt.Sprintf("%s://%s", protocol, host),
|
||||
}
|
||||
|
||||
insertQ := a.conn.
|
||||
insertQ := a.db.
|
||||
NewInsert().
|
||||
Model(i)
|
||||
|
||||
_, err = insertQ.Exec(ctx)
|
||||
if err != nil {
|
||||
return a.conn.ProcessError(err)
|
||||
return a.db.ProcessError(err)
|
||||
}
|
||||
|
||||
log.Infof(ctx, "created instance instance %s with id %s", host, i.ID)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue