Skip to content

Commit 1cb585a

Browse files
adaltonclaude
andauthored
feat(operator): make default inactivity timeout configurable via env var (#824)
## Summary - Make the hardcoded 24h default inactivity timeout configurable via the `DEFAULT_INACTIVITY_TIMEOUT` env var on the operator deployment (value in seconds) - Setting to `0` disables auto-stop globally (session and project overrides still apply) - Add commented-out env var entry to operator deployment manifest for discoverability ## Test plan - [x] All existing inactivity tests pass (`go test -race ./internal/handlers/`) - [x] New test verifies `resolveInactivityTimeout` respects overridden default - [x] `golangci-lint` and `go vet` clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent eebd8ac commit 1cb585a

3 files changed

Lines changed: 36 additions & 4 deletions

File tree

components/manifests/base/operator-deployment.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ spec:
115115
value: "http://minio.ambient-code.svc:9000" # In-cluster MinIO (change for external S3)
116116
- name: S3_BUCKET
117117
value: "ambient-sessions" # Create this bucket in MinIO console
118+
# Inactivity auto-stop configuration
119+
# - name: DEFAULT_INACTIVITY_TIMEOUT
120+
# value: "86400" # Default inactivity timeout in seconds (24h). Set to 0 to disable.
118121
# OpenTelemetry configuration
119122
- name: OTEL_EXPORTER_OTLP_ENDPOINT
120123
value: "otel-collector.ambient-code.svc:4317" # Deploy OTel collector separately

components/operator/internal/handlers/inactivity.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"context"
99
"fmt"
1010
"log"
11+
"os"
12+
"strconv"
1113
"sync"
1214
"time"
1315

@@ -24,10 +26,6 @@ const (
2426
// Stopping phase handler can distinguish inactivity from user stops.
2527
stopReasonAnnotation = "ambient-code.io/stop-reason"
2628

27-
// defaultInactivityTimeoutSec is the fallback when neither the session
28-
// nor the project specifies an inactivity timeout (24 hours).
29-
defaultInactivityTimeoutSec = 86400
30-
3129
// inactivityTimeoutCacheTTL controls how long cached ProjectSettings
3230
// timeout values are valid before re-fetching from the API server.
3331
inactivityTimeoutCacheTTL = 5 * time.Minute
@@ -37,6 +35,22 @@ const (
3735
projectSettingsName = "projectsettings"
3836
)
3937

38+
// defaultInactivityTimeoutSec is the fallback when neither the session
39+
// nor the project specifies an inactivity timeout. Defaults to 86400 (24 hours).
40+
// Override via the DEFAULT_INACTIVITY_TIMEOUT env var (value in seconds).
41+
var defaultInactivityTimeoutSec int64 = 86400
42+
43+
func init() {
44+
if v := os.Getenv("DEFAULT_INACTIVITY_TIMEOUT"); v != "" {
45+
if parsed, err := strconv.ParseInt(v, 10, 64); err == nil {
46+
defaultInactivityTimeoutSec = parsed
47+
log.Printf("[Inactivity] Default inactivity timeout set to %ds via DEFAULT_INACTIVITY_TIMEOUT", parsed)
48+
} else {
49+
log.Printf("[Inactivity] Invalid DEFAULT_INACTIVITY_TIMEOUT value %q, using default %ds", v, defaultInactivityTimeoutSec)
50+
}
51+
}
52+
}
53+
4054
// --- Project-level timeout cache ---
4155

4256
// projectTimeoutCache caches inactivityTimeoutSeconds from ProjectSettings per namespace.

components/operator/internal/handlers/inactivity_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,21 @@ func TestResolveInactivityTimeout(t *testing.T) {
285285
}
286286
})
287287

288+
t.Run("default timeout respects env var override", func(t *testing.T) {
289+
resetTimeoutCache()
290+
setupFakeDynamicClient()
291+
292+
original := defaultInactivityTimeoutSec
293+
defaultInactivityTimeoutSec = 7200
294+
defer func() { defaultInactivityTimeoutSec = original }()
295+
296+
obj := newSessionObj("s1", "ns-empty")
297+
got := resolveInactivityTimeout(obj)
298+
if got != 7200 {
299+
t.Errorf("expected 7200 (overridden default), got %d", got)
300+
}
301+
})
302+
288303
t.Run("session timeout zero overrides project and default", func(t *testing.T) {
289304
resetTimeoutCache()
290305

0 commit comments

Comments
 (0)