autobee 2.0.0-rc.31 → 2.0.0-rc.34
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 +52 -72
- package/lib/apply-calls.js +0 -5
- package/lib/fast-forward.js +3 -16
- package/lib/migrations.js +3 -1
- package/lib/system.js +14 -25
- package/lib/witness.js +1 -2
- package/lib/writers.js +41 -46
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -129,12 +129,10 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
129
129
|
this._hasApply = !!handlers.apply
|
|
130
130
|
this._hasUpdate = !!handlers.update
|
|
131
131
|
this._needsUpdate = false
|
|
132
|
-
this._ackRequired = false
|
|
133
132
|
this._approvalCheck = true
|
|
134
133
|
this._approvedPending = new Map()
|
|
135
134
|
this._approvalRequests = []
|
|
136
135
|
this._prefetchingApprovals = false
|
|
137
|
-
this._ackedHeads = new Map()
|
|
138
136
|
this._updateLocalCore = null
|
|
139
137
|
this._host = new ApplyCalls(this)
|
|
140
138
|
this._notifyHandler = null
|
|
@@ -385,7 +383,6 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
385
383
|
}
|
|
386
384
|
|
|
387
385
|
this.local.setEncryption(this._getEncryptionProvider())
|
|
388
|
-
this.local.setActive(true)
|
|
389
386
|
|
|
390
387
|
this.writers = new ActiveWriters(this)
|
|
391
388
|
|
|
@@ -464,6 +461,11 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
464
461
|
for (const head of this.system.heads) {
|
|
465
462
|
await this.writers.add(head.key)
|
|
466
463
|
}
|
|
464
|
+
|
|
465
|
+
if (!this.system.heads.length) {
|
|
466
|
+
await this.writers.add(this.bootstrap.key)
|
|
467
|
+
}
|
|
468
|
+
|
|
467
469
|
await this._bump()
|
|
468
470
|
}
|
|
469
471
|
|
|
@@ -554,8 +556,6 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
554
556
|
else if (head) await this._bootFromHead(head, bootCondition, wait)
|
|
555
557
|
}
|
|
556
558
|
|
|
557
|
-
this._ackRequired = false
|
|
558
|
-
|
|
559
559
|
const changes = this._hasUpdate ? new UpdateChanges(this) : null
|
|
560
560
|
if (changes) changes.track()
|
|
561
561
|
|
|
@@ -578,16 +578,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
578
578
|
break // revaluate conditions...
|
|
579
579
|
}
|
|
580
580
|
|
|
581
|
-
if (await this._bumpPendingWriters())
|
|
582
|
-
this._needsUpdate = true
|
|
583
|
-
continue
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
if (!this._appendAck()) break
|
|
587
|
-
this._needsUpdate = true
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
if (!this._interrupting && (await this._appendApprovals())) {
|
|
581
|
+
if (!(await this._bumpPendingWriters())) break
|
|
591
582
|
this._needsUpdate = true
|
|
592
583
|
}
|
|
593
584
|
|
|
@@ -647,24 +638,44 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
647
638
|
// wakeup hints keep arriving asynchronously
|
|
648
639
|
async _applyWakeupHints() {
|
|
649
640
|
const hints = this._wakeup.flush()
|
|
650
|
-
if (!hints.size) return
|
|
641
|
+
if (!hints.size) return []
|
|
651
642
|
|
|
652
643
|
this.previousDrain = Date.now()
|
|
644
|
+
const results = await this._filterHints(hints)
|
|
653
645
|
|
|
654
|
-
for (const
|
|
655
|
-
const key = b4a.from(hex, 'hex')
|
|
646
|
+
for (const { key, length } of results) {
|
|
656
647
|
// wakeup() itself no-ops the add for an already-active writer, but still
|
|
657
648
|
// needs to run so it can hint() the announced length - skipping it here
|
|
658
649
|
// for active writers left gc with no hint to protect them
|
|
659
650
|
await this.writers.wakeup(key, length)
|
|
660
651
|
}
|
|
661
652
|
|
|
662
|
-
return
|
|
653
|
+
return results
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
async _filterHints(hints) {
|
|
657
|
+
const results = []
|
|
658
|
+
const promises = []
|
|
659
|
+
for (const [hex, length] of hints) {
|
|
660
|
+
const key = b4a.from(hex, 'hex')
|
|
661
|
+
promises.push(this._filterTracked(key, length, results))
|
|
662
|
+
}
|
|
663
|
+
await Promise.all(promises)
|
|
664
|
+
return results
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
async _filterTracked(key, length, results) {
|
|
668
|
+
if (length) {
|
|
669
|
+
const info = await this.system.get(key)
|
|
670
|
+
// if we've seen this already, ignore
|
|
671
|
+
if (info && info.length >= length) return
|
|
672
|
+
}
|
|
673
|
+
results.push({ key, length })
|
|
663
674
|
}
|
|
664
675
|
|
|
665
676
|
async _flushWakeup() {
|
|
666
677
|
const hints = await this._applyWakeupHints()
|
|
667
|
-
if (!hints.
|
|
678
|
+
if (!hints.length) return
|
|
668
679
|
|
|
669
680
|
if (!this._ffEnabled) return
|
|
670
681
|
|
|
@@ -688,10 +699,9 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
688
699
|
async _readCandidateHeads(hints, timeout) {
|
|
689
700
|
const promises = []
|
|
690
701
|
|
|
691
|
-
for (const
|
|
702
|
+
for (const { key, length } of hints) {
|
|
692
703
|
if (length === 0) continue
|
|
693
|
-
|
|
694
|
-
promises.push(this._getOplog(key, length, timeout ? { timeout } : null))
|
|
704
|
+
promises.push(this._resolveOplogHint(key, length, timeout ? { timeout } : null))
|
|
695
705
|
}
|
|
696
706
|
|
|
697
707
|
const ops = await Promise.all(promises)
|
|
@@ -714,6 +724,22 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
714
724
|
return heads
|
|
715
725
|
}
|
|
716
726
|
|
|
727
|
+
async _resolveOplogHint(key, length, opts) {
|
|
728
|
+
const core = this.openCore(key)
|
|
729
|
+
|
|
730
|
+
try {
|
|
731
|
+
await core.ready()
|
|
732
|
+
const max = Math.max(length, core.length)
|
|
733
|
+
|
|
734
|
+
const block = await this.readOplog(core, max, opts)
|
|
735
|
+
if (max >= core.length) return block // best one
|
|
736
|
+
|
|
737
|
+
return await this.readOplog(core, core.length, opts)
|
|
738
|
+
} finally {
|
|
739
|
+
await core.close()
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
717
743
|
async _getOplog(key, length, opts = null) {
|
|
718
744
|
const core = this.openCore(key)
|
|
719
745
|
|
|
@@ -987,51 +1013,6 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
987
1013
|
}
|
|
988
1014
|
}
|
|
989
1015
|
|
|
990
|
-
async _appendApprovals() {
|
|
991
|
-
if (!this.writers.writable) return false
|
|
992
|
-
|
|
993
|
-
const approvals = await this._collectApprovals()
|
|
994
|
-
if (!approvals) return false
|
|
995
|
-
|
|
996
|
-
const links = this.system.getLinks(this.local.key)
|
|
997
|
-
const t = Math.max(this._now(), this.system.timestamp)
|
|
998
|
-
this.writers.appendLocal(null, t, { start: 0, end: 0 }, links, false, null, approvals)
|
|
999
|
-
return true
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
// append a null value node to ack writer
|
|
1003
|
-
_appendAck() {
|
|
1004
|
-
if (!this._ackRequired) return false
|
|
1005
|
-
if (!this.writers.writable) return false
|
|
1006
|
-
|
|
1007
|
-
if (this.writers.localWriter.pending !== null) return false
|
|
1008
|
-
|
|
1009
|
-
const links = this.system.getLinks(this.local.key)
|
|
1010
|
-
const t = Math.max(this._now(), this.system.timestamp)
|
|
1011
|
-
|
|
1012
|
-
let unlinked = false
|
|
1013
|
-
for (const { key, length } of links) {
|
|
1014
|
-
const hex = b4a.toString(key, 'hex')
|
|
1015
|
-
const acked = this._ackedHeads.get(hex) || 0
|
|
1016
|
-
if (length > acked) {
|
|
1017
|
-
unlinked = true
|
|
1018
|
-
break
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
if (!unlinked) {
|
|
1022
|
-
this._ackRequired = false
|
|
1023
|
-
return false
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
for (const { key, length } of links) {
|
|
1027
|
-
this._ackedHeads.set(b4a.toString(key, 'hex'), length)
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
this.writers.appendLocal(null, t, { start: 0, end: 0 }, links, false, null)
|
|
1031
|
-
this._ackRequired = false
|
|
1032
|
-
return true
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
1016
|
async _bumpPendingWriters({ local = false } = {}) {
|
|
1036
1017
|
if (!local && this._catchupMigratedNodes !== null) {
|
|
1037
1018
|
const updated = await this._bumpMigratedWriters()
|
|
@@ -1398,10 +1379,9 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1398
1379
|
|
|
1399
1380
|
async _bootAttempt(head, bootCondition, reference) {
|
|
1400
1381
|
// peek, so the hints are still there for the drain once we have booted
|
|
1401
|
-
const
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
)
|
|
1382
|
+
const result = await this._filterHints(this._wakeup.hints)
|
|
1383
|
+
|
|
1384
|
+
const candidates = await this._readCandidateHeads(result, FastForward.DEFAULT_TIMEOUT)
|
|
1405
1385
|
|
|
1406
1386
|
const ff = await FastForward.fromHeads(this, [head, ...candidates], {
|
|
1407
1387
|
force: true,
|
package/lib/apply-calls.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const ID = require('hypercore-id-encoding')
|
|
2
|
-
const b4a = require('b4a')
|
|
3
2
|
|
|
4
3
|
class ApplyCalls {
|
|
5
4
|
constructor(auto) {
|
|
@@ -44,10 +43,6 @@ class ApplyCalls {
|
|
|
44
43
|
|
|
45
44
|
ackWriter(key) {
|
|
46
45
|
if (typeof key === 'string') key = ID.decode(key)
|
|
47
|
-
// acking an optimistic node means we owe it a linking node
|
|
48
|
-
if (this.applying && this.applying[0].optimistic && !b4a.equals(key, this.auto.local.key)) {
|
|
49
|
-
this.auto._ackRequired = true
|
|
50
|
-
}
|
|
51
46
|
return this.auto.system.ackWriter(key)
|
|
52
47
|
}
|
|
53
48
|
|
package/lib/fast-forward.js
CHANGED
|
@@ -9,10 +9,6 @@ const { LEGACY_AUTOBASE_VERSION } = require('./constants.js')
|
|
|
9
9
|
const DEFAULT_OP_TIMEOUT = 5_000
|
|
10
10
|
const MIN_FF_GAP = 32
|
|
11
11
|
|
|
12
|
-
// views are only stamped on the last node of a flush, so a head may sit above
|
|
13
|
-
// the most recent one - how far back we look for it
|
|
14
|
-
const MAX_FLUSH_SEARCH = 64
|
|
15
|
-
|
|
16
12
|
module.exports = class FastForward {
|
|
17
13
|
constructor(auto, head, { timeout = DEFAULT_OP_TIMEOUT } = {}) {
|
|
18
14
|
this.auto = auto
|
|
@@ -147,18 +143,9 @@ module.exports = class FastForward {
|
|
|
147
143
|
const core = auto.openCore(head.key)
|
|
148
144
|
|
|
149
145
|
try {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const oplog = await auto.readOplog(core, length, opts)
|
|
154
|
-
if (oplog === null) return null
|
|
155
|
-
if (oplog.op.views) return oplog
|
|
156
|
-
|
|
157
|
-
length = oplog.length - 1
|
|
158
|
-
if (length <= 0) return null
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return null
|
|
146
|
+
const oplog = await auto.readOplog(core, head.length, opts)
|
|
147
|
+
if (oplog === null) return null
|
|
148
|
+
return oplog.op.views ? oplog : null
|
|
162
149
|
} finally {
|
|
163
150
|
await core.close()
|
|
164
151
|
}
|
package/lib/migrations.js
CHANGED
|
@@ -223,7 +223,9 @@ async function inflateLegacyOplog(buf, core, seq, timeout) {
|
|
|
223
223
|
|
|
224
224
|
fetches.push(m.digest.pointer ? core.get(seq - m.digest.pointer, { timeout }) : buf)
|
|
225
225
|
fetches.push(
|
|
226
|
-
m.checkpoint.
|
|
226
|
+
m.checkpoint.system.checkpointer
|
|
227
|
+
? core.get(seq - m.checkpoint.system.checkpointer, { timeout })
|
|
228
|
+
: buf
|
|
227
229
|
)
|
|
228
230
|
|
|
229
231
|
const [digestNode, checkpointNode] = await Promise.all(fetches)
|
package/lib/system.js
CHANGED
|
@@ -71,12 +71,12 @@ module.exports = class Systembee {
|
|
|
71
71
|
const added = info && info.isAdded !== false
|
|
72
72
|
if (added && !info.isRemoved && length <= info.length && !hint && pending === -1) return
|
|
73
73
|
|
|
74
|
-
this.update(key, length, -1, -1, false, true, false,
|
|
74
|
+
this.update(key, length, -1, -1, false, true, false, -1, hint, pending)
|
|
75
75
|
return
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
const w = isGenesis ? effective : -1
|
|
79
|
-
this.update(key, length, w, effective, isGenesis, true, false,
|
|
79
|
+
this.update(key, length, w, effective, isGenesis, true, false, -1, hint, pending)
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
async ackWriter(key, { length = 0 } = {}) {
|
|
@@ -84,7 +84,7 @@ module.exports = class Systembee {
|
|
|
84
84
|
const info = await this.get(key, { unflushed: false })
|
|
85
85
|
length = info ? info.length : 0
|
|
86
86
|
}
|
|
87
|
-
this.update(key, length, -1, -1, false, false, false,
|
|
87
|
+
this.update(key, length, -1, -1, false, false, false, -1, null)
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
async removeWriter(key, { length = 0 } = {}) {
|
|
@@ -92,17 +92,24 @@ module.exports = class Systembee {
|
|
|
92
92
|
const info = await this.get(key, { unflushed: true })
|
|
93
93
|
length = info ? info.length : 0
|
|
94
94
|
}
|
|
95
|
-
this.update(key, length, -1, 0, false, false, true,
|
|
95
|
+
this.update(key, length, -1, 0, false, false, true, -1, null)
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
addAnchor(key) {
|
|
99
|
-
this.update(key, 0, -1, -1, false, true, false,
|
|
99
|
+
this.update(key, 0, -1, -1, false, true, false, -1, null)
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
isGenesis() {
|
|
103
103
|
return this.bee.head() === null || this.bee.head().length === 0
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
isHead(key) {
|
|
107
|
+
for (const head of this.heads) {
|
|
108
|
+
if (b4a.equals(head.key, key)) return true
|
|
109
|
+
}
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
|
|
106
113
|
async boot(view, { timeout } = {}) {
|
|
107
114
|
await this.bee.ready()
|
|
108
115
|
this.bee.move(view)
|
|
@@ -184,18 +191,7 @@ module.exports = class Systembee {
|
|
|
184
191
|
|
|
185
192
|
// resolved sort weight, re-stamped on every reapplication - this is what
|
|
186
193
|
// topo reads back out of the changes stream
|
|
187
|
-
this.update(
|
|
188
|
-
node.key,
|
|
189
|
-
node.length,
|
|
190
|
-
node.weight,
|
|
191
|
-
-1,
|
|
192
|
-
false,
|
|
193
|
-
false,
|
|
194
|
-
false,
|
|
195
|
-
false,
|
|
196
|
-
node.timestamp,
|
|
197
|
-
null
|
|
198
|
-
)
|
|
194
|
+
this.update(node.key, node.length, node.weight, -1, false, false, false, node.timestamp, null)
|
|
199
195
|
}
|
|
200
196
|
|
|
201
197
|
async canApply(key, optimistic) {
|
|
@@ -236,14 +232,12 @@ module.exports = class Systembee {
|
|
|
236
232
|
isGenesis: upd.maxWeight !== -1 && !!upd.isGenesis,
|
|
237
233
|
length: upd.length,
|
|
238
234
|
clock: 0,
|
|
239
|
-
isAdded: upd.isAdded
|
|
240
|
-
isAcked: upd.isAcked
|
|
235
|
+
isAdded: upd.isAdded
|
|
241
236
|
}
|
|
242
237
|
}
|
|
243
238
|
|
|
244
239
|
if (upd.isAdded) info.isAdded = true
|
|
245
240
|
if (upd.isRemoved) info.isRemoved = true
|
|
246
|
-
if (upd.isAcked) info.isAcked = true
|
|
247
241
|
if (upd.maxWeight !== -1) {
|
|
248
242
|
info.isGenesis = upd.isGenesis
|
|
249
243
|
info.maxWeight = upd.maxWeight
|
|
@@ -284,7 +278,6 @@ module.exports = class Systembee {
|
|
|
284
278
|
isGenesis,
|
|
285
279
|
isAdded,
|
|
286
280
|
isRemoved,
|
|
287
|
-
isAcked,
|
|
288
281
|
timestamp,
|
|
289
282
|
grant,
|
|
290
283
|
pending = -1
|
|
@@ -308,7 +301,6 @@ module.exports = class Systembee {
|
|
|
308
301
|
isGenesis: false,
|
|
309
302
|
isRemoved: false,
|
|
310
303
|
isAdded: false,
|
|
311
|
-
isAcked: false,
|
|
312
304
|
timestamp: 0,
|
|
313
305
|
grant: null,
|
|
314
306
|
pending: -1
|
|
@@ -330,9 +322,6 @@ module.exports = class Systembee {
|
|
|
330
322
|
upd.isRemoved = true
|
|
331
323
|
upd.isAdded = false
|
|
332
324
|
}
|
|
333
|
-
if (isAcked) {
|
|
334
|
-
upd.isAcked = true
|
|
335
|
-
}
|
|
336
325
|
if (length > upd.length) {
|
|
337
326
|
upd.length = length
|
|
338
327
|
}
|
package/lib/witness.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const b4a = require('b4a')
|
|
2
2
|
const encoding = require('./encoding.js')
|
|
3
|
-
const { DEFAULT_OP_TIMEOUT } = require('./constants.js')
|
|
4
3
|
|
|
5
4
|
exports.currentWeight = currentWeight
|
|
6
5
|
exports.resolveWeight = resolveWeight
|
|
@@ -56,7 +55,7 @@ async function readOplogNode(auto, key, length) {
|
|
|
56
55
|
|
|
57
56
|
try {
|
|
58
57
|
await core.ready()
|
|
59
|
-
const block = await core.get(length - 1
|
|
58
|
+
const block = await core.get(length - 1)
|
|
60
59
|
return encoding.decodeOplog(block)
|
|
61
60
|
} finally {
|
|
62
61
|
await core.close()
|
package/lib/writers.js
CHANGED
|
@@ -18,17 +18,20 @@ class ActiveWriters {
|
|
|
18
18
|
|
|
19
19
|
this.auto = auto
|
|
20
20
|
this.active = new Map()
|
|
21
|
-
this._adding = new Map()
|
|
22
21
|
this.triggers = new Triggers()
|
|
23
|
-
this.localWriter =
|
|
22
|
+
this.localWriter = null
|
|
24
23
|
this.writable = false
|
|
25
24
|
this.pending = []
|
|
26
25
|
|
|
27
26
|
this._pendingBuffer = new Map()
|
|
27
|
+
this._adding = new Map()
|
|
28
28
|
|
|
29
|
+
this.localWriter = new Writer(this, auto.system, true, local, b4a.toString(local.key, 'hex'))
|
|
29
30
|
this.localWriter.attach()
|
|
31
|
+
}
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
get size() {
|
|
34
|
+
return this.active.size
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
[Symbol.iterator]() {
|
|
@@ -195,10 +198,7 @@ class ActiveWriters {
|
|
|
195
198
|
if (local) await this.updateLocalState()
|
|
196
199
|
|
|
197
200
|
let w = this.active.get(id)
|
|
198
|
-
if (w)
|
|
199
|
-
w.couple() // couple if we weren't ready first time
|
|
200
|
-
return w
|
|
201
|
-
}
|
|
201
|
+
if (w) return w
|
|
202
202
|
|
|
203
203
|
// no new sessions once teardown started
|
|
204
204
|
if (this.auto._interrupting) return null
|
|
@@ -206,6 +206,7 @@ class ActiveWriters {
|
|
|
206
206
|
const encryption = this.auto.encryptionKey ? new WriterEncryption(this.auto) : null
|
|
207
207
|
|
|
208
208
|
const core = this.auto.store.get({
|
|
209
|
+
active: false,
|
|
209
210
|
key,
|
|
210
211
|
encryption,
|
|
211
212
|
group: local || !this.auto.wakeupCapability ? null : this.auto.wakeupCapability.discoveryKey
|
|
@@ -222,7 +223,6 @@ class ActiveWriters {
|
|
|
222
223
|
|
|
223
224
|
w = new Writer(this, this.auto.system, false, core, id)
|
|
224
225
|
w.attach()
|
|
225
|
-
w.couple()
|
|
226
226
|
|
|
227
227
|
return w
|
|
228
228
|
}
|
|
@@ -250,29 +250,6 @@ class ActiveWriters {
|
|
|
250
250
|
w.decouple()
|
|
251
251
|
if (w !== this.localWriter) await w.close()
|
|
252
252
|
}
|
|
253
|
-
|
|
254
|
-
_bootstrap() {
|
|
255
|
-
const bootstrap = this.auto.bootstrap
|
|
256
|
-
|
|
257
|
-
bootstrap.setEncryption(this.auto._getEncryptionProvider())
|
|
258
|
-
bootstrap.setActive(true)
|
|
259
|
-
|
|
260
|
-
const id = b4a.toString(bootstrap.key, 'hex')
|
|
261
|
-
let w = this.active.get(id)
|
|
262
|
-
if (w) {
|
|
263
|
-
w.isBootstrap = true
|
|
264
|
-
w.couple() // couple if we weren't ready first time
|
|
265
|
-
return
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const session = bootstrap.session()
|
|
269
|
-
session.setEncryption(this.auto._getEncryptionProvider())
|
|
270
|
-
|
|
271
|
-
w = new Writer(this, this.auto.system, false, session, id)
|
|
272
|
-
w.isBootstrap = true // the root of the autobase, never gc'd
|
|
273
|
-
w.attach()
|
|
274
|
-
w.couple()
|
|
275
|
-
}
|
|
276
253
|
}
|
|
277
254
|
|
|
278
255
|
class Writer {
|
|
@@ -298,20 +275,26 @@ class Writer {
|
|
|
298
275
|
this.isRemoved = false
|
|
299
276
|
this.isCoupled = false
|
|
300
277
|
this.isFrozen = false
|
|
301
|
-
this.
|
|
278
|
+
this.isHead = false
|
|
302
279
|
|
|
303
280
|
this._onchangeBound = this._onchange.bind(this)
|
|
304
281
|
|
|
305
282
|
if (!local) this.core.on('append', this._onchangeBound)
|
|
306
283
|
if (!local) this.core.on('download', this._onchangeBound)
|
|
307
|
-
|
|
308
|
-
this.couple()
|
|
309
284
|
}
|
|
310
285
|
|
|
311
286
|
get isIndexer() {
|
|
312
287
|
return this.weight >= 2
|
|
313
288
|
}
|
|
314
289
|
|
|
290
|
+
isSystemHead() {
|
|
291
|
+
if (this.system.heads.length === 0) {
|
|
292
|
+
return b4a.equals(this.core.key, this.writers.auto.key)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return this.system.isHead(this.core.key)
|
|
296
|
+
}
|
|
297
|
+
|
|
315
298
|
couple() {
|
|
316
299
|
if (this.isCoupled) return
|
|
317
300
|
// if we don't have coupler yet we can't add
|
|
@@ -357,7 +340,10 @@ class Writer {
|
|
|
357
340
|
|
|
358
341
|
// a peer announced this length for us, so we're not caught up until we've seen it
|
|
359
342
|
hint(length) {
|
|
360
|
-
if (length > this.hintedLength)
|
|
343
|
+
if (length > this.hintedLength) {
|
|
344
|
+
this.hintedLength = length
|
|
345
|
+
this.core.setActive(true)
|
|
346
|
+
}
|
|
361
347
|
}
|
|
362
348
|
|
|
363
349
|
_onchange() {
|
|
@@ -400,7 +386,7 @@ class Writer {
|
|
|
400
386
|
// don't drop any local nodes left in buffer, or work a peer told us about
|
|
401
387
|
if (length < this.core.length || length < this.hintedLength || this.appending) {
|
|
402
388
|
this.addPending()
|
|
403
|
-
} else if (this !== this.writers.localWriter && !this.
|
|
389
|
+
} else if (this !== this.writers.localWriter && !this.isHead) {
|
|
404
390
|
await this.detachAndClose()
|
|
405
391
|
}
|
|
406
392
|
}
|
|
@@ -447,12 +433,24 @@ class Writer {
|
|
|
447
433
|
|
|
448
434
|
async update() {
|
|
449
435
|
const info = await this.system.get(this.core.key)
|
|
436
|
+
const length = info ? info.length : 0
|
|
450
437
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
if (
|
|
454
|
-
|
|
455
|
-
|
|
438
|
+
const isHead = this.isSystemHead()
|
|
439
|
+
|
|
440
|
+
if (isHead) {
|
|
441
|
+
this.isHead = true
|
|
442
|
+
this.couple()
|
|
443
|
+
} else {
|
|
444
|
+
this.isHead = false
|
|
445
|
+
this.decouple()
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const active = length < this.core.length || length < this.hintedLength
|
|
449
|
+
|
|
450
|
+
if (this.isHead || active) {
|
|
451
|
+
this.core.setActive(true)
|
|
452
|
+
} else {
|
|
453
|
+
this.core.setActive(false)
|
|
456
454
|
}
|
|
457
455
|
|
|
458
456
|
if (!info) {
|
|
@@ -468,7 +466,7 @@ class Writer {
|
|
|
468
466
|
this.writers._updateLocalState()
|
|
469
467
|
}
|
|
470
468
|
|
|
471
|
-
return
|
|
469
|
+
return length
|
|
472
470
|
}
|
|
473
471
|
|
|
474
472
|
next() {
|
|
@@ -693,6 +691,7 @@ class Writer {
|
|
|
693
691
|
head.views = views
|
|
694
692
|
|
|
695
693
|
head.trusted = trusted ? [{ key: trusted.key, length: trusted.length }] : null
|
|
694
|
+
this.writers.auto.emit('appending', this.pending)
|
|
696
695
|
|
|
697
696
|
const buffers = []
|
|
698
697
|
for (let i = 0; i < this.processed; i++) {
|
|
@@ -762,7 +761,3 @@ function finalizeNodeBatch(batch) {
|
|
|
762
761
|
}
|
|
763
762
|
|
|
764
763
|
function noop() {}
|
|
765
|
-
|
|
766
|
-
function isAnchor(core) {
|
|
767
|
-
return !!(core.manifest && core.manifest.signers.length === 0 && core.length === 1)
|
|
768
|
-
}
|