autobee 2.5.0 → 2.5.2

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.
Files changed (3) hide show
  1. package/index.js +38 -17
  2. package/lib/system.js +16 -3
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -1098,6 +1098,7 @@ module.exports = class Autobee extends ReadyResource {
1098
1098
 
1099
1099
  for await (const p of this._servableRequests(standing)) {
1100
1100
  approving.push(fetchApproval.call(this, p.key, p.amount, approvals))
1101
+ if (approving.length === 32) break
1101
1102
  }
1102
1103
 
1103
1104
  if (!approving.length) return null
@@ -1164,21 +1165,33 @@ module.exports = class Autobee extends ReadyResource {
1164
1165
 
1165
1166
  const { writer: w, batch } = next
1166
1167
 
1167
- if (w.isAdded || (w.isRemoved && w.hasReferrals())) {
1168
- await this._processBatch(batch)
1169
- w.notify(batch)
1170
- return true
1171
- }
1168
+ // an optimistic batch from a writer that is not (or no longer) added gets a
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
+ }
1172
1175
 
1173
- if (this.optimistic && !w.isRemoved && batch[0].optimistic) {
1174
- if (!(await this._optimisticBatch(batch))) {
1176
+ if (!(w.isRemoved && w.hasReferrals())) {
1175
1177
  w.removePending()
1176
1178
  return true
1177
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
+ }
1184
+
1185
+ if (w.isAdded || (w.isRemoved && w.hasReferrals())) {
1186
+ await this._processBatch(batch)
1178
1187
  w.notify(batch)
1179
1188
  return true
1180
1189
  }
1181
1190
 
1191
+ // not added and not applicable optimistically: nothing can apply this
1192
+ // batch now, so drop the writer for this drain instead of reselecting it
1193
+ // (a refresh re-adds it once it has been added or has new blocks)
1194
+ w.removePending()
1182
1195
  return true
1183
1196
  }
1184
1197
 
@@ -1190,19 +1203,19 @@ module.exports = class Autobee extends ReadyResource {
1190
1203
  if (t.view) this._workingBee.move(t.view)
1191
1204
 
1192
1205
  for (const b of t.tip) {
1193
- let failed = true
1206
+ const optimistic = b[0].optimistic
1207
+ let accepted = false
1194
1208
  try {
1195
- if (await this.system.canApply(b[0].key, true)) {
1196
- await this._applyBatch(b, true)
1197
- failed = false
1198
- }
1199
- } catch {}
1209
+ accepted = await this._applyBatch(b, optimistic)
1210
+ } catch (err) {
1211
+ if (!optimistic) throw err
1212
+ }
1200
1213
 
1201
1214
  // only check if batch was successful
1202
1215
  if (b !== batch) continue
1203
1216
 
1204
- const w = failed ? null : await this.system.get(b[0].key)
1205
- if (!w || w.length < b[0].length) {
1217
+ // declined: apply threw, or never called addWriter/ackWriter for this writer
1218
+ if (!accepted) {
1206
1219
  this._workingBee.move(rollbackView)
1207
1220
  this.system.bee.move(rollbackSystem)
1208
1221
  await this.system.reset()
@@ -1289,10 +1302,16 @@ module.exports = class Autobee extends ReadyResource {
1289
1302
  if (this._hasApply && (await this.system.canApply(batch[0].key, optimistic))) {
1290
1303
  this.stats.applies++
1291
1304
  this._host.applying = batch
1292
- await this._workingView.apply(userBatch)
1293
- this._host.applying = null
1305
+ try {
1306
+ await this._workingView.apply(userBatch)
1307
+ } finally {
1308
+ this._host.applying = null
1309
+ }
1294
1310
  }
1295
1311
 
1312
+ // read before flush clears it
1313
+ const accepted = this.system.touched(batch[0].key)
1314
+
1296
1315
  const changed = await this.system.flush(batch, this._workingBee)
1297
1316
 
1298
1317
  if (this.system.promotions.changed) this._prefetchApprovals().catch(safetyCatch)
@@ -1307,6 +1326,8 @@ module.exports = class Autobee extends ReadyResource {
1307
1326
  if (added) await this.writers.add(key)
1308
1327
  else await this.writers.remove(key)
1309
1328
  }
1329
+
1330
+ return accepted
1310
1331
  }
1311
1332
 
1312
1333
  async _storeBoot() {
package/lib/system.js CHANGED
@@ -86,11 +86,16 @@ module.exports = class Systembee {
86
86
  }
87
87
 
88
88
  async ackWriter(key, { length = 0 } = {}) {
89
+ const info = await this.get(key, { unflushed: true })
89
90
  if (length === 0) {
90
- const info = await this.get(key, { unflushed: false })
91
91
  length = info ? info.length : 0
92
92
  }
93
- this.update(key, length, -1, -1, false, false, false, -1, null)
93
+ // acked but never granted (unknown, ack-only or removed): keep the op
94
+ // (record its length) but record the writer as removed - it is not writable
95
+ // and only its optimistic ops reach apply, each rolled back unless acked again
96
+ const w = this.writers.get(b4a.toString(key, 'hex'))
97
+ const granted = w ? w.added : info !== null && info.isAdded !== false && !info.isRemoved
98
+ this.update(key, length, -1, -1, false, false, !granted, -1, null)
94
99
  }
95
100
 
96
101
  async removeWriter(key, { length = 0 } = {}) {
@@ -224,12 +229,20 @@ module.exports = class Systembee {
224
229
  this.update(node.key, node.length, node.weight, -1, false, false, false, node.timestamp, null)
225
230
  }
226
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
+
227
237
  async canApply(key, optimistic) {
238
+ // an optimistic node always reaches apply, whether its writer is unknown,
239
+ // acked or removed - the caller rolls it back unless apply accepts it
240
+ if (optimistic) return true
228
241
  const id = b4a.toString(key, 'hex')
229
242
  const w = this.writers.get(id)
230
243
  if (w) return w.added
231
244
  const info = await this.get(key)
232
- return info ? !info.isRemoved : !!optimistic
245
+ return info ? !info.isRemoved : false
233
246
  }
234
247
 
235
248
  snapshot(head = null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autobee",
3
- "version": "2.5.0",
3
+ "version": "2.5.2",
4
4
  "description": "Bee based autobase",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Holepunch Inc.",