hypercore-storage 2.4.1 → 2.5.1

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
@@ -547,6 +547,21 @@ class CorestoreStorage {
547
547
  }
548
548
  }
549
549
 
550
+ async _maybeRecover(view) {
551
+ const r = path.join(this.db.path, 'RECOVERING')
552
+ if (!(await fileExists(r))) return
553
+ await this.setRecovering(view)
554
+ await fs.promises.unlink(r)
555
+ }
556
+
557
+ _maybeRecoverLater(err) {
558
+ if (!shouldRecover(err)) return
559
+ fs.writeFileSync(path.join(this.db.path, 'RECOVERING'), '')
560
+ for (const file of fs.readdirSync(this.db.path)) {
561
+ if (file.endsWith('.log')) fs.unlinkSync(path.join(this.db.path, file))
562
+ }
563
+ }
564
+
550
565
  // runs pre any other mutation and read
551
566
  async _migrateStore() {
552
567
  const view = await this._enter()
@@ -555,7 +570,15 @@ class CorestoreStorage {
555
570
  if (this.version === VERSION) return
556
571
 
557
572
  await this._preopen
558
- await this.db.ready()
573
+
574
+ try {
575
+ await this.db.ready()
576
+ } catch (err) {
577
+ this._maybeRecoverLater(err)
578
+ throw err
579
+ }
580
+
581
+ await this._maybeRecover(view)
559
582
 
560
583
  const rx = new CorestoreRX(this.db, view)
561
584
  const headPromise = rx.getHead()
@@ -775,6 +798,36 @@ class CorestoreStorage {
775
798
  }
776
799
  }
777
800
 
801
+ async setRecovering(view = null) {
802
+ const recovering = Date.now()
803
+ let keys = []
804
+
805
+ for await (const data of this.createDiscoveryKeyStream()) {
806
+ keys.push(data)
807
+ if (keys.length > 16 * 1024) {
808
+ await this._flushRecovering(recovering, view, keys)
809
+ keys = []
810
+ }
811
+ }
812
+
813
+ if (keys.length) await this._flushRecovering(recovering, view, keys)
814
+ }
815
+
816
+ async _flushRecovering(recovering, view, keys) {
817
+ const own = !view
818
+ if (own) view = await this._enter()
819
+ const tx = new CorestoreTX(view)
820
+
821
+ try {
822
+ const infos = await this._getInfos(keys, { auth: false, head: false, hints: true })
823
+ for (const inf of infos) {
824
+ tx.setCoreHints(inf.core, { ...inf.hints, recovering })
825
+ }
826
+ } finally {
827
+ if (own) await this._exit()
828
+ }
829
+ }
830
+
778
831
  async getDefaultDiscoveryKey() {
779
832
  if (this.version === 0) await this._migrateStore()
780
833
 
@@ -850,9 +903,12 @@ class CorestoreStorage {
850
903
  return (await this.getInfos([discoveryKey], opts))[0]
851
904
  }
852
905
 
853
- async getInfos(discoveryKeys, { auth = true, head = true, hints = true } = {}) {
906
+ async getInfos(discoveryKeys, opts) {
854
907
  if (this.version === 0) await this._migrateStore()
908
+ return this._getInfos(discoveryKeys, opts)
909
+ }
855
910
 
911
+ async _getInfos(discoveryKeys, { auth = true, head = true, hints = true } = {}) {
856
912
  const rx = new CorestoreRX(this.db, EMPTY)
857
913
  const corePromises = new Array(discoveryKeys.length)
858
914
 
@@ -1128,6 +1184,19 @@ async function toArray(stream) {
1128
1184
  return all
1129
1185
  }
1130
1186
 
1187
+ async function fileExists(path) {
1188
+ try {
1189
+ await fs.promises.stat(path)
1190
+ return true
1191
+ } catch {
1192
+ return false
1193
+ }
1194
+ }
1195
+
1196
+ function shouldRecover(err) {
1197
+ return err.message.toLowerCase().indexOf('sequence number is being set backwards') > -1
1198
+ }
1199
+
1131
1200
  function noop() {}
1132
1201
 
1133
1202
  async function getInfoFromBatch(db, c, discoveryKey, getAuth, getHead, getHints) {
package/lib/tx.js CHANGED
@@ -244,6 +244,10 @@ class CorestoreTX {
244
244
  this.changes.push([store.head(), encode(CORESTORE_HEAD, head), null])
245
245
  }
246
246
 
247
+ setCoreHints(c, hints) {
248
+ this.changes.push([core.hints(c.dataPointer), encode(CORE_HINTS, hints), null])
249
+ }
250
+
247
251
  putCore(discoveryKey, ptr) {
248
252
  this.changes.push([store.core(discoveryKey), encode(CORESTORE_CORE, ptr), null])
249
253
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore-storage",
3
- "version": "2.4.1",
3
+ "version": "2.5.1",
4
4
  "main": "index.js",
5
5
  "files": [
6
6
  "index.js",
@@ -11,9 +11,10 @@
11
11
  "scripts": {
12
12
  "format": "prettier --write .",
13
13
  "lint": "prettier --check . && lunte",
14
- "test": "node test/all.js",
15
- "test:bare": "bare test/all.js",
16
- "test:generate": "brittle -r test/all.js test/*.js"
14
+ "test": "npm run test:node && npm run test:bare",
15
+ "test:bare": "brittle-bare test/all.js",
16
+ "test:generate": "brittle -r test/all.js test/*.js",
17
+ "test:node": "brittle-node test/all.js"
17
18
  },
18
19
  "author": "Holepunch Inc.",
19
20
  "license": "Apache-2.0",
@@ -45,7 +46,7 @@
45
46
  },
46
47
  "devDependencies": {
47
48
  "brittle": "^3.7.0",
48
- "lunte": "^1.2.0",
49
+ "lunte": "^1.3.0",
49
50
  "prettier": "^3.6.2",
50
51
  "prettier-config-holepunch": "^2.0.0",
51
52
  "test-tmp": "^1.3.1"
@@ -43,10 +43,7 @@ const encoding1 = {
43
43
  if (m.defaultDiscoveryKey) c.fixed32.preencode(state, m.defaultDiscoveryKey)
44
44
  },
45
45
  encode(state, m) {
46
- const flags =
47
- (m.allocated ? 1 : 0) |
48
- (m.seed ? 2 : 0) |
49
- (m.defaultDiscoveryKey ? 4 : 0)
46
+ const flags = (m.allocated ? 1 : 0) | (m.seed ? 2 : 0) | (m.defaultDiscoveryKey ? 4 : 0)
50
47
 
51
48
  c.uint.encode(state, m.version)
52
49
  c.uint.encode(state, flags)
@@ -269,10 +266,7 @@ const encoding9 = {
269
266
  },
270
267
  encode(state, m) {
271
268
  const flags =
272
- (m.allowPatch ? 1 : 0) |
273
- (m.prologue ? 2 : 0) |
274
- (m.linked ? 4 : 0) |
275
- (m.userData ? 8 : 0)
269
+ (m.allowPatch ? 1 : 0) | (m.prologue ? 2 : 0) | (m.linked ? 4 : 0) | (m.userData ? 8 : 0)
276
270
 
277
271
  c.uint.encode(state, m.version)
278
272
  c.uint.encode(state, flags)
@@ -337,10 +331,7 @@ const encoding11 = {
337
331
  if (m.encryptionKey) c.buffer.preencode(state, m.encryptionKey)
338
332
  },
339
333
  encode(state, m) {
340
- const flags =
341
- (m.manifest ? 1 : 0) |
342
- (m.keyPair ? 2 : 0) |
343
- (m.encryptionKey ? 4 : 0)
334
+ const flags = (m.manifest ? 1 : 0) | (m.keyPair ? 2 : 0) | (m.encryptionKey ? 4 : 0)
344
335
 
345
336
  c.fixed32.encode(state, m.key)
346
337
  c.fixed32.encode(state, m.discoveryKey)
@@ -397,27 +388,29 @@ const encoding12 = {
397
388
  // @core/hints
398
389
  const encoding13 = {
399
390
  preencode(state, m) {
400
- state.end++ // max flag is 2 so always one byte
391
+ state.end++ // max flag is 4 so always one byte
401
392
 
402
393
  if (m.contiguousLength) c.uint.preencode(state, m.contiguousLength)
403
394
  if (m.remoteContiguousLength) c.uint.preencode(state, m.remoteContiguousLength)
395
+ if (m.recovering) c.uint.preencode(state, m.recovering)
404
396
  },
405
397
  encode(state, m) {
406
398
  const flags =
407
- (m.contiguousLength ? 1 : 0) |
408
- (m.remoteContiguousLength ? 2 : 0)
399
+ (m.contiguousLength ? 1 : 0) | (m.remoteContiguousLength ? 2 : 0) | (m.recovering ? 4 : 0)
409
400
 
410
401
  c.uint.encode(state, flags)
411
402
 
412
403
  if (m.contiguousLength) c.uint.encode(state, m.contiguousLength)
413
404
  if (m.remoteContiguousLength) c.uint.encode(state, m.remoteContiguousLength)
405
+ if (m.recovering) c.uint.encode(state, m.recovering)
414
406
  },
415
407
  decode(state) {
416
408
  const flags = c.uint.decode(state)
417
409
 
418
410
  return {
419
411
  contiguousLength: (flags & 1) !== 0 ? c.uint.decode(state) : 0,
420
- remoteContiguousLength: (flags & 2) !== 0 ? c.uint.decode(state) : 0
412
+ remoteContiguousLength: (flags & 2) !== 0 ? c.uint.decode(state) : 0,
413
+ recovering: (flags & 4) !== 0 ? c.uint.decode(state) : 0
421
414
  }
422
415
  }
423
416
  }