Skip to content

Write the version/metadata prefix on LMDB→RocksDB migrated records (v5.1 backport of #2014) - #2020

Open
kriszyp wants to merge 4 commits into
v5.1from
kris/2012-migration-prefix-v51
Open

Write the version/metadata prefix on LMDB→RocksDB migrated records (v5.1 backport of #2014)#2020
kriszyp wants to merge 4 commits into
v5.1from
kris/2012-migration-prefix-v51

Conversation

@kriszyp

@kriszyp kriszyp commented Jul 31, 2026

Copy link
Copy Markdown
Member

Manual v5.1 backport of #2014 (fixes the v5.1 exposure of #2012). The v5.1 line is affected from v5.1.2#1307 shipped in it the same day it merged — so every storage.migrateOnStart run on v5.1.2–v5.1.23 wrote records without the [8-byte version][flags word] prefix, silently dropping record versions. Empirically confirmed by @heskew on 5.1.23 and by ancestry check (details).

Why v5.1 instances look healthy: this branch has no PrimaryRocksDatabase; the handleLocalTimeForGets wrapper repairs record prototypes unconditionally on point reads, so affected instances read correctly and only lose versions (cache admission, ifVersion/CAS, replication version comparisons). The invisible-records symptom fires when they upgrade to 5.2 — so shipping this in 5.1 stops new damage, and verifyMigratedDatabase identifies instances needing the rewrite pass before any 5.2 upgrade.

Variant differences from #2014 (main)

  • Dropped: the resources/PrimaryRocksDatabase.ts read-side changes and unitTests/resources/primaryRocksMetadataRepair.test.js — the file doesn't exist on v5.1 and the wrapper already repairs unconditionally.
  • Adapted: the migration tests verify via RecordEncoder.decode metadata wrappers ({ value, version }) instead of PrimaryRocksDatabase point reads.
  • Ported unchanged: copyDb.ts wholesale (byte-identical base pre-fix): explicit useVersions === false opt-out in the RecordEncoder encode hook, staged migration (<db>.migrating + atomic rename + close-all-handles + Windows rename retry), exact-header tripwire, key-exempted full verification sweep, verifyMigratedDatabase export, discovery exclusion of *.migrating dirs, MIGRATING_DIR_SUFFIX in hdbTerms.

Tests

unitTests/bin/migration*.test.js: 7 passing under HARPER_STORAGE_ENGINE=lmdb, 7 pending (visible skip) under rocks; full lmdb bin suite 69 passing locally. Note: local run used a newer rocksdb-js than the branch lockfile (shared node_modules) — CI arbitrates against the real pin.

All review findings from #2014 (Codex tripwire ambiguity, kriszyp staging restart-safety, heskew verification gaps, cb1kenobi sweep byte-sniffing) are incorporated since this ports the final state.

🤖 Generated with Claude Code (Claude Fable 5)

…rated records (v5.1 backport of #2014)

Backport of #2014 (harper#2012) to the v5.1 line, which
is affected from v5.1.2 (#1307 shipped the same day): every migrateOnStart
run wrote prefix-less records — versions silently dropped. On v5.1 the
handleLocalTimeForGets wrapper still repairs prototypes on point reads, so
migrated instances look healthy until they upgrade to 5.2 and hit the
prototype-loss symptom; the version loss is live on v5.1 today.

Variant differences from main: no PrimaryRocksDatabase on this branch, so
the read-side repair changes and primaryRocksMetadataRepair.test.js are
dropped, and the migration tests verify via RecordEncoder.decode metadata
wrappers instead of PrimaryRocksDatabase point reads. Write-side fix,
staged+verified promotion (staging dir, atomic rename, close-all-handles,
exact-header tripwire, key-exempted sweep), verifyMigratedDatabase export,
and discovery exclusion are ported unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.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 restart-safe promotion for the LMDB to RocksDB migration by staging the database copy in a ".migrating" directory and atomically renaming it upon successful verification. It also fixes a critical issue where versioned records were incorrectly stripped of their metadata prefix during migration due to an implicit falsy check on useVersions. The review feedback correctly identifies a potential resource leak in verifyMigratedDatabase if an error occurs during the initialization of the second database handle before entering the try-finally block.

Comment thread bin/copyDb.ts
@claude

claude Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found. The latest commit (a8e59e2) closes each per-table rawDbi immediately after countRecords in bin/copyDb.ts:463-468 via try/finally, instead of holding all table handles open until the end of the sweep — addresses the #2022 bot-review suggestion cleanly, and the pre-loop handles (rootStore/dbisDb) still use the leak-safety array as before.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread bin/copyDb.ts Outdated
…tial-open failure

Track every open in a handles array closed in finally (the copyDbToRocks
pattern): a throw opening the second store leaked the first, holding the
RocksDB lock on the diagnostic path operators use after a broken
migration. Flagged by both review bots.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…iew on #2022)

Keeps the v5.1 backport identical to main: only rootStore/dbisDb need the
leak-safety array; per-table CF handles close immediately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kriszyp
kriszyp requested review from heskew and ldt1996 and removed request for Devin-Holland and sleekmountaincat July 31, 2026 12:15
kriszyp added a commit that referenced this pull request Jul 31, 2026
…tial-open failure

Track every open in a handles array closed in finally (the copyDbToRocks
pattern): a throw opening the second store leaked the first, holding the
RocksDB lock on the diagnostic path operators use after a broken
migration. Caught by the review bots on the v5.1 backport (#2020) of
the change that introduced it (#2014).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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