@nxtedition/rocksdb 15.3.0 → 15.4.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.
@@ -28,7 +28,8 @@
28
28
  "Bash(git rm:*)",
29
29
  "WebFetch(domain:raw.githubusercontent.com)",
30
30
  "Bash(git log:*)",
31
- "WebFetch(domain:github.com)"
31
+ "WebFetch(domain:github.com)",
32
+ "Bash(npm run rebuild:*)"
32
33
  ]
33
34
  }
34
35
  }
package/binding.cc CHANGED
@@ -812,7 +812,7 @@ static void FinalizeDatabase(napi_env env, void* data, void* hint) {
812
812
  }
813
813
 
814
814
  NAPI_METHOD(db_init) {
815
- NAPI_ARGV(1);
815
+ NAPI_ARGV(2);
816
816
 
817
817
  Database* database = nullptr;
818
818
 
@@ -1024,7 +1024,35 @@ napi_status InitOptions(napi_env env, T& columnOptions, const U& options) {
1024
1024
  tableOptions.decouple_partitioned_filters = true;
1025
1025
 
1026
1026
  std::shared_ptr<rocksdb::Cache> cache;
1027
+
1027
1028
  {
1029
+ napi_value cacheValue;
1030
+ NAPI_STATUS_RETURN(napi_get_named_property(env, options, "cache", &cacheValue));
1031
+
1032
+ napi_valuetype cacheType;
1033
+ NAPI_STATUS_RETURN(napi_typeof(env, cacheValue, &cacheType));
1034
+
1035
+ if (cacheType == napi_object) {
1036
+ napi_value handleValue;
1037
+ NAPI_STATUS_RETURN(napi_get_named_property(env, cacheValue, "handle", &handleValue));
1038
+
1039
+ bool lossless;
1040
+ int64_t ptr;
1041
+ NAPI_STATUS_RETURN(napi_get_value_bigint_int64(env, handleValue, &ptr, &lossless));
1042
+
1043
+ cache = *reinterpret_cast<std::shared_ptr<rocksdb::Cache>*>(ptr);
1044
+ } else if (cacheType == napi_bigint) {
1045
+ bool lossless;
1046
+ int64_t ptr;
1047
+ NAPI_STATUS_RETURN(napi_get_value_bigint_int64(env, cacheValue, &ptr, &lossless));
1048
+
1049
+ cache = *reinterpret_cast<std::shared_ptr<rocksdb::Cache>*>(ptr);
1050
+ } else if (cacheType != napi_undefined && cacheType != napi_null) {
1051
+ return napi_invalid_arg;
1052
+ }
1053
+ }
1054
+
1055
+ if (!cache) {
1028
1056
  uint32_t cacheSize = 8 << 20;
1029
1057
  double compressedRatio = 0.0;
1030
1058
 
@@ -1032,7 +1060,7 @@ napi_status InitOptions(napi_env env, T& columnOptions, const U& options) {
1032
1060
  NAPI_STATUS_RETURN(GetProperty(env, options, "cacheCompressedRatio", compressedRatio));
1033
1061
 
1034
1062
  if (cacheSize == 0) {
1035
- cache = nullptr;
1063
+ // Do nothing...
1036
1064
  } else if (compressedRatio > 0.0) {
1037
1065
  rocksdb::TieredCacheOptions options;
1038
1066
  options.cache_type = rocksdb::PrimaryCacheType::kCacheTypeHCC;
@@ -1398,10 +1426,6 @@ NAPI_METHOD(db_open) {
1398
1426
  return 0;
1399
1427
  }
1400
1428
 
1401
- napi_value noop_callback(napi_env env, napi_callback_info info) {
1402
- return 0;
1403
- }
1404
-
1405
1429
  NAPI_METHOD(db_close) {
1406
1430
  NAPI_ARGV(2);
1407
1431
 
@@ -2248,6 +2272,32 @@ NAPI_METHOD(db_compact_range) {
2248
2272
  return 0;
2249
2273
  }
2250
2274
 
2275
+ NAPI_METHOD(cache_init) {
2276
+ NAPI_ARGV(1);
2277
+
2278
+ size_t capacity = 32 * 1024 * 1024; // 32 MiB
2279
+ NAPI_STATUS_THROWS(GetProperty(env, argv[0], "capacity", capacity));
2280
+
2281
+ auto cache = new std::shared_ptr<rocksdb::Cache>(rocksdb::HyperClockCacheOptions(capacity, 0).MakeSharedCache());
2282
+
2283
+ napi_value result;
2284
+ NAPI_STATUS_THROWS(napi_create_external(env, cache, Finalize<std::shared_ptr<rocksdb::Cache>>, cache, &result));
2285
+
2286
+ return result;
2287
+ }
2288
+
2289
+ NAPI_METHOD(cache_get_handle) {
2290
+ NAPI_ARGV(1);
2291
+
2292
+ std::shared_ptr<rocksdb::Cache>* cache;
2293
+ NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&cache)));
2294
+
2295
+ napi_value result;
2296
+ NAPI_STATUS_THROWS(napi_create_bigint_int64(env, reinterpret_cast<intptr_t>(cache), &result));
2297
+
2298
+ return result;
2299
+ }
2300
+
2251
2301
  NAPI_INIT() {
2252
2302
  NAPI_EXPORT_FUNCTION(db_init);
2253
2303
  NAPI_EXPORT_FUNCTION(db_open);
@@ -2286,4 +2336,7 @@ NAPI_INIT() {
2286
2336
  NAPI_EXPORT_FUNCTION(batch_merge);
2287
2337
  NAPI_EXPORT_FUNCTION(batch_count);
2288
2338
  NAPI_EXPORT_FUNCTION(batch_iterate);
2339
+
2340
+ NAPI_EXPORT_FUNCTION(cache_init);
2341
+ NAPI_EXPORT_FUNCTION(cache_get_handle);
2289
2342
  }
package/cache.js ADDED
@@ -0,0 +1,17 @@
1
+ 'use strict'
2
+
3
+ const binding = require('./binding')
4
+
5
+ const kCacheContext = Symbol('cacheContext')
6
+
7
+ class RocksCache {
8
+ constructor (optionsOrHandle = {}) {
9
+ this[kCacheContext] = binding.cache_init(optionsOrHandle)
10
+ }
11
+
12
+ get handle () {
13
+ return binding.cache_get_handle(this[kCacheContext])
14
+ }
15
+ }
16
+
17
+ exports.RocksCache = RocksCache
package/chained-batch.js CHANGED
@@ -23,6 +23,10 @@ class ChainedBatch extends AbstractChainedBatch {
23
23
  this[kBusy] = false
24
24
  }
25
25
 
26
+ [Symbol.asyncDispose] () {
27
+ return this.close()
28
+ }
29
+
26
30
  get length () {
27
31
  assert(this[kBatchContext])
28
32
 
@@ -109,10 +113,15 @@ class ChainedBatch extends AbstractChainedBatch {
109
113
  callback = fromCallback(callback, kPromise)
110
114
 
111
115
  this[kBusy] = true
112
- binding.batch_write(this[kDbContext], this[kBatchContext], options ?? EMPTY, (err) => {
116
+ try {
117
+ binding.batch_write(this[kDbContext], this[kBatchContext], options ?? EMPTY, (err) => {
118
+ this[kBusy] = false
119
+ callback(err)
120
+ })
121
+ } catch (err) {
113
122
  this[kBusy] = false
114
- callback(err)
115
- })
123
+ process.nextTick(callback, err)
124
+ }
116
125
 
117
126
  return callback[kPromise]
118
127
  }
package/index.js CHANGED
@@ -5,6 +5,7 @@ const { AbstractLevel } = require('abstract-level')
5
5
  const ModuleError = require('module-error')
6
6
  const binding = require('./binding')
7
7
  const { ChainedBatch } = require('./chained-batch')
8
+ const { RocksCache } = require('./cache')
8
9
  const { Iterator } = require('./iterator')
9
10
  const fs = require('node:fs')
10
11
  const assert = require('node:assert')
@@ -17,10 +18,10 @@ const kPendingClose = Symbol('pendingClose')
17
18
 
18
19
  const { kRef, kUnref } = require('./util')
19
20
 
20
- const kEmpty = {}
21
+ const kEmpty = Object.freeze({})
21
22
 
22
23
  class RocksLevel extends AbstractLevel {
23
- constructor (locationOrHandle, options) {
24
+ constructor (locationOrHandle, { ...options } = {}) {
24
25
  super({
25
26
  encodings: {
26
27
  buffer: true,
@@ -40,6 +41,10 @@ class RocksLevel extends AbstractLevel {
40
41
  this[kPendingClose] = null
41
42
  }
42
43
 
44
+ [Symbol.asyncDispose] () {
45
+ return this.close()
46
+ }
47
+
43
48
  static async open (...args) {
44
49
  const db = new this(...args)
45
50
  await db.open()
@@ -89,7 +94,7 @@ class RocksLevel extends AbstractLevel {
89
94
 
90
95
  if (options.createIfMissing) {
91
96
  fs.mkdir(this.location, { recursive: true }, (err) => {
92
- if (err) {
97
+ if (err && err.code !== 'EEXIST') {
93
98
  callback(err)
94
99
  } else {
95
100
  doOpen()
@@ -156,6 +161,10 @@ class RocksLevel extends AbstractLevel {
156
161
  }
157
162
 
158
163
  _getManyAsync (keys, options, callback) {
164
+ if (keys.some(key => typeof key === 'string')) {
165
+ keys = keys.map(key => typeof key === 'string' ? Buffer.from(key) : key)
166
+ }
167
+
159
168
  callback = fromCallback(callback, kPromise)
160
169
 
161
170
  try {
@@ -169,6 +178,7 @@ class RocksLevel extends AbstractLevel {
169
178
  }
170
179
  })
171
180
  } catch (err) {
181
+ this[kUnref]()
172
182
  process.nextTick(callback, err)
173
183
  }
174
184
 
@@ -339,3 +349,4 @@ class RocksLevel extends AbstractLevel {
339
349
  }
340
350
 
341
351
  exports.RocksLevel = RocksLevel
352
+ exports.RocksCache = RocksCache
package/iterator.js CHANGED
@@ -16,7 +16,7 @@ const kFirst = Symbol('first')
16
16
  const kPosition = Symbol('position')
17
17
  const kBusy = Symbol('busy')
18
18
 
19
- const kEmpty = []
19
+ const kEmpty = Object.freeze([])
20
20
 
21
21
  class Iterator extends AbstractIterator {
22
22
  constructor (db, context, options) {
@@ -32,6 +32,10 @@ class Iterator extends AbstractIterator {
32
32
  this[kBusy] = false
33
33
  }
34
34
 
35
+ [Symbol.asyncDispose] () {
36
+ return this.close()
37
+ }
38
+
35
39
  _seek (target) {
36
40
  this._seekSync(target)
37
41
  }
@@ -132,6 +136,8 @@ class Iterator extends AbstractIterator {
132
136
  this[kPosition] = 0
133
137
 
134
138
  try {
139
+ this[kDB][kRef]()
140
+ this[kBusy] = true
135
141
  binding.iterator_seek(this[kContext], target, (err) => {
136
142
  this[kBusy] = false
137
143
  this[kDB][kUnref]()
@@ -142,9 +148,9 @@ class Iterator extends AbstractIterator {
142
148
  callback(null)
143
149
  }
144
150
  })
145
- this[kDB][kRef]()
146
- this[kBusy] = true
147
151
  } catch (err) {
152
+ this[kBusy] = false
153
+ this[kDB][kUnref]()
148
154
  process.nextTick(callback, err)
149
155
  }
150
156
 
@@ -175,6 +181,8 @@ class Iterator extends AbstractIterator {
175
181
  if (this[kFinished]) {
176
182
  process.nextTick(callback, null, { rows: [], finished: true })
177
183
  } else {
184
+ this[kDB][kRef]()
185
+ this[kBusy] = true
178
186
  binding.iterator_nextv(this[kContext], size, options, (err, result) => {
179
187
  this[kBusy] = false
180
188
  this[kDB][kUnref]()
@@ -186,10 +194,10 @@ class Iterator extends AbstractIterator {
186
194
  callback(null, result)
187
195
  }
188
196
  })
189
- this[kBusy] = true
190
- this[kDB][kRef]()
191
197
  }
192
198
  } catch (err) {
199
+ this[kBusy] = false
200
+ this[kDB][kUnref]()
193
201
  process.nextTick(callback, err)
194
202
  }
195
203
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/rocksdb",
3
- "version": "15.3.0",
3
+ "version": "15.4.1",
4
4
  "description": "A low-level Node.js RocksDB binding",
5
5
  "license": "MIT",
6
6
  "main": "index.js",