Skip to content

cherry-pick: Skip relayed duplicates of a record's committed head without reading the transaction log (conflicts → v5.3) - #3478

Merged
kriszyp merged 7 commits into
v5.3from
cherry-pick/v5.3/pr-3476
Oct 23, 2026
Merged

kriszyp merged 7 commits into
v5.3from
cherry-pick/v5.3/pr-3476

Conversation

@github-actions

@github-actions github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

⊙ Problem

This brings two main fixes to v5.3:

🤔 Should #3499 ride along?

Yes. Without it, this cherry-pick would ship #3476's put-drop to v5.3. The drop reproduced on this branch before #3499 was added.

💡 Solution

Both commits are ported with v5.3's single log key. v5.3 has no origin-closed floor, so main's receivedLogKey === txnTime && appendedLogKey === receivedLogKey becomes txnLogKey === txnTime. Main-only code next to the changes stays out: #3183's skip marking on an older relocate, and the priorStaged and receivedIdentityRefIsReceipt parts of the ref check.

🤔 Is a base-copied row's head at V a whole transaction?

I assume yes, as main does. On first delivery, a put and a patch at V over a copied row at V are both skipped. That is wrong only if a copy could hold part of a transaction. A copy is one snapshot.

🔧 Changes

✅ Verification

Refs #3467

🤖 Generated by Claude Code (Claude Opus 5.5); posted via @kriszyp.

Release target: v5.3 — cherry-pick of #3476 with its follow-up #3499

Related PRs: #3476 overlaps (source), #3499 overlaps (source), #3453 overlaps, #3506 overlaps, #3469 overlaps, #3423 overlaps, #3375 overlaps, 14 others independent
Complexity: complicated

Review-Coverage: authored=claude; ran=gemini,cursor-composer,codex,cursor-grok; adjudicated=domain; declined=muse; rounds=2; full=1 @ c8f95d0

Review-Attention: study ~20m (critical: DatabaseTransaction.ts, Table.ts; decisions: head-tie-skip-on-first-delivery, committed-read-over-staging-eager-writes) @ c8f95d0

kriszyp and others added 5 commits October 23, 2026 14:33
…the transaction log

A replicated write that matches the committed record's origin, version and log key (no explicit refs) is
already applied. That was only recognized on a retry; on a first delivery the keyed dedup looked for the
head's log entry, and when the receiver had none (a base-copied record) the exact-start lookup scanned to
end-of-log and the write was applied and logged again, so every peer was re-sent it (harper#3467).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e skip

A publish or relocate earlier in the same source transaction restamps the record at the transaction's
version without staging it, so the put after it tied with that restamp and was dropped. The skip now
requires every earlier write to the key in the transaction to have been skipped, which still lets a
re-delivered multi-write transaction skip all of its writes from the record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…entation on it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v5.3 has a single log key, so the head-tie skip keeps txnLogKey === txnTime and adds priorWritesSkipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kriszyp

kriszyp commented Oct 23, 2026

Copy link
Copy Markdown
Member

Conflicts resolved at 85cc095. v5.3 has a single log key (no receivedLogKey/appendedLogKey split from #3085), so the head-tie guard keeps its txnLogKey === txnTime condition and gains priorWritesSkipped(write); DESIGN.md keeps v5.3's refs paragraph plus the #3467 bullet. The changed lines are identical to #3476's. On v5.3 with its own dependencies (rocksdb-js 2.11.0), relayedHeadTieDuplicate.test.js passes all 5 cases; the related suites have one failure (the [put, delete] re-delivery case in replicatedDeleteRedelivery.test.js), which also fails on unmodified v5.3.

Note: the cherry-pick workflow recreates this branch whenever #3476's branch is pushed or merged, which drops this resolution; it then has to be re-applied.

🤖 Generated by Claude Code (Claude Opus 5.5); posted via @kriszyp.

@kriszyp
kriszyp marked this pull request as draft October 23, 2026 15:36
@kriszyp

kriszyp commented Oct 23, 2026

Copy link
Copy Markdown
Member

Held — do not merge. #3476 drops a put when a later write to the same key in the same source transaction is a publish/message or relocate: [put r, message r] at one version keeps the old value. Those writes save eagerly when added, so they restamp the record before the put's commit decides its head tie. This backport would ship the same defect to v5.3. The fix is going to main first, deciding the tie against the committed entry instead of the transaction's staged base; its commit will be carried into this branch afterwards. This supersedes my earlier note that the backport was ready.

🤖 Generated by Claude Code (Claude Opus 5.5); posted via @kriszyp.

…lish or relocate from being skipped as a duplicate (#3499)

Port of 5d94a9a to v5.3. The head-tie identity now comes from the committed record whenever
another write to the key already saved unskipped, and a source-applied relocate that ties with the
committed head is skipped. v5.3 has a single txnLogKey (no origin-closed floor), so main's
receivedLogKey/appendedLogKey checks map to `txnLogKey === txnTime`; the relocate keeps v5.3's
plain return on an older version (#3183's skipped marking is not on v5.3), and the ref check keeps
v5.3's form without main's priorStaged guard.

(cherry picked from commit 5d94a9a)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SbvHaBBdQ7Cp7yVDuSD5GS
Dispatch-Task: cherry-resolve-kriszyp_harper_3476-123ff057
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant