mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[performance] cached oauth database types (#2838)
* update token + client code to use struct caches * add code comments * slight tweak to default mem ratios * fix envparsing * add appropriate invalidate hooks * update the tokenstore sweeping function to rely on caches * update to use PutClient() * add ClientID to list of token struct indices
This commit is contained in:
@@ -35,4 +35,40 @@ type Application interface {
|
||||
|
||||
// DeleteApplicationByClientID deletes the application with corresponding client_id value from the database.
|
||||
DeleteApplicationByClientID(ctx context.Context, clientID string) error
|
||||
|
||||
// GetClientByID ...
|
||||
GetClientByID(ctx context.Context, id string) (*gtsmodel.Client, error)
|
||||
|
||||
// PutClient ...
|
||||
PutClient(ctx context.Context, client *gtsmodel.Client) error
|
||||
|
||||
// DeleteClientByID ...
|
||||
DeleteClientByID(ctx context.Context, id string) error
|
||||
|
||||
// GetAllTokens ...
|
||||
GetAllTokens(ctx context.Context) ([]*gtsmodel.Token, error)
|
||||
|
||||
// GetTokenByCode ...
|
||||
GetTokenByCode(ctx context.Context, code string) (*gtsmodel.Token, error)
|
||||
|
||||
// GetTokenByAccess ...
|
||||
GetTokenByAccess(ctx context.Context, access string) (*gtsmodel.Token, error)
|
||||
|
||||
// GetTokenByRefresh ...
|
||||
GetTokenByRefresh(ctx context.Context, refresh string) (*gtsmodel.Token, error)
|
||||
|
||||
// PutToken ...
|
||||
PutToken(ctx context.Context, token *gtsmodel.Token) error
|
||||
|
||||
// DeleteTokenByID ...
|
||||
DeleteTokenByID(ctx context.Context, id string) error
|
||||
|
||||
// DeleteTokenByCode ...
|
||||
DeleteTokenByCode(ctx context.Context, code string) error
|
||||
|
||||
// DeleteTokenByAccess ...
|
||||
DeleteTokenByAccess(ctx context.Context, access string) error
|
||||
|
||||
// DeleteTokenByRefresh ...
|
||||
DeleteTokenByRefresh(ctx context.Context, refresh string) error
|
||||
}
|
||||
|
@@ -397,7 +397,7 @@ func (a *adminDB) CreateInstanceApplication(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Store it.
|
||||
return a.state.DB.Put(ctx, oc)
|
||||
return a.state.DB.PutClient(ctx, oc)
|
||||
}
|
||||
|
||||
func (a *adminDB) GetInstanceApplication(ctx context.Context) (*gtsmodel.Application, error) {
|
||||
|
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
@@ -95,3 +96,181 @@ func (a *applicationDB) DeleteApplicationByClientID(ctx context.Context, clientI
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *applicationDB) GetClientByID(ctx context.Context, id string) (*gtsmodel.Client, error) {
|
||||
return a.state.Caches.GTS.Client.LoadOne("ID", func() (*gtsmodel.Client, error) {
|
||||
var client gtsmodel.Client
|
||||
|
||||
if err := a.db.NewSelect().
|
||||
Model(&client).
|
||||
Where("? = ?", bun.Ident("id"), id).
|
||||
Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &client, nil
|
||||
}, id)
|
||||
}
|
||||
|
||||
func (a *applicationDB) PutClient(ctx context.Context, client *gtsmodel.Client) error {
|
||||
return a.state.Caches.GTS.Client.Store(client, func() error {
|
||||
_, err := a.db.NewInsert().Model(client).Exec(ctx)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (a *applicationDB) DeleteClientByID(ctx context.Context, id string) error {
|
||||
_, err := a.db.NewDelete().
|
||||
Table("clients").
|
||||
Where("? = ?", bun.Ident("id"), id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.state.Caches.GTS.Client.Invalidate("ID", id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *applicationDB) GetAllTokens(ctx context.Context) ([]*gtsmodel.Token, error) {
|
||||
var tokenIDs []string
|
||||
|
||||
// Select ALL token IDs.
|
||||
if err := a.db.NewSelect().
|
||||
Table("tokens").
|
||||
Column("id").
|
||||
Scan(ctx, &tokenIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Load all input token IDs via cache loader callback.
|
||||
tokens, err := a.state.Caches.GTS.Token.LoadIDs("ID",
|
||||
tokenIDs,
|
||||
func(uncached []string) ([]*gtsmodel.Token, error) {
|
||||
// Preallocate expected length of uncached tokens.
|
||||
tokens := make([]*gtsmodel.Token, 0, len(uncached))
|
||||
|
||||
// Perform database query scanning
|
||||
// the remaining (uncached) token IDs.
|
||||
if err := a.db.NewSelect().
|
||||
Model(tokens).
|
||||
Where("? IN (?)", bun.Ident("id"), bun.In(uncached)).
|
||||
Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tokens, nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Reoroder the tokens by their
|
||||
// IDs to ensure in correct order.
|
||||
getID := func(t *gtsmodel.Token) string { return t.ID }
|
||||
util.OrderBy(tokens, tokenIDs, getID)
|
||||
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
func (a *applicationDB) GetTokenByCode(ctx context.Context, code string) (*gtsmodel.Token, error) {
|
||||
return a.getTokenBy(
|
||||
"Code",
|
||||
func(t *gtsmodel.Token) error {
|
||||
return a.db.NewSelect().Model(t).Where("? = ?", bun.Ident("code"), code).Scan(ctx)
|
||||
},
|
||||
code,
|
||||
)
|
||||
}
|
||||
|
||||
func (a *applicationDB) GetTokenByAccess(ctx context.Context, access string) (*gtsmodel.Token, error) {
|
||||
return a.getTokenBy(
|
||||
"Access",
|
||||
func(t *gtsmodel.Token) error {
|
||||
return a.db.NewSelect().Model(t).Where("? = ?", bun.Ident("access"), access).Scan(ctx)
|
||||
},
|
||||
access,
|
||||
)
|
||||
}
|
||||
|
||||
func (a *applicationDB) GetTokenByRefresh(ctx context.Context, refresh string) (*gtsmodel.Token, error) {
|
||||
return a.getTokenBy(
|
||||
"Refresh",
|
||||
func(t *gtsmodel.Token) error {
|
||||
return a.db.NewSelect().Model(t).Where("? = ?", bun.Ident("refresh"), refresh).Scan(ctx)
|
||||
},
|
||||
refresh,
|
||||
)
|
||||
}
|
||||
|
||||
func (a *applicationDB) getTokenBy(lookup string, dbQuery func(*gtsmodel.Token) error, keyParts ...any) (*gtsmodel.Token, error) {
|
||||
return a.state.Caches.GTS.Token.LoadOne(lookup, func() (*gtsmodel.Token, error) {
|
||||
var token gtsmodel.Token
|
||||
|
||||
if err := dbQuery(&token); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &token, nil
|
||||
}, keyParts...)
|
||||
}
|
||||
|
||||
func (a *applicationDB) PutToken(ctx context.Context, token *gtsmodel.Token) error {
|
||||
return a.state.Caches.GTS.Token.Store(token, func() error {
|
||||
_, err := a.db.NewInsert().Model(token).Exec(ctx)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (a *applicationDB) DeleteTokenByID(ctx context.Context, id string) error {
|
||||
_, err := a.db.NewDelete().
|
||||
Table("tokens").
|
||||
Where("? = ?", bun.Ident("id"), id).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.state.Caches.GTS.Token.Invalidate("ID", id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *applicationDB) DeleteTokenByCode(ctx context.Context, code string) error {
|
||||
_, err := a.db.NewDelete().
|
||||
Table("tokens").
|
||||
Where("? = ?", bun.Ident("code"), code).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.state.Caches.GTS.Token.Invalidate("Code", code)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *applicationDB) DeleteTokenByAccess(ctx context.Context, access string) error {
|
||||
_, err := a.db.NewDelete().
|
||||
Table("tokens").
|
||||
Where("? = ?", bun.Ident("access"), access).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.state.Caches.GTS.Token.Invalidate("Access", access)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *applicationDB) DeleteTokenByRefresh(ctx context.Context, refresh string) error {
|
||||
_, err := a.db.NewDelete().
|
||||
Table("tokens").
|
||||
Where("? = ?", bun.Ident("refresh"), refresh).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.state.Caches.GTS.Token.Invalidate("Refresh", refresh)
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user