@nxtedition/rocksdb 7.0.45 → 7.0.48

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/chained-batch.js CHANGED
@@ -3,11 +3,13 @@
3
3
  const { AbstractChainedBatch } = require('abstract-level')
4
4
  const binding = require('./binding')
5
5
  const ModuleError = require('module-error')
6
+ const { fromCallback } = require('catering')
7
+
6
8
  const kWrite = Symbol('write')
7
9
  const kBatchContext = Symbol('batchContext')
8
10
  const kDbContext = Symbol('dbContext')
11
+ const kPromise = Symbol('promise')
9
12
 
10
- const NOOP = () => {}
11
13
  const EMPTY = {}
12
14
 
13
15
  class ChainedBatch extends AbstractChainedBatch {
@@ -50,7 +52,11 @@ class ChainedBatch extends AbstractChainedBatch {
50
52
  }
51
53
 
52
54
  _write (options, callback) {
53
- this[kWrite](this, this[kBatchContext], options ?? EMPTY, callback ?? NOOP)
55
+ callback = fromCallback(callback, kPromise)
56
+
57
+ this[kWrite](this, this[kBatchContext], options ?? EMPTY, callback)
58
+
59
+ return callback[kPromise]
54
60
  }
55
61
 
56
62
  _close (callback) {
package/common.js ADDED
@@ -0,0 +1,7 @@
1
+ module.exports.AbortError = class AbortError extends Error {
2
+ constructor () {
3
+ super('The operation was aborted')
4
+ this.code = 'ABORT_ERR'
5
+ this.name = 'AbortError'
6
+ }
7
+ }
package/index.js CHANGED
@@ -1,16 +1,23 @@
1
1
  'use strict'
2
2
 
3
+ const { fromCallback } = require('catering')
4
+ const { AbortError } = require('./common')
3
5
  const { AbstractLevel } = require('abstract-level')
4
6
  const ModuleError = require('module-error')
5
7
  const fs = require('fs')
6
8
  const binding = require('./binding')
7
9
  const { ChainedBatch } = require('./chained-batch')
8
10
  const { Iterator } = require('./iterator')
11
+ const { Readable } = require('readable-stream')
9
12
  const os = require('os')
13
+ const AbortController = require('abort-controller')
10
14
 
11
15
  const kContext = Symbol('context')
12
16
  const kColumns = Symbol('columns')
13
17
  const kLocation = Symbol('location')
18
+ const kPromise = Symbol('promise')
19
+
20
+ const EMPTY = {}
14
21
 
15
22
  class RocksLevel extends AbstractLevel {
16
23
  constructor (location, options, _) {
@@ -95,17 +102,21 @@ class RocksLevel extends AbstractLevel {
95
102
  }
96
103
 
97
104
  _put (key, value, options, callback) {
105
+ callback = fromCallback(callback, kPromise)
106
+
98
107
  try {
99
108
  const batch = this.batch()
100
- batch.put(key, value, options)
109
+ batch.put(key, value, options ?? EMPTY)
101
110
  batch.write(callback)
102
111
  } catch (err) {
103
112
  process.nextTick(callback, err)
104
113
  }
114
+
115
+ return callback[kPromise]
105
116
  }
106
117
 
107
118
  _get (key, options, callback) {
108
- this._getMany([key], options, (err, val) => {
119
+ this._getMany([key], options ?? EMPTY, (err, val) => {
109
120
  if (err) {
110
121
  callback(err)
111
122
  } else if (val[0] === undefined) {
@@ -119,31 +130,43 @@ class RocksLevel extends AbstractLevel {
119
130
  }
120
131
 
121
132
  _getMany (keys, options, callback) {
133
+ callback = fromCallback(callback, kPromise)
134
+
122
135
  try {
123
- binding.db_get_many(this[kContext], keys, options, callback)
136
+ binding.db_get_many(this[kContext], keys, options ?? EMPTY, callback)
124
137
  } catch (err) {
125
138
  process.nextTick(callback, err)
126
139
  }
140
+
141
+ return callback[kPromise]
127
142
  }
128
143
 
129
144
  _del (key, options, callback) {
145
+ callback = fromCallback(callback, kPromise)
146
+
130
147
  try {
131
148
  const batch = this.batch()
132
- batch.del(key, options)
149
+ batch.del(key, options ?? EMPTY)
133
150
  batch.write(callback)
134
151
  } catch (err) {
135
152
  process.nextTick(callback, err)
136
153
  }
154
+
155
+ return callback[kPromise]
137
156
  }
138
157
 
139
158
  _clear (options, callback) {
159
+ callback = fromCallback(callback, kPromise)
160
+
140
161
  try {
141
162
  // TODO (fix): Use batch + DeleteRange...
142
- binding.db_clear(this[kContext], options)
163
+ binding.db_clear(this[kContext], options ?? EMPTY)
143
164
  process.nextTick(callback, null)
144
165
  } catch (err) {
145
166
  process.nextTick(callback, err)
146
167
  }
168
+
169
+ return callback[kPromise]
147
170
  }
148
171
 
149
172
  _chainedBatch () {
@@ -160,16 +183,20 @@ class RocksLevel extends AbstractLevel {
160
183
  }
161
184
 
162
185
  _batch (operations, options, callback) {
186
+ callback = fromCallback(callback, kPromise)
187
+
163
188
  try {
164
- binding.batch_do(this[kContext], operations, options)
189
+ binding.batch_do(this[kContext], operations, options ?? EMPTY)
165
190
  process.nextTick(callback, null)
166
191
  } catch (err) {
167
192
  process.nextTick(callback, err)
168
193
  }
194
+
195
+ return callback[kPromise]
169
196
  }
170
197
 
171
198
  _iterator (options) {
172
- return new Iterator(this, this[kContext], options)
199
+ return new Iterator(this, this[kContext], options ?? EMPTY)
173
200
  }
174
201
 
175
202
  getProperty (property) {
@@ -257,6 +284,11 @@ class RocksLevel extends AbstractLevel {
257
284
  }
258
285
 
259
286
  async * updates (options) {
287
+ // TODO (fix): Ensure open status etc...?
288
+ if (this.status !== 'open') {
289
+ throw new Error('Database is not open')
290
+ }
291
+
260
292
  if (this.status !== 'open') {
261
293
  throw new ModuleError('Database is not open', {
262
294
  code: 'LEVEL_DATABASE_NOT_OPEN'
@@ -268,12 +300,14 @@ class RocksLevel extends AbstractLevel {
268
300
  keys: options?.keys ?? true,
269
301
  values: options?.values ?? true,
270
302
  data: options?.data ?? true,
271
- column: options?.column ?? null
303
+ live: options?.live ?? false,
304
+ column: options?.column ?? null,
305
+ signal: options?.signal ?? null
272
306
  }
273
307
 
274
308
  // HACK: We don't properly check for nully column in binding.
275
- if (!options.column) {
276
- delete options.column
309
+ if (options.column) {
310
+ throw new TypeError("'column' not supported")
277
311
  }
278
312
 
279
313
  if (typeof options.since !== 'number') {
@@ -296,6 +330,85 @@ class RocksLevel extends AbstractLevel {
296
330
  throw new TypeError("'column' must be nully or a object")
297
331
  }
298
332
 
333
+ if (typeof options.live !== 'boolean') {
334
+ throw new TypeError("'live' must be nully or a boolean")
335
+ }
336
+
337
+ const ac = new AbortController()
338
+ const onAbort = () => {
339
+ ac.abort()
340
+ }
341
+
342
+ options.signal?.addEventListener('abort', onAbort)
343
+
344
+ try {
345
+ let since = options.since
346
+
347
+ const db = this
348
+ while (true) {
349
+ const buffer = new Readable({
350
+ signal: ac.signal,
351
+ objectMode: true,
352
+ readableHighWaterMark: 1024,
353
+ construct (callback) {
354
+ this._next = (batch, sequence) => {
355
+ const rows = []
356
+ for (const { type, key, value } of batch) {
357
+ rows.push(type, key, value, null)
358
+ }
359
+ if (!this.push({ rows, sequence, count: batch.length })) {
360
+ this.push(null)
361
+ db.off('write', this._next)
362
+ }
363
+ }
364
+ db.on('write', this._next)
365
+ callback()
366
+ },
367
+ read () {},
368
+ destroy (err, callback) {
369
+ db.off('write', this._next)
370
+ callback(err)
371
+ }
372
+ })
373
+
374
+ if (ac.signal.aborted) {
375
+ throw new AbortError()
376
+ }
377
+
378
+ try {
379
+ if (since <= this.sequence) {
380
+ for await (const update of this._updates(options)) {
381
+ if (ac.signal.aborted) {
382
+ throw new AbortError()
383
+ }
384
+
385
+ yield update
386
+ since = update.sequence + update.count
387
+ }
388
+ }
389
+ } catch (err) {
390
+ if (err.code !== 'LEVEL_TRYAGAIN') {
391
+ throw err
392
+ }
393
+ }
394
+
395
+ if (!options.live) {
396
+ return
397
+ }
398
+
399
+ for await (const update of buffer) {
400
+ if (update.sequence >= since) {
401
+ yield update
402
+ since = update.sequence + update.count
403
+ }
404
+ }
405
+ }
406
+ } finally {
407
+ options.signal?.removeventListener('abort', onAbort)
408
+ }
409
+ }
410
+
411
+ async * _updates (options) {
299
412
  class Updates {
300
413
  constructor (db, options) {
301
414
  this.context = binding.updates_init(db[kContext], options)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/rocksdb",
3
- "version": "7.0.45",
3
+ "version": "7.0.48",
4
4
  "description": "A low-level Node.js RocksDB binding",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -11,10 +11,13 @@
11
11
  "rebuild": "npm run install --build-from-source"
12
12
  },
13
13
  "dependencies": {
14
+ "abort-controller": "^3.0.0",
14
15
  "abstract-level": "^1.0.2",
16
+ "catering": "^2.1.1",
15
17
  "module-error": "^1.0.2",
16
18
  "napi-macros": "~2.0.0",
17
- "node-gyp-build": "^4.3.0"
19
+ "node-gyp-build": "^4.3.0",
20
+ "readable-stream": "^4.1.0"
18
21
  },
19
22
  "devDependencies": {
20
23
  "@types/node": "^17.0.16",
Binary file
Binary file