hypercore 11.35.0 → 11.35.2
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/lib/replicator.js +115 -38
- package/package.json +1 -1
package/lib/replicator.js
CHANGED
|
@@ -285,6 +285,10 @@ class RangeRequest extends Attachable {
|
|
|
285
285
|
this.ranges[rangeIndex] = h
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
if (!this.resolved && this.replicator._updatesRunning) {
|
|
289
|
+
this.replicator._updatesQueued = true
|
|
290
|
+
}
|
|
291
|
+
|
|
288
292
|
if (this.end === -1) {
|
|
289
293
|
this.replicator._alwaysLatestBlock--
|
|
290
294
|
}
|
|
@@ -974,7 +978,8 @@ class Peer {
|
|
|
974
978
|
this.remoteOpened &&
|
|
975
979
|
this.protomux.drained &&
|
|
976
980
|
this.receiverQueue.length > 0 &&
|
|
977
|
-
!this.removed
|
|
981
|
+
!this.removed &&
|
|
982
|
+
this.core.closing === null
|
|
978
983
|
) {
|
|
979
984
|
const msg = this.receiverQueue.shift()
|
|
980
985
|
await this._handleRequest(msg)
|
|
@@ -985,6 +990,7 @@ class Peer {
|
|
|
985
990
|
}
|
|
986
991
|
|
|
987
992
|
async push(index) {
|
|
993
|
+
if (this.core.closing !== null) return
|
|
988
994
|
if (!this.remoteAllowPush) return
|
|
989
995
|
if (!this.remoteDownloading) return
|
|
990
996
|
if (this.core.state.length <= index) return
|
|
@@ -1265,7 +1271,7 @@ class Peer {
|
|
|
1265
1271
|
return
|
|
1266
1272
|
}
|
|
1267
1273
|
|
|
1268
|
-
if (this.core.closed && !isCriticalError(err)) return
|
|
1274
|
+
if ((this.core.closing !== null || this.core.closed) && !isCriticalError(err)) return
|
|
1269
1275
|
|
|
1270
1276
|
if (err.code !== 'INVALID_OPERATION') {
|
|
1271
1277
|
// might be a fork, verify
|
|
@@ -1401,6 +1407,8 @@ class Peer {
|
|
|
1401
1407
|
}
|
|
1402
1408
|
|
|
1403
1409
|
async onrange({ drop, start, length }) {
|
|
1410
|
+
if (this.core.closing !== null) return
|
|
1411
|
+
|
|
1404
1412
|
const has = drop === false
|
|
1405
1413
|
|
|
1406
1414
|
if (drop === true && start < this._remoteContiguousLength) {
|
|
@@ -1541,8 +1549,8 @@ class Peer {
|
|
|
1541
1549
|
}
|
|
1542
1550
|
|
|
1543
1551
|
_requestSeek(s) {
|
|
1544
|
-
// if replicator is updating the seeks
|
|
1545
|
-
if (this.replicator.
|
|
1552
|
+
// if replicator is updating the seeks, bail and wait for it to drain
|
|
1553
|
+
if (this.replicator._updatingSeeks) return false
|
|
1546
1554
|
if (this.replicator.pushOnly) return false
|
|
1547
1555
|
|
|
1548
1556
|
const { length, fork } = this.core.state
|
|
@@ -1952,6 +1960,7 @@ class Peer {
|
|
|
1952
1960
|
}
|
|
1953
1961
|
}
|
|
1954
1962
|
} catch (err) {
|
|
1963
|
+
if (this.core.closing !== null) return
|
|
1955
1964
|
this.stream.destroy(err)
|
|
1956
1965
|
return
|
|
1957
1966
|
}
|
|
@@ -2028,7 +2037,9 @@ module.exports = class Replicator {
|
|
|
2028
2037
|
this._hadPeers = false
|
|
2029
2038
|
this._active = 0
|
|
2030
2039
|
this._ifAvailable = 0
|
|
2031
|
-
this.
|
|
2040
|
+
this._updatingSeeks = false
|
|
2041
|
+
this._updatesRunning = false
|
|
2042
|
+
this._updatesQueued = false
|
|
2032
2043
|
this._applyingReorg = null
|
|
2033
2044
|
this._manifestPeer = null
|
|
2034
2045
|
this._notDownloadingLinger = notDownloadingLinger
|
|
@@ -2614,55 +2625,117 @@ module.exports = class Replicator {
|
|
|
2614
2625
|
}
|
|
2615
2626
|
}
|
|
2616
2627
|
|
|
2628
|
+
_updateRanges(index, limit) {
|
|
2629
|
+
index = Math.min(index, this._ranges.length - 1)
|
|
2630
|
+
|
|
2631
|
+
let checked = 0
|
|
2632
|
+
let resolved = 0
|
|
2633
|
+
let updateAll = false
|
|
2634
|
+
let remaining = Math.min(limit, this._ranges.length)
|
|
2635
|
+
|
|
2636
|
+
while (remaining-- > 0 && this._ranges.length > 0) {
|
|
2637
|
+
if (index >= this._ranges.length) index = 0
|
|
2638
|
+
|
|
2639
|
+
const r = this._ranges[index]
|
|
2640
|
+
|
|
2641
|
+
clampRange(this.core, r)
|
|
2642
|
+
checked++
|
|
2643
|
+
|
|
2644
|
+
if (r.end !== -1 && r.start >= r.end) {
|
|
2645
|
+
this._resolveRangeRequest(r)
|
|
2646
|
+
resolved++
|
|
2647
|
+
// Crossing into the capped window exposes another range to peer scheduling.
|
|
2648
|
+
if (this._ranges.length === MAX_RANGES) updateAll = true
|
|
2649
|
+
} else {
|
|
2650
|
+
index++
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2654
|
+
index = this._ranges.length === 0 ? 0 : index % this._ranges.length
|
|
2655
|
+
|
|
2656
|
+
return { checked, resolved, index, updateAll }
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2617
2659
|
// "slow" updates here - async but not allowed to ever throw
|
|
2618
2660
|
async _updateNonPrimary(updateAll) {
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2661
|
+
this._updatesQueued = true
|
|
2662
|
+
if (this._updatesRunning) {
|
|
2663
|
+
if (this._inflight.idle || updateAll) this.queueUpdateAll()
|
|
2664
|
+
return
|
|
2665
|
+
}
|
|
2622
2666
|
|
|
2623
|
-
|
|
2624
|
-
const r = this._ranges[i]
|
|
2667
|
+
this._updatesRunning = true
|
|
2625
2668
|
|
|
2626
|
-
|
|
2669
|
+
while (this._updatesQueued) {
|
|
2670
|
+
this._updatesQueued = false
|
|
2627
2671
|
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
if (this._ranges.length === MAX_RANGES) updateAll = true
|
|
2633
|
-
}
|
|
2634
|
-
}
|
|
2672
|
+
let checkedSinceResolve = 0
|
|
2673
|
+
let rangeIndex = 0
|
|
2674
|
+
const drain = this._inflight.idle || updateAll
|
|
2675
|
+
const checkedSeeks = new Set()
|
|
2635
2676
|
|
|
2636
|
-
|
|
2637
|
-
const
|
|
2677
|
+
while (true) {
|
|
2678
|
+
const limit = Math.min(MAX_RANGES, this._ranges.length - checkedSinceResolve)
|
|
2679
|
+
const {
|
|
2680
|
+
checked,
|
|
2681
|
+
resolved,
|
|
2682
|
+
index,
|
|
2683
|
+
updateAll: resultUpdateAll
|
|
2684
|
+
} = this._updateRanges(rangeIndex, limit)
|
|
2685
|
+
rangeIndex = index
|
|
2638
2686
|
|
|
2639
|
-
|
|
2640
|
-
let res = null
|
|
2687
|
+
if (resultUpdateAll) updateAll = true
|
|
2641
2688
|
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2689
|
+
if (resolved > 0) checkedSinceResolve = 0
|
|
2690
|
+
else checkedSinceResolve += checked
|
|
2691
|
+
|
|
2692
|
+
const continueRanges = checked > 0 && checkedSinceResolve < this._ranges.length && drain
|
|
2693
|
+
|
|
2694
|
+
this._updatingSeeks = true
|
|
2695
|
+
|
|
2696
|
+
let checkedSeek = false
|
|
2697
|
+
for (const s of this._seeks.slice()) {
|
|
2698
|
+
if (checkedSeeks.has(s) || !this._seeks.includes(s)) continue
|
|
2699
|
+
checkedSeeks.add(s)
|
|
2700
|
+
checkedSeek = true
|
|
2701
|
+
|
|
2702
|
+
let err = null
|
|
2703
|
+
let res = null
|
|
2704
|
+
|
|
2705
|
+
try {
|
|
2706
|
+
res = await s.seeker.update()
|
|
2707
|
+
} catch (error) {
|
|
2708
|
+
err = error
|
|
2709
|
+
}
|
|
2647
2710
|
|
|
2648
|
-
|
|
2711
|
+
const seekIndex = this._seeks.indexOf(s)
|
|
2712
|
+
if (seekIndex === -1 || (!res && !err)) continue
|
|
2649
2713
|
|
|
2650
|
-
|
|
2651
|
-
|
|
2714
|
+
const h = this._seeks.pop()
|
|
2715
|
+
if (h !== s) this._seeks[seekIndex] = h
|
|
2652
2716
|
|
|
2653
|
-
|
|
2717
|
+
if (err) s.reject(err)
|
|
2718
|
+
else s.resolve(res)
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
this._updatingSeeks = false
|
|
2722
|
+
|
|
2723
|
+
if (
|
|
2724
|
+
(!continueRanges || (checkedSeek && this._seeks.length > 0)) &&
|
|
2725
|
+
(this._inflight.idle || updateAll)
|
|
2726
|
+
) {
|
|
2727
|
+
this.queueUpdateAll()
|
|
2728
|
+
}
|
|
2729
|
+
if (!continueRanges) break
|
|
2654
2730
|
|
|
2655
|
-
|
|
2656
|
-
|
|
2731
|
+
await yieldToLoop()
|
|
2732
|
+
if (this.destroyed) break
|
|
2657
2733
|
}
|
|
2658
2734
|
|
|
2659
|
-
|
|
2660
|
-
if (--this._updatesPending === 0) break
|
|
2661
|
-
// Debounce the additional updates - continue
|
|
2662
|
-
this._updatesPending = 0
|
|
2735
|
+
if (this.destroyed) break
|
|
2663
2736
|
}
|
|
2664
2737
|
|
|
2665
|
-
|
|
2738
|
+
this._updatesRunning = false
|
|
2666
2739
|
}
|
|
2667
2740
|
|
|
2668
2741
|
_clearRequest(peer, req) {
|
|
@@ -3398,6 +3471,10 @@ function incrementRx(stats1, stats2) {
|
|
|
3398
3471
|
|
|
3399
3472
|
function noop() {}
|
|
3400
3473
|
|
|
3474
|
+
function yieldToLoop() {
|
|
3475
|
+
return new Promise((resolve) => setImmediate(resolve))
|
|
3476
|
+
}
|
|
3477
|
+
|
|
3401
3478
|
function backoff(times) {
|
|
3402
3479
|
const sleep = times < 2 ? 200 : times < 5 ? 500 : times < 40 ? 1000 : 5000
|
|
3403
3480
|
return new Promise((resolve) => setTimeout(resolve, sleep))
|