autobee 2.9.5 → 2.10.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 +62 -10
- package/lib/fast-forward.js +1 -0
- package/lib/migrations.js +26 -7
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -114,6 +114,8 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
114
114
|
this.ff = null
|
|
115
115
|
this.fastForwarding = null
|
|
116
116
|
this.fastForwardTo = null
|
|
117
|
+
this._ffCandidates = new Map()
|
|
118
|
+
this._ffSearching = null
|
|
117
119
|
|
|
118
120
|
this._workingBee = bee
|
|
119
121
|
this._workingView = new ApplyView(this._workingBee, this)
|
|
@@ -425,6 +427,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
425
427
|
// rugpull the rest
|
|
426
428
|
await this.store.close()
|
|
427
429
|
|
|
430
|
+
if (this._ffSearching) await this._ffSearching
|
|
428
431
|
if (this._updating) await this._updating
|
|
429
432
|
if (this._draining) await this._draining
|
|
430
433
|
|
|
@@ -816,8 +819,22 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
816
819
|
const hints = await this._applyWakeupHints()
|
|
817
820
|
if (!hints.length) return
|
|
818
821
|
|
|
822
|
+
this._queueFastForward(hints)
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
_queueFastForward(hints) {
|
|
819
826
|
if (!this._ffEnabled) return
|
|
820
827
|
|
|
828
|
+
for (const { key, length } of hints) {
|
|
829
|
+
if (length === 0) continue
|
|
830
|
+
|
|
831
|
+
const hex = b4a.toString(key, 'hex')
|
|
832
|
+
const previous = this._ffCandidates.get(hex)
|
|
833
|
+
if (previous === undefined || previous < length) this._ffCandidates.set(hex, length)
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
if (!this._ffCandidates.size || this._ffSearching !== null) return
|
|
837
|
+
|
|
821
838
|
// a scheduled fast-forward is applied by the drain before we look again
|
|
822
839
|
if (this.fastForwardTo !== null || this.fastForwarding !== null) return
|
|
823
840
|
if (this._interrupting || this.closing || this.bootFrom) return
|
|
@@ -829,14 +846,34 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
829
846
|
return
|
|
830
847
|
}
|
|
831
848
|
|
|
849
|
+
this._ffSearching = this._searchFastForward().finally(() => {
|
|
850
|
+
this._ffSearching = null
|
|
851
|
+
})
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
async _searchFastForward() {
|
|
832
855
|
try {
|
|
833
|
-
|
|
856
|
+
while (this._ffCandidates.size) {
|
|
857
|
+
if (this.fastForwardTo !== null || this.fastForwarding !== null) return
|
|
858
|
+
if (this._interrupting || this.closing || this.bootFrom) return
|
|
859
|
+
|
|
860
|
+
const hints = flushCandidates(this._ffCandidates)
|
|
834
861
|
|
|
835
|
-
|
|
836
|
-
timeout: FastForward.DEFAULT_TIMEOUT
|
|
837
|
-
})
|
|
862
|
+
const heads = await this._readCandidateHeads(hints, FastForward.DEFAULT_TIMEOUT)
|
|
838
863
|
|
|
839
|
-
|
|
864
|
+
const ff = await FastForward.fromHeads(this, heads, {
|
|
865
|
+
timeout: FastForward.DEFAULT_TIMEOUT
|
|
866
|
+
})
|
|
867
|
+
|
|
868
|
+
if (ff === null) continue
|
|
869
|
+
|
|
870
|
+
if (this._interrupting || this.closing) {
|
|
871
|
+
await ff.close()
|
|
872
|
+
return
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
if (await this._runFastForward(ff)) return
|
|
876
|
+
}
|
|
840
877
|
} catch (err) {
|
|
841
878
|
safetyCatch(err)
|
|
842
879
|
}
|
|
@@ -1475,7 +1512,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1475
1512
|
const ff = await FastForward.fromHead(this, head, null, { force: true, timeout })
|
|
1476
1513
|
if (ff === null) return null
|
|
1477
1514
|
|
|
1478
|
-
if (!(await this._runFastForward(ff))) return null
|
|
1515
|
+
if (!(await this._runFastForward(ff, { force: true }))) return null
|
|
1479
1516
|
|
|
1480
1517
|
return this.ff.promise
|
|
1481
1518
|
}
|
|
@@ -1484,7 +1521,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1484
1521
|
async _bootFromSystem(system) {
|
|
1485
1522
|
try {
|
|
1486
1523
|
const ff = new FastForward(this, system, { timeout: FastForward.DEFAULT_TIMEOUT })
|
|
1487
|
-
return await this._runFastForward(ff)
|
|
1524
|
+
return await this._runFastForward(ff, { force: true })
|
|
1488
1525
|
} catch (err) {
|
|
1489
1526
|
safetyCatch(err)
|
|
1490
1527
|
return false
|
|
@@ -1500,14 +1537,14 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1500
1537
|
|
|
1501
1538
|
const ff = await FastForward.fromHead(this, oplog, null, { force: true, timeout })
|
|
1502
1539
|
|
|
1503
|
-
return ff !== null && (await this._runFastForward(ff))
|
|
1540
|
+
return ff !== null && (await this._runFastForward(ff, { force: true }))
|
|
1504
1541
|
} catch (err) {
|
|
1505
1542
|
safetyCatch(err)
|
|
1506
1543
|
return false
|
|
1507
1544
|
}
|
|
1508
1545
|
}
|
|
1509
1546
|
|
|
1510
|
-
async _runFastForward(ff) {
|
|
1547
|
+
async _runFastForward(ff, { force = false } = {}) {
|
|
1511
1548
|
if (this.fastForwardTo !== null || this.fastForwarding !== null) {
|
|
1512
1549
|
await ff.close()
|
|
1513
1550
|
return false
|
|
@@ -1516,12 +1553,15 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1516
1553
|
this.fastForwarding = ff
|
|
1517
1554
|
|
|
1518
1555
|
const result = await ff.run()
|
|
1556
|
+
const flushes = ff.system.flushes
|
|
1519
1557
|
await ff.close()
|
|
1520
1558
|
|
|
1521
1559
|
if (this.fastForwarding === ff) this.fastForwarding = null
|
|
1522
1560
|
|
|
1523
1561
|
if (!result) return false
|
|
1524
1562
|
|
|
1563
|
+
if (!force && flushes - this.system.flushes < FastForward.MIN_GAP) return false
|
|
1564
|
+
|
|
1525
1565
|
this.fastForwardTo = result
|
|
1526
1566
|
this.ff = rrp()
|
|
1527
1567
|
|
|
@@ -1561,7 +1601,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1561
1601
|
this.fastForwardTo = null
|
|
1562
1602
|
|
|
1563
1603
|
// process any wakeup while fast-forward itself was in flight
|
|
1564
|
-
await this._applyWakeupHints()
|
|
1604
|
+
this._queueFastForward(await this._applyWakeupHints())
|
|
1565
1605
|
await this.writers.refresh()
|
|
1566
1606
|
|
|
1567
1607
|
// we moved, so ask our peers to tell us their heads again
|
|
@@ -1597,6 +1637,18 @@ function getBootOption(boot) {
|
|
|
1597
1637
|
return boot
|
|
1598
1638
|
}
|
|
1599
1639
|
|
|
1640
|
+
function flushCandidates(candidates) {
|
|
1641
|
+
const hints = []
|
|
1642
|
+
|
|
1643
|
+
for (const [hex, length] of candidates) {
|
|
1644
|
+
hints.push({ key: b4a.from(hex, 'hex'), length })
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
candidates.clear()
|
|
1648
|
+
|
|
1649
|
+
return hints
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1600
1652
|
function noop() {}
|
|
1601
1653
|
|
|
1602
1654
|
function createAnchorCore(store, prologue, manifestData) {
|
package/lib/fast-forward.js
CHANGED
package/lib/migrations.js
CHANGED
|
@@ -84,7 +84,7 @@ async function checkAutobaseMigration(store, local, bootstrap) {
|
|
|
84
84
|
let catchup
|
|
85
85
|
|
|
86
86
|
try {
|
|
87
|
-
length = await findLocalSystemLength(core, session, systemLength)
|
|
87
|
+
length = await findLocalSystemLength(store, core, session, systemLength)
|
|
88
88
|
catchup = await getCatchupHeads(session, length)
|
|
89
89
|
} finally {
|
|
90
90
|
await session.close()
|
|
@@ -205,18 +205,14 @@ function deriveNamespace(name, bootstrap, entropy, encryptionKey) {
|
|
|
205
205
|
// scan back for the newest block the signed core actually has locally
|
|
206
206
|
// the newest INFO the signed core holds that the batch session agrees with -
|
|
207
207
|
// past its dependency the batch is speculative and may have diverged
|
|
208
|
-
async function findLocalSystemLength(core, session, systemLength) {
|
|
208
|
+
async function findLocalSystemLength(store, core, session, systemLength) {
|
|
209
209
|
let length = Math.min(core.length, systemLength)
|
|
210
210
|
|
|
211
211
|
while (length > 0) {
|
|
212
212
|
const seq = length - 1
|
|
213
213
|
const node = await core.get(seq, { wait: false })
|
|
214
214
|
|
|
215
|
-
if (node)
|
|
216
|
-
const blk = decodeBlock(node)
|
|
217
|
-
const entry = blk.keys[0]
|
|
218
|
-
if (b4a.equals(entry.key, INFO) && (await sameTree(core, session, length))) return length
|
|
219
|
-
}
|
|
215
|
+
if (node && (await isReachableInfo(store, core, session, node, length))) return length
|
|
220
216
|
|
|
221
217
|
length--
|
|
222
218
|
}
|
|
@@ -224,6 +220,15 @@ async function findLocalSystemLength(core, session, systemLength) {
|
|
|
224
220
|
return 0
|
|
225
221
|
}
|
|
226
222
|
|
|
223
|
+
// an INFO block the batch agrees with whose views the store has caught up to -
|
|
224
|
+
// otherwise the migrated view would be ahead of what the system can prove
|
|
225
|
+
async function isReachableInfo(store, core, session, node, length) {
|
|
226
|
+
const entry = decodeBlock(node).keys[0]
|
|
227
|
+
if (!b4a.equals(entry.key, INFO)) return false
|
|
228
|
+
if (!(await sameTree(core, session, length))) return false
|
|
229
|
+
return viewsReached(store, decodeLegacySystemInfo(entry.value))
|
|
230
|
+
}
|
|
231
|
+
|
|
227
232
|
async function sameTree(core, session, length) {
|
|
228
233
|
if (length <= session.signedLength) return true
|
|
229
234
|
if (length > session.length) return false
|
|
@@ -358,3 +363,17 @@ async function getWriterBatch(store, head, key, encryptionKey, nodes = []) {
|
|
|
358
363
|
|
|
359
364
|
return batch
|
|
360
365
|
}
|
|
366
|
+
|
|
367
|
+
async function viewsReached(store, info) {
|
|
368
|
+
for (const v of info.views) {
|
|
369
|
+
if (!v.length) continue
|
|
370
|
+
const core = store.get({ key: v.key, active: false })
|
|
371
|
+
try {
|
|
372
|
+
await core.ready()
|
|
373
|
+
if (core.length < v.length) return false
|
|
374
|
+
} finally {
|
|
375
|
+
await core.close()
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return true
|
|
379
|
+
}
|