Repository navigation
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/template-mgr-guarded-dirty-ack
branch
from
October 31, 2026 07:20
960d867 to
1265e6e
Compare
ac-pplx
force-pushed
the
ac/template-mgr-guarded-dirty-ack
branch
from
November 1, 2026 09:18
1265e6e to
ea3ddcc
Compare
ac-pplx
changed the base branch from
main
to
ac/template-mgr-reverse-dirty-ref-revisions
November 1, 2026 10:43
ac-pplx
force-pushed
the
ac/template-mgr-guarded-dirty-ack
branch
from
November 1, 2026 10:59
ea3ddcc to
8f20eb5
Compare
zibi-pplx
previously approved these changes
Nov 1, 2026
zibi-pplx
dismissed
their stale review
November 1, 2026 22:29
Withdrawing this approval for now. Any feedback above still stands.
…ing a send survives template-manager's node_dirty_refs outbox worker lists rows, calls node-ctl without holding the database lock, then deletes the listed refs by key alone. An enqueue of the same ref between the list and the delete updates the row in place, so the delete removed the new obligation too. That change reached node-ctl only when the ref was marked again or node-ctl's periodic reconciliation caught up. Add an additive template-manager SQLite migration that gives node_dirty_refs a revision column, stamped from a node-wide counter by insert and update triggers (the same shape sandbox-manager's outbox uses), and make the ack delete only rows whose revision still matches the one listed. Existing rows keep revision 0 and are acked as before. The MarkFacetDirty request sent to node-ctl is unchanged. This ships in a release after one that lists 20261031050126 among the template-manager migrations its runner can reverse. That release returns a database recording the migration to its own schema at startup and keeps every outbox row, so rolling back from this release to that one is image-only; an older release refuses such a database. The bundled up SQL must stay byte-identical to that release's history copy, because that release compares the recorded checksum with its copy. The pplx-space-sqlite module doc now says a migration ships only in a release after one that lists it, so the image a rollback returns to can reverse it. Tests: template-manager covers a re-enqueue during a send, a stale ack against a deleted and recreated key, a same-timestamp write with recursive_triggers off and on, and revision exhaustion leaving the pending row unchanged. In pplx-space-sqlite, the reversal tests roll back to the previous release's catalog (this one without 20261031050126), the round trip starts from that release's database so this catalog applies the migration and keeps it on a second startup, and the bundled-schema test checks that recorded revisions survive a restart, which they would not if the migration were reversed and re-applied. The retired-migration tests derive the expected history from the bundled catalog, and a new test upgrades a database from the release that recorded the retired migration (baseline plus that migration only) to the bundled catalog in one startup.
ac-pplx
force-pushed
the
ac/template-mgr-reverse-dirty-ref-revisions
branch
from
November 4, 2026 14:55
6530fd8 to
3beb564
Compare
ac-pplx
force-pushed
the
ac/template-mgr-guarded-dirty-ack
branch
from
November 4, 2026 14:55
8f20eb5 to
2510443
Compare
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
|
This branch has not been deployed
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
template-manager's
node_dirty_refsoutbox worker (template/mgr/src/node_state_sync.rs) lists a batch, sendsMarkFacetDirtyto node-ctl without holding the database lock, then deletes the listed refs by key. A re-enqueue of the same ref in between updates that row in place, so the delete dropped it until the ref was marked again or reconciliation caught up. Now it stays pending for the next pass.db/template-manager/20261031050126_node_dirty_ref_revisions(additive, sandbox-manager's outbox shape):node_dirty_refs.revision INTEGER NOT NULL DEFAULT 0, a singleton counternode_dirty_ref_revision, and insert and update triggers that stamp each enqueue with the next value. The update trigger fires onUPDATE OF requested_at, updated_at, which every upsert sets, so a same-second re-enqueue gets a new revision.template/mgr/src/db.rs:list_node_dirty_refsreadsrevision.delete_node_dirty_refsdeletes only rows still at the listed revision. Enqueues andMarkFacetDirtyare unchanged.sqlite/src/template_manager.rs: the module doc now says a migration ships only in a release after one that lists it, so the image a rollback returns to can reverse it;20261031050126's check never refuses, so that rollback is image-only. template-manager: reverse the next release's node_dirty_ref_revisions migration so its rollback stays image-only #1277'sDIRTY_REF_REVISIONSentry stays, documented as bundled from here on; the bundled up SQL is byte-identical to its history copy, which template-manager: reverse the next release's node_dirty_ref_revisions migration so its rollback stays image-only #1277's checksum tests pin.recursive_triggersoff and on); revision exhaustion.pplx-space-sqlite:UNREVISIONED(this catalog without20261031050126: the previous release).a_bundled_schema_is_left_untouchedchecks recorded revisions survive a restart.HISTORICALcovers upgrading from the release that recorded it.Stack
Stacked on #1277; ship in a release after one that contains #1277. That release reverses
20261031050126when a database records it without the catalog bundling it. Merge and release #1277 first, then retarget tomain.Validation
Linux KVM devbox, at
ea3ddcc6. This head differs from it only in the commit message and one module-doc comment insqlite/src/template_manager.rs.acking_a_sent_dirty_ref_keeps_a_re_enqueue_made_during_the_sendfails on template-manager: reverse the next release's node_dirty_ref_revisions migration so its rollback stays image-only #1277's code (left: 1, right: 0: the stale ack deleted the re-enqueue) and passes here; the other three new template-manager tests also fail there.WHEN OLD.updated_at IS NOT NEW.updated_aton the update trigger: the same-timestamp, regression and exhaustion tests fail;a_bundled_schema_is_left_untouched: revisions(3, [3, 2])become(0, [0, 0]).cargo nextest run -p pplx-space-sqlite -p pplx-space-template-mgr -p pplx-space-db-migrate: 383 passed, 0 skipped (privileged group included); with-p pplx-space-archcheck: 113 passed.-D warnings,cargo fmt --check,scripts/check-migration-versions.shandcargo arch(0 required findings) pass.space-db-migratorfrom this branch and template-manager: reverse the next release's node_dirty_ref_revisions migration so its rollback stays image-only #1277, separate target dirs):up: history[20260930000000, 20261031050126], column, counter and triggers; seeded revisions[3, 2];up: logged the reversal, history[20260930000000], revision schema gone, both rows kept;up: re-applied, revisions restart at 0; a re-enqueue's revision 1 survives anotherup.[20260930000000, 20261031050126].local.template_startup_recovery_decision_table,local.template_cache_lru_eviction_reclaims,local.unanswered_template_deleted_after_wait,local.ecw_template_build_from_oci_boots,local.private_template_build_isolation,local.node_ctl_fence_refuses_and_reconciles,ecw.background_process_control.local.btrfs_send_restore_pulls_parent_template:infra_error(needs Prometheus).local.btrfs_send_restore_pulls_parent_templatepassed.scripts/tests/smoke-kind-typed.sh allthere (62 min 27 s): ECW 87 passed, 2 inconclusive (ecw.cold_create_environment,ecw.warm_pool_environment: the script doesn't setSPACE_SMOKE_KIND_COLD_RECEIPTS; both passed with it set as inkind-ci.yml); native 35 passed; 0 failed.Not validated: a multi-node fleet rollout, or a Kind rollback to #1277's image (covered by the binary round trip).
Severity and risk
Severity: medium. A lost ack delays a policy or template-inventory change on a node until it is marked again or reconciled; rare and unreported.
Risk: two small trigger updates per enqueue, in its existing transaction. A stale ack leaves the row to be resent, at-least-once delivery node-ctl already handles.
Rollout
Node-local SQLite; template-manager migrates at startup. The previous release works on the migrated schema (explicit columns; the triggers stamp its writes). Existing rows keep revision 0.
Rollback to a release containing #1277 is image-only. Its startup (or migrator
up) reverses20261031050126in one transaction and keeps every outbox row. That release acks by key again, as before this change. A release without #1277 refuses the database (unbundled migration), so roll back from this release only to one that contains #1277.Overlaps: #1075 deletes
sqlite/src/template_manager.rsand itstests.rs(changed here and in #1277) and re-lands the older20261026220935; whichever lands second resolves that. Itsdb.rsanddb/tests.rshunks don't touch this PR's code. #1164 edits another section ofdb/README.md, untouched here.AI assistance: Claude Code (an AI agent) wrote the code, the migration, the tests and this description, and ran the validation above.