hypercore 10.24.5 → 10.24.7
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/index.js +7 -7
- package/lib/batch.js +13 -53
- package/lib/core.js +57 -26
- package/lib/replicator.js +16 -4
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -85,6 +85,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
85
85
|
this._snapshot = null
|
|
86
86
|
this._batch = opts._batch || null
|
|
87
87
|
this._findingPeers = 0
|
|
88
|
+
this._active = opts.active !== false
|
|
88
89
|
|
|
89
90
|
this.opening = this._openSession(key, storage, opts)
|
|
90
91
|
this.opening.catch(noop)
|
|
@@ -323,6 +324,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
323
324
|
// It's required so that corestore can load a name from userData before 'ready' is emitted.
|
|
324
325
|
if (opts._preready) await opts._preready(this)
|
|
325
326
|
|
|
327
|
+
this.replicator.updateActivity(this._active ? 1 : 0, this)
|
|
328
|
+
|
|
326
329
|
this.opened = true
|
|
327
330
|
this.emit('ready')
|
|
328
331
|
}
|
|
@@ -441,6 +444,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
441
444
|
if (this.replicator !== null) {
|
|
442
445
|
this.replicator.findingPeers -= this._findingPeers
|
|
443
446
|
this.replicator.clearRequests(this.activeRequests, err)
|
|
447
|
+
this.replicator.updateActivity(this._active ? -1 : 0, this)
|
|
444
448
|
}
|
|
445
449
|
|
|
446
450
|
this._findingPeers = 0
|
|
@@ -530,7 +534,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
530
534
|
_attachToMuxerOpened (mux, useSession) {
|
|
531
535
|
// If the user wants to, we can make this replication run in a session
|
|
532
536
|
// that way the core wont close "under them" during replication
|
|
533
|
-
const session = useSession ? this.session() : null
|
|
537
|
+
const session = useSession ? this.session({ active: false }) : null
|
|
534
538
|
this.replicator.attachTo(mux, session)
|
|
535
539
|
}
|
|
536
540
|
|
|
@@ -958,12 +962,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
958
962
|
}
|
|
959
963
|
|
|
960
964
|
async append (blocks, opts = {}) {
|
|
961
|
-
if (this._batch && this !== this._batch.session) throw BATCH_UNFLUSHED()
|
|
962
|
-
|
|
963
|
-
// if a batched append, run unlocked as it already locked...
|
|
964
|
-
const lock = !this._batch
|
|
965
|
-
|
|
966
965
|
if (this.opened === false) await this.opening
|
|
966
|
+
if (this._batch) throw BATCH_UNFLUSHED()
|
|
967
967
|
|
|
968
968
|
const { keyPair = this.keyPair, signature = null } = opts
|
|
969
969
|
const writable = !this._readonly && !!(signature || (keyPair && keyPair.secretKey))
|
|
@@ -982,7 +982,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
982
982
|
}
|
|
983
983
|
}
|
|
984
984
|
|
|
985
|
-
return this.core.append(buffers, {
|
|
985
|
+
return this.core.append(buffers, { keyPair, signature, preappend })
|
|
986
986
|
}
|
|
987
987
|
|
|
988
988
|
async treeHash (length) {
|
package/lib/batch.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { BLOCK_NOT_AVAILABLE, SESSION_CLOSED } = require('hypercore-errors')
|
|
2
2
|
const EventEmitter = require('events')
|
|
3
3
|
const c = require('compact-encoding')
|
|
4
|
-
const b4a = require('b4a')
|
|
5
4
|
|
|
6
5
|
module.exports = class HypercoreBatch extends EventEmitter {
|
|
7
6
|
constructor (session, autoClose) {
|
|
@@ -76,7 +75,6 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
76
75
|
async update (opts) {
|
|
77
76
|
if (this.opened === false) await this.ready()
|
|
78
77
|
await this.session.update(opts)
|
|
79
|
-
await this._catchup()
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
setUserData (key, value, opts) {
|
|
@@ -253,64 +251,26 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
253
251
|
return flushed
|
|
254
252
|
}
|
|
255
253
|
|
|
256
|
-
async _catchup () {
|
|
257
|
-
if (this.core.tree.length === this._sessionLength) return true
|
|
258
|
-
|
|
259
|
-
const batchLength = this._sessionLength + this._appends.length
|
|
260
|
-
|
|
261
|
-
if (this.core.tree.length > batchLength) return false
|
|
262
|
-
|
|
263
|
-
const b = this.createTreeBatch()
|
|
264
|
-
|
|
265
|
-
for (const root of this.core.tree.roots) {
|
|
266
|
-
const batchRoot = await b.get(root.index)
|
|
267
|
-
|
|
268
|
-
if (batchRoot === null) continue // in the shared tree
|
|
269
|
-
if (batchRoot.size !== root.size || !b4a.equals(batchRoot.hash, root.hash)) {
|
|
270
|
-
// TODO: type this error
|
|
271
|
-
throw new Error('Batch is uncommitable due to a conflict at ' + root.index)
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const offset = this.core.tree.length - this._sessionLength
|
|
276
|
-
for (let i = 0; i < offset; i++) this._byteLength -= this._appends[i].byteLength
|
|
277
|
-
|
|
278
|
-
await this.core.insertValuesUnsafe(this._appends.slice(0, offset), this._sessionLength, this._sessionByteLength, b.nodes)
|
|
279
|
-
|
|
280
|
-
this._sessionLength = this.session.length
|
|
281
|
-
this._sessionByteLength = this.session.byteLength
|
|
282
|
-
this._sessionBatch = this.session.createTreeBatch()
|
|
283
|
-
this._appends = this._appends.slice(offset)
|
|
284
|
-
|
|
285
|
-
return true
|
|
286
|
-
}
|
|
287
|
-
|
|
288
254
|
async _flush (length, keyPair, signature) { // TODO: make this safe to interact with a parallel truncate...
|
|
289
|
-
|
|
290
|
-
if (
|
|
255
|
+
const flushingLength = Math.min(length - this._sessionLength, this._appends.length)
|
|
256
|
+
if (flushingLength <= 0) return true
|
|
291
257
|
|
|
292
|
-
|
|
258
|
+
const batch = this.createTreeBatch(this._sessionLength + flushingLength)
|
|
259
|
+
if (batch === null) return false
|
|
293
260
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
if (flushingLength <= 0) return true
|
|
261
|
+
const info = await this.core.insertBatch(batch, this._appends, { keyPair, signature })
|
|
262
|
+
if (info === null) return false
|
|
297
263
|
|
|
298
|
-
|
|
264
|
+
const delta = info.byteLength - this._sessionByteLength
|
|
299
265
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
this._sessionLength = info.length
|
|
304
|
-
this._sessionByteLength = info.byteLength
|
|
305
|
-
this._sessionBatch = this.session.createTreeBatch()
|
|
266
|
+
this._sessionLength = info.length
|
|
267
|
+
this._sessionByteLength = info.byteLength
|
|
268
|
+
this._sessionBatch = this.session.createTreeBatch()
|
|
306
269
|
|
|
307
|
-
|
|
308
|
-
|
|
270
|
+
this._appends = this._appends.slice(flushingLength)
|
|
271
|
+
this._byteLength -= delta
|
|
309
272
|
|
|
310
|
-
|
|
311
|
-
} finally {
|
|
312
|
-
this.core._mutex.unlock()
|
|
313
|
-
}
|
|
273
|
+
this.emit('flush')
|
|
314
274
|
|
|
315
275
|
return true
|
|
316
276
|
}
|
package/lib/core.js
CHANGED
|
@@ -432,40 +432,71 @@ module.exports = class Core {
|
|
|
432
432
|
})
|
|
433
433
|
}
|
|
434
434
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
if (!values.length) return
|
|
435
|
+
async insertBatch (batch, values, { signature, keyPair = this.header.keyPair } = {}) {
|
|
436
|
+
await this._mutex.lock()
|
|
438
437
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
end: offset + values.length
|
|
443
|
-
}
|
|
438
|
+
try {
|
|
439
|
+
// upsert compat manifest
|
|
440
|
+
if (this.verifier === null && keyPair) this.setManifest(null, keyPair)
|
|
444
441
|
|
|
445
|
-
|
|
446
|
-
await this.oplog.append({
|
|
447
|
-
userData: null,
|
|
448
|
-
treeNodes,
|
|
449
|
-
treeUpgrade: null,
|
|
450
|
-
bitfield
|
|
451
|
-
}, false)
|
|
442
|
+
if (this.tree.fork !== batch.fork) return null
|
|
452
443
|
|
|
453
|
-
|
|
454
|
-
|
|
444
|
+
if (this.tree.length > batch.treeLength) {
|
|
445
|
+
if (this.tree.length > batch.length) return null // TODO: partial commit in the future if possible
|
|
455
446
|
|
|
456
|
-
|
|
457
|
-
|
|
447
|
+
for (const root of this.tree.roots) {
|
|
448
|
+
const batchRoot = await batch.get(root.index)
|
|
449
|
+
if (batchRoot.size !== root.size || !b4a.equals(batchRoot.hash, root.hash)) {
|
|
450
|
+
return null
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
458
454
|
|
|
459
|
-
|
|
460
|
-
|
|
455
|
+
const offset = batch.treeLength
|
|
456
|
+
const adding = batch.length - batch.treeLength
|
|
461
457
|
|
|
462
|
-
|
|
463
|
-
|
|
458
|
+
batch.upgraded = batch.length > this.tree.length
|
|
459
|
+
batch.treeLength = this.tree.length
|
|
460
|
+
if (batch.upgraded) batch.signature = signature || this.verifier.sign(batch, keyPair)
|
|
464
461
|
|
|
465
|
-
|
|
466
|
-
|
|
462
|
+
let byteOffset = batch.byteLength
|
|
463
|
+
for (let i = 0; i < adding; i++) byteOffset -= values[i].byteLength
|
|
464
|
+
|
|
465
|
+
const entry = {
|
|
466
|
+
userData: null,
|
|
467
|
+
treeNodes: batch.nodes,
|
|
468
|
+
treeUpgrade: batch.upgraded ? batch : null,
|
|
469
|
+
bitfield: {
|
|
470
|
+
drop: false,
|
|
471
|
+
start: offset,
|
|
472
|
+
length: adding
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
await this.blocks.putBatch(offset, adding > values.length ? values.slice(0, adding) : values, byteOffset)
|
|
477
|
+
await this.oplog.append([entry], false)
|
|
478
|
+
|
|
479
|
+
this.bitfield.setRange(entry.bitfield.start, entry.bitfield.length, true)
|
|
480
|
+
batch.commit()
|
|
481
|
+
|
|
482
|
+
const status = (batch.upgraded ? 0b0001 : 0) | updateContig(this.header, entry.bitfield, this.bitfield)
|
|
483
|
+
this.onupdate(status, entry.bitfield, null, null)
|
|
484
|
+
|
|
485
|
+
if (this._shouldFlush()) await this._flushOplog()
|
|
486
|
+
} finally {
|
|
487
|
+
this._mutex.unlock()
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return { length: batch.length, byteLength: batch.byteLength }
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
async append (values, { signature, keyPair = this.header.keyPair, preappend } = {}) {
|
|
494
|
+
await this._mutex.lock()
|
|
467
495
|
|
|
468
496
|
try {
|
|
497
|
+
// upsert compat manifest
|
|
498
|
+
if (this.verifier === null && keyPair) this.setManifest(null, keyPair)
|
|
499
|
+
|
|
469
500
|
if (preappend) await preappend(values)
|
|
470
501
|
|
|
471
502
|
if (!values.length) {
|
|
@@ -506,7 +537,7 @@ module.exports = class Core {
|
|
|
506
537
|
|
|
507
538
|
return { length: batch.length, byteLength }
|
|
508
539
|
} finally {
|
|
509
|
-
|
|
540
|
+
this._mutex.unlock()
|
|
510
541
|
}
|
|
511
542
|
}
|
|
512
543
|
|
package/lib/replicator.js
CHANGED
|
@@ -1046,7 +1046,7 @@ module.exports = class Replicator {
|
|
|
1046
1046
|
this.findingPeers = 0 // updateable from the outside
|
|
1047
1047
|
this.destroyed = false
|
|
1048
1048
|
this.downloading = true
|
|
1049
|
-
this.
|
|
1049
|
+
this.activeSessions = 0
|
|
1050
1050
|
|
|
1051
1051
|
this._attached = new Set()
|
|
1052
1052
|
this._inflight = new InflightTracker()
|
|
@@ -1074,15 +1074,29 @@ module.exports = class Replicator {
|
|
|
1074
1074
|
}
|
|
1075
1075
|
}
|
|
1076
1076
|
|
|
1077
|
+
updateActivity (inc, session) {
|
|
1078
|
+
this.activeSessions += inc
|
|
1079
|
+
this.setDownloading(this.activeSessions !== 0, session)
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1077
1082
|
isDownloading () {
|
|
1078
1083
|
return this.downloading || !this._inflight.idle
|
|
1079
1084
|
}
|
|
1080
1085
|
|
|
1081
|
-
setDownloading (downloading) {
|
|
1086
|
+
setDownloading (downloading, session) {
|
|
1082
1087
|
if (this.downloading === downloading) return
|
|
1083
1088
|
this.downloading = downloading
|
|
1084
1089
|
if (!downloading && this.isDownloading()) return
|
|
1090
|
+
|
|
1085
1091
|
for (const peer of this.peers) peer.signalUpgrade()
|
|
1092
|
+
|
|
1093
|
+
if (downloading) { // restart channel if needed...
|
|
1094
|
+
for (const protomux of this._attached) {
|
|
1095
|
+
if (!protomux.stream.handshakeHash) continue
|
|
1096
|
+
if (protomux.opened({ protocol: 'hypercore/alpha', id: this.discoveryKey })) continue
|
|
1097
|
+
this._makePeer(protomux, session && session.session())
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1086
1100
|
}
|
|
1087
1101
|
|
|
1088
1102
|
cork () {
|
|
@@ -1779,12 +1793,10 @@ module.exports = class Replicator {
|
|
|
1779
1793
|
}
|
|
1780
1794
|
|
|
1781
1795
|
_closeSession (session) {
|
|
1782
|
-
if (!session.closing) this.sessions--
|
|
1783
1796
|
session.close().catch(noop)
|
|
1784
1797
|
}
|
|
1785
1798
|
|
|
1786
1799
|
attachTo (protomux, session) {
|
|
1787
|
-
if (session) this.sessions++
|
|
1788
1800
|
const makePeer = this._makePeer.bind(this, protomux, session)
|
|
1789
1801
|
|
|
1790
1802
|
this._attached.add(protomux)
|