hypercore-storage 2.4.0 → 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
@@ -343,36 +343,6 @@ class HypercoreStorage {
343
343
  return this.atomize(atom)
344
344
  }
345
345
 
346
- async createStaticCore() {
347
- const rx = this.read()
348
-
349
- const headPromise = rx.getHead()
350
- const authPromise = rx.getAuth()
351
-
352
- rx.tryFlush()
353
-
354
- const [head, auth] = await Promise.all([headPromise, authPromise])
355
- if (!head || head.length === 0) throw new Error('Must have data')
356
-
357
- const prologue = {
358
- length: head.length,
359
- hash: head.rootHash
360
- }
361
-
362
- const manifest = {
363
- version: 1,
364
- hash: auth.manifest.hash,
365
- quorum: 0,
366
- signers: [],
367
- prologue
368
- }
369
-
370
- return {
371
- manifest,
372
- core: { ...this.core, dependencies: this.core.dependencies.slice() }
373
- }
374
- }
375
-
376
346
  _addDependency(dep) {
377
347
  const deps = []
378
348
 
@@ -577,6 +547,21 @@ class CorestoreStorage {
577
547
  }
578
548
  }
579
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
+
580
565
  // runs pre any other mutation and read
581
566
  async _migrateStore() {
582
567
  const view = await this._enter()
@@ -585,7 +570,15 @@ class CorestoreStorage {
585
570
  if (this.version === VERSION) return
586
571
 
587
572
  await this._preopen
588
- 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()
589
582
 
590
583
  const rx = new CorestoreRX(this.db, view)
591
584
  const headPromise = rx.getHead()
@@ -805,6 +798,35 @@ class CorestoreStorage {
805
798
  }
806
799
  }
807
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
+
808
830
  async getDefaultDiscoveryKey() {
809
831
  if (this.version === 0) await this._migrateStore()
810
832
 
@@ -1158,6 +1180,19 @@ async function toArray(stream) {
1158
1180
  return all
1159
1181
  }
1160
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
+
1161
1196
  function noop() {}
1162
1197
 
1163
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.0",
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
  }