Run every Volume run through SetVolumeCopy#1690

merged9
volume-cut/p5-add
volume-cut/p6-switch
openedOct 12, 2026byNNick
View on GitHubGitHub import enabledPR last imported 21d ago

Summary

This is PR 6 of 7 in the Volume RPC cut. Cloud's Volume runs now move copies with SetVolumeCopy, and no dashboard code outside tests sends the old lease verbs. Every run kind stays: mirror, sync, sync --full, delete_mirror, move, release, restore and demote.

A user notices three things. A Server whose record lists no capabilities now shows the Upgrade. Every Volume run refuses with "needs a newer Ployz" until a release that serves ployz.volume.copy.set.v1 reaches every Server with storage. The restore message gives the snapshot time as ISO.

Each run takes an epoch, max(observed, recorded) + 1, and stores it on the run row. Every step states the copy it expects, so a request from a run that already ended refuses instead of landing on a newer state.

Changes

  • plan.ts. Plans every run kind from the copies its Machines report. The cut source is the slot at the cut snapshot that keeps the stopped Container. It is no longer found by matching an f-N snapshot name. A Move onto a Server whose writer is already at the source's newest snapshot plans as landed.
  • volume-run.inngest.ts. A Move sends rounds, the image copy, the cut, the final pull, B as writer with Create, and then removes A's kept Container. Forward removes A's Container only once B's runs, and resends B's start with the same creation key. The pull loop asks again once B's newest is the target, so B finishes a landed pull.
  • Undo. After the cut, an undo forgets B first with expect: Mirror{G, slot}, then makes A writer at the run's epoch with Kept. It refuses when B is a root other than the writer at G, and names that state. Before the cut, an undo raises A to the run's epoch, so a late cut from that run refuses on its expect.
  • delete_mirror. Refuses two writers before it sends anything. Two read-only roots read as a run in progress.
  • Restore and demote. Restore starts no Container. A demote fails its row with a message saying the older copy is now read-only, its writes since the newer writer took over are lost, and to run it again. serviceSpec is no longer written.
  • volume-run.server.ts. setVolumeCopy turns each refusal into a message. It retries only Busy and transport failures.
  • volume_run table. Gains an epoch column. The lease column stays for SeedVolume until PR 7.
  • Capability gate. daemon-compat, daemon-release, placement and StoreVolumePlacement treat an empty capability list as lacking ployz.volume.copy.set.v1.
  • ployz.server.ts. The session gains removeContainer.
  • Postgres tests. A fake Machine models the daemon. It gives each new slot a fresh id, matches Mirror expects on that id, raises a root's epoch on a Writer at its snapshot, refuses a lower epoch, and keeps pull set after a receive lands until a resend finishes it.
  • Volume move harness. The soak is keyed on SetVolumeCopy transitions and on the fault points the daemon defines. The rows on PullImageFromMachine and RemoveContainer are gone, because no fault point serves them. Undo-before-cut kills the writer inside the WriterToMirror cut after its Container stopped. The WriterToSnapshot and MirrorToForget rows say they are restart checks.
  • Docs. docs/user pages move-a-volume, restore-a-volume and manage-servers describe runs as copy transitions. Move-a-volume and restore-a-volume no longer name 0.2.5. dashboard/DESIGN.md replaces the 0.2.5 Placement rule with the empty-list rule, so Cloud code holds no release number.

Verification

Every result is measured. The cargo and test commands ran at d6f448b99. Typecheck and lint ran at 70f503bbb, and the one later commit touches only the Python harness.

  • cargo check -p ployzd -p ployz-core -p ployz --tests exited 0.
  • cargo test -p ployz --test sdk_payloads passed 3.
  • pnpm typecheck exited 0.
  • pnpm lint exited 0, with warnings only in files this PR does not touch.
  • pnpm vitest run src/modules/volume-run src/modules/volume-placement passed 294.
  • pnpm vitest run --project postgres src/modules/volume-run src/modules/volume-placement passed 113. That includes two ended runs whose held requests land late in either order, with one writable root at the end.
  • python3 -m py_compile core/scripts/test-verify-volume-move.py exited 0.
  • With the fake Machine keeping pull set like the daemon and the Cloud resend removed, the postgres run timed out 17 tests.
  • In the first fix round, removing the slot comparison from the fake Machine failed the late-request test for two ended runs. Reverting undoBeforeCut to the old epoch failed the late-cut test, and the late cut landed.
  • The dashboard has no formatter, so none ran.

Not run on real Machines yet. The 2-VM harness, the kill matrix and the real-ZFS soak run once at the top of the stack.

Merge Danger

No users run ZFS mirrors yet, and no released daemon was ever cut with these verbs. None of these breaks has a shim.

  • Merging main deploys Cloud.
  • A Server whose record lists no capabilities now reads as lacking and shows the Upgrade. Every Volume run refuses with "needs a newer Ployz" until a release serving ployz.volume.copy.set.v1 reaches every Server with storage.
  • Migration 20261012122320_volume_run_epoch adds the epoch column.
  • dashboard/DESIGN.md changes its Placement exception. An empty capability list now proves the lack, and the 0.2.5 version check is gone.
  • A run in flight under the old flow is abandoned.
  • The docs/user pages move-a-volume, restore-a-volume and manage-servers change.
  • PR 6 needs PR 5's daemon. An older daemon does not accept the slot field or the epoch raise. Land them together.
  • Create carries no registry auth, so a Move copies the image to B first.
  • An undo before the cut moves A to the run's epoch. A Move refused before the cut still bumps the Volume's epoch on A.
  • Release keeps demoting silently when two writable roots exist. The review judged that harmless, because demote seals the older root. Inferred.
  • Every pull costs one more SetVolumeCopy round trip to finish. Inferred.
  • A Cloud path that waits for pull to clear without asking again would hang against a real Machine. Only the pull loop reads pull today. Measured by grep.

Checks

3 failing ยท 22 successful
Some checks failed

Failing3

e356a9d
Synced from GitHub

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

yaml
1reviews:
2 auto_review:
3 drafts: true
  • Autofix ยท Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Synced from GitHub

โš ๏ธ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

๐Ÿ”Ž Detected hardcoded secret in your pull request
GitGuardian idGitGuardian statusSecretCommitFilename
37990433TriggeredGeneric Password7e907b7631b432363a89c547f9a1daddd8f39394dashboard/src/modules/volume-run/volume-run.postgres.test.tsView secret
๐Ÿ›  Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


๐Ÿฆ‰ GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Added 9 commits

  • Key the volume move soak on SetVolumeCopy transitions3df6472
  • Ask a landed pull again so B finishes it, and have the fake Machine keep pull set until that resend4d7caf5
  • Run every Volume run through SetVolumeCopy7e907b7
  • Find the cut source by the kept Container and never leave two writers or a down Service8580e26
  • Record which late-request order lands two writable rootsaed7a58
  • Key the volume move harness on fault points the daemon definesb874eae
  • Name the slot in every Mirror expect and give A the run's epoch on an undo before the cut, so late requests from ended runs refusec2ed344
  • Mark the WriterToSnapshot and MirrorToForget kill rows as restart checkse356a9d
  • Describe Volume runs as copy transitions in the docsf8e7ee7