hypercore 10.0.0-alpha.43 → 10.0.0-alpha.46
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 +32 -9
- package/lib/caps.js +1 -3
- package/lib/core.js +6 -2
- package/lib/replicator.js +54 -15
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -191,8 +191,10 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
191
191
|
|
|
192
192
|
s._passCapabilities(this)
|
|
193
193
|
|
|
194
|
-
//
|
|
195
|
-
if (opts.cache !== false)
|
|
194
|
+
// Configure the cache unless explicitly disabled.
|
|
195
|
+
if (opts.cache !== false) {
|
|
196
|
+
s.cache = opts.cache === true || !opts.cache ? this.cache : opts.cache
|
|
197
|
+
}
|
|
196
198
|
|
|
197
199
|
ensureEncryption(s, opts)
|
|
198
200
|
|
|
@@ -295,7 +297,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
295
297
|
crypto: this.crypto,
|
|
296
298
|
legacy: opts.legacy,
|
|
297
299
|
auth: opts.auth,
|
|
298
|
-
onupdate: this._oncoreupdate.bind(this)
|
|
300
|
+
onupdate: this._oncoreupdate.bind(this),
|
|
301
|
+
oncontigupdate: this._oncorecontigupdate.bind(this)
|
|
299
302
|
})
|
|
300
303
|
|
|
301
304
|
if (opts.userData) {
|
|
@@ -482,9 +485,10 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
482
485
|
if (s._snapshot && bitfield.start < s._snapshot.compatLength) s._snapshot.compatLength = bitfield.start
|
|
483
486
|
}
|
|
484
487
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
+
// For sparse sessions, immediately emit appends. Non-sparse sessions
|
|
489
|
+
// are handled separately and only emit appends when their contiguous
|
|
490
|
+
// length is updated.
|
|
491
|
+
if (appended && s.sparse) s.emit('append')
|
|
488
492
|
}
|
|
489
493
|
|
|
490
494
|
this.replicator.onupgrade()
|
|
@@ -503,6 +507,16 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
503
507
|
}
|
|
504
508
|
}
|
|
505
509
|
|
|
510
|
+
_oncorecontigupdate () {
|
|
511
|
+
// For non-sparse sessions, emit appends only when the contiguous length is
|
|
512
|
+
// updated.
|
|
513
|
+
for (let i = 0; i < this.sessions.length; i++) {
|
|
514
|
+
const s = this.sessions[i]
|
|
515
|
+
|
|
516
|
+
if (!s.sparse) s.emit('append')
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
506
520
|
_onpeerupdate (added, peer) {
|
|
507
521
|
const name = added ? 'peer-add' : 'peer-remove'
|
|
508
522
|
|
|
@@ -559,10 +573,19 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
559
573
|
const activeRequests = (opts && opts.activeRequests) || this.activeRequests
|
|
560
574
|
const req = this.replicator.addUpgrade(activeRequests)
|
|
561
575
|
|
|
562
|
-
|
|
563
|
-
|
|
576
|
+
const upgraded = await req.promise
|
|
577
|
+
|
|
578
|
+
if (!this.sparse) {
|
|
579
|
+
// Download all available blocks in non-sparse mode
|
|
580
|
+
const start = this.length
|
|
581
|
+
const end = this.core.tree.length
|
|
582
|
+
|
|
583
|
+
await this.download({ start, end, ifAvailable: true }).downloaded()
|
|
584
|
+
}
|
|
564
585
|
|
|
565
|
-
|
|
586
|
+
if (!upgraded) return false
|
|
587
|
+
if (this.snapshotted) return this._updateSnapshot()
|
|
588
|
+
return true
|
|
566
589
|
}
|
|
567
590
|
|
|
568
591
|
async seek (bytes, opts) {
|
package/lib/caps.js
CHANGED
|
@@ -4,9 +4,7 @@ const b4a = require('b4a')
|
|
|
4
4
|
const c = require('compact-encoding')
|
|
5
5
|
|
|
6
6
|
// TODO: rename this to "crypto" and move everything hashing related etc in here
|
|
7
|
-
// Also lets move the tree stuff from hypercore-crypto here
|
|
8
|
-
// from the hashes there - they are not needed since we lock the indexes in the tree
|
|
9
|
-
// hash and just makes alignment etc harder in other languages
|
|
7
|
+
// Also lets move the tree stuff from hypercore-crypto here
|
|
10
8
|
|
|
11
9
|
const [TREE, REPLICATE_INITIATOR, REPLICATE_RESPONDER] = crypto.namespace('hypercore', 3)
|
|
12
10
|
|
package/lib/core.js
CHANGED
|
@@ -9,8 +9,9 @@ const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_SIGNATURE } = req
|
|
|
9
9
|
const m = require('./messages')
|
|
10
10
|
|
|
11
11
|
module.exports = class Core {
|
|
12
|
-
constructor (header, crypto, oplog, tree, blocks, bitfield, auth, legacy, onupdate) {
|
|
12
|
+
constructor (header, crypto, oplog, tree, blocks, bitfield, auth, legacy, onupdate, oncontigupdate) {
|
|
13
13
|
this.onupdate = onupdate
|
|
14
|
+
this.oncontigupdate = oncontigupdate
|
|
14
15
|
this.header = header
|
|
15
16
|
this.crypto = crypto
|
|
16
17
|
this.oplog = oplog
|
|
@@ -164,7 +165,7 @@ module.exports = class Core {
|
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
return new this(header, crypto, oplog, tree, blocks, bitfield, auth, !!opts.legacy, opts.onupdate || noop)
|
|
168
|
+
return new this(header, crypto, oplog, tree, blocks, bitfield, auth, !!opts.legacy, opts.onupdate || noop, opts.oncontigupdate || noop)
|
|
168
169
|
}
|
|
169
170
|
|
|
170
171
|
_shouldFlush () {
|
|
@@ -202,6 +203,7 @@ module.exports = class Core {
|
|
|
202
203
|
while (this.bitfield.get(i)) i++
|
|
203
204
|
|
|
204
205
|
this.header.contiguousLength = i
|
|
206
|
+
this.oncontigupdate()
|
|
205
207
|
}
|
|
206
208
|
}
|
|
207
209
|
|
|
@@ -285,6 +287,7 @@ module.exports = class Core {
|
|
|
285
287
|
batch.commit()
|
|
286
288
|
|
|
287
289
|
this.header.contiguousLength = batch.length
|
|
290
|
+
this.oncontigupdate()
|
|
288
291
|
this.header.tree.length = batch.length
|
|
289
292
|
this.header.tree.rootHash = hash
|
|
290
293
|
this.header.tree.signature = batch.signature
|
|
@@ -472,6 +475,7 @@ module.exports = class Core {
|
|
|
472
475
|
const appended = batch.length > batch.ancestors
|
|
473
476
|
|
|
474
477
|
this.header.contiguousLength = Math.min(batch.ancestors, this.header.contiguousLength)
|
|
478
|
+
this.oncontigupdate()
|
|
475
479
|
this.header.tree.fork = batch.fork
|
|
476
480
|
this.header.tree.length = batch.length
|
|
477
481
|
this.header.tree.rootHash = batch.hash()
|
package/lib/replicator.js
CHANGED
|
@@ -102,12 +102,13 @@ class BlockRequest extends Attachable {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
class RangeRequest extends Attachable {
|
|
105
|
-
constructor (ranges, start, end, linear, blocks) {
|
|
105
|
+
constructor (ranges, start, end, linear, ifAvailable, blocks) {
|
|
106
106
|
super()
|
|
107
107
|
|
|
108
108
|
this.start = start
|
|
109
109
|
this.end = end
|
|
110
110
|
this.linear = linear
|
|
111
|
+
this.ifAvailable = ifAvailable
|
|
111
112
|
this.blocks = blocks
|
|
112
113
|
this.ranges = ranges
|
|
113
114
|
|
|
@@ -172,6 +173,10 @@ class InflightTracker {
|
|
|
172
173
|
this._free = []
|
|
173
174
|
}
|
|
174
175
|
|
|
176
|
+
get idle () {
|
|
177
|
+
return this._requests.length === this._free.length
|
|
178
|
+
}
|
|
179
|
+
|
|
175
180
|
* [Symbol.iterator] () {
|
|
176
181
|
for (const req of this._requests) {
|
|
177
182
|
if (req !== null) yield req
|
|
@@ -260,6 +265,7 @@ class Peer {
|
|
|
260
265
|
|
|
261
266
|
this.inflight = 0
|
|
262
267
|
this.maxInflight = DEFAULT_MAX_INFLIGHT
|
|
268
|
+
this.dataProcessing = 0
|
|
263
269
|
|
|
264
270
|
this.canUpgrade = true
|
|
265
271
|
|
|
@@ -515,6 +521,8 @@ class Peer {
|
|
|
515
521
|
|
|
516
522
|
if (reorg === true) return this.replicator._onreorgdata(this, req, data)
|
|
517
523
|
|
|
524
|
+
this.dataProcessing++
|
|
525
|
+
|
|
518
526
|
try {
|
|
519
527
|
if (!matchingRequest(req, data) || !(await this.core.verify(data, this))) {
|
|
520
528
|
this.replicator._onnodata(this, req)
|
|
@@ -523,6 +531,8 @@ class Peer {
|
|
|
523
531
|
} catch (err) {
|
|
524
532
|
this.replicator._onnodata(this, req)
|
|
525
533
|
throw err
|
|
534
|
+
} finally {
|
|
535
|
+
this.dataProcessing--
|
|
526
536
|
}
|
|
527
537
|
|
|
528
538
|
this.replicator._ondata(this, req, data)
|
|
@@ -909,13 +919,21 @@ module.exports = class Replicator {
|
|
|
909
919
|
return ref
|
|
910
920
|
}
|
|
911
921
|
|
|
912
|
-
addRange (session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false } = {}) {
|
|
913
|
-
if (blocks !== null) {
|
|
914
|
-
|
|
915
|
-
|
|
922
|
+
addRange (session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false, ifAvailable = false } = {}) {
|
|
923
|
+
if (blocks !== null) { // if using blocks, start, end just acts as frames around the blocks array
|
|
924
|
+
start = 0
|
|
925
|
+
end = length = blocks.length
|
|
916
926
|
}
|
|
917
927
|
|
|
918
|
-
const r = new RangeRequest(
|
|
928
|
+
const r = new RangeRequest(
|
|
929
|
+
this._ranges,
|
|
930
|
+
start,
|
|
931
|
+
length === -1 ? -1 : start + length,
|
|
932
|
+
linear,
|
|
933
|
+
ifAvailable,
|
|
934
|
+
blocks
|
|
935
|
+
)
|
|
936
|
+
|
|
919
937
|
const ref = r.attach(session)
|
|
920
938
|
|
|
921
939
|
this._ranges.push(r)
|
|
@@ -1115,6 +1133,14 @@ module.exports = class Replicator {
|
|
|
1115
1133
|
return true
|
|
1116
1134
|
}
|
|
1117
1135
|
|
|
1136
|
+
_resolveRangeRequest (req, index) {
|
|
1137
|
+
const head = this._ranges.pop()
|
|
1138
|
+
|
|
1139
|
+
if (index < this._ranges.length) this._ranges[index] = head
|
|
1140
|
+
|
|
1141
|
+
req.resolve(true)
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1118
1144
|
_clearInflightBlock (tracker, req) {
|
|
1119
1145
|
const isBlock = tracker === this._blocks
|
|
1120
1146
|
const index = isBlock === true ? req.block.index : req.hash.index / 2
|
|
@@ -1168,14 +1194,9 @@ module.exports = class Replicator {
|
|
|
1168
1194
|
while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.start)) === true) r.start++
|
|
1169
1195
|
while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.end - 1)) === true) r.end--
|
|
1170
1196
|
|
|
1171
|
-
if (r.end
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
else this._ranges.pop()
|
|
1175
|
-
|
|
1176
|
-
i--
|
|
1177
|
-
|
|
1178
|
-
r.resolve(true)
|
|
1197
|
+
if (r.end !== -1 && r.start >= r.end) {
|
|
1198
|
+
this._resolveRangeRequest(r, i--)
|
|
1199
|
+
}
|
|
1179
1200
|
}
|
|
1180
1201
|
|
|
1181
1202
|
for (let i = 0; i < this._seeks.length; i++) {
|
|
@@ -1201,7 +1222,7 @@ module.exports = class Replicator {
|
|
|
1201
1222
|
else s.resolve(res)
|
|
1202
1223
|
}
|
|
1203
1224
|
|
|
1204
|
-
this.updateAll()
|
|
1225
|
+
if (this._inflight.idle) this.updateAll()
|
|
1205
1226
|
|
|
1206
1227
|
// No additional updates scheduled - return
|
|
1207
1228
|
if (--this._updatesPending === 0) return
|
|
@@ -1210,6 +1231,22 @@ module.exports = class Replicator {
|
|
|
1210
1231
|
}
|
|
1211
1232
|
}
|
|
1212
1233
|
|
|
1234
|
+
_maybeResolveIfAvailableRanges () {
|
|
1235
|
+
if (this._ifAvailable > 0 || !this._inflight.idle || !this._ranges.length) return
|
|
1236
|
+
|
|
1237
|
+
for (let i = 0; i < this.peers.length; i++) {
|
|
1238
|
+
if (this.peers[i].dataProcessing > 0) return
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
for (let i = 0; i < this._ranges.length; i++) {
|
|
1242
|
+
const r = this._ranges[i]
|
|
1243
|
+
|
|
1244
|
+
if (r.ifAvailable) {
|
|
1245
|
+
this._resolveRangeRequest(r, i--)
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1213
1250
|
_clearRequest (peer, req) {
|
|
1214
1251
|
if (req.block !== null) {
|
|
1215
1252
|
this._clearInflightBlock(this._blocks, req)
|
|
@@ -1407,6 +1444,7 @@ module.exports = class Replicator {
|
|
|
1407
1444
|
while (this._updatePeerNonPrimary(peer) === true);
|
|
1408
1445
|
|
|
1409
1446
|
this._checkUpgradeIfAvailable()
|
|
1447
|
+
this._maybeResolveIfAvailableRanges()
|
|
1410
1448
|
}
|
|
1411
1449
|
|
|
1412
1450
|
updateAll () {
|
|
@@ -1434,6 +1472,7 @@ module.exports = class Replicator {
|
|
|
1434
1472
|
}
|
|
1435
1473
|
|
|
1436
1474
|
this._checkUpgradeIfAvailable()
|
|
1475
|
+
this._maybeResolveIfAvailableRanges()
|
|
1437
1476
|
}
|
|
1438
1477
|
|
|
1439
1478
|
attachTo (protomux) {
|