From 6bec4db11f3a3cca13fd64b60d13629ccf8798c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Isager=20Dalsgar=C3=B0?= Date: Tue, 3 Sep 2024 16:06:44 +0200 Subject: [PATCH] Support snapshots before `db.ready()` (#10) --- index.js | 6 ++++-- lib/batch.js | 4 ++-- lib/snapshot.js | 15 +++++++++------ test.js | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index 787e2e7..4f5f9fa 100644 --- a/index.js +++ b/index.js @@ -76,7 +76,9 @@ const RocksDB = module.exports = class RocksDB extends ReadyResource { RocksDB._instances.add(this) - return promise + await promise + + for (const snapshot of this._snapshots) snapshot._init() function onopen (err) { if (err) req.reject(new Error(err)) @@ -98,7 +100,7 @@ const RocksDB = module.exports = class RocksDB extends ReadyResource { RocksDB._instances.delete(this) - return promise + await promise function onclose (err) { if (err) req.reject(new Error(err)) diff --git a/lib/batch.js b/lib/batch.js index 851a5a3..ca58f70 100644 --- a/lib/batch.js +++ b/lib/batch.js @@ -117,7 +117,7 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch { this._snapshot = snapshot } - async _init () { + _init () { this._handle = binding.readInit(this) this._buffer = binding.readBuffer(this._handle, this._capacity) } @@ -161,7 +161,7 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch { } exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch { - async _init () { + _init () { this._handle = binding.writeInit(this) this._buffer = binding.writeBuffer(this._handle, this._capacity) } diff --git a/lib/snapshot.js b/lib/snapshot.js index f79008f..8885604 100644 --- a/lib/snapshot.js +++ b/lib/snapshot.js @@ -2,22 +2,25 @@ const binding = require('../binding') module.exports = class RocksDBSnapshot { constructor (db) { - if (db.opened === false) throw new Error('Database is not open') - this._db = db + this._db._snapshots.add(this) - this._handle = binding.snapshotCreate(db._handle) + this._handle = null - this._db._snapshots.add(this) + if (db.opened === true) this._init() + } + + _init () { + this._handle = binding.snapshotCreate(this._db._handle) } destroy () { + this._db._snapshots.delete(this) + if (this._handle === null) return binding.snapshotDestroy(this._handle) this._handle = null - - this._db._snapshots.delete(this) } } diff --git a/test.js b/test.js index 1c282ab..d7f2fa9 100644 --- a/test.js +++ b/test.js @@ -317,6 +317,42 @@ test('iterator with snapshot', async (t) => { await db.close() }) +test('iterator with snapshot before db open', async (t) => { + const db = new RocksDB(await tmp(t)) + + const snapshot = db.snapshot() + + await db.ready() + + const batch = db.write() + batch.put('aa', 'ba') + batch.put('ab', 'bb') + batch.put('ac', 'bc') + await batch.flush() + + const entries = [] + + for await (const entry of db.iterator({ gte: 'a', lt: 'b' }, { snapshot })) { + entries.push(entry) + } + + snapshot.destroy() + + t.alike(entries, []) + + await db.close() +}) + +test('destroy snapshot before db open', async (t) => { + const db = new RocksDB(await tmp(t)) + + const snapshot = db.snapshot() + snapshot.destroy() + + await db.ready() + await db.close() +}) + test('peek', async (t) => { const db = new RocksDB(await tmp(t)) await db.ready()