Skip to content

cherry-pick: replay conflict retry on a fresh transaction after ERR_TRY_AGAIN (#1696) (→ v5.1) - #1852

Merged
kriszyp merged 1 commit into
v5.1from
cherry-pick/v5.1/pr-1696
Jul 17, 2026
Merged

cherry-pick: replay conflict retry on a fresh transaction after ERR_TRY_AGAIN (#1696) (→ v5.1)#1852
kriszyp merged 1 commit into
v5.1from
cherry-pick/v5.1/pr-1696

Conversation

@kriszyp

@kriszyp kriszyp commented Jul 17, 2026

Copy link
Copy Markdown
Member

Cherry-pick of #1696"fix(storage): replay conflict retry on a fresh transaction after ERR_TRY_AGAIN" — onto the 5.1.x patch line, per Kris's request.

Apply

Before merge

  • Confirm CI is green on v5.1 (validates the change against the 5.1.x base).
  • v5.1 is unprotected — hold for Kris to merge, then cut 5.1.22.

🤖 Cherry-pick prepared by Claude (Opus 4.8) on Kris's behalf.

…TRY_AGAIN (#1696)

* fix(storage): replay conflict retry on a fresh transaction after ERR_TRY_AGAIN

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(storage): keep retries from deduping against their own audit entry

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: log the swallowed abort error (review)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(storage): per-write sticky own-audit-entry marker for retry dedup (review)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(storage): abort before the MAX_RETRIES throw, pin change-feed entries in tests (review)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Kris Zyp <kriszyp@gmail.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a mechanism to replay writes onto a fresh transaction when a commit fails with ERR_TRY_AGAIN (e.g., due to a memtable flush stranding the snapshot), preventing infinite retry loops. It also tracks whether a write has already appended its audit entry in a prior attempt to avoid incorrect deduplication during replay. The feedback suggests using optional chaining (?.) when accessing store.store on the found write operation in DatabaseTransaction.ts to prevent potential runtime TypeError exceptions.

// transaction object, which abort() leaves intact); isRetry in save() keeps the log
// entries themselves from being re-added.
const retryTransaction: RocksTransactionWithRetry = new RocksTransaction(
(this.writes.find((write) => write)?.store.store ?? this.db.store) as RocksStore

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To prevent potential runtime TypeError exceptions if write.store is undefined or null, use optional chaining (?.) when accessing store.store on the found write operation. This aligns with defensive programming best practices.

Suggested change
(this.writes.find((write) => write)?.store.store ?? this.db.store) as RocksStore
(this.writes.find((write) => write)?.store?.store ?? this.db.store) as RocksStore
References
  1. When accessing properties of a result from a method that might return nullish, guard against nullish values to prevent runtime errors.

@kriszyp
kriszyp merged commit 2b4c4b2 into v5.1 Jul 17, 2026
46 of 49 checks passed
@kriszyp
kriszyp deleted the cherry-pick/v5.1/pr-1696 branch July 17, 2026 22:27
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.

2 participants