rocksdb-native 3.8.1 → 3.9.1

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.
package/CMakeLists.txt CHANGED
@@ -1,4 +1,4 @@
1
- cmake_minimum_required(VERSION 3.31)
1
+ cmake_minimum_required(VERSION 4.0)
2
2
 
3
3
  find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4
4
  find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
@@ -9,8 +9,8 @@ project(rocksdb_native C CXX)
9
9
 
10
10
  bare_target(target)
11
11
 
12
- fetch_package("github:holepunchto/librocksdb#ac350df")
13
- fetch_package("github:holepunchto/libjstl#34a7894")
12
+ fetch_package("github:holepunchto/librocksdb#3aaa9dc")
13
+ fetch_package("github:holepunchto/libjstl#098664c")
14
14
 
15
15
  add_bare_module(rocksdb_native_bare)
16
16
 
package/README.md CHANGED
@@ -6,6 +6,9 @@
6
6
  npm i rocksdb-native
7
7
  ```
8
8
 
9
+ > [!IMPORTANT]
10
+ > On Linux `libatomic` must be installed as well.
11
+
9
12
  ## Usage
10
13
 
11
14
  ```js
package/binding.cc CHANGED
@@ -24,6 +24,7 @@ using cb_on_iterator_read_t = js_function_t<
24
24
  std::vector<js_arraybuffer_t>,
25
25
  std::vector<js_arraybuffer_t>>;
26
26
  using cb_on_compact_range_t = js_function_t<void, js_receiver_t, std::optional<js_string_t>>;
27
+ using cb_on_approximate_size_t = js_function_t<void, js_receiver_t, std::optional<js_string_t>, uint64_t>;
27
28
  }; // namespace
28
29
 
29
30
  struct rocksdb_native_column_family_t {
@@ -147,6 +148,14 @@ struct rocksdb_native_compact_range_t {
147
148
  js_persistent_t<cb_on_compact_range_t> on_compact_range;
148
149
  };
149
150
 
151
+ struct rocksdb_native_approximate_size_t {
152
+ rocksdb_approximate_size_t handle;
153
+
154
+ js_env_t *env;
155
+ js_persistent_t<js_receiver_t> ctx;
156
+ js_persistent_t<cb_on_approximate_size_t> on_approximate_size;
157
+ };
158
+
150
159
  static void
151
160
  rocksdb_native__on_free(js_env_t *env, char *data) {
152
161
  free(data);
@@ -319,7 +328,11 @@ rocksdb_native_init(
319
328
  int32_t max_background_jobs,
320
329
  uint64_t bytes_per_sync,
321
330
  int32_t max_open_files,
322
- bool use_direct_reads
331
+ bool use_direct_reads,
332
+ bool avoid_unnecessary_blocking_io,
333
+ bool skip_stats_update_on_db_open,
334
+ bool use_direct_io_for_flush_and_compaction,
335
+ int32_t max_file_opening_threads
323
336
  ) {
324
337
  int err;
325
338
 
@@ -345,7 +358,11 @@ rocksdb_native_init(
345
358
  max_background_jobs,
346
359
  bytes_per_sync,
347
360
  max_open_files,
348
- use_direct_reads
361
+ use_direct_reads,
362
+ avoid_unnecessary_blocking_io,
363
+ skip_stats_update_on_db_open,
364
+ use_direct_io_for_flush_and_compaction,
365
+ max_file_opening_threads
349
366
  };
350
367
 
351
368
  err = rocksdb_init(loop, &db->handle);
@@ -634,7 +651,10 @@ rocksdb_native_column_family_init(
634
651
  int32_t bloom_before_level,
635
652
  uint32_t top_level_index_pinning_tier,
636
653
  uint32_t partition_pinning_tier,
637
- uint32_t unpartitioned_pinning_tier
654
+ uint32_t unpartitioned_pinning_tier,
655
+ bool optimize_filters_for_hits,
656
+ int32_t num_levels,
657
+ int32_t max_write_buffer_number
638
658
  ) {
639
659
  int err;
640
660
 
@@ -689,6 +709,9 @@ rocksdb_native_column_family_init(
689
709
  rocksdb_pinning_tier_t(top_level_index_pinning_tier),
690
710
  rocksdb_pinning_tier_t(partition_pinning_tier),
691
711
  rocksdb_pinning_tier_t(unpartitioned_pinning_tier),
712
+ optimize_filters_for_hits,
713
+ num_levels,
714
+ max_write_buffer_number
692
715
  }
693
716
  };
694
717
 
@@ -1178,6 +1201,8 @@ rocksdb_native_read(
1178
1201
  js_arraybuffer_span_of_t<rocksdb_native_read_batch_t, 1> req,
1179
1202
  js_array_t operations,
1180
1203
  std::optional<js_arraybuffer_t> snapshot,
1204
+ bool async_io,
1205
+ bool fill_cache,
1181
1206
  js_receiver_t ctx,
1182
1207
  cb_on_read_t on_read
1183
1208
  ) {
@@ -1233,6 +1258,8 @@ rocksdb_native_read(
1233
1258
 
1234
1259
  rocksdb_read_options_t options = {
1235
1260
  .version = 0,
1261
+ .async_io = async_io,
1262
+ .fill_cache = fill_cache
1236
1263
  };
1237
1264
 
1238
1265
  if (snapshot) {
@@ -1615,6 +1642,102 @@ rocksdb_native_compact_range(
1615
1642
  return handle;
1616
1643
  }
1617
1644
 
1645
+ static void
1646
+ rocksdb_native__on_approximate_size(rocksdb_approximate_size_t *handle, int status) {
1647
+ int err;
1648
+
1649
+ assert(status == 0);
1650
+
1651
+ rocksdb_native_approximate_size_t *req = (rocksdb_native_approximate_size_t *) handle->data;
1652
+
1653
+ rocksdb_native_t *db = (rocksdb_native_t *) req->handle.req.db;
1654
+
1655
+ js_env_t *env = req->env;
1656
+
1657
+ if (db->exiting) {
1658
+ req->on_approximate_size.reset();
1659
+ req->ctx.reset();
1660
+ } else {
1661
+ js_handle_scope_t *scope;
1662
+ err = js_open_handle_scope(env, &scope);
1663
+ assert(err == 0);
1664
+
1665
+ std::optional<js_string_t> error;
1666
+
1667
+ if (req->handle.error) {
1668
+ err = js_create_string(env, req->handle.error, error.emplace());
1669
+ assert(err == 0);
1670
+ }
1671
+
1672
+ js_receiver_t ctx;
1673
+ err = js_get_reference_value(env, req->ctx, ctx);
1674
+ assert(err == 0);
1675
+
1676
+ cb_on_approximate_size_t cb;
1677
+ err = js_get_reference_value(env, req->on_approximate_size, cb);
1678
+ assert(err == 0);
1679
+
1680
+ req->on_approximate_size.reset();
1681
+ req->ctx.reset();
1682
+
1683
+ js_call_function_with_checkpoint(env, cb, ctx, error, req->handle.result);
1684
+
1685
+ err = js_close_handle_scope(env, scope);
1686
+ assert(err == 0);
1687
+ }
1688
+ }
1689
+
1690
+ static js_arraybuffer_t
1691
+ rocksdb_native_approximate_size(
1692
+ js_env_t *env,
1693
+ js_arraybuffer_span_of_t<rocksdb_native_t, 1> db,
1694
+ js_arraybuffer_span_of_t<rocksdb_native_column_family_t, 1> column_family,
1695
+ js_typedarray_t<> start,
1696
+ js_typedarray_t<> end,
1697
+ bool include_memtables,
1698
+ bool include_files,
1699
+ double error_margin,
1700
+ js_receiver_t ctx,
1701
+ cb_on_approximate_size_t on_approximate_size
1702
+ ) {
1703
+ int err;
1704
+
1705
+ js_arraybuffer_t handle;
1706
+
1707
+ rocksdb_native_approximate_size_t *req;
1708
+ err = js_create_arraybuffer(env, req, handle);
1709
+ assert(err == 0);
1710
+
1711
+ req->env = env;
1712
+ req->handle.data = (void *) req;
1713
+
1714
+ err = js_create_reference(env, ctx, req->ctx);
1715
+ assert(err == 0);
1716
+
1717
+ err = js_create_reference(env, on_approximate_size, req->on_approximate_size);
1718
+ assert(err == 0);
1719
+
1720
+ rocksdb_approximate_size_options_t options = {
1721
+ .version = 0,
1722
+ .include_memtables = include_memtables,
1723
+ .include_files = include_files,
1724
+ .files_size_error_margin = error_margin,
1725
+ };
1726
+
1727
+ rocksdb_slice_t start_slice;
1728
+ err = js_get_typedarray_info(env, start, start_slice.data, start_slice.len);
1729
+ assert(err == 0);
1730
+
1731
+ rocksdb_slice_t end_slice;
1732
+ err = js_get_typedarray_info(env, end, end_slice.data, end_slice.len);
1733
+ assert(err == 0);
1734
+
1735
+ err = rocksdb_approximate_size(&db->handle, &req->handle, column_family->handle, start_slice, end_slice, &options, rocksdb_native__on_approximate_size);
1736
+ assert(err == 0);
1737
+
1738
+ return handle;
1739
+ }
1740
+
1618
1741
  static js_value_t *
1619
1742
  rocksdb_native_exports(js_env_t *env, js_value_t *exports) {
1620
1743
  int err;
@@ -1652,6 +1775,7 @@ rocksdb_native_exports(js_env_t *env, js_value_t *exports) {
1652
1775
  V("snapshotDestroy", rocksdb_native_snapshot_destroy)
1653
1776
 
1654
1777
  V("compactRange", rocksdb_native_compact_range)
1778
+ V("approximateSize", rocksdb_native_approximate_size)
1655
1779
  #undef V
1656
1780
 
1657
1781
  #define V(name, n) \
package/index.js CHANGED
@@ -189,6 +189,10 @@ class RocksDB {
189
189
  await this._state.compactRange(this, start, end, opts)
190
190
  }
191
191
 
192
+ async approximateSize(start, end, opts = {}) {
193
+ return this._state.approximateSize(this, start, end, opts)
194
+ }
195
+
192
196
  _ref() {
193
197
  if (this._snapshot) this._snapshot.ref()
194
198
  this._state.handles.inc()
@@ -209,6 +213,5 @@ exports.BloomFilterPolicy = BloomFilterPolicy
209
213
  exports.RibbonFilterPolicy = RibbonFilterPolicy
210
214
 
211
215
  function maybeClosed(db) {
212
- if (db._state.closing || db._index === -1)
213
- throw new Error('RocksDB session is closed')
216
+ if (db._state.closing || db._index === -1) throw new Error('RocksDB session is closed')
214
217
  }
package/lib/batch.js CHANGED
@@ -168,6 +168,15 @@ class RocksDBBatch {
168
168
  }
169
169
 
170
170
  exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
171
+ constructor(db, opts = {}) {
172
+ super(db, opts)
173
+
174
+ const { asyncIO = false, fillCache = true } = opts
175
+
176
+ this._asyncIO = asyncIO
177
+ this._fillCache = fillCache
178
+ }
179
+
171
180
  _init() {
172
181
  this._handle = binding.readInit()
173
182
  this._buffer = binding.readBuffer(this._handle, this._capacity)
@@ -190,6 +199,8 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
190
199
  this._handle,
191
200
  this._operations,
192
201
  this._db._snapshot ? this._db._snapshot._handle : undefined,
202
+ this._asyncIO,
203
+ this._fillCache,
193
204
  this,
194
205
  this._onread
195
206
  )
@@ -213,9 +224,7 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
213
224
 
214
225
  promise.reject(new Error(err))
215
226
  } else {
216
- promise.resolve(
217
- values[i] ? this._decodeValue(Buffer.from(values[i])) : null
218
- )
227
+ promise.resolve(values[i] ? this._decodeValue(Buffer.from(values[i])) : null)
219
228
  }
220
229
  }
221
230
 
@@ -227,9 +236,7 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
227
236
 
228
237
  const promise = new Promise(this._enqueuePromise)
229
238
 
230
- this._operations.push(
231
- new RocksDBGet(this._encodeKey(key), this._db._columnFamily)
232
- )
239
+ this._operations.push(new RocksDBGet(this._encodeKey(key), this._db._columnFamily))
233
240
 
234
241
  this._resize()
235
242
 
@@ -259,13 +266,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
259
266
  if (this._destroyed) return
260
267
 
261
268
  try {
262
- binding.write(
263
- this._db._state._handle,
264
- this._handle,
265
- this._operations,
266
- this,
267
- this._onwrite
268
- )
269
+ binding.write(this._db._state._handle, this._handle, this._operations, this, this._onwrite)
269
270
  } catch (err) {
270
271
  this._db._state.io.dec()
271
272
  throw err
@@ -297,11 +298,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
297
298
  const promise = new Promise(this._enqueuePromise)
298
299
 
299
300
  this._operations.push(
300
- new RocksDBPut(
301
- this._encodeKey(key),
302
- this._encodeValue(value),
303
- this._db._columnFamily
304
- )
301
+ new RocksDBPut(this._encodeKey(key), this._encodeValue(value), this._db._columnFamily)
305
302
  )
306
303
 
307
304
  this._resize()
@@ -313,11 +310,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
313
310
  if (this._request) throw new Error('Request already in progress')
314
311
 
315
312
  this._operations.push(
316
- new RocksDBPut(
317
- this._encodeKey(key),
318
- this._encodeValue(value),
319
- this._db._columnFamily
320
- )
313
+ new RocksDBPut(this._encodeKey(key), this._encodeValue(value), this._db._columnFamily)
321
314
  )
322
315
 
323
316
  this._promises.push(null)
@@ -330,9 +323,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
330
323
 
331
324
  const promise = new Promise(this._enqueuePromise)
332
325
 
333
- this._operations.push(
334
- new RocksDBDelete(this._encodeKey(key), this._db._columnFamily)
335
- )
326
+ this._operations.push(new RocksDBDelete(this._encodeKey(key), this._db._columnFamily))
336
327
 
337
328
  this._resize()
338
329
 
@@ -342,9 +333,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
342
333
  tryDelete(key) {
343
334
  if (this._request) throw new Error('Request already in progress')
344
335
 
345
- this._operations.push(
346
- new RocksDBDelete(this._encodeKey(key), this._db._columnFamily)
347
- )
336
+ this._operations.push(new RocksDBDelete(this._encodeKey(key), this._db._columnFamily))
348
337
 
349
338
  this._promises.push(null)
350
339
 
@@ -357,11 +346,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
357
346
  const promise = new Promise(this._enqueuePromise)
358
347
 
359
348
  this._operations.push(
360
- new RocksDBDeleteRange(
361
- this._encodeKey(start),
362
- this._encodeKey(end),
363
- this._db._columnFamily
364
- )
349
+ new RocksDBDeleteRange(this._encodeKey(start), this._encodeKey(end), this._db._columnFamily)
365
350
  )
366
351
 
367
352
  this._resize()
@@ -373,11 +358,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
373
358
  if (this._request) throw new Error('Request already in progress')
374
359
 
375
360
  this._operations.push(
376
- new RocksDBDeleteRange(
377
- this._encodeKey(start),
378
- this._encodeKey(end),
379
- this._db._columnFamily
380
- )
361
+ new RocksDBDeleteRange(this._encodeKey(start), this._encodeKey(end), this._db._columnFamily)
381
362
  )
382
363
 
383
364
  this._promises.push(null)
@@ -19,7 +19,10 @@ class RocksDBColumnFamily {
19
19
  filterPolicy = new BloomFilterPolicy(10),
20
20
  topLevelIndexPinningTier = constants.pinningTier.ALL,
21
21
  partitionPinningTier = constants.pinningTier.ALL,
22
- unpartitionedPinningTier = constants.pinningTier.ALL
22
+ unpartitionedPinningTier = constants.pinningTier.ALL,
23
+ optimizeFiltersForHits = false,
24
+ numLevels = 7,
25
+ maxWriteBufferNumber = 2
23
26
  } = opts
24
27
 
25
28
  this._name = name
@@ -37,7 +40,10 @@ class RocksDBColumnFamily {
37
40
  filterPolicy,
38
41
  topLevelIndexPinningTier,
39
42
  partitionPinningTier,
40
- unpartitionedPinningTier
43
+ unpartitionedPinningTier,
44
+ optimizeFiltersForHits,
45
+ numLevels,
46
+ maxWriteBufferNumber
41
47
  }
42
48
 
43
49
  const filterPolicyArguments = [0, 0, 0]
@@ -71,7 +77,10 @@ class RocksDBColumnFamily {
71
77
  ...filterPolicyArguments,
72
78
  topLevelIndexPinningTier,
73
79
  partitionPinningTier,
74
- unpartitionedPinningTier
80
+ unpartitionedPinningTier,
81
+ optimizeFiltersForHits,
82
+ numLevels,
83
+ maxWriteBufferNumber
75
84
  )
76
85
  }
77
86
 
package/lib/iterator.js CHANGED
@@ -186,21 +186,18 @@ module.exports = class RocksDBIterator extends Readable {
186
186
  }
187
187
 
188
188
  _encodeKey(k) {
189
- if (this._db._keyEncoding !== null)
190
- return c.encode(this._db._keyEncoding, k)
189
+ if (this._db._keyEncoding !== null) return c.encode(this._db._keyEncoding, k)
191
190
  if (typeof k === 'string') return Buffer.from(k)
192
191
  return k
193
192
  }
194
193
 
195
194
  _decodeKey(b) {
196
- if (this._db._keyEncoding !== null)
197
- return c.decode(this._db._keyEncoding, b)
195
+ if (this._db._keyEncoding !== null) return c.decode(this._db._keyEncoding, b)
198
196
  return b
199
197
  }
200
198
 
201
199
  _decodeValue(b) {
202
- if (this._db._valueEncoding !== null)
203
- return c.decode(this._db._valueEncoding, b)
200
+ if (this._db._valueEncoding !== null) return c.decode(this._db._valueEncoding, b)
204
201
  return b
205
202
  }
206
203
  }
package/lib/state.js CHANGED
@@ -23,7 +23,11 @@ module.exports = class RocksDBState extends ReadyResource {
23
23
  maxBackgroundJobs = 6,
24
24
  bytesPerSync = 1048576,
25
25
  maxOpenFiles = -1,
26
- useDirectReads = false
26
+ useDirectReads = false,
27
+ avoidUnnecessaryBlockingIO = false,
28
+ skipStatsUpdateOnOpen = false,
29
+ useDirectIOForFlushAndCompaction = false,
30
+ maxFileOpeningThreads = 16
27
31
  } = opts
28
32
 
29
33
  this.path = path
@@ -45,9 +49,7 @@ module.exports = class RocksDBState extends ReadyResource {
45
49
 
46
50
  for (const columnFamily of columnFamilies) {
47
51
  this.columnFamilies.push(
48
- typeof columnFamily === 'string'
49
- ? new ColumnFamily(columnFamily, opts)
50
- : columnFamily
52
+ typeof columnFamily === 'string' ? new ColumnFamily(columnFamily, opts) : columnFamily
51
53
  )
52
54
  }
53
55
 
@@ -58,7 +60,11 @@ module.exports = class RocksDBState extends ReadyResource {
58
60
  maxBackgroundJobs,
59
61
  bytesPerSync,
60
62
  maxOpenFiles,
61
- useDirectReads
63
+ useDirectReads,
64
+ avoidUnnecessaryBlockingIO,
65
+ skipStatsUpdateOnOpen,
66
+ useDirectIOForFlushAndCompaction,
67
+ maxFileOpeningThreads
62
68
  )
63
69
  }
64
70
 
@@ -214,12 +220,7 @@ module.exports = class RocksDBState extends ReadyResource {
214
220
  })
215
221
 
216
222
  try {
217
- req.handle = binding.flush(
218
- this._handle,
219
- db._columnFamily._handle,
220
- req,
221
- onflush
222
- )
223
+ req.handle = binding.flush(this._handle, db._columnFamily._handle, req, onflush)
223
224
 
224
225
  await promise
225
226
  } finally {
@@ -348,6 +349,44 @@ module.exports = class RocksDBState extends ReadyResource {
348
349
  }
349
350
  }
350
351
 
352
+ async approximateSize(db, start, end, opts) {
353
+ if (this.opened === false) await this.ready()
354
+
355
+ this.io.inc()
356
+
357
+ const { includeMemtables = false, includeFiles = true, filesSizeErrorMargin = -1 } = opts
358
+
359
+ const req = { resolve: null, reject: null, handle: null }
360
+
361
+ const promise = new Promise((resolve, reject) => {
362
+ req.resolve = resolve
363
+ req.reject = reject
364
+ })
365
+
366
+ try {
367
+ req.handle = binding.approximateSize(
368
+ this._handle,
369
+ db._columnFamily._handle,
370
+ this._encodeKey(start),
371
+ this._encodeKey(end),
372
+ includeMemtables,
373
+ includeFiles,
374
+ filesSizeErrorMargin,
375
+ req,
376
+ onapproximatesize
377
+ )
378
+
379
+ return await promise
380
+ } finally {
381
+ this.io.dec()
382
+ }
383
+
384
+ function onapproximatesize(err, result) {
385
+ if (err) req.reject(new Error(err))
386
+ else req.resolve(result)
387
+ }
388
+ }
389
+
351
390
  _encodeKey(k) {
352
391
  if (this.db._keyEncoding) return c.encode(this.db._keyEncoding, k)
353
392
  if (typeof k === 'string') return Buffer.from(k)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rocksdb-native",
3
- "version": "3.8.1",
3
+ "version": "3.9.1",
4
4
  "description": "librocksdb bindings for JavaScript",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -17,10 +17,11 @@
17
17
  ],
18
18
  "addon": true,
19
19
  "scripts": {
20
+ "format": "prettier --write .",
21
+ "lint": "prettier --check .",
20
22
  "test": "npm run lint && npm run test:bare && npm run test:node",
21
23
  "test:bare": "bare test.js",
22
- "test:node": "node test.js",
23
- "lint": "prettier . --check"
24
+ "test:node": "node test.js"
24
25
  },
25
26
  "repository": {
26
27
  "type": "git",
@@ -50,7 +51,7 @@
50
51
  "cmake-bare": "^1.1.14",
51
52
  "cmake-fetch": "^1.0.1",
52
53
  "cmake-napi": "^1.0.6",
53
- "prettier": "^3.4.1",
54
- "prettier-config-standard": "^7.0.0"
54
+ "prettier": "^3.6.2",
55
+ "prettier-config-holepunch": "^2.0.0"
55
56
  }
56
57
  }