autobee 2.0.0-rc.25 → 2.0.0-rc.27
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 +45 -16
- package/lib/system.js +2 -2
- package/lib/topo.js +16 -1
- package/lib/writers.js +22 -6
- package/package.json +3 -2
package/index.js
CHANGED
|
@@ -14,6 +14,7 @@ const asserts = require('./lib/asserts.js')
|
|
|
14
14
|
const boot = require('./lib/boot.js')
|
|
15
15
|
const { resolveWeight, currentWeight } = require('./lib/witness.js')
|
|
16
16
|
const encoding = require('./lib/encoding.js')
|
|
17
|
+
const { LEGACY_OPLOG_VERSION } = require('./lib/constants.js')
|
|
17
18
|
const FastForward = require('./lib/fast-forward.js')
|
|
18
19
|
const System = require('./lib/system.js')
|
|
19
20
|
const ApplyCalls = require('./lib/apply-calls.js')
|
|
@@ -176,6 +177,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
176
177
|
this._bootingAll.catch(safetyCatch)
|
|
177
178
|
|
|
178
179
|
await this.bee.ready()
|
|
180
|
+
await this._workingBee.ready()
|
|
179
181
|
await this._bootingState
|
|
180
182
|
|
|
181
183
|
this._localSystemStart = this.system.bee.context.local.length
|
|
@@ -527,12 +529,12 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
527
529
|
this.stats.drains++
|
|
528
530
|
|
|
529
531
|
if (this.bootFrom) {
|
|
530
|
-
const { head = null, legacy = null, bootCondition = null } = this.bootFrom
|
|
532
|
+
const { head = null, legacy = null, bootCondition = null, wait = false } = this.bootFrom
|
|
531
533
|
|
|
532
534
|
this.bootFrom = null
|
|
533
535
|
|
|
534
536
|
if (legacy) await this._bootFromSystem(legacy)
|
|
535
|
-
else if (head) await this._bootFromHead(head, bootCondition)
|
|
537
|
+
else if (head) await this._bootFromHead(head, bootCondition, wait)
|
|
536
538
|
}
|
|
537
539
|
|
|
538
540
|
this._ackRequired = false
|
|
@@ -1041,12 +1043,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1041
1043
|
|
|
1042
1044
|
this.writers.attest(witnessed)
|
|
1043
1045
|
|
|
1044
|
-
for (const { key, added
|
|
1045
|
-
if (isAnchor) {
|
|
1046
|
-
// no Writer/ActiveWriters tracking, but still wake anything linked to it
|
|
1047
|
-
this.writers.triggers.trigger(b4a.toString(key, 'hex'), 1)
|
|
1048
|
-
continue
|
|
1049
|
-
}
|
|
1046
|
+
for (const { key, added } of changed) {
|
|
1050
1047
|
if (added) await this.writers.add(key)
|
|
1051
1048
|
else await this.writers.remove(key)
|
|
1052
1049
|
}
|
|
@@ -1195,9 +1192,9 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1195
1192
|
|
|
1196
1193
|
// the boot head seeds the view every trust decision here is made against,
|
|
1197
1194
|
// since our own view is still empty
|
|
1198
|
-
async _bootFromHead(head, bootCondition) {
|
|
1195
|
+
async _bootFromHead(head, bootCondition, wait = false) {
|
|
1199
1196
|
// just a head: one attempt, we do not wait around if it cannot be read
|
|
1200
|
-
if (bootCondition === null) {
|
|
1197
|
+
if (bootCondition === null && !wait) {
|
|
1201
1198
|
try {
|
|
1202
1199
|
const ff = await FastForward.fromHead(this, head, null, {
|
|
1203
1200
|
force: true,
|
|
@@ -1211,8 +1208,8 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1211
1208
|
}
|
|
1212
1209
|
}
|
|
1213
1210
|
|
|
1214
|
-
//
|
|
1215
|
-
//
|
|
1211
|
+
// park until the head can be read and, if a condition is set, something
|
|
1212
|
+
// acceptable turns up
|
|
1216
1213
|
let opened = null
|
|
1217
1214
|
|
|
1218
1215
|
try {
|
|
@@ -1220,10 +1217,28 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1220
1217
|
this._bootWait = rrp()
|
|
1221
1218
|
|
|
1222
1219
|
try {
|
|
1223
|
-
if (
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1220
|
+
if (bootCondition === null) {
|
|
1221
|
+
const ff = await FastForward.fromHead(this, head, null, {
|
|
1222
|
+
force: true,
|
|
1223
|
+
timeout: FastForward.DEFAULT_TIMEOUT
|
|
1224
|
+
})
|
|
1225
|
+
|
|
1226
|
+
if (ff !== null && (await this._runFastForward(ff))) return true
|
|
1227
|
+
} else {
|
|
1228
|
+
if (opened === null) opened = await this._bootReference(head)
|
|
1229
|
+
|
|
1230
|
+
if (opened !== null) {
|
|
1231
|
+
if (await this._bootAttempt(head, bootCondition, opened.view)) {
|
|
1232
|
+
return true
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
// the reference may be stale - resolve it afresh next attempt
|
|
1236
|
+
await opened.close()
|
|
1237
|
+
opened = null
|
|
1238
|
+
} else if (await this._bootLegacyHead(head)) {
|
|
1239
|
+
// boot legacy head through the migration pathway
|
|
1240
|
+
return true
|
|
1241
|
+
}
|
|
1227
1242
|
}
|
|
1228
1243
|
} catch (err) {
|
|
1229
1244
|
safetyCatch(err)
|
|
@@ -1258,6 +1273,20 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1258
1273
|
return ff !== null && (await this._runFastForward(ff))
|
|
1259
1274
|
}
|
|
1260
1275
|
|
|
1276
|
+
async _bootLegacyHead(head) {
|
|
1277
|
+
const oplog = await FastForward.flushHead(this, head, {
|
|
1278
|
+
timeout: FastForward.DEFAULT_TIMEOUT
|
|
1279
|
+
})
|
|
1280
|
+
if (oplog === null || oplog.op.version > LEGACY_OPLOG_VERSION) return false
|
|
1281
|
+
|
|
1282
|
+
const ff = await FastForward.fromHead(this, head, null, {
|
|
1283
|
+
force: true,
|
|
1284
|
+
timeout: FastForward.DEFAULT_TIMEOUT
|
|
1285
|
+
})
|
|
1286
|
+
|
|
1287
|
+
return ff !== null && (await this._runFastForward(ff))
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1261
1290
|
async _bootReference(head) {
|
|
1262
1291
|
const oplog = await FastForward.flushHead(this, head, {
|
|
1263
1292
|
timeout: FastForward.DEFAULT_TIMEOUT
|
package/lib/system.js
CHANGED
|
@@ -85,8 +85,8 @@ module.exports = class Systembee {
|
|
|
85
85
|
this.update(key, length, -1, 0, false, false, true, false, false, -1, false)
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
addAnchor(key
|
|
89
|
-
this.update(key,
|
|
88
|
+
addAnchor(key) {
|
|
89
|
+
this.update(key, 0, -1, -1, false, true, false, false, true, -1, false)
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
isGenesis() {
|
package/lib/topo.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const b4a = require('b4a')
|
|
2
2
|
const encoding = require('./encoding.js')
|
|
3
|
-
const { createNode } = require('./writers.js')
|
|
3
|
+
const { createNode, finalizeNodeBatch } = require('./writers.js')
|
|
4
4
|
const asserts = require('./asserts.js')
|
|
5
|
+
const { LEGACY_OPLOG_VERSION } = require('./constants.js')
|
|
5
6
|
|
|
6
7
|
const EMPTY_HEAD = { length: 0, key: null }
|
|
7
8
|
const INFO_LEGACY_KEY = b4a.concat([b4a.from([0, 0]), b4a.from('info')])
|
|
@@ -275,8 +276,20 @@ async function getOplogBatch(undo, core, length, weight, index, opts = null) {
|
|
|
275
276
|
const seq = length - 1
|
|
276
277
|
const block = await core.get(seq, opts)
|
|
277
278
|
if (block === null) return null
|
|
279
|
+
|
|
278
280
|
const oplog = encoding.decodeOplog(block)
|
|
279
281
|
const head = createNode(core, length, weight, oplog)
|
|
282
|
+
const legacy = oplog.version <= LEGACY_OPLOG_VERSION
|
|
283
|
+
|
|
284
|
+
// if this is legacy the start pointer is always 0, fix
|
|
285
|
+
if (legacy) {
|
|
286
|
+
for (let i = length - 1; i > 0; i--) {
|
|
287
|
+
const block = await core.get(i - 1, opts)
|
|
288
|
+
const oplog = encoding.decodeOplog(block)
|
|
289
|
+
if (oplog.batch.end === 0) break
|
|
290
|
+
head.batch.start++
|
|
291
|
+
}
|
|
292
|
+
}
|
|
280
293
|
|
|
281
294
|
const batch = []
|
|
282
295
|
const result = { undo, batch, index }
|
|
@@ -304,6 +317,8 @@ async function getOplogBatch(undo, core, length, weight, index, opts = null) {
|
|
|
304
317
|
}
|
|
305
318
|
|
|
306
319
|
batch.push(head)
|
|
320
|
+
finalizeNodeBatch(batch)
|
|
321
|
+
|
|
307
322
|
return result
|
|
308
323
|
}
|
|
309
324
|
|
package/lib/writers.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const b4a = require('b4a')
|
|
2
2
|
const encoding = require('./encoding.js')
|
|
3
3
|
const Triggers = require('./triggers.js')
|
|
4
|
+
const { LEGACY_OPLOG_VERSION } = require('./constants.js')
|
|
4
5
|
const { signAttestation, resolveWeight } = require('./witness.js')
|
|
5
6
|
const { WriterEncryption } = require('autobee-encryption')
|
|
6
7
|
|
|
@@ -59,21 +60,23 @@ class ActiveWriters {
|
|
|
59
60
|
let w = this.active.get(id)
|
|
60
61
|
|
|
61
62
|
if (w === this.localWriter) return
|
|
63
|
+
|
|
64
|
+
let added = false
|
|
62
65
|
if (!w) {
|
|
63
|
-
// anchors are local-only and never replicated - nothing to fetch
|
|
64
|
-
const info = await this.auto.system.get(key, { unflushed: true })
|
|
65
|
-
if (info && info.isAnchor) return
|
|
66
66
|
w = await this.add(key)
|
|
67
67
|
if (!w) return
|
|
68
|
+
added = true
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
const advanced = length > w.hintedLength
|
|
72
|
+
|
|
70
73
|
// remember the announced length so gc doesn't drop a writer we haven't caught up on
|
|
71
74
|
w.hint(length)
|
|
72
75
|
|
|
73
76
|
// prefetch the oplog head for the fast-forward that runs right after us
|
|
74
77
|
if (w && length > 0) w.core.get(length - 1).catch(noop)
|
|
75
78
|
|
|
76
|
-
this.bump()
|
|
79
|
+
if (added || advanced) this.bump()
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
getLatestLocalOplog() {
|
|
@@ -448,7 +451,9 @@ class Writer {
|
|
|
448
451
|
async update() {
|
|
449
452
|
const info = await this.system.get(this.core.key)
|
|
450
453
|
|
|
451
|
-
|
|
454
|
+
// an anchor core is prologue-only, so once its single node has applied
|
|
455
|
+
// nothing more can ever come - retire the writer
|
|
456
|
+
if (info && info.isAnchor && info.length > 0 && this !== this.writers.localWriter) {
|
|
452
457
|
await this.detachAndClose()
|
|
453
458
|
return info.length
|
|
454
459
|
}
|
|
@@ -567,7 +572,7 @@ class Writer {
|
|
|
567
572
|
}
|
|
568
573
|
|
|
569
574
|
batch.push(node)
|
|
570
|
-
if (b.end === 0) return batch
|
|
575
|
+
if (b.end === 0) return finalizeNodeBatch(batch)
|
|
571
576
|
|
|
572
577
|
// TODO: mark as dead
|
|
573
578
|
if (batch.length >= BATCH_WRITER_SANITY) return null
|
|
@@ -758,6 +763,7 @@ function sortsBefore(a, b) {
|
|
|
758
763
|
exports.ActiveWriters = ActiveWriters
|
|
759
764
|
exports.Writer = Writer
|
|
760
765
|
exports.createNode = createNode
|
|
766
|
+
exports.finalizeNodeBatch = finalizeNodeBatch
|
|
761
767
|
|
|
762
768
|
function createNode(core, length, weight, oplog) {
|
|
763
769
|
return {
|
|
@@ -779,4 +785,14 @@ function createNode(core, length, weight, oplog) {
|
|
|
779
785
|
}
|
|
780
786
|
}
|
|
781
787
|
|
|
788
|
+
function finalizeNodeBatch(batch) {
|
|
789
|
+
if (batch.length === 0 || batch[0].version > LEGACY_OPLOG_VERSION) return batch
|
|
790
|
+
|
|
791
|
+
for (let i = 0; i < batch.length; i++) {
|
|
792
|
+
batch[i].batch.start = i
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
return batch
|
|
796
|
+
}
|
|
797
|
+
|
|
782
798
|
function noop() {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autobee",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.27",
|
|
4
4
|
"description": "Bee based autobase",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Holepunch Inc.",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"lunte": "^1.6.0",
|
|
44
44
|
"prettier": "^3.8.1",
|
|
45
45
|
"prettier-config-holepunch": "^2.0.0",
|
|
46
|
-
"protomux-wakeup": "^2.9.0"
|
|
46
|
+
"protomux-wakeup": "^2.9.0",
|
|
47
|
+
"replication-simulator": "^3.0.0"
|
|
47
48
|
}
|
|
48
49
|
}
|