Skip to content

feat: add user-authored restart backoff and max-retries container fields - #1340

Merged
eminwux merged 1 commit into
mainfrom
feat/restart-tuning-fields
Jun 17, 2026
Merged

feat: add user-authored restart backoff and max-retries container fields#1340
eminwux merged 1 commit into
mainfrom
feat/restart-tuning-fields

Conversation

@eminwux

@eminwux eminwux commented Jun 17, 2026

Copy link
Copy Markdown
Owner

Summary

Phase 3 of the restart-on-exit epic (#1151), parameterizing the hardcoded backoff floor and on-failure retry cap that step 1 (#1233) shipped as the constants restartBackoff (30s) and onFailureMaxRestarts (5) in internal/controller/runner/refresh.go.

  • New optional v1beta1.ContainerSpec fields restartBackoffSeconds *int64 and restartMaxRetries *int64, mirrored on intmodel.ContainerSpec, with scheme conversion both ways across all four container-conversion sites in internal/apischeme/scheme.go.
  • New validateContainerRestart (sibling to validateContainerTty), wired into both the standalone ContainerDoc path and the nested CellSpec.Containers path. Rejects out-of-bounds or inapplicable values at apply time rather than silently ignoring config that can't take effect (the established validateContainerTty contract):
    • restartBackoffSeconds must be >= 0 and requires a restarting policy (always or on-failure).
    • restartMaxRetries must be >= 1 and requires on-failure (the cap is on-failure-specific; always is uncapped by contract).
  • Runner consumption: restartDecisionFor now takes the effective backoff/cap, resolved by effectiveRestartBackoff / effectiveOnFailureMaxRestarts, which fall back to the hardcoded constants when the field is nil (unset). An unset spec sees byte-identical behavior to before; an explicit 0 backoff disables the floor.
  • Field reference docs in docs/site/manifests/container.md (table rows + a "Tuning the backoff and cap" subsection with a YAML example).

Scope decisions (please push back)

  • Runner consumption wired in, beyond the AC's literal "conversion to intmodel". The epic frames step 3 as "parameterizes step 1's constants" / "exposes them as user-authored knobs", so the fields are consumed at cell create/reconcile time — inert fields wouldn't be knobs. The fallback (nil → constant) is exactly AC item 2's "no behavior change for existing specs" guarantee. Kept minimal: one helper pair + threading two args into restartDecisionFor.
  • Deliberately deferred (separable follow-ups), since the AC scopes to ContainerSpec and frames the step as "additive API surface … file-and-forget until operator demand materializes":
    • DiffCell drift-detection (internal/controller/apply/diff.go) and the kuke run reapply-reject diff (cmd/kuke/run/run.go:divergedContainerFields) — changing these fields via kuke apply on an existing cell is not yet detected as drift. Note both diffs are already curated subsets (they omit Resources, Devices, Git, etc.), so this is consistent with the existing pattern rather than a new gap. The knobs take effect at cell create time.
    • The CellBlueprint authoring layer (BlueprintContainer + cellconfig materialize) — restartPolicy's peer there is unextended, so the fields are authored via a direct CellDoc (kuke run -f / kuke apply), not via a blueprint template.
    • Happy to fold any of these in if you'd prefer the full peer-of-restartPolicy treatment in one PR; recommend PM file follow-ups otherwise.

Test plan

  • make test (full CI suite, GOWORK=off) — passes
  • go vet on the touched packages — clean
  • Conversion round-trip tests (set + omitted) and validateContainerRestart table (internal/apischeme/scheme_test.go), incl. the nested-cell validation path
  • Runner fallback/override tests: effectiveRestartBackoff, effectiveOnFailureMaxRestarts, and restartDecisionFor honoring user backoff/cap over the defaults (internal/controller/runner/restart_on_exit_test.go)

Acceptance criteria

  • v1beta1 ContainerSpec gains restart-backoff and max-retries fields with schema, scheme conversion to intmodel.ContainerSpec, and validation
  • Unset fields preserve step 1's hardcoded defaults — no behavior change for existing specs
  • Field reference docs updated
  • Unit coverage for conversion and validation

Closes #1235

@eminwux eminwux added ready-for-review PR is handed off to the reviewer agent in-review Reviewer agent is actively reading this PR and removed ready-for-review PR is handed off to the reviewer agent labels Jun 17, 2026
@eminwux

eminwux commented Jun 17, 2026

Copy link
Copy Markdown
Owner Author

PR #1340 Review — feat: add user-authored restart backoff and max-retries container fields

Clean phase-3 of the restart epic. Both *int64 fields thread through all four internal/apischeme/scheme.go conversion sites alongside RestartPolicy (no silent field-drop), the nil→constant fallback is byte-identical to prior behavior, and validateContainerRestart correctly mirrors the validateContainerTty "config that can't take effect is an error" contract on both the standalone and nested-cell paths. Validation, conversion, and runner-honoring tests are all present; CI green; commits verified. No dead code, no leaks.

A few non-blocking notes:

  • Test plan internal/controller/runner/refresh.go:1363: the change lives in the daemon reconcile loop, so per the project CLAUDE.md daemon-smoke convention the PR would ideally cite make dev-init (or note it's N/A). It's host-gated and doesn't actually exercise restart-tuning, so not blocking — worth a one-line note for the record.
  • Scope deferrals: agree the BlueprintContainer materialize layer (pkg/api/model/v1beta1/cellblueprint.go:153 carries RestartPolicy but not the tuning fields) and the DiffCell/reapply-reject drift gaps are separable — the new fields stay reachable via a direct CellDoc/ContainerSpec, so no public-API parity gap. Reasonable as PM follow-ups.

LGTM to proceed — all items above are non-blocking.

@eminwux eminwux added ready-to-merge Reviewed and ready to merge and removed in-review Reviewer agent is actively reading this PR labels Jun 17, 2026
@eminwux
eminwux merged commit 463d537 into main Jun 17, 2026
5 checks passed
@eminwux
eminwux deleted the feat/restart-tuning-fields branch June 17, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Reviewed and ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

api: user-authored restart backoff and max-retries fields (step 3)

1 participant