Skip to content

sandbox-store: move the Kubernetes suspend writes of the sandboxes row into the store - #1338

Merged
ac-pplx merged 1 commit into
ac/lifecycle-move-wakefrom
ac/lifecycle-move-suspend
Nov 3, 2026
Merged

ac-pplx merged 1 commit into
ac/lifecycle-move-wakefrom
ac/lifecycle-move-suspend

Conversation

@ac-pplx

@ac-pplx ac-pplx commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Mechanical move, no functional change. The sandboxes row writes listed below move into pplx-space-sandbox-store with their SQL byte-for-byte; callers keep their locks, transactions and error handling. Everything else is doc comments. Part of the wave-2 stack (3 of 10, on #1336); it lands with the stack.

Problem
crates/libs/api/src/controllers/substrate/kubernetes/store/suspend.rs still wrote the sandboxes row itself: 8 lines that pattern_ratchet.sandbox_writes counts. The crate boundary says every write of the row belongs in pplx-space-sandbox-store.

Change
The four statements behind those 8 lines move into a new module, pplx_space_sandbox_store::suspend. Moved functions (all api …/kubernetes/store/suspend.rs → sandbox/store/src/suspend.rs):

  • claim_suspend_execution: the suspend claim CAS → suspend::claim. Operation step. The started/paused loop stays at the caller.
  • persist_or_accept_suspend_commit: the committed-artifact UPDATE → suspend::record_committed_artifact. Operation step. Its only guard is lifecycle = 'suspending', and it re-assigns that same value.
  • K8sStore::finalize_suspended_sandbox_in, removed (both callers now call the store directly) → suspend::finalize_with_committed_artifact. Operation step. It matches the row by id only and relies on the caller's row locks.
  • finalize_missing_suspending_pod_with_current_snapshot: the final UPDATE → suspend::finalize_missing_pod_from_current_snapshot. Inference. It matches by id only and relies on the caller's lock, its eligibility select, and the execution it already retired.

SQL text is byte-for-byte the same, including the CAS guards and the interpolated pplx_space_sandbox_portability fragments. Each statement is still built the same way. The binds carry the same primitive values: typed ExecutionGeneration, PodUid, LocalArtifactId, ArtifactKind and SandboxLifecycle are converted inside the store. The FOR UPDATE reads, transactions, execution-row writes and slot deletes stay with the callers. The store functions are impl PgExecutor. No test files changed.

architecture-baseline.toml: the suspend store's sandbox_writes entry (= 8) is removed. Neither file has a file_size entry.

sql! locators: the moved statements now carry the store module's path, so they show up under a new name in pg_stat_activity and query monitoring.

Validation

  • cargo nextest run --all-features -p pplx-space-sandbox-store -p pplx-space-api with the shared Postgres: 2168 passed, 1 skipped (an #[ignore] benchmark). 77 Kubernetes suspend-path Postgres tests ran.
  • Mutation check: I removed AND lifecycle = 'suspending' from record_committed_artifact and suspend_lifecycle_matrix_tests::suspend_claim_and_commit_move_only_their_stored_lifecycles failed. With the guard restored it passes; the mutation was not committed.
  • cargo clippy --locked -p pplx-space-sandbox-store -p pplx-space-api --all-targets --all-features -- -D warnings is clean. A lib-only clippy and check of the store is clean. cargo fmt --check is clean.
  • cargo arch, with and without --base-baseline: 0 required findings. The 110 advisory findings were already there and involve none of these files.
  • Kind, fresh cluster from this commit (every image at d9d1265f): up.sh took 10m08s. scripts/tests/smoke-kind-typed.sh all took 51m23s.
    • Native pass: 35/35 passed.
    • ECW pass: 85 passed, 0 failed, 3 inconclusive because of how I set up the bench.
    • ecw.cold_create_environment (14s) and ecw.warm_pool_environment (22s) passed on rerun with SPACE_SMOKE_KIND_COLD_RECEIPTS and a token file, as CI sets them.
    • local.restarted_btrfs_send_is_rejected_and_retried passed (40s) after re-running up.sh with SPACE_KIND_TELEMETRY_MODE=otel.

Risk and rollback: the statements are unchanged, so revert the commit to roll back. Mixed versions: old and new api pods send identical SQL; only the locator comment differs.

Open PRs that will need to rebase

AI assistance: an AI agent (Claude) wrote this change and its validation; a human reviews it.

After the wave-2 restack

This PR is one layer of a 10-PR stack, restacked onto main c5fdf0c7 (which includes #826) and then rebased mechanically onto 42a99002, which changed only baseline context lines, in order #1329 → #1336 → #1338 → #1339 → #1342 → #1347 → #1333 → #1335 → #1328 → #1332. The validation earlier in this description ran at pre-restack heads; this layer's head is 7d6d00ca.

@github-actions github-actions Bot added the triage:pending Waiting for a maintainer to triage label Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown

Thanks for opening this pull request! A SPACE maintainer will take a look.

CONTRIBUTING.md explains how we review outside contributions.

@ac-pplx
ac-pplx force-pushed the ac/lifecycle-move-suspend branch from d9d1265 to a66319c Compare November 2, 2026 23:25
@ac-pplx
ac-pplx changed the base branch from main to ac/lifecycle-move-wake November 3, 2026 03:50
@ac-pplx
ac-pplx added this pull request to stack #1382 November 3, 2026 03:50
@ac-pplx
ac-pplx marked this pull request as ready for review November 3, 2026 03:51
@ac-pplx
ac-pplx marked this pull request as draft November 3, 2026 03:52
@ac-pplx
ac-pplx force-pushed the ac/lifecycle-move-suspend branch from a66319c to 285435b Compare November 3, 2026 06:00
@ac-pplx
ac-pplx marked this pull request as ready for review November 3, 2026 06:29
…w into the store

The four statements in the Kubernetes substrate's suspend store that write
`sandboxes` (the suspend claim CAS, the committed-artifact record, the
committed-artifact finalization and the missing-pod finalization from the
current snapshot) move into a new `pplx_space_sandbox_store::suspend`
module. Their SQL text, CAS guards and interpolated
`pplx_space_sandbox_portability` fragments are unchanged; binds carry the
same values. The callers keep their `SELECT ... FOR UPDATE` locks, their
transactions, the execution-row writes and the claimed-slot delete.

The `sql!` locators of the moved statements now name the store module.

`pattern_ratchet.sandbox_writes` drops the suspend store's entry (8 lines).
@ac-pplx
ac-pplx force-pushed the ac/lifecycle-move-suspend branch from 285435b to 7d6d00c Compare November 3, 2026 21:23
@ac-pplx
ac-pplx added this pull request to the merge queue Nov 3, 2026
Merged via the queue into main with commit d644990 Nov 3, 2026
27 checks passed
@ac-pplx
ac-pplx deleted the ac/lifecycle-move-suspend branch November 3, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage:pending Waiting for a maintainer to triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants