autobee 2.5.2 → 2.5.4
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/README.md +8 -1
- package/index.js +18 -65
- package/lib/apply-calls.js +4 -4
- package/lib/system.js +4 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -133,6 +133,12 @@ Optionally pass `{ optimistic: true }` to write without waiting to be a confirme
|
|
|
133
133
|
await db.append(buf, { optimistic: true })
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
+
An optimistic node always reaches `apply`, whoever wrote it, and is always
|
|
137
|
+
recorded afterwards. `apply` decides what it does: call `host.addWriter` to
|
|
138
|
+
grant the writer, or do nothing to leave it unwritable. An op `apply` does not
|
|
139
|
+
accept must be handled in `apply` (ie. ignored) - throwing is a bug, as for any
|
|
140
|
+
other node, and closes the db.
|
|
141
|
+
|
|
136
142
|
#### `await db.update()`
|
|
137
143
|
|
|
138
144
|
Trigger a new apply cycle. Useful after replication to process new data.
|
|
@@ -216,7 +222,8 @@ Remove a writer by public key (Buffer or hex string).
|
|
|
216
222
|
|
|
217
223
|
#### `host.ackWriter(key)`
|
|
218
224
|
|
|
219
|
-
|
|
225
|
+
Deprecated, a no-op. Optimistic nodes are always recorded once applied, whether
|
|
226
|
+
or not apply acks the writer. Kept so existing apply functions keep working.
|
|
220
227
|
|
|
221
228
|
#### `host.interrupt(reason)`
|
|
222
229
|
|
package/index.js
CHANGED
|
@@ -206,7 +206,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
206
206
|
|
|
207
207
|
async _updateAcking() {
|
|
208
208
|
if (this._interrupting) return
|
|
209
|
-
this.setAcking(await this.trusted.isTrusted(this.local.key, this.view))
|
|
209
|
+
this.setAcking(await this.trusted.isTrusted(this.local.key, this._workingView.view))
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
// network free: only a migration needs peers, so ready() awaits the full
|
|
@@ -290,7 +290,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
290
290
|
if (local) {
|
|
291
291
|
result.writers.push(this.local.key)
|
|
292
292
|
|
|
293
|
-
if (await this.trusted.isTrusted(this.local.key, this.view)) {
|
|
293
|
+
if (await this.trusted.isTrusted(this.local.key, this._workingView.view)) {
|
|
294
294
|
const localViews = await this.writers.localWriter.views()
|
|
295
295
|
for (const { key } of localViews) {
|
|
296
296
|
views.set(b4a.toString(key, 'hex'), key)
|
|
@@ -690,10 +690,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
690
690
|
break // revaluate conditions...
|
|
691
691
|
}
|
|
692
692
|
|
|
693
|
-
if (await this._bumpPendingWriters())
|
|
694
|
-
this._needsUpdate = true
|
|
695
|
-
continue
|
|
696
|
-
}
|
|
693
|
+
if (await this._bumpPendingWriters()) continue
|
|
697
694
|
|
|
698
695
|
if (!(await this._appendAck())) break
|
|
699
696
|
this._needsUpdate = true
|
|
@@ -1156,7 +1153,10 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1156
1153
|
if (!local && this._catchupMigratedNodes !== null) {
|
|
1157
1154
|
const updated = await this._bumpMigratedWriters()
|
|
1158
1155
|
this._catchupMigratedNodes = null
|
|
1159
|
-
if (updated)
|
|
1156
|
+
if (updated) {
|
|
1157
|
+
this._needsUpdate = true
|
|
1158
|
+
return true
|
|
1159
|
+
}
|
|
1160
1160
|
}
|
|
1161
1161
|
|
|
1162
1162
|
// apply the best next node to keep the prefix stable
|
|
@@ -1165,64 +1165,17 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1165
1165
|
|
|
1166
1166
|
const { writer: w, batch } = next
|
|
1167
1167
|
|
|
1168
|
-
|
|
1169
|
-
// shot at apply and is rolled back unless apply adds or acks the writer
|
|
1170
|
-
if (this.optimistic && batch[0].optimistic && (!w.isAdded || w.isRemoved)) {
|
|
1171
|
-
if (await this._optimisticBatch(batch)) {
|
|
1172
|
-
w.notify(batch)
|
|
1173
|
-
return true
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
if (!(w.isRemoved && w.hasReferrals())) {
|
|
1177
|
-
w.removePending()
|
|
1178
|
-
return true
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
// declined, but other writers link to it: fall through and process it
|
|
1182
|
-
// like any other node from a removed writer
|
|
1183
|
-
}
|
|
1168
|
+
const optimistic = this.optimistic && batch[0].optimistic
|
|
1184
1169
|
|
|
1185
|
-
if (w.isAdded || (w.isRemoved && w.hasReferrals())) {
|
|
1170
|
+
if (optimistic || w.isAdded || (w.isRemoved && w.hasReferrals())) {
|
|
1186
1171
|
await this._processBatch(batch)
|
|
1187
|
-
|
|
1172
|
+
} else {
|
|
1173
|
+
w.removePending()
|
|
1188
1174
|
return true
|
|
1189
1175
|
}
|
|
1190
1176
|
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
// (a refresh re-adds it once it has been added or has new blocks)
|
|
1194
|
-
w.removePending()
|
|
1195
|
-
return true
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
async _optimisticBatch(batch) {
|
|
1199
|
-
const rollbackSystem = this.system.bee.head()
|
|
1200
|
-
const rollbackView = this._workingBee.head()
|
|
1201
|
-
|
|
1202
|
-
const t = await this.prepareBatch(batch)
|
|
1203
|
-
if (t.view) this._workingBee.move(t.view)
|
|
1204
|
-
|
|
1205
|
-
for (const b of t.tip) {
|
|
1206
|
-
const optimistic = b[0].optimistic
|
|
1207
|
-
let accepted = false
|
|
1208
|
-
try {
|
|
1209
|
-
accepted = await this._applyBatch(b, optimistic)
|
|
1210
|
-
} catch (err) {
|
|
1211
|
-
if (!optimistic) throw err
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
// only check if batch was successful
|
|
1215
|
-
if (b !== batch) continue
|
|
1216
|
-
|
|
1217
|
-
// declined: apply threw, or never called addWriter/ackWriter for this writer
|
|
1218
|
-
if (!accepted) {
|
|
1219
|
-
this._workingBee.move(rollbackView)
|
|
1220
|
-
this.system.bee.move(rollbackSystem)
|
|
1221
|
-
await this.system.reset()
|
|
1222
|
-
return false
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1177
|
+
w.notify(batch)
|
|
1178
|
+
this._needsUpdate = true
|
|
1226
1179
|
return true
|
|
1227
1180
|
}
|
|
1228
1181
|
|
|
@@ -1309,8 +1262,10 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1309
1262
|
}
|
|
1310
1263
|
}
|
|
1311
1264
|
|
|
1312
|
-
//
|
|
1313
|
-
|
|
1265
|
+
// an optimistic node is always consumed: record its length and, unless apply
|
|
1266
|
+
// granted the writer, record the writer as removed so that only its
|
|
1267
|
+
// optimistic nodes reach apply
|
|
1268
|
+
if (optimistic) await this.system.ackWriter(batch[0].key)
|
|
1314
1269
|
|
|
1315
1270
|
const changed = await this.system.flush(batch, this._workingBee)
|
|
1316
1271
|
|
|
@@ -1326,8 +1281,6 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1326
1281
|
if (added) await this.writers.add(key)
|
|
1327
1282
|
else await this.writers.remove(key)
|
|
1328
1283
|
}
|
|
1329
|
-
|
|
1330
|
-
return accepted
|
|
1331
1284
|
}
|
|
1332
1285
|
|
|
1333
1286
|
async _storeBoot() {
|
|
@@ -1426,7 +1379,7 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
1426
1379
|
async _flushLocal() {
|
|
1427
1380
|
// pull any available local nodes in before flushing
|
|
1428
1381
|
while (!this._interrupting && (await this._bumpPendingWriters({ local: true }))) {
|
|
1429
|
-
|
|
1382
|
+
// a bump that applied a batch flags the update itself
|
|
1430
1383
|
}
|
|
1431
1384
|
|
|
1432
1385
|
const flushed = await this.writers.flushLocal({
|
package/lib/apply-calls.js
CHANGED
|
@@ -41,10 +41,10 @@ class ApplyCalls {
|
|
|
41
41
|
return this.auto.system.addWriter(key, { weight, isGenesis, coord, carrier })
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
44
|
+
// deprecated: every optimistic node is recorded once applied, whether or not
|
|
45
|
+
// apply acks its writer, so this has nothing left to do. kept so contracts
|
|
46
|
+
// written against older versions keep applying
|
|
47
|
+
ackWriter() {}
|
|
48
48
|
|
|
49
49
|
removeWriter(key) {
|
|
50
50
|
if (typeof key === 'string') key = ID.decode(key)
|
package/lib/system.js
CHANGED
|
@@ -90,9 +90,9 @@ module.exports = class Systembee {
|
|
|
90
90
|
if (length === 0) {
|
|
91
91
|
length = info ? info.length : 0
|
|
92
92
|
}
|
|
93
|
-
//
|
|
94
|
-
// (record its length) but record the
|
|
95
|
-
// and only its optimistic ops reach apply
|
|
93
|
+
// called for every optimistic node once applied. not granted (unknown,
|
|
94
|
+
// ack-only or removed): keep the op (record its length) but record the
|
|
95
|
+
// writer as removed - it is not writable and only its optimistic ops reach apply
|
|
96
96
|
const w = this.writers.get(b4a.toString(key, 'hex'))
|
|
97
97
|
const granted = w ? w.added : info !== null && info.isAdded !== false && !info.isRemoved
|
|
98
98
|
this.update(key, length, -1, -1, false, false, !granted, -1, null)
|
|
@@ -229,14 +229,9 @@ module.exports = class Systembee {
|
|
|
229
229
|
this.update(node.key, node.length, node.weight, -1, false, false, false, node.timestamp, null)
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
// did this apply add or remove (ack) the writer
|
|
233
|
-
touched(key) {
|
|
234
|
-
return this.writers.has(b4a.toString(key, 'hex'))
|
|
235
|
-
}
|
|
236
|
-
|
|
237
232
|
async canApply(key, optimistic) {
|
|
238
233
|
// an optimistic node always reaches apply, whether its writer is unknown,
|
|
239
|
-
// acked or removed -
|
|
234
|
+
// acked or removed - it is self-verifying, apply decides what it does
|
|
240
235
|
if (optimistic) return true
|
|
241
236
|
const id = b4a.toString(key, 'hex')
|
|
242
237
|
const w = this.writers.get(id)
|