perf(admin): cache the suspension gate lookup
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 46s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m4s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 46s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m4s
The suspension gate runs CurrentSuspension on every authenticated request. Add a write-through in-memory cache on account.Store keyed by account id, invalidated on Suspend/LiftSuspension, with the cached entry re-evaluated against the wall clock so a temporary block lapses without an explicit invalidation. Single-instance, matching the deployment (one shared Store). Keeps the gate off the database on the hot path while a block still takes effect on the next request.
This commit is contained in:
@@ -99,12 +99,15 @@ type Identity struct {
|
||||
type Store struct {
|
||||
db *sql.DB
|
||||
metrics *accountMetrics
|
||||
// suspensions caches each account's current manual block, read by the suspension gate on
|
||||
// every authenticated request and invalidated on Suspend/LiftSuspension. See suspension.go.
|
||||
suspensions *suspensionCache
|
||||
}
|
||||
|
||||
// NewStore constructs a Store wrapping db. Metrics default to a no-op meter until
|
||||
// SetMetrics installs the real one during startup wiring.
|
||||
func NewStore(db *sql.DB) *Store {
|
||||
return &Store{db: db, metrics: defaultAccountMetrics()}
|
||||
return &Store{db: db, metrics: defaultAccountMetrics(), suspensions: newSuspensionCache()}
|
||||
}
|
||||
|
||||
// ProvisionByIdentity returns the account bound to (kind, externalID), creating
|
||||
|
||||
Reference in New Issue
Block a user