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:
2026-09-30 21:44:28 +02:00
parent 62cc14c02a
commit 3e327d0c78
20 changed files with 544 additions and 87 deletions
+10
View File
@@ -16,6 +16,7 @@ type Config struct {
CORS CORSConfig `mapstructure:"cors"`
EventBroker EventBrokerConfig `mapstructure:"event_broker"`
DBManager DBManagerConfig `mapstructure:"dbmanager"`
DBTrace DBTraceConfig `mapstructure:"db_trace"`
Paths PathsConfig `mapstructure:"paths"`
Extensions map[string]interface{} `mapstructure:"extensions"`
}
@@ -142,6 +143,15 @@ type CORSConfig struct {
MaxAge int `mapstructure:"max_age"`
}
// DBTraceConfig controls database usage logging (off by default).
// Env: RESOLVESPEC_DB_TRACE_ENABLED, _MIN_CALLS, _MIN_DURATION, _POOL_LOG.
type DBTraceConfig struct {
Enabled bool `mapstructure:"enabled"` // per-request DB call logging
MinCalls int `mapstructure:"min_calls"` // log requests with at least this many DB calls
MinDuration time.Duration `mapstructure:"min_duration"` // or that took at least this long (0 = off)
PoolLog bool `mapstructure:"pool_log"` // log pool changes on each metrics publish
}
// ErrorTrackingConfig holds error tracking configuration
type ErrorTrackingConfig struct {
Enabled bool `mapstructure:"enabled"`
+7
View File
@@ -167,6 +167,7 @@ func (m *Manager) SetConfig(cfg *Config) error {
m.v.Set("cors", cfg.CORS)
m.v.Set("event_broker", cfg.EventBroker)
m.v.Set("dbmanager", cfg.DBManager)
m.v.Set("db_trace", cfg.DBTrace)
m.v.Set("paths", cfg.Paths)
m.v.Set("extensions", cfg.Extensions)
@@ -282,6 +283,12 @@ func setDefaults(v *viper.Viper) {
v.SetDefault("database.url", "")
// Database Manager defaults
// DB trace defaults (disabled)
v.SetDefault("db_trace.enabled", false)
v.SetDefault("db_trace.min_calls", 5)
v.SetDefault("db_trace.min_duration", "0s")
v.SetDefault("db_trace.pool_log", false)
v.SetDefault("dbmanager.default_connection", "default")
v.SetDefault("dbmanager.max_open_conns", 25)
v.SetDefault("dbmanager.max_idle_conns", 5)