MCPcopy Create free account
hub / github.com/PostHog/duckgres / DestroySession

Method DestroySession

duckdbservice/service.go:1206–1339  ·  view source on GitHub ↗

DestroySession closes and removes a session.

(token string)

Source from the content-addressed store, hash-verified

1204 // ConfigureMainDB sets these once at warmup, but in cluster mode the
1205 // per-session evictConnFromPool call discards the settings along with
1206 // the conn — so for every session after the first we need to re-apply.
1207 // DuckDB rejects `SET GLOBAL` for these keys, so this is the only path.
1208 server.ApplyProfilingSettings(context.Background(), conn)
1209
1210 // Apply initial resource limits if provided (optimizes handshake by avoiding
1211 // roundtrips from control plane).
1212 if memoryLimit != "" {
1213 if _, err := conn.ExecContext(context.Background(), fmt.Sprintf("SET memory_limit = '%s'", memoryLimit)); err != nil {
1214 slog.Warn("Failed to set initial memory_limit.", "user", username, "error", err)
1215 }
1216 }
1217 if threads > 0 {
1218 if _, err := conn.ExecContext(context.Background(), fmt.Sprintf("SET threads = %d", threads)); err != nil {
1219 slog.Warn("Failed to set initial threads.", "user", username, "error", err)
1220 }
1221 }
1222
1223 // User-secret hygiene + replay (shared-warm / k8s mode only). DuckDB
1224 // secrets are instance-global, so a hot-idle worker reused by a different
1225 // user of the same org would otherwise see the previous user's secrets —
1226 // both persistent ones and non-persistent (plain/TEMPORARY CREATE SECRET)
1227 // ones that pass through to the worker. Wipe ALL user secrets first
1228 // (mandatory — this is the cross-user isolation step), then replay this
1229 // user's secrets from the control plane. Replay failures degrade to
1230 // warnings; a wipe failure fails the session because handing user A's
1231 // secrets to user B is not acceptable.
1232 var secretWarnings []string
1233 switch {
1234 case p.sharedWarmMode && p.maxSessions != 1:
1235 // The wipe and replay below are only safe because exactly one session
1236 // runs at a time (DuckDB secrets are instance-global; k8s workers are
1237 // spawned with DUCKGRES_DUCKDB_MAX_SESSIONS=1). Assert that here, at
1238 // the point of reliance, instead of trusting a flag set two layers
1239 // away: with any other cap, wiping would delete a concurrent
1240 // session's secrets mid-query. Skip hygiene entirely and scream.
1241 slog.Error("User secret hygiene requires max_sessions=1 on shared-warm workers; skipping wipe+replay.",
1242 "max_sessions", p.maxSessions, "user", username, "secrets", len(secretStatements))
1243 if len(secretStatements) > 0 {
1244 secretWarnings = []string{"persistent secrets were NOT restored: worker session cap is misconfigured (requires max_sessions=1)"}
1245 }
1246 case p.sharedWarmMode:
1247 secretCtx, secretCancel := context.WithTimeout(context.Background(), userSecretOpTimeout)
1248 wiped, wipeErr := wipeUserSecrets(secretCtx, conn)
1249 if wipeErr != nil {
1250 secretCancel()
1251 _ = conn.Close()
1252 p.mu.Lock()
1253 p.reserved--
1254 p.mu.Unlock()
1255 return nil, nil, fmt.Errorf("wipe user secrets before session start: %w", wipeErr)
1256 }
1257 if len(wiped) > 0 {
1258 slog.Info("Wiped user secrets left by previous session.", "user", username, "count", len(wiped))
1259 }
1260 // Same isolation step for client-ATTACHed databases: they are
1261 // instance-global too, and an attached catalog keeps the credentials
1262 // it was built from even after the secret above is gone. Mandatory for
1263 // the same reason as the wipe — see detachUserCatalogs.

Calls 8

releaseDrainFuncFunction · 0.85
evictConnFromPoolFunction · 0.85
cleanupSessionStateFunction · 0.85
wipeUserSecretsFunction · 0.85
rollbackTxMethod · 0.80
NowMethod · 0.80
CloseMethod · 0.65