corestore 7.0.12 → 7.0.14

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 +81 -26
  2. package/lib/audit.js +2 -17
  3. package/package.json +1 -8
package/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  const b4a = require('b4a')
2
2
  const Hypercore = require('hypercore')
3
3
  const ReadyResource = require('ready-resource')
4
- const EventEmitter = require('events')
5
4
  const sodium = require('sodium-universal')
6
5
  const crypto = require('hypercore-crypto')
7
6
  const ID = require('hypercore-id-encoding')
@@ -77,11 +76,14 @@ class SessionTracker {
77
76
  }
78
77
  }
79
78
 
80
- class CoreTracker extends EventEmitter {
79
+ class CoreTracker {
81
80
  constructor () {
82
- super()
83
81
  this.map = new Map()
84
82
  this.watching = []
83
+
84
+ this._gcing = new Set()
85
+ this._gcInterval = null
86
+ this._gcCycleBound = this._gcCycle.bind(this)
85
87
  }
86
88
 
87
89
  get size () {
@@ -100,15 +102,33 @@ class CoreTracker extends EventEmitter {
100
102
  store.watchIndex = -1
101
103
  }
102
104
 
105
+ resume (id) {
106
+ const core = this.map.get(id)
107
+
108
+ if (!core) return null
109
+
110
+ // signal back that we have a closing one stored
111
+ if (core.closing) return core
112
+
113
+ if (core.gc) {
114
+ this._gcing.delete(core)
115
+ if (this._gcing.size === 0) this._stopGC()
116
+ core.gc = 0
117
+ }
118
+
119
+ return core
120
+ }
121
+
103
122
  get (id) {
104
123
  // we allow you do call this from the outside, so support normal buffers also
105
124
  if (b4a.isBuffer(id)) id = b4a.toString(id, 'hex')
106
- return this.map.get(id) || null
125
+ const core = this.map.get(id)
126
+ if (!core || core.closing) return null
127
+ return core
107
128
  }
108
129
 
109
130
  set (id, core) {
110
131
  this.map.set(id, core)
111
- this.emit('add', core) // TODO: will be removed
112
132
  if (this.watching.length > 0) this._emit(core)
113
133
  }
114
134
 
@@ -119,13 +139,51 @@ class CoreTracker extends EventEmitter {
119
139
  }
120
140
  }
121
141
 
122
- delete (id, core) {
123
- this.map.delete(id)
124
- this.emit('remove', core) // TODO: will be removed
142
+ _gc (core) {
143
+ const id = toHex(core.discoveryKey)
144
+ if (this.map.get(id) === core) this.map.delete(id)
145
+ }
146
+
147
+ _gcCycle () {
148
+ for (const core of this._gcing) {
149
+ if (++core.gc < 4) continue
150
+ const gc = this._gc.bind(this, core)
151
+ core.close().then(gc, gc)
152
+ this._gcing.delete(core)
153
+ }
154
+
155
+ if (this._gcing.size === 0) this._stopGC()
125
156
  }
126
157
 
127
- [Symbol.iterator] () {
128
- return this.map.values()
158
+ gc (core) {
159
+ core.gc = 1 // first strike
160
+ this._gcing.add(core)
161
+ if (this._gcing.size === 1) this._startGC()
162
+ }
163
+
164
+ _stopGC () {
165
+ clearInterval(this._gcInterval)
166
+ this._gcInterval = null
167
+ }
168
+
169
+ _startGC () {
170
+ if (this._gcInterval) return
171
+ this._gcInterval = setInterval(this._gcCycleBound, 2000)
172
+ }
173
+
174
+ close () {
175
+ this._stopGC()
176
+ this._gcing.clear()
177
+
178
+ const all = []
179
+ for (const core of this.map.values()) all.push(core.close())
180
+ return Promise.all(all)
181
+ }
182
+
183
+ * [Symbol.iterator] () {
184
+ for (const core of this.map.values()) {
185
+ if (!core.closing) yield core
186
+ }
129
187
  }
130
188
  }
131
189
 
@@ -286,17 +344,15 @@ class Corestore extends ReadyResource {
286
344
 
287
345
  await Promise.all(closing)
288
346
 
289
- const cores = []
290
- for (const core of this.cores) cores.push(core.close())
291
- await Promise.all(cores)
347
+ await this.cores.close()
292
348
  await this.storage.close()
293
349
  }
294
350
 
295
351
  async _attachMaybe (muxer, discoveryKey) {
296
352
  if (this.opened === false) await this.ready()
297
- if (this.cores.get(toHex(discoveryKey)) === null && !(await this.storage.has(discoveryKey))) return
353
+ if (this.cores.get(toHex(discoveryKey)) === null && !(await this.storage.has(discoveryKey, { ifMigrated: true }))) return
298
354
 
299
- const core = this._getCore(discoveryKey, { createIfMissing: false })
355
+ const core = this._openCore(discoveryKey, { createIfMissing: false })
300
356
 
301
357
  if (!core) return
302
358
  if (!core.opened) await core.ready()
@@ -304,6 +360,8 @@ class Corestore extends ReadyResource {
304
360
  if (!core.replicator.attached(muxer)) {
305
361
  core.replicator.attachTo(muxer)
306
362
  }
363
+
364
+ core.checkIfIdle()
307
365
  }
308
366
 
309
367
  replicate (isInitiator, opts) {
@@ -378,11 +436,12 @@ class Corestore extends ReadyResource {
378
436
 
379
437
  // if not not we can sync create it, which just is easier for the
380
438
  // upstream user in terms of guarantees (key is there etc etc)
381
- const core = this._getCore(null, opts)
439
+ const core = this._openCore(null, opts)
382
440
 
383
441
  conf.core = core
384
442
  conf.sessions = this.sessions.get(core.id)
385
443
  conf.ongc = this._ongcBound
444
+
386
445
  return this._makeSession(conf)
387
446
  }
388
447
 
@@ -404,7 +463,7 @@ class Corestore extends ReadyResource {
404
463
  const discoveryKey = opts.name ? await this.storage.getAlias({ name: opts.name, namespace: this.ns }) : null
405
464
  this._maybeClosed()
406
465
 
407
- const core = this._getCore(discoveryKey, opts)
466
+ const core = this._openCore(discoveryKey, opts)
408
467
 
409
468
  return {
410
469
  core,
@@ -448,18 +507,15 @@ class Corestore extends ReadyResource {
448
507
  return result
449
508
  }
450
509
 
451
- _hasCore (discoveryKey) {
452
- return this.cores.get(toHex(discoveryKey)) !== null
453
- }
454
-
455
- _getCore (discoveryKey, opts) {
510
+ _openCore (discoveryKey, opts) {
456
511
  const auth = this._auth(discoveryKey, opts)
457
512
 
458
513
  const id = toHex(auth.discoveryKey)
459
- const existing = this.cores.get(id)
460
- if (existing) return existing
514
+ const existing = this.cores.resume(id)
515
+ if (existing && !existing.closing) return existing
461
516
 
462
517
  const core = Hypercore.createCore(this.storage, {
518
+ preopen: existing ? existing.closing : null, // always wait for the prev one to close first in any case...
463
519
  eagerUpgrade: true,
464
520
  notDownloadingLinger: opts.notDownloadingLinger,
465
521
  allowFork: opts.allowFork !== false,
@@ -478,8 +534,7 @@ class Corestore extends ReadyResource {
478
534
  })
479
535
 
480
536
  core.onidle = () => {
481
- core.destroy()
482
- this.cores.delete(id, core)
537
+ this.cores.gc(core)
483
538
  }
484
539
 
485
540
  core.replicator.ondownloading = () => {
package/lib/audit.js CHANGED
@@ -1,29 +1,14 @@
1
- module.exports = async function audit (store, { dryRun = false } = {}) {
2
- const stats = { cores: 0, skipped: 0, rootless: 0, dropped: 0 }
3
-
1
+ module.exports = async function * audit (store, { dryRun = false } = {}) {
4
2
  for await (const { discoveryKey } of store.storage.createCoreStream()) {
5
- stats.cores++
6
-
7
3
  const core = store.get({ discoveryKey, active: false })
8
4
  await core.ready()
9
5
 
10
- const audit = await core.core.audit({ dryRun })
6
+ yield { discoveryKey, key: core.key, audit: await core.core.audit({ dryRun }) }
11
7
 
12
8
  try {
13
9
  await core.close()
14
10
  } catch {
15
11
  // ignore if failed, we are auditing...
16
12
  }
17
-
18
- if (audit === null || audit.corrupt) {
19
- stats.rootless++
20
- continue
21
- }
22
-
23
- if (audit.droppedTreeNodes || audit.droppedBlocks || audit.droppedBits) {
24
- stats.dropped++
25
- }
26
13
  }
27
-
28
- return stats
29
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corestore",
3
- "version": "7.0.12",
3
+ "version": "7.0.14",
4
4
  "description": "A Hypercore factory that simplifies managing collections of cores.",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -9,7 +9,6 @@
9
9
  ],
10
10
  "dependencies": {
11
11
  "b4a": "^1.6.7",
12
- "bare-events": "^2.5.0",
13
12
  "hypercore": "^11.0.0",
14
13
  "hypercore-crypto": "^3.4.2",
15
14
  "hypercore-id-encoding": "^1.3.0",
@@ -25,12 +24,6 @@
25
24
  "scripts": {
26
25
  "test": "standard && brittle test/*.js"
27
26
  },
28
- "imports": {
29
- "events": {
30
- "bare": "bare-events",
31
- "default": "events"
32
- }
33
- },
34
27
  "repository": {
35
28
  "type": "git",
36
29
  "url": "https://github.com/holepunchto/corestore2.git"