hypercore 11.35.0 → 11.35.1
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 +108 -36
- 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
|
}
|
|
@@ -1541,8 +1545,8 @@ class Peer {
|
|
|
1541
1545
|
}
|
|
1542
1546
|
|
|
1543
1547
|
_requestSeek(s) {
|
|
1544
|
-
// if replicator is updating the seeks
|
|
1545
|
-
if (this.replicator.
|
|
1548
|
+
// if replicator is updating the seeks, bail and wait for it to drain
|
|
1549
|
+
if (this.replicator._updatingSeeks) return false
|
|
1546
1550
|
if (this.replicator.pushOnly) return false
|
|
1547
1551
|
|
|
1548
1552
|
const { length, fork } = this.core.state
|
|
@@ -2028,7 +2032,9 @@ module.exports = class Replicator {
|
|
|
2028
2032
|
this._hadPeers = false
|
|
2029
2033
|
this._active = 0
|
|
2030
2034
|
this._ifAvailable = 0
|
|
2031
|
-
this.
|
|
2035
|
+
this._updatingSeeks = false
|
|
2036
|
+
this._updatesRunning = false
|
|
2037
|
+
this._updatesQueued = false
|
|
2032
2038
|
this._applyingReorg = null
|
|
2033
2039
|
this._manifestPeer = null
|
|
2034
2040
|
this._notDownloadingLinger = notDownloadingLinger
|
|
@@ -2614,55 +2620,117 @@ module.exports = class Replicator {
|
|
|
2614
2620
|
}
|
|
2615
2621
|
}
|
|
2616
2622
|
|
|
2623
|
+
_updateRanges(index, limit) {
|
|
2624
|
+
index = Math.min(index, this._ranges.length - 1)
|
|
2625
|
+
|
|
2626
|
+
let checked = 0
|
|
2627
|
+
let resolved = 0
|
|
2628
|
+
let updateAll = false
|
|
2629
|
+
let remaining = Math.min(limit, this._ranges.length)
|
|
2630
|
+
|
|
2631
|
+
while (remaining-- > 0 && this._ranges.length > 0) {
|
|
2632
|
+
if (index >= this._ranges.length) index = 0
|
|
2633
|
+
|
|
2634
|
+
const r = this._ranges[index]
|
|
2635
|
+
|
|
2636
|
+
clampRange(this.core, r)
|
|
2637
|
+
checked++
|
|
2638
|
+
|
|
2639
|
+
if (r.end !== -1 && r.start >= r.end) {
|
|
2640
|
+
this._resolveRangeRequest(r)
|
|
2641
|
+
resolved++
|
|
2642
|
+
// Crossing into the capped window exposes another range to peer scheduling.
|
|
2643
|
+
if (this._ranges.length === MAX_RANGES) updateAll = true
|
|
2644
|
+
} else {
|
|
2645
|
+
index++
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2649
|
+
index = this._ranges.length === 0 ? 0 : index % this._ranges.length
|
|
2650
|
+
|
|
2651
|
+
return { checked, resolved, index, updateAll }
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2617
2654
|
// "slow" updates here - async but not allowed to ever throw
|
|
2618
2655
|
async _updateNonPrimary(updateAll) {
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2656
|
+
this._updatesQueued = true
|
|
2657
|
+
if (this._updatesRunning) {
|
|
2658
|
+
if (this._inflight.idle || updateAll) this.queueUpdateAll()
|
|
2659
|
+
return
|
|
2660
|
+
}
|
|
2622
2661
|
|
|
2623
|
-
|
|
2624
|
-
const r = this._ranges[i]
|
|
2662
|
+
this._updatesRunning = true
|
|
2625
2663
|
|
|
2626
|
-
|
|
2664
|
+
while (this._updatesQueued) {
|
|
2665
|
+
this._updatesQueued = false
|
|
2627
2666
|
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
if (this._ranges.length === MAX_RANGES) updateAll = true
|
|
2633
|
-
}
|
|
2634
|
-
}
|
|
2667
|
+
let checkedSinceResolve = 0
|
|
2668
|
+
let rangeIndex = 0
|
|
2669
|
+
const drain = this._inflight.idle || updateAll
|
|
2670
|
+
const checkedSeeks = new Set()
|
|
2635
2671
|
|
|
2636
|
-
|
|
2637
|
-
const
|
|
2672
|
+
while (true) {
|
|
2673
|
+
const limit = Math.min(MAX_RANGES, this._ranges.length - checkedSinceResolve)
|
|
2674
|
+
const {
|
|
2675
|
+
checked,
|
|
2676
|
+
resolved,
|
|
2677
|
+
index,
|
|
2678
|
+
updateAll: resultUpdateAll
|
|
2679
|
+
} = this._updateRanges(rangeIndex, limit)
|
|
2680
|
+
rangeIndex = index
|
|
2638
2681
|
|
|
2639
|
-
|
|
2640
|
-
let res = null
|
|
2682
|
+
if (resultUpdateAll) updateAll = true
|
|
2641
2683
|
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2684
|
+
if (resolved > 0) checkedSinceResolve = 0
|
|
2685
|
+
else checkedSinceResolve += checked
|
|
2686
|
+
|
|
2687
|
+
const continueRanges = checked > 0 && checkedSinceResolve < this._ranges.length && drain
|
|
2688
|
+
|
|
2689
|
+
this._updatingSeeks = true
|
|
2690
|
+
|
|
2691
|
+
let checkedSeek = false
|
|
2692
|
+
for (const s of this._seeks.slice()) {
|
|
2693
|
+
if (checkedSeeks.has(s) || !this._seeks.includes(s)) continue
|
|
2694
|
+
checkedSeeks.add(s)
|
|
2695
|
+
checkedSeek = true
|
|
2696
|
+
|
|
2697
|
+
let err = null
|
|
2698
|
+
let res = null
|
|
2699
|
+
|
|
2700
|
+
try {
|
|
2701
|
+
res = await s.seeker.update()
|
|
2702
|
+
} catch (error) {
|
|
2703
|
+
err = error
|
|
2704
|
+
}
|
|
2647
2705
|
|
|
2648
|
-
|
|
2706
|
+
const seekIndex = this._seeks.indexOf(s)
|
|
2707
|
+
if (seekIndex === -1 || (!res && !err)) continue
|
|
2649
2708
|
|
|
2650
|
-
|
|
2651
|
-
|
|
2709
|
+
const h = this._seeks.pop()
|
|
2710
|
+
if (h !== s) this._seeks[seekIndex] = h
|
|
2652
2711
|
|
|
2653
|
-
|
|
2712
|
+
if (err) s.reject(err)
|
|
2713
|
+
else s.resolve(res)
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
this._updatingSeeks = false
|
|
2717
|
+
|
|
2718
|
+
if (
|
|
2719
|
+
(!continueRanges || (checkedSeek && this._seeks.length > 0)) &&
|
|
2720
|
+
(this._inflight.idle || updateAll)
|
|
2721
|
+
) {
|
|
2722
|
+
this.queueUpdateAll()
|
|
2723
|
+
}
|
|
2724
|
+
if (!continueRanges) break
|
|
2654
2725
|
|
|
2655
|
-
|
|
2656
|
-
|
|
2726
|
+
await yieldToLoop()
|
|
2727
|
+
if (this.destroyed) break
|
|
2657
2728
|
}
|
|
2658
2729
|
|
|
2659
|
-
|
|
2660
|
-
if (--this._updatesPending === 0) break
|
|
2661
|
-
// Debounce the additional updates - continue
|
|
2662
|
-
this._updatesPending = 0
|
|
2730
|
+
if (this.destroyed) break
|
|
2663
2731
|
}
|
|
2664
2732
|
|
|
2665
|
-
|
|
2733
|
+
this._updatesRunning = false
|
|
2666
2734
|
}
|
|
2667
2735
|
|
|
2668
2736
|
_clearRequest(peer, req) {
|
|
@@ -3398,6 +3466,10 @@ function incrementRx(stats1, stats2) {
|
|
|
3398
3466
|
|
|
3399
3467
|
function noop() {}
|
|
3400
3468
|
|
|
3469
|
+
function yieldToLoop() {
|
|
3470
|
+
return new Promise((resolve) => setImmediate(resolve))
|
|
3471
|
+
}
|
|
3472
|
+
|
|
3401
3473
|
function backoff(times) {
|
|
3402
3474
|
const sleep = times < 2 ? 200 : times < 5 ? 500 : times < 40 ? 1000 : 5000
|
|
3403
3475
|
return new Promise((resolve) => setTimeout(resolve, sleep))
|