hypercore-storage 0.0.33 → 0.0.35

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 (2) hide show
  1. package/index.js +104 -13
  2. package/package.json +3 -1
package/index.js CHANGED
@@ -4,6 +4,8 @@ const { UINT } = require('index-encoder')
4
4
  const RW = require('read-write-mutexify')
5
5
  const b4a = require('b4a')
6
6
  const flat = require('flat-tree')
7
+ const rrp = require('resolve-reject-promise')
8
+ const queueTick = require('queue-tick')
7
9
  const assert = require('nanoassert')
8
10
 
9
11
  const m = require('./lib/messages')
@@ -71,9 +73,10 @@ const SLAB = {
71
73
  // PREFIX + BATCH + TYPE + INDEX
72
74
 
73
75
  class WriteBatch {
74
- constructor (storage, write) {
76
+ constructor (storage, write, atom) {
75
77
  this.storage = storage
76
78
  this.write = write
79
+ this.atom = atom
77
80
  }
78
81
 
79
82
  setCoreHead (head) {
@@ -153,10 +156,12 @@ class WriteBatch {
153
156
  }
154
157
 
155
158
  destroy () {
156
- this.write.destroy()
159
+ if (this.atom) this.atom.destroy()
160
+ else this.write.destroy()
157
161
  }
158
162
 
159
163
  flush () {
164
+ if (this.atom) return this.atom.flush()
160
165
  return this.write.flush()
161
166
  }
162
167
  }
@@ -262,6 +267,87 @@ class ReadBatch {
262
267
  }
263
268
  }
264
269
 
270
+ class Atomizer {
271
+ constructor (db) {
272
+ this.db = db
273
+ this.batch = null
274
+ this.refs = 0
275
+ this.destroyed = false
276
+ this.flushing = null
277
+ this.resolve = null
278
+ this.reject = null
279
+ }
280
+
281
+ enter () {
282
+ this.refs++
283
+ }
284
+
285
+ exit () {
286
+ if (--this.refs === 0) this._commit()
287
+ }
288
+
289
+ createBatch () {
290
+ if (this.refs === 0) this._ensureTick()
291
+ this.enter()
292
+ if (this.batch === null) this.batch = this.db.write()
293
+ return this.batch
294
+ }
295
+
296
+ _ensureTick () {
297
+ this.enter()
298
+ queueTick(() => this.exit())
299
+ }
300
+
301
+ async _commit () {
302
+ const batch = this.batch
303
+ const resolve = this.resolve
304
+ const reject = this.reject
305
+
306
+ this.batch = null
307
+ this.flushing = null
308
+ this.resolve = this.reject = null
309
+
310
+ if (this.destroyed) {
311
+ this.destroyed = false
312
+ batch.destroy()
313
+ if (reject !== null) reject(new Error('Atomic batch destroyed'))
314
+ return
315
+ }
316
+
317
+ try {
318
+ await batch.flush()
319
+ } catch (err) {
320
+ reject(err)
321
+ return
322
+ }
323
+
324
+ resolve()
325
+ }
326
+
327
+ _createFlushing () {
328
+ if (this.flushing !== null) return this.flushing
329
+
330
+ const { resolve, reject, promise } = rrp()
331
+
332
+ this.flushing = promise
333
+ this.resolve = resolve
334
+ this.reject = reject
335
+
336
+ return this.flushing
337
+ }
338
+
339
+ destroy () {
340
+ this.destroyed = true
341
+ this.exit()
342
+ }
343
+
344
+ flush () {
345
+ const flushing = this._createFlushing()
346
+ this.exit()
347
+ return flushing
348
+ }
349
+ }
350
+
265
351
  module.exports = class CoreStorage {
266
352
  constructor (dir) {
267
353
  this.db = new RocksDB(dir)
@@ -334,6 +420,10 @@ module.exports = class CoreStorage {
334
420
  return this.db.close()
335
421
  }
336
422
 
423
+ atomizer () {
424
+ return new Atomizer(this.db)
425
+ }
426
+
337
427
  async clear () {
338
428
  const b = this.db.write()
339
429
  b.tryDeleteRange(b4a.from([TL.STORAGE_INFO]), INF)
@@ -387,7 +477,7 @@ module.exports = class CoreStorage {
387
477
  write.tryPut(b4a.from([TL.STORAGE_INFO]), encode(m.StorageInfo, info))
388
478
 
389
479
  const storage = new HypercoreStorage(this, discoveryKey, core, data, null)
390
- const batch = new WriteBatch(storage, write)
480
+ const batch = new WriteBatch(storage, write, null)
391
481
 
392
482
  initialiseCoreInfo(batch, { key, manifest, keyPair, encryptionKey })
393
483
  initialiseCoreData(batch, { userData })
@@ -422,6 +512,10 @@ class HypercoreStorage {
422
512
  return this.dbSnapshot !== null
423
513
  }
424
514
 
515
+ atomizer () {
516
+ return this.root.atomizer()
517
+ }
518
+
425
519
  dependencyLength () {
426
520
  return this.dependencies.length
427
521
  ? this.dependencies[this.dependencies.length - 1].length
@@ -454,7 +548,7 @@ class HypercoreStorage {
454
548
 
455
549
  write.tryPut(b4a.from([TL.STORAGE_INFO]), encode(m.StorageInfo, info))
456
550
 
457
- const batch = new WriteBatch(storage, write)
551
+ const batch = new WriteBatch(storage, write, null)
458
552
 
459
553
  initialiseCoreData(batch)
460
554
 
@@ -487,16 +581,11 @@ class HypercoreStorage {
487
581
  return new MemoryOverlay(this)
488
582
  }
489
583
 
490
- snapshot (sharedLength = -1) {
584
+ snapshot () {
491
585
  assert(this.destroyed === false)
492
586
  const s = new HypercoreStorage(this.root, this.discoveryKey, this.corePointer, this.dataPointer, this.db.snapshot())
493
587
 
494
- for (const dep of this.dependencies) {
495
- const length = sharedLength !== -1 && sharedLength < dep.length ? sharedLength : dep.length
496
- s.dependencies.push({ data: dep.data, length })
497
-
498
- if (length === sharedLength) break
499
- }
588
+ for (const dep of this.dependencies) s.dependencies.push(dep)
500
589
 
501
590
  return s
502
591
  }
@@ -531,10 +620,12 @@ class HypercoreStorage {
531
620
  return new ReadBatch(this, this.db.read({ snapshot }))
532
621
  }
533
622
 
534
- createWriteBatch () {
623
+ createWriteBatch (atomizer) {
535
624
  assert(this.destroyed === false)
536
625
 
537
- return new WriteBatch(this, this.db.write())
626
+ if (atomizer) return new WriteBatch(this, atomizer.createBatch(), atomizer)
627
+
628
+ return new WriteBatch(this, this.db.write(), null)
538
629
  }
539
630
 
540
631
  createBlockStream (opts = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore-storage",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "main": "index.js",
5
5
  "files": [
6
6
  "index.js",
@@ -19,7 +19,9 @@
19
19
  "hypercore-errors": "^1.3.0",
20
20
  "index-encoder": "^3.0.1",
21
21
  "nanoassert": "^2.0.0",
22
+ "queue-tick": "^1.0.1",
22
23
  "read-write-mutexify": "^2.1.0",
24
+ "resolve-reject-promise": "^1.0.0",
23
25
  "rocksdb-native": "^2.2.0",
24
26
  "streamx": "^2.20.1"
25
27
  },