Summary
Add a thin native method that exposes RocksDB's Checkpoint::CreateCheckpoint API so callers can produce a hardlinked, point-in-time, fully independent copy of an open database.
Motivation
Needed by HarperFast/harper to implement a "branched databases" feature for application isolation (umbrella issue to follow). RocksDB Checkpoint is the right primitive because:
- It produces a writable sibling DB (not a read-only snapshot).
- It is near-instant — SST files are hardlinked, only memtable contents are flushed/copied.
- It is safe to call on a live, actively-written database — that's exactly what the C++ API is designed for.
Reimplementing this in JS (flush + manual hardlink + manifest copy) is fragile compared to using the upstream primitive.
Proposed API
JS surface on RocksDatabase:
```ts
db.createCheckpoint(targetPath: string): Promise
```
- `targetPath` must not exist (RocksDB requires this).
- Resolves once the checkpoint has been written; rejects with a Status-derived error on failure.
- Caller is responsible for opening the checkpoint as a new `RocksDatabase` and for eventual cleanup of the directory.
Native sketch
```cpp
Napi::Value RocksDatabase::CreateCheckpoint(const Napi::CallbackInfo& info) {
std::string path = info[0].AsNapi::String();
rocksdb::Checkpoint* checkpoint;
rocksdb::Status s = rocksdb::Checkpoint::Create(db_, &checkpoint);
if (!s.ok()) { /* throw / }
std::unique_ptrrocksdb::Checkpoint guard(checkpoint);
s = checkpoint->CreateCheckpoint(path);
if (!s.ok()) { / throw with s.ToString() */ }
return info.Env().Undefined();
}
```
Run the actual checkpoint call on the worker pool (Napi AsyncWorker) so the Node main thread is not blocked — the call can take a few hundred ms when memtables need flushing.
Acceptance criteria
Out of scope
- Column-family selection (use the full DB).
- Incremental / differential checkpoints.
🤖 Filed by Claude on behalf of Kris
Summary
Add a thin native method that exposes RocksDB's
Checkpoint::CreateCheckpointAPI so callers can produce a hardlinked, point-in-time, fully independent copy of an open database.Motivation
Needed by HarperFast/harper to implement a "branched databases" feature for application isolation (umbrella issue to follow). RocksDB Checkpoint is the right primitive because:
Reimplementing this in JS (flush + manual hardlink + manifest copy) is fragile compared to using the upstream primitive.
Proposed API
JS surface on
RocksDatabase:```ts
db.createCheckpoint(targetPath: string): Promise
```
Native sketch
```cpp
Napi::Value RocksDatabase::CreateCheckpoint(const Napi::CallbackInfo& info) {
std::string path = info[0].AsNapi::String();
rocksdb::Checkpoint* checkpoint;
rocksdb::Status s = rocksdb::Checkpoint::Create(db_, &checkpoint);
if (!s.ok()) { /* throw / }
std::unique_ptrrocksdb::Checkpoint guard(checkpoint);
s = checkpoint->CreateCheckpoint(path);
if (!s.ok()) { / throw with s.ToString() */ }
return info.Env().Undefined();
}
```
Run the actual checkpoint call on the worker pool (Napi AsyncWorker) so the Node main thread is not blocked — the call can take a few hundred ms when memtables need flushing.
Acceptance criteria
Out of scope
🤖 Filed by Claude on behalf of Kris