hypercore 11.26.0 → 11.27.0
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 +17 -12
- package/lib/core.js +6 -3
- package/lib/replicator.js +1 -0
- package/lib/session-state.js +47 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1057,22 +1057,27 @@ class Hypercore extends EventEmitter {
|
|
|
1057
1057
|
async recoverFromRemoteProof(remoteProof) {
|
|
1058
1058
|
this.core.replicator.setPushOnly(true)
|
|
1059
1059
|
this.core._repairMode = true
|
|
1060
|
+
|
|
1060
1061
|
await this.core.state.mutex.lock()
|
|
1061
|
-
const p = await verify(this.core.db, remoteProof)
|
|
1062
|
-
if (!p) return false
|
|
1063
1062
|
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
}
|
|
1068
|
-
await tx.flush()
|
|
1063
|
+
try {
|
|
1064
|
+
const p = await verify(this.core.db, remoteProof)
|
|
1065
|
+
if (!p) return false
|
|
1069
1066
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1067
|
+
const tx = this.core.storage.write()
|
|
1068
|
+
for (const node of p.proof.upgrade.nodes) {
|
|
1069
|
+
tx.putTreeNode(node)
|
|
1070
|
+
}
|
|
1071
|
+
await tx.flush()
|
|
1072
|
+
|
|
1073
|
+
const succeed = p.proof.upgrade.nodes.length !== 0
|
|
1074
|
+
if (succeed) {
|
|
1075
|
+
this.core.replicator.setPushOnly(false)
|
|
1076
|
+
}
|
|
1077
|
+
return succeed
|
|
1078
|
+
} finally {
|
|
1079
|
+
this.core.state.mutex.unlock()
|
|
1074
1080
|
}
|
|
1075
|
-
return succeed
|
|
1076
1081
|
}
|
|
1077
1082
|
|
|
1078
1083
|
recoverTreeNodeFromPeers() {
|
package/lib/core.js
CHANGED
|
@@ -204,7 +204,8 @@ module.exports = class Core {
|
|
|
204
204
|
hints: {
|
|
205
205
|
reorgs: [],
|
|
206
206
|
contiguousLength: 0,
|
|
207
|
-
remoteContiguousLength: 0
|
|
207
|
+
remoteContiguousLength: 0,
|
|
208
|
+
recovering: 0
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
|
|
@@ -553,7 +554,8 @@ module.exports = class Core {
|
|
|
553
554
|
|
|
554
555
|
tx.setHints({
|
|
555
556
|
contiguousLength: this.header.hints.contiguousLength,
|
|
556
|
-
remoteContiguousLength: this.header.hints.remoteContiguousLength
|
|
557
|
+
remoteContiguousLength: this.header.hints.remoteContiguousLength,
|
|
558
|
+
recovering: this.header.hints.recovering
|
|
557
559
|
})
|
|
558
560
|
|
|
559
561
|
await tx.flush()
|
|
@@ -963,7 +965,8 @@ function parseHeader(info) {
|
|
|
963
965
|
hints: {
|
|
964
966
|
reorgs: [],
|
|
965
967
|
contiguousLength: info.hints ? info.hints.contiguousLength : 0,
|
|
966
|
-
remoteContiguousLength: info.hints ? info.hints.remoteContiguousLength : 0
|
|
968
|
+
remoteContiguousLength: info.hints ? info.hints.remoteContiguousLength : 0,
|
|
969
|
+
recovering: info.recovering || 0
|
|
967
970
|
}
|
|
968
971
|
}
|
|
969
972
|
}
|
package/lib/replicator.js
CHANGED
|
@@ -987,6 +987,7 @@ class Peer {
|
|
|
987
987
|
async push(index) {
|
|
988
988
|
if (!this.remoteAllowPush) return
|
|
989
989
|
if (!this.remoteDownloading) return
|
|
990
|
+
if (this.core.state.length <= index) return
|
|
990
991
|
if (this.core.state.fork !== this.remoteFork) return
|
|
991
992
|
if (this.remoteBitfield.get(index)) return
|
|
992
993
|
|
package/lib/session-state.js
CHANGED
|
@@ -4,7 +4,13 @@ const assert = require('nanoassert')
|
|
|
4
4
|
const flat = require('flat-tree')
|
|
5
5
|
const quickbit = require('quickbit-universal')
|
|
6
6
|
|
|
7
|
-
const {
|
|
7
|
+
const {
|
|
8
|
+
INVALID_OPERATION,
|
|
9
|
+
INVALID_SIGNATURE,
|
|
10
|
+
ASSERTION,
|
|
11
|
+
SESSION_CLOSED,
|
|
12
|
+
SESSION_NOT_WRITABLE
|
|
13
|
+
} = require('hypercore-errors')
|
|
8
14
|
|
|
9
15
|
const Mutex = require('./mutex')
|
|
10
16
|
const Bitfield = require('./bitfield')
|
|
@@ -562,9 +568,47 @@ module.exports = class SessionState {
|
|
|
562
568
|
}
|
|
563
569
|
}
|
|
564
570
|
|
|
571
|
+
// simple tool to wait for other peers to catch us up
|
|
572
|
+
async _waitForRecovery() {
|
|
573
|
+
const length = this.length
|
|
574
|
+
const replicator = this.core.replicator
|
|
575
|
+
|
|
576
|
+
while (!this.closing) {
|
|
577
|
+
if (replicator.peers.length < 1) {
|
|
578
|
+
await new Promise((resolve) => setTimeout(resolve, 5000))
|
|
579
|
+
continue
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
await new Promise((resolve) => setTimeout(resolve, 5000))
|
|
583
|
+
|
|
584
|
+
const peers = replicator.peers
|
|
585
|
+
|
|
586
|
+
if (peers.length < 1 || this.closing) continue
|
|
587
|
+
if (peers[0].remoteLength > this.length) continue
|
|
588
|
+
|
|
589
|
+
if (this.length !== length) {
|
|
590
|
+
throw SESSION_NOT_WRITABLE('core recovered during append')
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
this.core.header.hints.recovering = 0
|
|
594
|
+
|
|
595
|
+
await this.mutex.lock()
|
|
596
|
+
try {
|
|
597
|
+
await this.core.flushHints()
|
|
598
|
+
return
|
|
599
|
+
} finally {
|
|
600
|
+
this.mutex.unlock()
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
throw SESSION_CLOSED('Cannot recover a closed session', this.discoveryKey)
|
|
605
|
+
}
|
|
606
|
+
|
|
565
607
|
async append(values, { signature, keyPair, preappend, postappend, maxLength = -1 } = {}) {
|
|
566
608
|
if (!keyPair && this.isDefault()) keyPair = this.core.header.keyPair
|
|
567
609
|
|
|
610
|
+
if (this.isDefault() && this.core.header.hints.recovering) await this._waitForRecovery()
|
|
611
|
+
|
|
568
612
|
await this.mutex.lock()
|
|
569
613
|
|
|
570
614
|
try {
|
|
@@ -921,6 +965,8 @@ module.exports = class SessionState {
|
|
|
921
965
|
throw ASSERTION('Cannot commit while repair mode is on')
|
|
922
966
|
}
|
|
923
967
|
|
|
968
|
+
if (this.core.header.hints.recovering) await this._waitForRecovery()
|
|
969
|
+
|
|
924
970
|
let srcLocked = false
|
|
925
971
|
await this.mutex.lock()
|
|
926
972
|
|