autobee 2.0.0 → 2.1.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 +151 -121
- package/lib/system.js +0 -9
- package/lib/topo.js +5 -9
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -51,11 +51,13 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
51
51
|
this.getSystemEncryption = this._getEncryptionProvider.bind(this, '_system')
|
|
52
52
|
this.getViewEncryption = this._getEncryptionProvider.bind(this, viewName)
|
|
53
53
|
|
|
54
|
-
const
|
|
54
|
+
const beeStore = store.session()
|
|
55
|
+
const bee = new Hyperbee(beeStore, {
|
|
56
|
+
core: beeStore.get({ preload: this._getCorePreload(viewName) }),
|
|
55
57
|
// defer one tick to ensure consistent state, then return state prom
|
|
56
58
|
preload: async () => {
|
|
57
59
|
await 1
|
|
58
|
-
await this.
|
|
60
|
+
await this._bootGuard.ready()
|
|
59
61
|
},
|
|
60
62
|
getEncryptionProvider: this.getViewEncryption
|
|
61
63
|
})
|
|
@@ -69,11 +71,12 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
69
71
|
this._handlers = handlers
|
|
70
72
|
this.stats = { undos: 0, fastForwards: 0, drains: 0, applies: 0, appends: 0 }
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
const systemStore = this.store.session()
|
|
75
|
+
this.system = new System(systemStore, this.name, {
|
|
76
|
+
core: systemStore.get({ preload: this._getCorePreload('system') }),
|
|
77
|
+
encrypted: this.encrypted,
|
|
78
|
+
getEncryptionProvider: this.getSystemEncryption
|
|
75
79
|
})
|
|
76
|
-
this.system.auto = this
|
|
77
80
|
|
|
78
81
|
this.bee = bee.snapshot()
|
|
79
82
|
this.view = ApplyView.open(this.bee, this)
|
|
@@ -120,9 +123,11 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
120
123
|
|
|
121
124
|
this.legacyViews = handlers.legacyViews || []
|
|
122
125
|
|
|
126
|
+
// the guards may be destroyed before anyone waits on them
|
|
123
127
|
this._bootGuard = new ReadyGuard()
|
|
124
|
-
this.
|
|
125
|
-
this.
|
|
128
|
+
this._bootGuard.ready().catch(safetyCatch)
|
|
129
|
+
this._bootOnlineGuard = new ReadyGuard()
|
|
130
|
+
this._bootOnlineGuard.ready().catch(safetyCatch)
|
|
126
131
|
|
|
127
132
|
this._now = handlers.now || Date.now // overridable for clock-drift tests
|
|
128
133
|
this._preapply = handlers.preapply || null
|
|
@@ -132,7 +137,6 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
132
137
|
this._needsUpdate = false
|
|
133
138
|
this._approvalCheck = true
|
|
134
139
|
this._approvedPending = new Map()
|
|
135
|
-
this._approvalRequests = []
|
|
136
140
|
this._prefetchingApprovals = false
|
|
137
141
|
this._updateLocalCore = null
|
|
138
142
|
this._host = new ApplyCalls(this)
|
|
@@ -150,6 +154,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
150
154
|
|
|
151
155
|
this._catchupMigratedNodes = null
|
|
152
156
|
this._migratedHead = null
|
|
157
|
+
this._prebooting = null
|
|
153
158
|
|
|
154
159
|
this.ready().catch(noop)
|
|
155
160
|
}
|
|
@@ -181,24 +186,56 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
181
186
|
return !!(this._draining || this._updating)
|
|
182
187
|
}
|
|
183
188
|
|
|
189
|
+
async _getCorePreload(name) {
|
|
190
|
+
await 1
|
|
191
|
+
const result = await this._prebooting
|
|
192
|
+
return {
|
|
193
|
+
name: 'autobee/' + result.local.id + '/' + name,
|
|
194
|
+
encryption: name === 'system' ? this.getSystemEncryption() : this.getViewEncryption(),
|
|
195
|
+
inflightRange: [256, 512]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// network free: only a migration needs peers, so ready() awaits the full
|
|
200
|
+
// state boot unless one is pending and defers it to the background if so -
|
|
201
|
+
// anything needing the booted system must wait on the boot guard
|
|
184
202
|
async _open() {
|
|
185
|
-
|
|
203
|
+
this._prebooting = this._preBoot()
|
|
186
204
|
|
|
187
|
-
|
|
188
|
-
this._bootingAll = this._bootAll()
|
|
205
|
+
let result = null
|
|
189
206
|
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
try {
|
|
208
|
+
result = await this._prebooting
|
|
209
|
+
|
|
210
|
+
this.key = result.key
|
|
211
|
+
this.bootstrap = result.bootstrap
|
|
212
|
+
this.discoveryKey = result.bootstrap.core.discoveryKey
|
|
213
|
+
this.id = result.bootstrap.core.id
|
|
214
|
+
this.encryptionKey = result.encryptionKey
|
|
215
|
+
this.previousDrain = result.previousDrain
|
|
216
|
+
this.local = result.local
|
|
217
|
+
|
|
218
|
+
if (this.encrypted && this.encryptionKey === null) {
|
|
219
|
+
throw new Error('Encryption key is expected')
|
|
220
|
+
}
|
|
192
221
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
222
|
+
this.local.setEncryption(this._getEncryptionProvider())
|
|
223
|
+
this.writers = new ActiveWriters(this)
|
|
224
|
+
} catch (err) {
|
|
225
|
+
// unblock the guard awaiters (bee preloads, bumps, wakeups, flushes)
|
|
226
|
+
this._bootGuard.destroy(err)
|
|
227
|
+
this._bootOnlineGuard.destroy(err)
|
|
228
|
+
throw err
|
|
229
|
+
}
|
|
196
230
|
|
|
197
|
-
|
|
198
|
-
this._localViewStart = this._workingBee.context.local.length
|
|
199
|
-
this._localFlushes = this.system.flushes
|
|
231
|
+
const booting = this._boot()
|
|
200
232
|
|
|
201
|
-
|
|
233
|
+
// waits on the boot guard internally and destroys its own guard on failure
|
|
234
|
+
this._bootOnline()
|
|
235
|
+
|
|
236
|
+
// if migrating, we might need network io, if not lets wait on it - less surprises
|
|
237
|
+
if (result.migration) booting.catch(this._onErrorBound)
|
|
238
|
+
else await booting
|
|
202
239
|
}
|
|
203
240
|
|
|
204
241
|
_requestWakeup() {
|
|
@@ -250,43 +287,40 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
250
287
|
|
|
251
288
|
async _close() {
|
|
252
289
|
this._interrupting = true
|
|
253
|
-
Hypercore.destroyRequests(this._approvalRequests, null)
|
|
254
|
-
if (this._bootWait !== null) this._bootWait.resolve()
|
|
255
|
-
if (this._notifyHandler) this._notifyHandler.destroy()
|
|
256
|
-
if (this._draining) {
|
|
257
|
-
// drain may be waiting on replicated blocks
|
|
258
|
-
this._clearRequests()
|
|
259
|
-
await this._draining
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (this._updating) await this._updating
|
|
263
290
|
|
|
264
|
-
// let in-flight writer adds finish
|
|
265
291
|
try {
|
|
266
|
-
await this.
|
|
267
|
-
} catch {
|
|
268
|
-
|
|
269
|
-
|
|
292
|
+
await ApplyView.close(this.view, this)
|
|
293
|
+
} catch (err) {
|
|
294
|
+
safetyCatch(err)
|
|
295
|
+
}
|
|
270
296
|
|
|
271
297
|
if (this.writers) await this.writers.close()
|
|
272
298
|
await this.local.close()
|
|
273
299
|
await this.system.close()
|
|
274
300
|
await this._wakeup.close()
|
|
275
|
-
if (this.bootstrap
|
|
276
|
-
await this._workingView.close()
|
|
277
|
-
await this.bee.close()
|
|
278
|
-
await this.store.close()
|
|
279
|
-
}
|
|
301
|
+
if (this.bootstrap) await this.bootstrap.close()
|
|
280
302
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
303
|
+
try {
|
|
304
|
+
await this._workingView.close()
|
|
305
|
+
await this.bee.close()
|
|
306
|
+
} catch (err) {
|
|
307
|
+
safetyCatch(err)
|
|
287
308
|
}
|
|
288
309
|
|
|
289
|
-
|
|
310
|
+
// don't rely on the store teardown to stop the notify watcher
|
|
311
|
+
if (this._notifyHandler) this._notifyHandler.destroy()
|
|
312
|
+
|
|
313
|
+
// rugpull the rest
|
|
314
|
+
await this.store.close()
|
|
315
|
+
|
|
316
|
+
if (this._bootWait !== null) this._bootWait.resolve()
|
|
317
|
+
if (this._updating) await this._updating
|
|
318
|
+
if (this._draining) await this._draining
|
|
319
|
+
|
|
320
|
+
// let in-flight writer adds finish
|
|
321
|
+
try {
|
|
322
|
+
await this._bootOnlineGuard.ready()
|
|
323
|
+
} catch {}
|
|
290
324
|
}
|
|
291
325
|
|
|
292
326
|
replicate(...args) {
|
|
@@ -296,7 +330,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
296
330
|
}
|
|
297
331
|
|
|
298
332
|
async flush() {
|
|
299
|
-
await this.
|
|
333
|
+
await this._bootOnlineGuard.ready()
|
|
300
334
|
}
|
|
301
335
|
|
|
302
336
|
hintWakeup(wakeup) {
|
|
@@ -322,6 +356,10 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
322
356
|
return new WriterEncryption(this)
|
|
323
357
|
}
|
|
324
358
|
|
|
359
|
+
getMostRecentHead() {
|
|
360
|
+
return topo.getMostRecentHead(this, this.system.bee.snapshot())
|
|
361
|
+
}
|
|
362
|
+
|
|
325
363
|
async _preBoot() {
|
|
326
364
|
if (this._handlers.wait) await this._handlers.wait()
|
|
327
365
|
|
|
@@ -338,17 +376,18 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
338
376
|
if (this.bootFrom) {
|
|
339
377
|
this.bootFrom = getBootOption(await this.bootFrom)
|
|
340
378
|
}
|
|
341
|
-
}
|
|
342
379
|
|
|
343
|
-
|
|
344
|
-
|
|
380
|
+
return boot(this.store, this.key, this.legacyViews, {
|
|
381
|
+
encryptionKey: this.encryptionKey,
|
|
382
|
+
keyPair: this.keyPair
|
|
383
|
+
})
|
|
345
384
|
}
|
|
346
385
|
|
|
347
|
-
async
|
|
386
|
+
async _boot() {
|
|
348
387
|
if (!this._bootGuard.enter()) return this._bootGuard.ready()
|
|
349
388
|
|
|
350
389
|
try {
|
|
351
|
-
await this.
|
|
390
|
+
await this._bootUnsafe()
|
|
352
391
|
} catch (err) {
|
|
353
392
|
this._bootGuard.destroy(err)
|
|
354
393
|
throw err
|
|
@@ -356,40 +395,13 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
356
395
|
|
|
357
396
|
this._bootGuard.exit()
|
|
358
397
|
|
|
359
|
-
|
|
360
|
-
}
|
|
398
|
+
this.bumpSoon()
|
|
361
399
|
|
|
362
|
-
|
|
363
|
-
if (this._bootGuard.opened) return true
|
|
364
|
-
try {
|
|
365
|
-
await this._bootGuard.ready()
|
|
366
|
-
return true
|
|
367
|
-
} catch {
|
|
368
|
-
return false
|
|
369
|
-
}
|
|
400
|
+
return this._bootGuard.ready()
|
|
370
401
|
}
|
|
371
402
|
|
|
372
|
-
async
|
|
373
|
-
const result = await
|
|
374
|
-
encryptionKey: this.encryptionKey,
|
|
375
|
-
keyPair: this.keyPair
|
|
376
|
-
})
|
|
377
|
-
|
|
378
|
-
this.key = result.key
|
|
379
|
-
this.bootstrap = result.bootstrap
|
|
380
|
-
this.discoveryKey = result.bootstrap.core.discoveryKey
|
|
381
|
-
this.id = result.bootstrap.core.id
|
|
382
|
-
this.encryptionKey = result.encryptionKey
|
|
383
|
-
this.previousDrain = result.previousDrain
|
|
384
|
-
this.local = result.local
|
|
385
|
-
|
|
386
|
-
if (this.encrypted && this.encryptionKey === null) {
|
|
387
|
-
throw new Error('Encryption key is expected')
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
this.local.setEncryption(this._getEncryptionProvider())
|
|
391
|
-
|
|
392
|
-
this.writers = new ActiveWriters(this)
|
|
403
|
+
async _bootUnsafe() {
|
|
404
|
+
const result = await this._prebooting
|
|
393
405
|
|
|
394
406
|
if (this._handlers.wakeupCapability) {
|
|
395
407
|
this.wakeupCapability = await this._handlers.wakeupCapability
|
|
@@ -458,31 +470,53 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
458
470
|
this.bee.move(view)
|
|
459
471
|
|
|
460
472
|
await this.writers.updateLocalState()
|
|
473
|
+
|
|
474
|
+
// roots are moved, so these resolve without re-entering the boot guard
|
|
475
|
+
await this.bee.ready()
|
|
476
|
+
await this._workingBee.ready()
|
|
477
|
+
|
|
478
|
+
// baseline before the guard opens so an early drain can't flush against stale offsets
|
|
479
|
+
this._localSystemStart = this.system.bee.context.local.length
|
|
480
|
+
this._localViewStart = this._workingBee.context.local.length
|
|
481
|
+
this._localFlushes = this.system.flushes
|
|
461
482
|
}
|
|
462
483
|
|
|
463
|
-
async
|
|
464
|
-
if (!
|
|
484
|
+
async _bootOnline() {
|
|
485
|
+
if (!this._bootOnlineGuard.enter()) return
|
|
465
486
|
|
|
466
|
-
|
|
467
|
-
await this.
|
|
468
|
-
|
|
487
|
+
try {
|
|
488
|
+
if (!this._bootGuard.opened) await this._bootGuard.ready()
|
|
489
|
+
|
|
490
|
+
for (const head of this.system.heads) {
|
|
491
|
+
await this.writers.add(head.key)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (!this.system.heads.length) {
|
|
495
|
+
await this.writers.add(this.bootstrap.key)
|
|
496
|
+
}
|
|
469
497
|
|
|
470
|
-
|
|
471
|
-
|
|
498
|
+
await this._bump(true)
|
|
499
|
+
} catch (err) {
|
|
500
|
+
this._bootOnlineGuard.destroy(err)
|
|
501
|
+
return
|
|
472
502
|
}
|
|
473
503
|
|
|
474
|
-
|
|
504
|
+
this._bootOnlineGuard.exit()
|
|
475
505
|
}
|
|
476
506
|
|
|
477
507
|
bumpSoon() {
|
|
478
|
-
this._bump().catch(safetyCatch)
|
|
508
|
+
this._bump(false).catch(safetyCatch)
|
|
479
509
|
}
|
|
480
510
|
|
|
481
|
-
async _bump() {
|
|
482
|
-
if (!
|
|
511
|
+
async _bump(force) {
|
|
512
|
+
if (!force && !this._bootGuard.opened) await this._bootGuard.ready()
|
|
483
513
|
|
|
514
|
+
// resolve before the bootAll gate: a parked boot-from retries on any bump,
|
|
515
|
+
// and its drain is the one _bootOnline itself is waiting on
|
|
484
516
|
if (this._bootWait !== null) this._bootWait.resolve()
|
|
485
517
|
|
|
518
|
+
if (!force && !this._bootOnlineGuard.opened) await this._bootOnlineGuard.ready()
|
|
519
|
+
|
|
486
520
|
this.bumping++
|
|
487
521
|
|
|
488
522
|
if (!this._draining) {
|
|
@@ -493,11 +527,11 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
493
527
|
}
|
|
494
528
|
|
|
495
529
|
update() {
|
|
496
|
-
return this._bump()
|
|
530
|
+
return this._bump(false)
|
|
497
531
|
}
|
|
498
532
|
|
|
499
533
|
async updated() {
|
|
500
|
-
if (this.opened
|
|
534
|
+
if (!this._bootGuard.opened) await this._bootGuard.ready()
|
|
501
535
|
if (this._draining) return this._draining
|
|
502
536
|
return Promise.resolve()
|
|
503
537
|
}
|
|
@@ -796,7 +830,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
796
830
|
}
|
|
797
831
|
|
|
798
832
|
async setLocal(key, { keyPair } = {}) {
|
|
799
|
-
if (!this.opened) await this.ready()
|
|
833
|
+
if (!this._bootGuard.opened) await this._bootGuard.ready()
|
|
800
834
|
if (this.closing) throw new Error('Autobee closed')
|
|
801
835
|
|
|
802
836
|
const manifest = keyPair
|
|
@@ -925,15 +959,13 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
925
959
|
if (this._prefetchingApprovals) return
|
|
926
960
|
this._prefetchingApprovals = true
|
|
927
961
|
|
|
928
|
-
const activeRequests = this._approvalRequests
|
|
929
|
-
|
|
930
962
|
try {
|
|
931
963
|
const prefetch = []
|
|
932
|
-
const standing = await this._standing(
|
|
964
|
+
const standing = await this._standing()
|
|
933
965
|
if (standing <= 0 || !this._pendingWork(standing)) return
|
|
934
|
-
for await (const p of this._servableRequests(standing
|
|
935
|
-
prefetch.push(this.system.get(p.key
|
|
936
|
-
prefetch.push(this.system.grantHint(p.key
|
|
966
|
+
for await (const p of this._servableRequests(standing)) {
|
|
967
|
+
prefetch.push(this.system.get(p.key).catch(safetyCatch))
|
|
968
|
+
prefetch.push(this.system.grantHint(p.key).catch(safetyCatch))
|
|
937
969
|
}
|
|
938
970
|
await Promise.allSettled(prefetch)
|
|
939
971
|
} finally {
|
|
@@ -941,8 +973,8 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
941
973
|
}
|
|
942
974
|
}
|
|
943
975
|
|
|
944
|
-
async _standing(
|
|
945
|
-
const rec = await this.system.get(this.local.key
|
|
976
|
+
async _standing() {
|
|
977
|
+
const rec = await this.system.get(this.local.key)
|
|
946
978
|
return currentWeight(rec)
|
|
947
979
|
}
|
|
948
980
|
|
|
@@ -960,8 +992,8 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
960
992
|
|
|
961
993
|
// the requests we could serve and by how much - shared by the prefetch and
|
|
962
994
|
// the collector so the two cannot drift on what counts as ours
|
|
963
|
-
async *_servableRequests(standing
|
|
964
|
-
for await (const p of this.system.listPendingPromotions(
|
|
995
|
+
async *_servableRequests(standing) {
|
|
996
|
+
for await (const p of this.system.listPendingPromotions()) {
|
|
965
997
|
const amount = Math.min(standing, p.weight)
|
|
966
998
|
if (amount <= 0) continue
|
|
967
999
|
yield { key: p.key, amount }
|
|
@@ -972,8 +1004,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
972
1004
|
if (!this.system.promotions.changed && !this._approvalCheck) return null
|
|
973
1005
|
if (!this.writers.writable) return null
|
|
974
1006
|
|
|
975
|
-
const
|
|
976
|
-
const standing = await this._standing(activeRequests)
|
|
1007
|
+
const standing = await this._standing()
|
|
977
1008
|
if (standing <= 0) return null
|
|
978
1009
|
|
|
979
1010
|
this.system.promotions.changed = false
|
|
@@ -984,7 +1015,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
984
1015
|
const approvals = []
|
|
985
1016
|
const approving = []
|
|
986
1017
|
|
|
987
|
-
for await (const p of this._servableRequests(standing
|
|
1018
|
+
for await (const p of this._servableRequests(standing)) {
|
|
988
1019
|
approving.push(fetchApproval.call(this, p.key, p.amount, approvals))
|
|
989
1020
|
}
|
|
990
1021
|
|
|
@@ -1008,10 +1039,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1008
1039
|
async function fetchApproval(key, weight, approvals) {
|
|
1009
1040
|
const hex = b4a.toString(key, 'hex')
|
|
1010
1041
|
if ((this._approvedPending.get(hex) || 0) >= weight) return
|
|
1011
|
-
const [target, hint] = await Promise.all([
|
|
1012
|
-
this.system.get(key, { activeRequests }),
|
|
1013
|
-
this.system.grantHint(key, { activeRequests })
|
|
1014
|
-
])
|
|
1042
|
+
const [target, hint] = await Promise.all([this.system.get(key), this.system.grantHint(key)])
|
|
1015
1043
|
if (!target || target.isRemoved) return
|
|
1016
1044
|
if (hint && hint.weight >= weight) return
|
|
1017
1045
|
approvals.push({ key, weight })
|
|
@@ -1209,10 +1237,12 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1209
1237
|
return encoding.encodeValue(value, opts)
|
|
1210
1238
|
}
|
|
1211
1239
|
|
|
1240
|
+
// gates on the state boot only, so hints can still feed a parked boot-from -
|
|
1241
|
+
// the trailing bump waits for bootAll like any other drain
|
|
1212
1242
|
async wakeup({ key, length }) {
|
|
1213
|
-
if (!
|
|
1243
|
+
if (!this._bootGuard.opened) await this._bootGuard.ready()
|
|
1214
1244
|
await this.writers.wakeup(key, length)
|
|
1215
|
-
await this._bump()
|
|
1245
|
+
await this._bump(false)
|
|
1216
1246
|
}
|
|
1217
1247
|
|
|
1218
1248
|
async append(values, { optimistic = false } = {}) {
|
|
@@ -1222,7 +1252,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1222
1252
|
|
|
1223
1253
|
if (!Array.isArray(values)) values = [values]
|
|
1224
1254
|
|
|
1225
|
-
if (!this.opened) await this.ready()
|
|
1255
|
+
if (!this._bootGuard.opened) await this._bootGuard.ready()
|
|
1226
1256
|
|
|
1227
1257
|
if (!optimistic && this.writers.localWriter.isRemoved) {
|
|
1228
1258
|
throw new Error('Not writable')
|
|
@@ -1263,7 +1293,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1263
1293
|
batch.push(node)
|
|
1264
1294
|
}
|
|
1265
1295
|
|
|
1266
|
-
return this._bump()
|
|
1296
|
+
return this._bump(false)
|
|
1267
1297
|
}
|
|
1268
1298
|
|
|
1269
1299
|
async _flushLocal() {
|
|
@@ -1294,7 +1324,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1294
1324
|
}
|
|
1295
1325
|
|
|
1296
1326
|
async moveTo(head) {
|
|
1297
|
-
if (!this.opened) await this.ready()
|
|
1327
|
+
if (!this._bootGuard.opened) await this._bootGuard.ready()
|
|
1298
1328
|
if (this.closing) throw new Error('Autobee closed')
|
|
1299
1329
|
|
|
1300
1330
|
const ff = await FastForward.fromHead(this, head, null, { force: true })
|
package/lib/system.js
CHANGED
|
@@ -8,8 +8,6 @@ const topo = require('./topo.js')
|
|
|
8
8
|
|
|
9
9
|
const INFO_KEY = b4a.from([0])
|
|
10
10
|
const INFO_LEGACY_KEY = b4a.concat([b4a.from([0, 0]), b4a.from('info')])
|
|
11
|
-
const INDEXER_GTE = b4a.from([2])
|
|
12
|
-
const INDEXER_LT = b4a.from([3])
|
|
13
11
|
const EMPTY_HEAD = { length: 0, key: null }
|
|
14
12
|
const EMPTY = b4a.from([])
|
|
15
13
|
|
|
@@ -124,13 +122,6 @@ module.exports = class Systembee {
|
|
|
124
122
|
return null
|
|
125
123
|
}
|
|
126
124
|
|
|
127
|
-
async *getIndexers() {
|
|
128
|
-
for await (const data of this.bee.createReadStream({ gte: INDEXER_GTE, lt: INDEXER_LT })) {
|
|
129
|
-
const key = data.key.subarray(1)
|
|
130
|
-
yield key
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
125
|
async reset({ timeout } = {}) {
|
|
135
126
|
const info = await this.getInfo({ timeout })
|
|
136
127
|
|
package/lib/topo.js
CHANGED
|
@@ -76,7 +76,7 @@ async function sort(auto, batch) {
|
|
|
76
76
|
for await (const data of ch) {
|
|
77
77
|
if (isLegacyNode(data)) break
|
|
78
78
|
|
|
79
|
-
const
|
|
79
|
+
const ref = getOplog(data)
|
|
80
80
|
const link = {
|
|
81
81
|
key: ref.oplog.key,
|
|
82
82
|
length: ref.oplog.length,
|
|
@@ -318,23 +318,18 @@ async function* oplogIterator(bee) {
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
function getOplog(data) {
|
|
321
|
-
const result = { ref: null, info: null }
|
|
322
321
|
for (const { keys } of data.batch) {
|
|
322
|
+
if (!keys) continue
|
|
323
|
+
|
|
323
324
|
for (const k of keys) {
|
|
324
325
|
const prefix = k.key[0]
|
|
325
326
|
|
|
326
|
-
if (prefix === 0) {
|
|
327
|
-
result.info = encoding.decodeSystemInfo(k.value)
|
|
328
|
-
if (result.ref) return result
|
|
329
|
-
}
|
|
330
|
-
|
|
331
327
|
if (prefix === 1) {
|
|
332
328
|
// expect inlined for now
|
|
333
329
|
const value = encoding.decodeSystemWriter(k.key, k.value)
|
|
334
330
|
if (!value.isOplog) continue
|
|
335
331
|
|
|
336
|
-
|
|
337
|
-
if (result.info) return result
|
|
332
|
+
return { undo: data.tail || EMPTY_HEAD, oplog: value }
|
|
338
333
|
}
|
|
339
334
|
}
|
|
340
335
|
}
|
|
@@ -395,6 +390,7 @@ function isLinkingAll(node, heads) {
|
|
|
395
390
|
|
|
396
391
|
function isLegacyNode(data) {
|
|
397
392
|
for (const { keys } of data.batch) {
|
|
393
|
+
if (!keys) continue
|
|
398
394
|
for (const k of keys) {
|
|
399
395
|
if (b4a.equals(k.key, INFO_LEGACY_KEY)) return true
|
|
400
396
|
}
|