Skip to content

feat(pool): lifecycle auto-archive for idle sandboxes#1

Merged
CMGS merged 3 commits into
mainfrom
feat/m7e-lifecycle-autoarchive
Jul 9, 2026
Merged

feat(pool): lifecycle auto-archive for idle sandboxes#1
CMGS merged 3 commits into
mainfrom
feat/m7e-lifecycle-autoarchive

Conversation

@CMGS

@CMGS CMGS commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

M7-E lifecycle auto-archive

Adds an archived lifecycle state after hibernation so idle sandboxes stop consuming local compute while staying instantly resumable under the same identity.

Behaviour

  • A hibernated claim idle past archive_after_seconds is checkpointed to the store and its local VM dropped (ArchiveCk set; VMName/VsockSocket/HibernateSnap cleared).
  • The next access wakes it from the store into a fresh local VM, keeping the same id/token/tenant and full guest state.
  • archive_delete_after_seconds bounds retention (0 = keep forever).
  • The archive image is lifecycle-internal: hidden from the checkpoint listing and refused by DeleteCheckpoint while its claim is live, so a sandbox cannot be bricked through the checkpoint API.
  • Every transition (archive / wake / release / reap) rolls back on a claim-store persist failure, so a durable claim never diverges from the store.
  • Archived count is exposed on GET /v1/info, /metrics (sandboxd_archived gauge + archives_total/unarchives_total/archive_deletes_total), and the Go SDK NodeInfo.Archived.

Hot-path cost

Zero on the warm-claim and data-plane paths — archiving runs on the reap tick, off the claim path. LastActivity moved to a lock-free atomic.Int64 (benchmarked in types/bench_test.go).

Tests

  • 12 pool regression tests (archive_test.go): full lifecycle round-trip, retention purge, keep-forever, the checkpoint-API brick guard, idle/in-flight dedup, and all four persist-failure rollback paths; 4 verified by reintroducing the bug and confirming the test fails.
  • go test -race ./... green; golangci-lint 0 issues on linux and darwin.
  • Hardware acceptance on the .52 testbed (scripts/archive-e2e.sh + e2e/cmd/lifecycle): claim -> idle-hibernate -> archive (local VM dropped) -> wake in ~115ms with the same id and guest state intact; full regression harness green.

CMGS added 3 commits July 9, 2026 10:43
Add an archived state after hibernation: a hibernated claim idle past
archive_after_seconds is checkpointed to the store and its local VM is
dropped; the next access wakes it from the store keeping the same
id/token/tenant and guest state, and archive_delete_after_seconds bounds
retention. The archive image is hidden from the checkpoint API and cannot
be listed or deleted while its claim is live. A persist failure on any
transition (archive, wake, release, reap) rolls back so a durable claim
never diverges from the store. Archived count is surfaced on /info,
/metrics, and the SDK NodeInfo.
Post-review /simplify pass:
- archive.go: extract deleteOrphanArchiveCk (two identical abort-path
  ck deletes) and compress the archive*For doc comment.
- pool.go: extract benignSweepErr - the released/woke-mid-sweep error
  set was inlined in idleOnce/archiveOnce/reapOnce.
- e2e/lifecycle: rename waitArchived's max param (shadowed the builtin).
Layout-only: the shared validation helper was wedged between the PoolSpec
and StoreConfig type declarations, breaking the config-type cluster. Move
it to the bottom with the other validate* funcs (standalone funcs below
the type+method blocks).
@CMGS CMGS merged commit e8f016f into main Jul 9, 2026
1 check passed
@CMGS CMGS deleted the feat/m7e-lifecycle-autoarchive branch July 9, 2026 04:42
CMGS added a commit that referenced this pull request Jul 9, 2026
Four comment em-dashes in pool.go were double-UTF-8-encoded (rendered as
mojibake) by a scripted edit and merged in #1. Byte-restore only, no code change.
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