Skip to content

feat(state): persist attached runs and cap state dir by size#8

Merged
enixCode merged 1 commit into
mainfrom
feat/state-persist-and-gc
May 29, 2026
Merged

feat(state): persist attached runs and cap state dir by size#8
enixCode merged 1 commit into
mainfrom
feat/state-persist-and-gc

Conversation

@enixCode
Copy link
Copy Markdown
Owner

What

Two changes so light-run can treat light-runner as the single source of truth for run state (read listStates / readState, reattach on boot, no separate store).

  • Persist attached runs. runner/attached.ts now writes the state file like the detached path: writeState({ status: 'running' }) before setup, updateState on exit / cancel / error. Synchronous runs become visible to listStates() and reconcilable after a launcher restart. Documented limitation: attached runs cannot be resumed live (AutoRemove removes the container on exit and onLog is not replayed).
  • State-dir GC. New DockerRunner.cleanupOldStates(maxBytes?) evicts terminal states (exited / cancelled / failed) oldest-first until the state dir is back under budget; running states are never removed. Wires up deleteState(), which existed but was never called. Kept distinct from cleanupOrphanStates (reconcile != delete).
  • New env var. LIGHT_RUNNER_STATE_MAX_BYTES (default 50 MiB) read via stateMaxBytes(), mirroring reapAgeMs().
  • Tests. 3 unit cases for cleanupOldStates (no-op under budget, oldest-first eviction, running preserved) + 1 e2e case asserting an attached run writes a terminal state file. Local run: unit 69/69, e2e attach.test.js 8/8.
  • Docs. README documents the env var, cleanupOldStates, attached persistence and the onLog limitation; API reference regenerated.

build with cc

- Persist attached (synchronous) runs to the state dir like detached:
  writeState(running) before setup, updateState on exit/cancel/error.
  Synchronous runs become visible to listStates() and reconcilable after a
  launcher restart. They cannot be resumed live (AutoRemove + no onLog
  replay); the state file is for observability and reconciliation only.
- Add DockerRunner.cleanupOldStates(maxBytes?): evicts terminal states
  (exited|cancelled|failed) oldest-first until the state dir is back under
  budget, never touching running states. Wires up deleteState(), which was
  defined but never called anywhere.
- Add LIGHT_RUNNER_STATE_MAX_BYTES (default 50 MiB) read via stateMaxBytes(),
  mirroring reapAgeMs(). Kept distinct from cleanupOrphanStates, which only
  reconciles running -> failed and deletes nothing.
- Tests: 3 unit cases for cleanupOldStates (no-op under budget, oldest-first
  eviction, running preserved) plus an e2e case asserting an attached run
  writes a terminal state file.

build with cc
@enixCode enixCode merged commit 7538028 into main May 29, 2026
4 checks passed
@enixCode enixCode deleted the feat/state-persist-and-gc branch May 29, 2026 14:30
enixCode added a commit that referenced this pull request May 29, 2026
Ship attached-run state persistence + state-dir size cap (PR #8) and the
GitHub Pages base-path fix (PR #9). Version bump done manually because the
preversion hook's local VitePress build is unusable on a OneDrive-synced
working tree; the published npm package (dist JS) and the deployed docs site
(CI Docs workflow) are unaffected.

build with cc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant