Repository navigation
sandbox-store: move the Direct substrate's restore-lease and receipt writes into a direct module - #1342
Merged
Conversation
|
Thanks for opening this pull request! A SPACE maintainer will take a look. CONTRIBUTING.md explains how we review outside contributions. |
ac-pplx
force-pushed
the
ac/lifecycle-move-direct
branch
from
November 2, 2026 21:39
3d05f85 to
3cb6431
Compare
ac-pplx
force-pushed
the
ac/lifecycle-move-direct
branch
from
November 2, 2026 23:25
3cb6431 to
01e4227
Compare
This was referenced Nov 3, 2026
This was referenced Nov 3, 2026
Merged
Merged
ac-pplx
marked this pull request as ready for review
November 3, 2026 03:51
ac-pplx
marked this pull request as draft
November 3, 2026 03:52
ac-pplx
force-pushed
the
ac/lifecycle-move-direct
branch
from
November 3, 2026 06:00
01e4227 to
14685f3
Compare
ac-pplx
marked this pull request as ready for review
November 3, 2026 06:29
kumarpallav-pplx
requested review from
kumarpallav-pplx and
nikhilbirmiwal-pplx
November 3, 2026 06:30
nikhilbirmiwal-pplx
approved these changes
Nov 3, 2026
…direct module The Direct substrate wrote the control-plane `sandboxes` row from inline SQL in `controllers/substrate/direct.rs`. Five of those six statements move into a new `direct` module of `pplx-space-sandbox-store`, one function per transition that runs on the executor its caller passes: - the restore lease's claim, release, renewal and completion (operation steps); - the placement an owned restore receipt records (observed projection). Statement text is unchanged byte for byte; binds carry the same values, with `SandboxId`/`NodeId` encoding as the UUIDs bound before. The restore-ownership `SELECT ... FOR UPDATE`, the route-identity writes, the owned-restore transaction and the lease durations stay in the substrate. Each function returns whether its guarded write matched, and the substrate maps a miss to the same error as before. The moved statements' `sql!` locators now name `pplx_space_sandbox_store::direct`. The `sandbox_writes` ratchet entry for `controllers/substrate/direct.rs` drops from 6 to 1. The adoption of a live node record by a row with no active node stays in the substrate. Its update joins `sandbox_direct_route_identities` and `sandbox_direct_route_provenance`, Direct-only tables that `pattern_ratchet.direct_tables` confines to the Direct substrate, and that rule allows no new exception. The module's doc comments now say that a guarded write that matches no row may also mean the row never met the guard, and how the restore-lease trigger and `insert_unplaced` keep a token-holding row `restoring`.
ac-pplx
force-pushed
the
ac/lifecycle-move-direct
branch
from
November 3, 2026 21:24
14685f3 to
5015384
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Direct substrate wrote the control-plane
sandboxesrow from inline SQL incrates/libs/api/src/controllers/substrate/direct.rs. Five of its six statements move into a newdirectmodule ofpplx-space-sandbox-store; the adoption update stays in the substrate (below). There is one function per transition, and each runs on the executor its caller passes:claim_direct_restore_lease→direct::claim_restore_lease(operation step)release_direct_restore_lease→direct::release_restore_lease(operation step)renew_direct_restore_lease→direct::renew_restore_lease(operation step)complete_direct_restore_lease→direct::complete_restore_lease(operation step)persist_owned_restore_route_identity_receipt(placement UPDATE) →direct::place_owned_restore_receipt(observed projection)The SQL text is the same byte for byte (checked by extracting the literals from both files). The binds carry the same values;
SandboxIdandNodeIdencode as the same UUIDs. These stay in the substrate: the restore-ownershipSELECT ... FOR UPDATE, the route-identity writes, the owned-restore transaction and the lease durations. Each function returns whether its guarded write matched, and the substrate maps a miss to the same error as before.The doc comments note the guards a reader might not expect:
sandboxes_clear_restore_leasetrigger clears the token whenever a row leavesrestoring.sql!locators change: the moved statements now reportpplx_space_sandbox_store::direct, which shows inpg_stat_activityand in query monitoring.pattern_ratchet.sandbox_writesforsubstrate/direct.rsdrops from 6 to 1. The one left isadopt_live_execution's update: its conditions join two Direct-only tables (sandbox_direct_route_identities,sandbox_direct_route_provenance), and moving it into the store would add an exception to thedirect_tablesrule. Exceptions there are not allowed to grow, so it stays in the substrate until those tables have an owning store.ARCHITECTURE.tomlandsubstrate/AGENTS.mdare unchanged.Validation
cargo nextest run -p pplx-space-sandbox-store -p pplx-space-api: 1583 of 1584 passed, Postgres-backed tests ran with no dependency skips. The one failure,routes::e2b::tests::detail_reports_authoritative_federated_ownership_not_metadata(a JSON key-order snapshot), fails the same way on unmodifiedorigin/main.'started'failsnon_restore_lifecycle_without_a_lease_reports_conflictandrestore_lease_claim_and_release_move_only_restore_lifecycles.cargo clippy --workspace --locked --all-targets --all-features -- -D warnings: clean.cargo fmt --check: clean.cargo arch: 0 required findings (110 advisory, also when run as CI does, against the merge base'sarchitecture-baseline.toml, renames andARCHITECTURE.toml). Thedirect_tablesno_crossing finding on the store'sdirect.rsis gone: the same run with the oldARCHITECTURE.tomlreports it, at 111 findings. In this PR's files the only finding left is the existingfile_size.listed_no_growthonsubstrate/direct.rs(grew from 3907 to 4424 code lines; its cap was already below the file's size on main).up.sh555 s,smoke-kind-typed.sh all3159 s):local.gentle_drain_leaves_sandbox_residentfailed once and passed on rerun.SPACE_KIND_SUBSTRATE=direct,up.sh122 s,all1023 s):native.stopped_restart_preserves_rootfsfailed at its cleanup step, after both stop/start cycles passed. On this branch's base, the fixture's cleanup looked up the sandbox's execution pod, which Direct doesn't create; kind-ci: run the Direct substrate lane nightly and on Direct-path PRs (not required) #1225 on main makes it use the API's node placement on Direct. None of the moved statements is on that step. This PR's Kind Direct CI run, on the merge with main, passed the full typed suite on Direct (ECW 51/51, native 27/27), this scenario included.Severity and risk
Severity: does not apply (pure move). Risk: the restore and adoption paths of the Direct substrate. Because the statements are unchanged, old and new pods issue the same SQL during a rollout. Rollback: revert the commit.
Open PRs that will need to rebase
DirectSubstrate::persist_owned_restore_route_identity_receipt. [space] fence every placement writer against the provider-terminate path #559 adds a fence before theFOR UPDATE; [api] record the activating client from Direct's start, wake and restore receipts #1175 addsrecord.writeafter the placement. Both additions stay at the call site, but the placement UPDATE they sit next to is nowpplx_space_sandbox_store::direct::place_owned_restore_receipt.sandbox_writescap forsubstrate/direct.rs(5 → 7), and this PR removes that entry.AI assistance: Claude Code (an AI agent) wrote the code change, ran the validation, and drafted this description.
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 onto42a99002, 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 is50153846.git range-diffshows=). For every file [cluster-controller] re-place an evacuated stopped sandbox as stopped on another node, materialized by the shim without a VM #826 and this stack share, each SQL line [cluster-controller] re-place an evacuated stopped sandbox as stopped on another node, materialized by the shim without a VM #826 added was checked to be present verbatim at the top head, in place or in the store module it moved to.cargo fmt --all -- --check,cargo check --workspace --all-targets --all-featuresandcargo arch(0 required findings, with main's layers and table-owner rules), and the ratchet and caps this layer changes are recounted exactly.e90aa284before that rebase; nextest passed 4370 tests again at77fbae1e):cargo clippy --workspace --locked --all-targets --all-features -- -D warningsis clean, andSPACE_CI_REQUIRE_TEST_DEPS=1 cargo nextest run --all-featurespassed 4355 tests across the store, api, internal-api server, cluster-controller server, metrics, db-test-fixtures, common-core, common-svc and portability crates, [cluster-controller] re-place an evacuated stopped sandbox as stopped on another node, materialized by the shim without a VM #826's suites included.scripts/tests/smoke-kind-typed.sh allgave ECW 91/91 and native 42/42, including [cluster-controller] re-place an evacuated stopped sandbox as stopped on another node, materialized by the shim without a VM #826'snative.forced_drain_re_places_stopped_sandboxand its re-drain and restarted variants. The Direct substrate lane'sallgave ECW 51/51 and native 27/27. No flakes and no reruns.+/-lines and its SQL string literals match its reviewed head (range-diff plus a literal multiset compare).