@nxtedition/rocksdb 7.0.56 → 7.0.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/binding.cc +47 -56
  2. package/index.js +24 -1
  3. package/package.json +1 -1
package/binding.cc CHANGED
@@ -872,6 +872,19 @@ Worker* createWorker(const std::string& name,
872
872
  name, env, callback, database, priority, std::forward<T1>(execute), std::forward<T2>(onOk));
873
873
  }
874
874
 
875
+ template <typename State, typename T1, typename T2>
876
+ void runWorker(const std::string& name,
877
+ napi_env env,
878
+ napi_value callback,
879
+ Database* database,
880
+ bool priority,
881
+ T1&& execute,
882
+ T2&& onOk) {
883
+ auto worker = new GenericWorker<State, typename std::decay<T1>::type, typename std::decay<T2>::type>(
884
+ name, env, callback, database, priority, std::forward<T1>(execute), std::forward<T2>(onOk));
885
+ worker->Queue(env);
886
+ }
887
+
875
888
  /**
876
889
  * Hook for when the environment exits. This hook will be called after
877
890
  * already-scheduled napi_async_work items have finished, which gives us
@@ -1139,29 +1152,26 @@ NAPI_METHOD(db_open) {
1139
1152
 
1140
1153
  auto callback = argv[3];
1141
1154
 
1142
- struct State {
1143
- std::vector<rocksdb::ColumnFamilyHandle*> handles;
1144
- };
1145
- auto worker = createWorker<State>(
1155
+ runWorker<std::vector<rocksdb::ColumnFamilyHandle*>>(
1146
1156
  "leveldown.open", env, callback, database, false,
1147
- [=](auto& state, auto& database) -> rocksdb::Status {
1157
+ [=](auto& handles, auto& database) -> rocksdb::Status {
1148
1158
  rocksdb::DB* db = nullptr;
1149
1159
  const auto status = descriptors.empty()
1150
1160
  ? rocksdb::DB::Open(dbOptions, location, &db)
1151
- : rocksdb::DB::Open(dbOptions, location, descriptors, &state.handles, &db);
1161
+ : rocksdb::DB::Open(dbOptions, location, descriptors, &handles, &db);
1152
1162
  database.db_.reset(db);
1153
1163
  return status;
1154
1164
  },
1155
- [=](auto& state, napi_env env, napi_value callback) -> napi_status {
1165
+ [=](auto& handles, napi_env env, napi_value callback) -> napi_status {
1156
1166
  napi_value argv[2];
1157
1167
  NAPI_STATUS_RETURN(napi_get_null(env, &argv[0]));
1158
1168
 
1159
- const auto size = state.handles.size();
1169
+ const auto size = handles.size();
1160
1170
  NAPI_STATUS_RETURN(napi_create_object(env, &argv[1]));
1161
1171
 
1162
1172
  for (size_t n = 0; n < size; ++n) {
1163
1173
  ColumnFamily column;
1164
- column.handle = state.handles[n];
1174
+ column.handle = handles[n];
1165
1175
  column.descriptor = descriptors[n];
1166
1176
  NAPI_STATUS_RETURN(napi_create_external(env, column.handle, nullptr, nullptr, &column.val));
1167
1177
  NAPI_STATUS_RETURN(napi_create_reference(env, column.val, 1, &column.ref));
@@ -1174,8 +1184,6 @@ NAPI_METHOD(db_open) {
1174
1184
  return CallFunction(env, callback, 2, argv);
1175
1185
  });
1176
1186
 
1177
- worker->Queue(env);
1178
-
1179
1187
  return 0;
1180
1188
  }
1181
1189
 
@@ -1270,14 +1278,9 @@ NAPI_METHOD(updates_next) {
1270
1278
 
1271
1279
  auto callback = argv[1];
1272
1280
 
1273
- auto result = std::make_shared<rocksdb::BatchResult>();
1274
-
1275
- struct State {
1276
- rocksdb::BatchResult batchResult;
1277
- };
1278
- auto worker = createWorker<State>(
1281
+ runWorker<rocksdb::BatchResult>(
1279
1282
  "leveldown.updates.next", env, callback, updates->database_, true,
1280
- [=](auto& state, auto& database) -> rocksdb::Status {
1283
+ [=](auto& batchResult, auto& database) -> rocksdb::Status {
1281
1284
  if (!updates->iterator_) {
1282
1285
  rocksdb::TransactionLogIterator::ReadOptions options;
1283
1286
  const auto status = database.db_->GetUpdatesSince(updates->start_, &updates->iterator_, options);
@@ -1292,32 +1295,27 @@ NAPI_METHOD(updates_next) {
1292
1295
  return updates->iterator_->status();
1293
1296
  }
1294
1297
 
1295
- state.batchResult = updates->iterator_->GetBatch();
1298
+ batchResult = updates->iterator_->GetBatch();
1296
1299
 
1297
1300
  return rocksdb::Status::OK();
1298
1301
  },
1299
- [=](auto& state, napi_env env, napi_value callback) -> napi_status {
1302
+ [=](auto& batchResult, napi_env env, napi_value callback) -> napi_status {
1300
1303
  napi_value argv[5];
1301
1304
 
1302
1305
  NAPI_STATUS_RETURN(napi_get_null(env, &argv[0]));
1303
1306
 
1304
- if (!state.batchResult.writeBatchPtr) {
1307
+ if (!batchResult.writeBatchPtr) {
1305
1308
  return CallFunction(env, callback, 1, argv);
1306
1309
  }
1307
1310
 
1308
- auto batch = std::move(state.batchResult.writeBatchPtr);
1309
-
1310
- NAPI_STATUS_RETURN(updates->Iterate(env, *batch, &argv[1]));
1311
-
1312
- NAPI_STATUS_RETURN(napi_create_int64(env, state.batchResult.sequence, &argv[2]));
1313
-
1314
- NAPI_STATUS_RETURN(napi_create_int64(env, batch->Count(), &argv[3]));
1311
+ NAPI_STATUS_RETURN(updates->Iterate(env, *batchResult.writeBatchPtr, &argv[1]));
1315
1312
 
1313
+ NAPI_STATUS_RETURN(napi_create_int64(env, batchResult.sequence, &argv[2]));
1314
+ NAPI_STATUS_RETURN(napi_create_int64(env, batchResult.writeBatchPtr->Count(), &argv[3]));
1316
1315
  NAPI_STATUS_RETURN(napi_create_int64(env, updates->start_, &argv[4]));
1317
1316
 
1318
1317
  return CallFunction(env, callback, 5, argv);
1319
1318
  });
1320
- worker->Queue(env);
1321
1319
 
1322
1320
  return 0;
1323
1321
  }
@@ -1365,14 +1363,9 @@ NAPI_METHOD(db_get_many) {
1365
1363
  auto snapshot = std::shared_ptr<const rocksdb::Snapshot>(
1366
1364
  database->db_->GetSnapshot(), [database](auto ptr) { database->db_->ReleaseSnapshot(ptr); });
1367
1365
 
1368
- struct State {
1369
- std::vector<rocksdb::PinnableSlice> values;
1370
- std::vector<rocksdb::Status> statuses;
1371
- };
1372
-
1373
- auto worker = createWorker<State>(
1366
+ runWorker<std::vector<rocksdb::PinnableSlice>>(
1374
1367
  "leveldown.get.many", env, callback, database, true,
1375
- [=, keys = std::move(keys)](auto& state, Database& db) -> rocksdb::Status {
1368
+ [=, keys = std::move(keys)](auto& values, Database& db) -> rocksdb::Status {
1376
1369
  rocksdb::ReadOptions readOptions;
1377
1370
  readOptions.fill_cache = fillCache;
1378
1371
  readOptions.snapshot = snapshot.get();
@@ -1384,32 +1377,33 @@ NAPI_METHOD(db_get_many) {
1384
1377
  for (const auto& key : keys) {
1385
1378
  keys2.emplace_back(key);
1386
1379
  }
1387
-
1388
- state.statuses.resize(keys2.size());
1389
- state.values.resize(keys2.size());
1390
-
1391
- db.db_->MultiGet(readOptions, column, keys2.size(), keys2.data(), state.values.data(), state.statuses.data());
1392
-
1393
- for (const auto& status : state.statuses) {
1394
- if (!status.ok() && !status.IsNotFound()) {
1395
- return status;
1380
+ std::vector<rocksdb::Status> statuses;
1381
+
1382
+ statuses.resize(keys2.size());
1383
+ values.resize(keys2.size());
1384
+
1385
+ db.db_->MultiGet(readOptions, column, keys2.size(), keys2.data(), values.data(), statuses.data());
1386
+
1387
+ for (size_t idx = 0; idx < keys2.size(); idx++) {
1388
+ if (statuses[idx].IsNotFound()) {
1389
+ values[idx] = rocksdb::PinnableSlice(nullptr);
1390
+ } else if (!statuses[idx].ok()) {
1391
+ return statuses[idx];
1396
1392
  }
1397
1393
  }
1398
1394
 
1399
1395
  return rocksdb::Status::OK();
1400
1396
  },
1401
- [=](auto& state, napi_env env, napi_value callback) -> napi_status {
1397
+ [=](auto& values, napi_env env, napi_value callback) -> napi_status {
1402
1398
  napi_value argv[2];
1403
1399
  NAPI_STATUS_RETURN(napi_get_null(env, &argv[0]));
1404
1400
 
1405
- const auto size = state.values.size();
1406
-
1407
- NAPI_STATUS_RETURN(napi_create_array_with_length(env, size, &argv[1]));
1401
+ NAPI_STATUS_RETURN(napi_create_array_with_length(env, values.size(), &argv[1]));
1408
1402
 
1409
- for (size_t idx = 0; idx < size; idx++) {
1403
+ for (size_t idx = 0; idx < values.size(); idx++) {
1410
1404
  napi_value element;
1411
- if (state.statuses[idx].ok()) {
1412
- NAPI_STATUS_RETURN(Convert(env, &state.values[idx], valueAsBuffer, element));
1405
+ if (values[idx].GetSelf()) {
1406
+ NAPI_STATUS_RETURN(Convert(env, &values[idx], valueAsBuffer, element));
1413
1407
  } else {
1414
1408
  NAPI_STATUS_RETURN(napi_get_undefined(env, &element));
1415
1409
  }
@@ -1419,8 +1413,6 @@ NAPI_METHOD(db_get_many) {
1419
1413
  return CallFunction(env, callback, 2, argv);
1420
1414
  });
1421
1415
 
1422
- worker->Queue(env);
1423
-
1424
1416
  return 0;
1425
1417
  }
1426
1418
 
@@ -1644,7 +1636,7 @@ NAPI_METHOD(iterator_nextv) {
1644
1636
  bool finished = false;
1645
1637
  };
1646
1638
 
1647
- auto worker = createWorker<State>(
1639
+ runWorker<State>(
1648
1640
  std::string("leveldown.iterator.next"), env, callback, iterator->database_, true,
1649
1641
  [=](auto& state, Database& db) -> rocksdb::Status {
1650
1642
  if (!iterator->DidSeek()) {
@@ -1712,7 +1704,6 @@ NAPI_METHOD(iterator_nextv) {
1712
1704
 
1713
1705
  return CallFunction(env, callback, 3, argv);
1714
1706
  });
1715
- worker->Queue(env);
1716
1707
 
1717
1708
  return 0;
1718
1709
  }
package/index.js CHANGED
@@ -341,6 +341,29 @@ class RocksLevel extends AbstractLevel {
341
341
  options.signal?.addEventListener('abort', onAbort)
342
342
  this.on('closing', onAbort)
343
343
 
344
+ // HACK: https://github.com/facebook/rocksdb/issues/10476
345
+ async function* _updates (options) {
346
+ let first = true
347
+ for await (const update of this[kUpdates](options)) {
348
+ if (first) {
349
+ if (update.sequence > options.since) {
350
+ this.emit('warning', `Invalid sequence ${update.sequence} > ${options.since}. Starting from 0.`)
351
+ first = null
352
+ break
353
+ } else {
354
+ first = false
355
+ }
356
+ }
357
+ yield update
358
+ }
359
+
360
+ if (first === null) {
361
+ for await (const update of this[kUpdates]({ ...options, since: 0 })) {
362
+ yield update
363
+ }
364
+ }
365
+ }
366
+
344
367
  try {
345
368
  let since = options.since
346
369
 
@@ -377,7 +400,7 @@ class RocksLevel extends AbstractLevel {
377
400
 
378
401
  try {
379
402
  if (since <= this.sequence) {
380
- for await (const update of this[kUpdates](options)) {
403
+ for await (const update of _updates(options)) {
381
404
  if (ac.signal.aborted) {
382
405
  throw new AbortError()
383
406
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/rocksdb",
3
- "version": "7.0.56",
3
+ "version": "7.0.57",
4
4
  "description": "A low-level Node.js RocksDB binding",
5
5
  "license": "MIT",
6
6
  "main": "index.js",