fix(workbench): bound session summary runtime query (#1952)
This commit is contained in:
@@ -71,12 +71,15 @@ type sessionsSummaryRevision struct {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Addr string
|
||||
DatabaseURL string
|
||||
QueryTimeout time.Duration
|
||||
ReadinessDelay time.Duration
|
||||
PoolMax int
|
||||
Cache cacheConfig
|
||||
Addr string
|
||||
DatabaseURL string
|
||||
QueryTimeout time.Duration
|
||||
ReadinessDelay time.Duration
|
||||
PoolMax int
|
||||
SessionSummaryMaxAttempts int
|
||||
SessionSummaryAttemptTimeout time.Duration
|
||||
SessionSummaryRetryBackoff time.Duration
|
||||
Cache cacheConfig
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
@@ -1442,16 +1445,17 @@ func (s *Server) dbQueryAttrs(table string, argCount int, extra map[string]any)
|
||||
|
||||
func (s *Server) querySessionSummaries(ctx context.Context, stage string, sqlText string, args []any) ([]any, error) {
|
||||
var lastErr error
|
||||
for attempt := 1; attempt <= sessionSummaryQueryMaxAttempts; attempt++ {
|
||||
attemptResult, err := s.querySessionSummariesAttempt(ctx, stage, sqlText, args, attempt, sessionSummaryQueryMaxAttempts)
|
||||
maxAttempts := positiveInt(s.config.SessionSummaryMaxAttempts, sessionSummaryQueryMaxAttempts)
|
||||
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
||||
attemptResult, err := s.querySessionSummariesAttempt(ctx, stage, sqlText, args, attempt, maxAttempts)
|
||||
if err == nil {
|
||||
return attemptResult, nil
|
||||
}
|
||||
lastErr = err
|
||||
if attempt == sessionSummaryQueryMaxAttempts || !retryableSessionSummaryQueryError(err) || ctx.Err() != nil {
|
||||
if attempt == maxAttempts || !retryableSessionSummaryQueryError(err) || ctx.Err() != nil {
|
||||
break
|
||||
}
|
||||
backoff := sessionSummaryRetryBackoff(attempt)
|
||||
backoff := s.sessionSummaryRetryBackoff(attempt)
|
||||
timer := time.NewTimer(backoff)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -1465,7 +1469,7 @@ func (s *Server) querySessionSummaries(ctx context.Context, stage string, sqlTex
|
||||
|
||||
func (s *Server) querySessionSummariesAttempt(ctx context.Context, stage string, sqlText string, args []any, attempt int, maxAttempts int) ([]any, error) {
|
||||
result := []any{}
|
||||
attemptCtx, cancel := context.WithTimeout(ctx, sessionSummaryQueryAttemptTimeout)
|
||||
attemptCtx, cancel := context.WithTimeout(ctx, positiveDuration(s.config.SessionSummaryAttemptTimeout, sessionSummaryQueryAttemptTimeout))
|
||||
defer cancel()
|
||||
attrs := s.dbQueryAttrs("workbench_sessions", len(args), map[string]any{
|
||||
"db.index.expected": "idx_workbench_sessions_owner_updated|idx_workbench_sessions_updated",
|
||||
@@ -1473,7 +1477,7 @@ func (s *Server) querySessionSummariesAttempt(ctx context.Context, stage string,
|
||||
"retryMax": int64(maxAttempts),
|
||||
})
|
||||
if attempt > 1 {
|
||||
attrs["retryBackoffMs"] = sessionSummaryRetryBackoff(attempt - 1).Milliseconds()
|
||||
attrs["retryBackoffMs"] = s.sessionSummaryRetryBackoff(attempt - 1).Milliseconds()
|
||||
}
|
||||
err := s.withOtelInternalSpan(attemptCtx, stage, attrs, func(spanCtx context.Context) error {
|
||||
rows, err := s.db.QueryContext(spanCtx, sqlText, args...)
|
||||
@@ -1513,11 +1517,26 @@ func (s *Server) querySessionSummariesAttempt(ctx context.Context, stage string,
|
||||
return result, err
|
||||
}
|
||||
|
||||
func sessionSummaryRetryBackoff(attempt int) time.Duration {
|
||||
func (s *Server) sessionSummaryRetryBackoff(attempt int) time.Duration {
|
||||
base := positiveDuration(s.config.SessionSummaryRetryBackoff, sessionSummaryQueryRetryBackoff)
|
||||
if attempt <= 1 {
|
||||
return sessionSummaryQueryRetryBackoff
|
||||
return base
|
||||
}
|
||||
return time.Duration(attempt) * sessionSummaryQueryRetryBackoff
|
||||
return time.Duration(attempt) * base
|
||||
}
|
||||
|
||||
func positiveDuration(value time.Duration, fallback time.Duration) time.Duration {
|
||||
if value > 0 {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func positiveInt(value int, fallback int) int {
|
||||
if value > 0 {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func retryableSessionSummaryQueryError(err error) bool {
|
||||
@@ -2310,12 +2329,15 @@ func normalizeProjectionHealth(value string, projectionStatus string) string {
|
||||
func configFromEnv() Config {
|
||||
port := first(os.Getenv("HWLAB_WORKBENCH_RUNTIME_PORT"), os.Getenv("PORT"), "6671")
|
||||
return Config{
|
||||
Addr: ":" + port,
|
||||
DatabaseURL: first(os.Getenv("HWLAB_WORKBENCH_RUNTIME_DB_URL"), os.Getenv("HWLAB_CLOUD_DB_URL")),
|
||||
QueryTimeout: time.Duration(envInt("HWLAB_WORKBENCH_RUNTIME_QUERY_TIMEOUT_MS", 10000)) * time.Millisecond,
|
||||
ReadinessDelay: time.Duration(envInt("HWLAB_WORKBENCH_RUNTIME_READY_TIMEOUT_MS", 2000)) * time.Millisecond,
|
||||
PoolMax: envInt("HWLAB_WORKBENCH_RUNTIME_DB_POOL_MAX", 8),
|
||||
Cache: cacheConfigFromEnv(),
|
||||
Addr: ":" + port,
|
||||
DatabaseURL: first(os.Getenv("HWLAB_WORKBENCH_RUNTIME_DB_URL"), os.Getenv("HWLAB_CLOUD_DB_URL")),
|
||||
QueryTimeout: time.Duration(envInt("HWLAB_WORKBENCH_RUNTIME_QUERY_TIMEOUT_MS", 10000)) * time.Millisecond,
|
||||
ReadinessDelay: time.Duration(envInt("HWLAB_WORKBENCH_RUNTIME_READY_TIMEOUT_MS", 2000)) * time.Millisecond,
|
||||
PoolMax: envInt("HWLAB_WORKBENCH_RUNTIME_DB_POOL_MAX", 8),
|
||||
SessionSummaryMaxAttempts: envInt("HWLAB_WORKBENCH_SESSIONS_SUMMARY_QUERY_MAX_ATTEMPTS", sessionSummaryQueryMaxAttempts),
|
||||
SessionSummaryAttemptTimeout: time.Duration(envInt("HWLAB_WORKBENCH_SESSIONS_SUMMARY_QUERY_ATTEMPT_TIMEOUT_MS", int(sessionSummaryQueryAttemptTimeout/time.Millisecond))) * time.Millisecond,
|
||||
SessionSummaryRetryBackoff: time.Duration(envInt("HWLAB_WORKBENCH_SESSIONS_SUMMARY_QUERY_BACKOFF_MS", int(sessionSummaryQueryRetryBackoff/time.Millisecond))) * time.Millisecond,
|
||||
Cache: cacheConfigFromEnv(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user