mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-10-02 11:31:57 +00:00
fix(db): reduce per-request connection bursts and add dbtrace
* Throttle async session-activity writes to once per token per minute * Add singleflight to session lookups, keystore validation and column/row security loads to stop cold-cache stampedes * Preload security rules in BeforeHandle (restheadspec, resolvespec) so they no longer need a second connection while the read tx is open * Add pkg/dbtrace: opt-in per-request DB call counting and pool logging (db_trace.* config, RESOLVESPEC_DB_TRACE_* env), wired into testserver * Add tests for load dedup, activity throttle and dbtrace
This commit is contained in:
@@ -12,6 +12,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/cache"
|
||||
"github.com/bitechdev/ResolveSpec/pkg/dbtrace"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
// DatabaseKeyStoreOptions configures DatabaseKeyStore.
|
||||
@@ -51,6 +53,9 @@ type DatabaseKeyStore struct {
|
||||
capability *dbCapability
|
||||
cache *cache.Cache
|
||||
cacheTTL time.Duration
|
||||
|
||||
// validateLoads collapses concurrent key lookups for the same key
|
||||
validateLoads singleflight.Group
|
||||
}
|
||||
|
||||
// NewDatabaseKeyStore creates a DatabaseKeyStore with optional configuration.
|
||||
@@ -237,6 +242,24 @@ func (ks *DatabaseKeyStore) ValidateKey(ctx context.Context, rawKey string, keyT
|
||||
}
|
||||
}
|
||||
|
||||
// Concurrent misses for the same key share one database lookup.
|
||||
v, err, _ := ks.validateLoads.Do(cacheKey+"|"+string(keyType), func() (any, error) {
|
||||
return ks.validateKeyLoad(ctx, hash, cacheKey, keyType)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, _ := v.(*UserKey)
|
||||
if key == nil {
|
||||
return nil, errors.New("invalid or expired key")
|
||||
}
|
||||
cp := *key
|
||||
return &cp, nil
|
||||
}
|
||||
|
||||
// validateKeyLoad validates against the database and fills the cache.
|
||||
func (ks *DatabaseKeyStore) validateKeyLoad(ctx context.Context, hash, cacheKey string, keyType KeyType) (*UserKey, error) {
|
||||
dbtrace.Raw(ctx, "keystore.validate")
|
||||
if !ks.capability.ShouldUseProcedure(ctx, ks.queryMode, ks.getDB(), ks.sqlNames.ValidateKey) {
|
||||
key, err := ks.validateKeyDirect(ctx, hash, keyType)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user