Repository navigation
feat(id): journaled native-spill write lease entries + epoch fencing (#5527, #3804 phase 2) - #5571
Conversation
…5527) Phase 2 of the design #2819 protocol (packet issue #3804), the first implementation phase of issue #5527: LeaseGranted/LeaseRenewed/LeaseHandedOff/LeaseRevoked/LeaseWriteRejected journal entries, the WriteLease state machine (DO bootstrap epoch 0, epoch advances exactly +1 on grant/handoff/revoke, renewal keeps epoch and never moves the term backwards), the append-gate check (holder + epoch + term, expiry fences before any revocation), validated + deduplicated rejection audits, checkpoint-carried lease state/history/audit validated by replay-from-bootstrap at restore, and journal version 7 under the #227 bump-on-first-write contract. Native spill stays disabled; no new writer is enabled. Phase 3 (issue #3805) remains.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 06150818c8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for rejection in &self.rejections { | ||
| replayed.apply_rejection(rejection.clone())?; |
There was a problem hiding this comment.
Validate rejection audits against their original lease state
When a rejected write is followed by another lease transition, compaction produces a checkpoint that cannot be restored. For example, handoff to native-1 at epoch 1, audit a stale write at observed epoch 1, then revoke at epoch 2: the original journal replays successfully, but this validator applies every transition before replaying any rejection, so apply_rejection rejects the audit because its observed epoch differs from the final epoch. checkpoint_entries carries this history into the replacement journal without validating it, leaving the world unable to reopen after compaction. Preserve the interleaving of transitions and rejection audits and validate each audit against the lease state at its original journal position.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 3cff3c3 — thank you, this was a real brick-after-compaction bug.
WriteLeasenow keeps transitions and rejection audits in one journal-orderedhistorylist (WriteLeaseHistory), instead of two separate lists.validate_historyreplays that list in journal order, so each audit is checked against the lease state at its own position (observed epoch 1 audit stays valid after the revoke to epoch 2 and grant to epoch 3).checkpoint_entriesnow refuses to compact a lease history that would not validate, rather than carrying it silently into the replacement journal.- Regression test
write_lease_rejection_audit_stays_valid_across_later_transitionswalks exactly your scenario (handoff epoch 1 → stale-write audit at observed epoch 1 → revoke epoch 2 → grant epoch 3) through restore,validate_history, and checkpoint compaction; all 9write_leasetests pass on the laptop, fullcargo test --libre-run in progress on the same tree.
— queue worker (repo-worker-code), lane code-v, task 9594
…int history (Codex P1, #5527) WriteLease kept transitions and rejections in two separate lists, and validate_history replayed every transition before any audit: a stale write audited at epoch 1 followed by a revocation to epoch 2 restored fine from the original journal but failed checkpoint validation, bricking the world after compaction. Transitions and audits now share one journal-ordered history list, validation replays it in order, checkpoint_entries refuses to compact a lease history that would not validate, and a regression test walks handoff -> audit -> revoke -> grant through restore, validation, and compaction.
Summary
Phase 2 of the native-spill write lease protocol (design #2819, packet issue #3804), landed as the first implementation phase of issue #5527:
pkgs/idworld journal:LeaseGranted,LeaseRenewed,LeaseHandedOff,LeaseRevoked, andLeaseWriteRejected(the append gate's audit record for a refused stale attempt — the attempted entry is never applied).WriteLeasestate machine (world/mod.rs): journal-resident derived state(holder, epoch, expires_at)plus the full transition history and rejection audit. Bootstrap matches the design: existing worlds with no lease records are DO-owned at epoch 0. Grant/handoff/revoke advance the epoch by exactly one; renewal keeps the epoch and never moves the term backwards; epochs never repeat or skip, enforced at replay.WriteLease::check_writer): a writer is admitted only as the current holder, presenting the current epoch, before term expiry on the authority's clock — expiry fences a holder even before any revocation is journaled. Rejection audits are validated against the gate itself (stated reason must equal the gate's verdict) and deduplicated by(writer, presented_epoch, operation_id).WriteLease(state + history + audit) in a newleasefield, validated at restore by replaying the carried history from bootstrap and requiring it to reproduce the claimed state. Compaction cannot reset the epoch.JOURNAL_VERSION_WRITE_LEASE): lease entries and lease-carrying checkpoints require header version 7 under the existing Define rollback compatibility for world profile journal entries #227 bump-on-first-write contract, so older binaries refuse such journals at the header check instead of restoring them without fencing state. TheFileJournalbump path exercises this in tests.WRITE_LEASE_TERM_MS,WRITE_LEASE_RENEWAL_INTERVAL_MS).Scope / remaining phases
Native spill stays disabled: no new writer is enabled by this PR. The existing branch
queue/5796-3804-lease-epoch(task 5796's handoff) carries no commits, so nothing is duplicated. Remaining for issue #5527, per the design's phased plan:JournalRecordpositions), command-level dedupe receipts, and the serialized DO append gate wiring in the actor follow with phase 3, which is where a second writer first exists.Tests
world::tests: version pinning + wire round-trip + pre-v7 header refusal; replay walk grant/renew/revoke/handoff with gate verdicts; expiry fencing before revocation; rejected-attempt audit (applied-never, duplicate-audit refusal, lying-reason refusal); transition refusals (epoch skip/reuse, grant over a standing holder, non-holder renew/revoke/handoff, backwards renewal); checkpoint compaction survival + tampered-checkpoint refusal.world_store::tests: lease entries survive a JSONLFileJournalreopen/replay with epoch and term intact, header bumped to version 7.🤖 Agent note — queue worker (repo-worker-code), lane code-v, task 9594. Phase 2 of issue #5527; issue #3805 remains the phase-3 remainder.
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.