Skip to content

Add RocksDB blob_dir patch so blob files can live on a separate volume - #13

Open
kriszyp wants to merge 11 commits into
mainfrom
kris/blob-dir-patch
Open

kriszyp wants to merge 11 commits into
mainfrom
kris/blob-dir-patch

Conversation

@kriszyp

@kriszyp kriszyp commented Aug 8, 2026

Copy link
Copy Markdown
Member

Adds a downstream RocksDB patch introducing AdvancedColumnFamilyOptions::blob_dir, so blob files can be placed on a different volume than the SST files.

Stock RocksDB derives every blob file path from cf_paths.front().path. That means db_paths/cf_paths cannot tier large values at all — they distribute SST files by level while every blob file stays put. Without this, there is no way to keep the LSM tree (and all of its compaction write traffic) on fast local storage while large values live on cheaper attached storage.

All blob path derivation now routes through a single ImmutableCFOptions::GetBlobDir(), so the option and its cf_paths.front() default cannot drift apart. ROCKSDB_HAS_CF_BLOB_DIR lets downstream code feature-detect and still compile against an unpatched RocksDB. Consumed by @harperfast/rocksdb-js via its new blobs.dir option.

The patch is authored against v11.8.1, the version rocksdb-js pins, and applied with patch -p1 -F0 so a version bump fails loudly instead of fuzzy-matching a hunk into a plausible-but-wrong site.

Where to look

GetBlobDir() is the whole contract; most of the rest is call sites. The parts worth reading closely are the ones review found rather than the ones the first pass wrote.

  • Checkpoint and BackupEngine refuse a blob_dir DB. CreateCustomCheckpoint — the shared implementation behind both — asks for a portable capture through LiveFilesStorageInfoOptions::require_portable_files, and GetLiveFilesStorageInfo evaluates it under mutex_ before the flush and again after, because FlushForGetLiveFiles() releases the mutex. The state is a monotone latch (has_ever_had_blob_dir_) set at column-family creation and never cleared, so dropping the only blob_dir CF does not re-open the hole. Reasoning below.
  • FlushJob::HasBlobFileAdditions() is total, not asserted. It answers false for a null edit_. edit_ is null exactly when PickMemTable() picked nothing — reachable when an overlapping flush already claimed the memtables, or when they all sit above the request's max_memtable_id — and Run() accepts that state and returns OK. A job that picked nothing wrote no blob files, so the predicate has a correct answer; guarding the call site instead would have been wrong, because pick_status[i] records that PickMemTable() ran, not that it picked.
  • Directory fsync. A blob directory outside cf_paths has no FSDirectory handle in Directories, so its entries were never fsynced after flush, compaction, or WAL recovery — a crash could leave a durable SST referencing a blob file with no directory entry. ColumnFamilyData now owns a handle, created through the shared created_dirs map so no directory is opened twice.
  • The audit's second regex was half dead. cf_paths(\.front\(\)|\[0\])\.path — the dot used to sit before the alternation, so cf_paths[0].path (which has no dot after cf_paths) could never match and the guard silently covered half of what it claimed. Fixing it surfaced seven call sites; all seven derive SST paths, and they are now pinned in cf-blob-path-inventory.txt so one that later derives a blob path shows up as a diff.

Checkpoint and backup

Two review threads asked for backup/checkpoint to be rejected while blob_dir is non-empty. Building the patched tree and measuring says the stated failure mode does not happen, but the conclusion is right anyway, for a worse reason.

Flattening is already refused. CreateCustomCheckpoint rejects any DB whose non-WAL files span more than one directory, and reporting the real blob directory from GetLiveFilesStorageInfo is what puts a tiered DB in that category. Measured: with blob_dir set and one live blob file, CreateCheckpoint and CreateNewBackup both return NotSupported and leave no partial artifact.

But only once a blob file exists to report. A DB with blob_dir set that has not written one yet backs up cleanly — and that backup is a landmine. The copied OPTIONS file carries blob_dir, an absolute path, so restoring elsewhere and opening produces a second DB pointed at the source's blob directory, whose obsolete-file scan deletes the source's live blob files. Measured on the patched build: source blob files 1 before, 0 after opening the restore, and the source DB then fails its own read with No such file or directory.

So the refusal keys on the option being set at all, not on the files reported and not on it differing from dbname_ — the path is absolute either way.

This is upstream's hazard, not one blob_dir introduces. The same sequence with cf_paths pointing at an external directory corrupts the source DB on stock v11.8.1, verified by building an unpatched tree. It is closed here because blob_dir is the option this patch owns, and because a tiered DB spends its early life blob-free — exactly the window that backs up cleanly and restores into a landmine.

Rebased onto the experimental-patches pipeline

This PR had been conflicting with main since #15 merged, which is why no PR workflow had ever run on it — GitHub cannot compute a merge commit for a conflicting PR, so the gate this branch adds had never once executed. Rebased; three conflicts, all in build.yml, all resolved in favour of keeping both sides:

conflict resolution
patch -F0 invocation took main — it had already adopted -F0 and a rationale comment, so this branch's intent was already there
audit call vs. the new EXPERIMENTAL_DIRS loop kept both, audit first: the inventories describe the official patch set, and an opt-in experiment is not drift
a later commit deletes that audit call honoured — it moves the audit into the dedicated nightly audit job

No RocksDB patch content changed in the rebase; vcpkg-overlays/ is byte-identical to the pre-rebase tree.

CI

A PR gate applies all patches at zero fuzz, runs the call-site audit, then builds and runs a focused set of upstream tests. It resolves the release from patched-version.txt rather than releases/latest: the inventories pin upstream line numbers, so resolving "latest" at run time would have turned every upstream release day into a red gate on every open PR. The nightly audit still runs against the latest release, which is where drift belongs and where it must block the publishing build.

Verification

All on a patched v11.8.1 tree built from this patch (make, debug, GCC 15).

suite result
db_basic_test *PortableLiveFileCapture*, *RecoveryBlobDirSynced* 4/4
db_flush_test.BlobDirIsFsyncedForOrdinaryAndAtomicFlush 1/1
checkpoint_test (full) 42/42
backup_engine_test (full) 108/108
options_test (full) 79/79
options_settable_test ColumnFamilyOptionsAllFieldsSettable fails — identically on a pristine v11.8.1 tree (unset_bytes_base 102 vs 126, both trees), so it is a GCC 15 artifact the patch neither causes nor masks
  • The PR gate this branch adds is green on its first-ever run (run 34369386485): the pinned download, the zero-fuzz apply, the call-site audit, and all five test binaries — options_settable_test included, so the GCC 15 failure above does not reproduce on ubuntu-latest.

  • The regenerated patch applies to a fresh v11.8.1 tarball at patch -p1 -F0 and git apply --check, and the tree it produces is byte-identical across all 28 patched files to the tree that was built and tested.

  • The inventory audit passes against that freshly reproduced tree.

  • RocksDB's own make check was run against the patched tree in an earlier round and found two real defects, both fixed here (a186bc7).

  • Behavior of the checkpoint/backup guard, measured against the patched library rather than traced:

    configuration CreateCheckpoint / CreateNewBackup
    blob_dir unset OK — and restore OK. Unchanged from stock.
    blob_dir set, one live blob file NotSupported, no partial artifact
    blob_dir set, no blob file yet NotSupported (the case the guard adds)
    blob_dir set to the DB directory itself NotSupported — still an absolute path that would not follow a copy
  • The resulting library passes @harperfast/rocksdb-js's tiered-storage suite 19/19. That predates this round; it does not exercise checkpoint or backup.

For the human reviewer

Reviewer sign-off at 729c24a. cb1kenobi's review closes the earlier blockers — "portable capture is latched under the DB mutex, backup and checkpoint refuse a configured blob_dir, and directory fsync plus call-site audit coverage match the stated contract" — and rules the items below "documented C++ layering tradeoffs that rocksdb-js already enforces, not unfixed defects on this diff." So none of these blocks merge. Items 1, 4 and 6 remain live only as offers to do more than this diff does; the only thing actually gating merge is the ordering in item 7.

  1. Refusing every backup of a blob_dir database is a real operational constraint, and it is the decision most worth disagreeing with. It is strictly more conservative than the status quo — it only refuses backups that were already dangerous — but a tiered database can never be checkpointed or backed up through RocksDB's own tooling, at any point in its life. Say if you would rather have documentation only and accept the footgun.
  2. The portable-capture latch reflects the descriptors this DB was opened with, not its persisted OPTIONS. A read-only open whose descriptors omit blob_dir, against a DB whose OPTIONS file still names one, admits a capture that copies that OPTIONS file — and restoring it can again aim obsolete-file cleanup at the source volume. rocksdb-js refuses such an open; the C++ API does not. Closing it in the engine means validating the captured OPTIONS artifact, which is the same layering question as item 3. Raised by review, left open deliberately.
  3. Enforcement of the immutability rule lives in the consumer. A blob file's directory is re-derived from the option on every open rather than recorded per file, so changing it on a populated database strands the existing blob files. RocksDB cannot enforce that without persisting more state, so the constraint is documented on the option and enforced by rocksdb-js, which compares against the persisted blob_dir. The layering is worth agreeing on.
  4. No regression test for the empty-pick window. The HasBlobFileAdditions() fix is total, so the crash is gone, but nothing pins it. Reaching that window from a test needs a second flush to claim the memtables inside the SyncClosedWals mutex-release window, and any second flush re-enters the same sync point, so the usual LoadDependency idiom deadlocks — forcing it means adding a new TEST_SYNC_POINT to upstream db_impl_compaction_flush.cc and widening the vendored patch. Say if you want that; it is a small change, just not a free one.
  5. The identical cf_paths hole upstream is left open. Same sequence, same corruption, stock v11.8.1. Fixing it would change behavior for configurations this patch does not own.
  6. Direct-write blob partition manager. New in 11.8.1 and off by default. It wrote to dbname_ regardless of blob placement; it now honors blob_dir only when explicitly set, so the default path is byte-for-byte unchanged. Two review legs argued it should unconditionally use GetBlobDir() — that is a real upstream inconsistency (with blob_dir unset and cf_paths.front() != dbname_, direct-write blobs are written to one and read from the other), but fixing it changes stock behavior on a path this patch does not own. Say if you would rather it were fixed here.
  7. Placement: answered — this moves to experimental-patches/. Add opt-in experimental patches pipeline #15 landed the opt-in patch layer after this branch was written, and I had left the question open here because making the patch opt-in means the default prebuild loses the feature. #24 "Move the cf-blob-dir patch into experimental-patches/" settles it: it targets this branch, not main, so it lands here first and this PR then merges to main with the patch already in the opt-in slot. It is a strict fast-forward of this branch, the patch file is byte-identical across the move (sha256 931b8b0a…), and its gate reproduces this PR's full test result under the new pipeline, so the move costs no coverage. The one thing that move does not settle is the consumer: official prebuilds will no longer carry ROCKSDB_HAS_CF_BLOB_DIR, so rocksdb-js #767 must either pin an experimental prebuild or wait for blob_dir to graduate into the official overlay. That decision is tracked on Move the cf-blob-dir patch into experimental-patches/ #24, not here.
  8. Rebase burden. A vendored patch across 19 files. 11.8.1 already introduced one new path-derivation site relative to 11.1.2, which is why the header carries a re-audit note and patched-version.txt now pins what the inventories were generated from. If that burden looks wrong, the alternative is proposing blob_dir upstream and waiting.

Review findings declined this round with the evidence that refuted them, so you do not have to re-derive it: the SstFileManager/DeleteScheduler trash and space-accounting findings (CollectAllDBPaths() already includes GetBlobDir(), and both db_impl_open.cc trash cleanup and db_impl_files.cc existing-file tracking iterate it); a RepairDB finding (repair.cc has no BlobFileName site and passes nullptr blob additions in stock 11.8.1, so tiering changes nothing there); a WAL-deadlock blocker on the second portability check (UnlockWAL appears nowhere in db_filesnapshot.cc; wal_locked only observes whether another caller holds the lock, and upstream's own early returns in that block have the identical shape); and a recovery null-check (the unconditional data_dir deref one line above is verbatim upstream v11.8.1).

Generated by Claude Opus 5.

🤖 Generated with Claude Code

https://claude.ai/code/session_011TPPxptQi3DTZk7UPDFsFQ

Complexity: complicated

Review-Coverage: authored=claude; ran=codex,gemini; declined=cursor-grok,cursor-composer,domain; rounds=5 @ 729c24a

Human-Review-Need: 4 @ 729c24a

@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 downstream patch to RocksDB that adds the blob_dir option to AdvancedColumnFamilyOptions, allowing blob files to be stored on a different volume than SST files. Feedback on the patch includes preventing duplicate paths in the directory creation list to avoid disabling NoSpace() recovery, ensuring the AdvancedColumnFamilyOptions constructor copies the new field, and using std::move for safer smart pointer ownership transfer.

Comment thread vcpkg-overlays/rocksdb/patches/0002-cf-blob-dir.patch Outdated
Comment thread vcpkg-overlays/rocksdb/patches/0002-cf-blob-dir.patch
Comment thread vcpkg-overlays/rocksdb/patches/0002-cf-blob-dir.patch Outdated
@cb1kenobi

Copy link
Copy Markdown
Member

Is this something we can PR with the RocksDB repo so we don't have to maintain this patch?

@kriszyp

kriszyp commented Aug 14, 2026

Copy link
Copy Markdown
Member Author

Is this something we can PR with the RocksDB repo so we don't have to maintain this patch?

Yes, I believe so, it seems like a very reasonable PR to submit.
But do you think we should do this patch first so we can test it thoroughly before submitting upstream? Also, I have no idea what kind of timelines to expect from a PR request upstream. (I think we probably want to start building and testing attached storage SRTL). But yes, would love to upstream this at some point, if it proves useful. (but let me know if you really think we should try for upstream first though.)

@kriszyp
kriszyp marked this pull request as ready for review August 14, 2026 17:31
@kriszyp
kriszyp marked this pull request as draft August 17, 2026 15:16
@kriszyp
kriszyp marked this pull request as ready for review August 18, 2026 13:15
@kriszyp

kriszyp commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@cb1kenobi Should I go ahead and merge this, per the discussion above?

Comment thread vcpkg-overlays/rocksdb/patches/0002-cf-blob-dir.patch
Comment thread vcpkg-overlays/rocksdb/patches/0002-cf-blob-dir.patch Outdated
Kris Zyp and others added 11 commits September 9, 2026 08:55
Adds AdvancedColumnFamilyOptions::blob_dir so blob files can be placed on a
different volume than the SST files.

db_paths/cf_paths distribute SST files by level, but every blob file path is
derived from cf_paths.front(), so large values cannot be tiered at all without
this. That makes it impossible to keep the LSM tree (and all its compaction
write traffic) on fast local storage while large values live on cheaper
attached storage.

All blob path derivation now goes through a single ImmutableCFOptions::
GetBlobDir() accessor, so the option and its cf_paths.front() default cannot
drift apart. That includes the two places a first pass missed: a blob directory
outside cf_paths has no handle in Directories, so its directory entries were
never fsynced after flush or compaction (a crash could leave a durable SST
referencing a blob file with no directory entry), and the common two-argument
DestroyDB overload never collected blob_dir because collection lived only in
the column_families loop.

blob_dir is the last field of AdvancedColumnFamilyOptions on purpose: inserting
mid-struct shifts every following field's offset and silently mismatches code
compiled against stock headers. ROCKSDB_HAS_CF_BLOB_DIR lets downstream code
feature-detect and still compile against an unpatched RocksDB.

Authored against v11.8.1, the version rocksdb-js pins. 11.8.1's new direct-write
blob partition manager was an additional path-derivation site, so the header
carries a note to re-audit them on every version bump.

Verified: applies cleanly to a fresh v11.8.1 tarball with patch -p1, builds
clean, and the resulting library passes @harperfast/rocksdb-js's blob_dir tests
— blobs written to a separate volume, read back across reopen, relocated, and
applied to named column families.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Running the upstream suite against the patched tree (which I had skipped)
turned up both:

- ColumnFamilyData::GetDbPaths() called GetBlobDir() unconditionally, whose
  assert fires when cf_paths is empty. Unit tests build ImmutableCFOptions
  that never went through SanitizeCfOptions, so memtable_list_test aborted.
  It now reads the raw blob_dir field: an unset one resolves to
  cf_paths.front(), which the loop above already covers.
- The options_settable_test exclusion entry was out of offset order.
  FillWithSpecialChar walks that list sequentially and computes
  pair.first - offset, so a misplaced entry underflows the length and the
  memset clobbers the very field the entry exists to protect — turning a
  pre-existing assertion failure on this toolchain into a segfault.
  blob_dir sits at 664, after blob_direct_write_partition_strategy at 616.

memtable_list_test now passes. options_settable_test still fails, but
identically to a pristine v11.8.1 tree on this toolchain (unset_bytes_base
102 vs 126, a GCC 15 padding artifact) — verified by building the same test
from an unpatched tarball.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copy blob_dir through AdvancedColumnFamilyOptions, avoid duplicate open paths, and transfer the blob directory handle without a raw-pointer round trip. Add a focused constructor regression test.

Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Drop a whitespace-only advanced_options.h hunk so future -F0 rebases have one fewer anchor to maintain.

Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Review asked us to reject backup/checkpoint while blob_dir is non-empty,
because a backup that flattens blob files into the DB directory restores
into a database that cannot read its large values. The flattening half of
that does not happen: CreateCustomCheckpoint -- the shared implementation
behind both Checkpoint and BackupEngine -- already refuses any DB whose
non-WAL files span more than one directory, and reporting the real blob
directory from GetLiveFilesStorageInfo is what puts a tiered DB in that
category.

But it only puts it there once a blob file exists to report, and the gap
is worse than the flattening would have been. Backing up a tiered DB that
has not written a blob file yet succeeds. The copied OPTIONS file carries
blob_dir, so restoring that backup elsewhere and opening it produces a
second DB pointed at the *source's* blob directory -- and its obsolete-file
scan deletes the source's live blob files. Measured on a patched v11.8.1
build: source blob files 1 before, 0 after opening the restore, and the
source DB then fails its own read with "No such file or directory".

So the rejection has to key on the option, not on the files reported.
CreateCustomCheckpoint now also asks DBImpl::HasBlobDirSet(), which is true
for any non-empty blob_dir rather than only one outside the DB directory:
blob_dir is an absolute path, so a copy of the DB opened anywhere resolves
its blob files back to the original directory whatever that directory is.

This is upstream's hazard, not one blob_dir introduces -- the same sequence
with cf_paths pointing at an external directory corrupts the source DB on
stock v11.8.1, verified the same way. It is closed here because blob_dir is
the option this patch owns, and because a tiered DB spends its early life
blob-free, which is exactly the window that backs up cleanly and restores
into a landmine.

Also: the file-spanning message now names blob_dir, so someone who set only
blob_dir does not read "db_paths / cf_paths not supported" as a bug, and the
option's doc comment states the restriction.

Verified with blob_dir unset: checkpoint, backup and restore unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Co-Authored-By: GPT-5 Codex <noreply@openai.com>
The `cf_paths[0].path` half of the audit regex could never match: `cf_paths\.`
requires a literal dot, which `cf_paths[0]` does not have. Moving the dot inside
the alternation surfaces seven previously invisible call sites, all of which
derive SST paths rather than blob paths — recorded in the inventory so a future
one that does derive a blob path shows up as a diff.

AtomicFlushMemTablesToOutputFiles enters its output-directory sync block on
`s.IsShutdownInProgress()`, a state reachable from SyncClosedWals before the
PickMemTable loop runs. FlushJob::edit_ is null until PickMemTable assigns it,
so the blob-directory addition dereferenced null on a shutdown flush. Guard on
`pick_status[i]`, the same condition the surrounding cancel loop already uses.

The PR gate resolved `releases/latest` at run time while the inventories pin
upstream line numbers, so an upstream release would have failed every open pull
request. It now applies and tests the release in `patched-version.txt`; the
nightly audit still runs against the latest release, which is where drift
belongs. `options_settable_test` joins the gate's test set — it is the upstream
test that covers the patch's ColumnFamilyOptions registration.

Verified on the patched v11.8.1 build: the blob_dir cases in db_basic_test (4),
db_flush_test (1), checkpoint_test (3), and backup_engine_test (1) all pass.
`options_settable_test.ColumnFamilyOptionsAllFieldsSettable` fails on GCC 15
with the identical numbers (unset_bytes_base 102 vs 126) on a pristine v11.8.1
tree, so the patch neither causes nor masks it. The regenerated patch applies to
a fresh tarball at `patch -p1 -F0` and `git apply --check`, and reproduces all
28 patched files byte-for-byte against the tree that was built and tested.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011TPPxptQi3DTZk7UPDFsFQ
Guarding the call site on pick_status[i] was not enough. pick_status[i] records
that PickMemTable() ran, not that it picked anything: PickMemtablesToFlush()
returns an empty set when every not-yet-flushed memtable is already claimed by
an overlapping flush or sits above the request's max_memtable_id, and
PickMemTable() then returns before assigning edit_. Run() accepts that state and
returns OK, so the atomic-flush sync block is reached with pick_status[i] true
and edit_ null.

edit_ is null exactly when nothing was picked, and a job that picked nothing
wrote no blob files, so the accessor answers false rather than making every
call site prove it picked memtables. The call-site guard goes away with it.

Also trims the added comments down to the invariants they carry — the Env path
registration reading the raw field, the data_dirs_ gap that blob_dir_ fills, the
NoSpace() interaction — dropping the sentences that narrate the code beside them.

Verified on the patched v11.8.1 build: db_basic_test blob_dir cases 4/4,
db_flush_test 1/1, checkpoint_test 42/42, backup_engine_test 108/108,
options_test 79/79. The regenerated patch applies at patch -p1 -F0 and
git apply --check and reproduces all 28 patched files byte-for-byte against the
tree that was built and tested; both inventories are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011TPPxptQi3DTZk7UPDFsFQ
The validate job downloads a RocksDB release, applies every patch and runs
upstream test binaries; on a 90-minute timeout that is not something to spend on
a pull request that cannot change the result. Restrict the pull_request trigger
to the overlay directory and this workflow, the same `paths` idiom
validate-experimental-patches.yml already uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011TPPxptQi3DTZk7UPDFsFQ
@cb1kenobi

Copy link
Copy Markdown
Member

Blocked by PR #24.

@kriszyp

kriszyp commented Sep 14, 2026

Copy link
Copy Markdown
Member Author

Blocked by PR #24.

Checked this rather than taking it on faith, and it holds — nothing on this PR needs to change for it, and the move is cheaper than it looks:

So the ordering is right, and I've updated item 7 of the description — it had the placement question as still open, and your comment answers it.

What is left is on #24 rather than here: two review threads are still unresolved against db581c7, and I confirmed both still hold at that commit —

  1. The nightly/dispatch audit checks one patch per fresh tree (apply-patches.sh "$SRC" "$name", build.yml:367) while the release build applies the composed stack (build.yml:472). Latent today, since 0001-cf-blob-dir is the only non-noop patch — it becomes reachable with the second one.
  2. .github/scripts/apply-patches.sh is in neither workflow's path filterbuild.yml lists .github/workflows/build.yml only, and validate-experimental-patches.yml lists experimental-ids.sh but not apply-patches.sh, so a helper-only change exercises neither gate.

The one thing #24 does not settle is the consumer: once the patch is opt-in, official prebuilds stop carrying ROCKSDB_HAS_CF_BLOB_DIR, so rocksdb-js #767 needs either a pinned experimental prebuild or an eventual graduation into the official overlay. You flagged that on #24 already; noting it here so the sequencing is in one place.

Nice call on the move, by the way — the per-patch patched-version.txt is the part that makes it hold up beyond this one patch.

— Claude Opus 5

@cb1kenobi cb1kenobi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The blob_dir patch's earlier blockers are closed: portable capture is latched under the DB mutex, backup and checkpoint refuse a configured blob_dir, and directory fsync plus call-site audit coverage match the stated contract. Remaining items in the PR body are documented C++ layering tradeoffs that rocksdb-js already enforces, not unfixed defects on this diff. No new blocking issue on the changed lines at 729c24a.


Reviewed 729c24a

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