hypercore-storage 2.4.1 → 2.5.0

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() {
551
+ const r = path.join(this.db.path, 'RECOVERING')
552
+ if (!(await fileExists(r))) return
553
+ await this.setRecovering()
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()
559
582
 
560
583
  const rx = new CorestoreRX(this.db, view)
561
584
  const headPromise = rx.getHead()
@@ -775,6 +798,35 @@ class CorestoreStorage {
775
798
  }
776
799
  }
777
800
 
801
+ async setRecovering() {
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, keys)
809
+ keys = []
810
+ }
811
+ }
812
+
813
+ if (keys.length) await this._flushRecovering(recovering, keys)
814
+ }
815
+
816
+ async _flushRecovering(recovering, keys) {
817
+ const view = await this._enter()
818
+ const tx = new CorestoreTX(view)
819
+
820
+ try {
821
+ const infos = await this.getInfos(keys, { auth: false, head: false, hints: true })
822
+ for (const inf of infos) {
823
+ tx.setCoreHints(inf.core, { ...inf.hints, recovering })
824
+ }
825
+ } finally {
826
+ await this._exit()
827
+ }
828
+ }
829
+
778
830
  async getDefaultDiscoveryKey() {
779
831
  if (this.version === 0) await this._migrateStore()
780
832
 
@@ -1128,6 +1180,19 @@ async function toArray(stream) {
1128
1180
  return all
1129
1181
  }
1130
1182
 
1183
+ async function fileExists(path) {
1184
+ try {
1185
+ await fs.promises.stat(path)
1186
+ return true
1187
+ } catch {
1188
+ return false
1189
+ }
1190
+ }
1191
+
1192
+ function shouldRecover(err) {
1193
+ return err.message.toLowerCase().indexOf('sequence number is being set backwards') > -1
1194
+ }
1195
+
1131
1196
  function noop() {}
1132
1197
 
1133
1198
  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.0",
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
  }