autobee 2.11.3 → 2.11.5

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 CHANGED
@@ -29,6 +29,7 @@ const migrations = require('./lib/migrations.js')
29
29
  const EMPTY_HEAD = { length: 0, key: null }
30
30
  const DEFAULT_ACK_THRESHOLD = 32
31
31
  const BOOT_NETWORK_TIMEOUT = 5000
32
+ const REINDEX_PREFETCH = 4096
32
33
  const INTERRUPT = new Error('Apply interrupted')
33
34
 
34
35
  module.exports = class Autobee extends ReadyResource {
@@ -150,6 +151,7 @@ module.exports = class Autobee extends ReadyResource {
150
151
  this._preapply = handlers.preapply || null
151
152
  this._preApplied = false
152
153
  this._reindexed = false
154
+ this._strictReindex = !!handlers.strictReindex
153
155
  this._warmup = handlers.warmup || null
154
156
  this._hasApply = !!handlers.apply
155
157
  this._hasUpdate = !!handlers.update
@@ -689,10 +691,14 @@ module.exports = class Autobee extends ReadyResource {
689
691
  const latest = await this.writers.getLatestLocalOplog()
690
692
  const views = latest ? latest.views : null
691
693
 
694
+ const from = this._workingBee.head()
692
695
  await this._reindexBee(this._workingBee, views ? views.view : null)
693
696
  this.bee.move(this._workingBee.head())
694
697
 
695
- await this._reindexBee(this.system.bee, views ? views.system : null)
698
+ const map = await migrations.mapReindexedView(this, from, REINDEX_PREFETCH)
699
+ await this._reindexBee(this.system.bee, views ? views.system : null, map)
700
+
701
+ await this.system.reset()
696
702
 
697
703
  this._reindexed = true
698
704
  }
@@ -707,7 +713,7 @@ module.exports = class Autobee extends ReadyResource {
707
713
  return !(await this._shouldReindex(view.key))
708
714
  }
709
715
 
710
- async _reindexBee(bee, flushed) {
716
+ async _reindexBee(bee, flushed, map = null) {
711
717
  const head = bee.head()
712
718
  const local = bee.context.local
713
719
  if (head === null) return
@@ -718,7 +724,10 @@ module.exports = class Autobee extends ReadyResource {
718
724
  return
719
725
  }
720
726
 
721
- await bee.reindex(async (change) => !(await this._shouldReindex(change.head.key)))
727
+ await bee.reindex(async (change) => !(await this._shouldReindex(change.head.key)), {
728
+ prefetch: REINDEX_PREFETCH,
729
+ map
730
+ })
722
731
  bee.move({ key: local.key, length: local.length })
723
732
  }
724
733
 
@@ -733,7 +742,8 @@ module.exports = class Autobee extends ReadyResource {
733
742
  }
734
743
 
735
744
  if (core.manifest === null) return unknown
736
- return core.manifest.version > 1 && core.manifest.version < DEFAULT_MANIFEST_VERSION
745
+ if (core.manifest.version >= DEFAULT_MANIFEST_VERSION) return false
746
+ return this._strictReindex || core.manifest.version > 1
737
747
  } finally {
738
748
  await core.close()
739
749
  }
@@ -1655,17 +1665,16 @@ module.exports = class Autobee extends ReadyResource {
1655
1665
  const hints = await this._applyWakeupHints()
1656
1666
  if (hints.length) this._queueFastForward(hints)
1657
1667
 
1658
- const remaining = deadline - Date.now()
1659
- if (remaining <= 0 || this.fastForwardTo !== null) return
1660
-
1668
+ // the search bounds its own reads, so it always settles
1661
1669
  if (this._ffSearching !== null) {
1662
- await Promise.race([this._ffSearching, this._bumpSignal.wait(remaining)])
1663
- this._bumpSignal.notify()
1664
- if (this._ffSearching === null) return
1665
- continue
1670
+ await this._ffSearching
1671
+ return
1666
1672
  }
1667
1673
 
1668
- if (hints.length) return
1674
+ if (hints.length || this.fastForwardTo !== null) return
1675
+
1676
+ const remaining = deadline - Date.now()
1677
+ if (remaining <= 0) return
1669
1678
 
1670
1679
  await this._bumpSignal.wait(remaining)
1671
1680
  }
package/lib/migrations.js CHANGED
@@ -6,6 +6,7 @@ const { decodeBlock } = require('hyperbee2/lib/encoding.js')
6
6
  const { AutobeeEncryption } = require('./encryption.js')
7
7
  const encoding = require('./encoding.js')
8
8
  const { assert, bail } = require('./asserts.js')
9
+ const { LEGACY_AUTOBASE_VERSION } = require('./constants.js')
9
10
 
10
11
  const { getEncoding } = require('../encoding/spec/autobee')
11
12
 
@@ -15,6 +16,7 @@ const SystemInfoV2 = getEncoding('@autobase-compat/info-v2')
15
16
  const EMPTY = b4a.alloc(0)
16
17
  const INDEX_VERSION = 1
17
18
  const INFO = b4a.from([0x00, 0x00, 0x69, 0x6e, 0x66, 0x6f])
19
+ const INFO_V3 = b4a.from([0])
18
20
  const [NS_SIGNER_NAMESPACE] = crypto.namespace('autobase', 1)
19
21
 
20
22
  module.exports = {
@@ -23,6 +25,7 @@ module.exports = {
23
25
  checkAutobaseMigration,
24
26
  readLegacySystemInfo,
25
27
  inflateLegacyOplog,
28
+ mapReindexedView,
26
29
  coreLength
27
30
  }
28
31
 
@@ -381,3 +384,50 @@ async function viewsReached(store, info) {
381
384
  }
382
385
  return true
383
386
  }
387
+
388
+ // the reindex copies the view batch for batch, so old and new heads line up
389
+ async function mapReindexedView(auto, from, prefetch) {
390
+ const bee = auto._workingBee
391
+ const to = bee.head()
392
+
393
+ if (from === null || to === null || b4a.equals(from.key, to.key)) return null
394
+
395
+ const olds = []
396
+ for await (const { head } of bee.createChangesStream({ head: from, prefetch })) {
397
+ if (!(await auto._shouldReindex(head.key))) break
398
+ olds.push(head)
399
+ }
400
+
401
+ const news = []
402
+ for await (const { head } of bee.createChangesStream({ head: to })) {
403
+ if (news.length === olds.length) break
404
+ news.push(head)
405
+ }
406
+
407
+ if (news.length !== olds.length) throw new Error('Reindexed view is missing changes')
408
+
409
+ const moved = new Map()
410
+
411
+ for (let i = 0; i < olds.length; i++) {
412
+ moved.set(headId(olds[i]), news[i])
413
+ moved.set(headId({ key: olds[i].key, length: 0 }), { key: to.key, length: 0 })
414
+ }
415
+
416
+ return function (key, value) {
417
+ if (!b4a.equals(key, INFO_V3) && !b4a.equals(key, INFO)) return null
418
+
419
+ const info = encoding.decodeSystemInfo(value)
420
+ if (info.version <= LEGACY_AUTOBASE_VERSION) return null
421
+ if (!info.view || !info.view.key) return null
422
+
423
+ const view = moved.get(headId(info.view))
424
+ if (!view) return null
425
+
426
+ info.view = view
427
+ return encoding.encodeSystemInfo(info)
428
+ }
429
+ }
430
+
431
+ function headId(head) {
432
+ return b4a.toString(head.key, 'hex') + ':' + head.length
433
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autobee",
3
- "version": "2.11.3",
3
+ "version": "2.11.5",
4
4
  "description": "Bee based autobase",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Holepunch Inc.",
@@ -26,7 +26,7 @@
26
26
  "autobee-wakeup": "^1.1.3",
27
27
  "b4a": "^1.8.0",
28
28
  "compact-encoding": "^3.4.0",
29
- "hyperbee2": "^2.17.1",
29
+ "hyperbee2": "^2.18.0",
30
30
  "hypercore": "^11.37.0",
31
31
  "hypercore-id-encoding": "^1.3.0",
32
32
  "hyperschema": "^1.26.2",