corestore 6.6.0 → 6.8.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.
Files changed (3) hide show
  1. package/README.md +5 -2
  2. package/index.js +42 -10
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -29,12 +29,15 @@ Create a new Corestore instance.
29
29
 
30
30
  `storage` can be either a random-access-storage module, a string, or a function that takes a path and returns an random-access-storage instance.
31
31
 
32
- #### `const core = store.get(key | { name: 'a-name', ...hypercoreOpts})`
32
+ #### `const core = store.get(key | { name: 'a-name', exclusive, ...hypercoreOpts})`
33
33
  Loads a Hypercore, either by name (if the `name` option is provided), or from the provided key (if the first argument is a Buffer, or if the `key` options is set).
34
34
 
35
35
  If that Hypercore has previously been loaded, subsequent calls to `get` will return a new Hypercore session on the existing core.
36
36
 
37
- All other options besides `name` and `key` will be forwarded to the Hypercore constructor.
37
+ If you set the `exclusive` option and you are opening a writable session it will wait for all other exclusive writable to close before
38
+ opening the Hypercore effectively meaning any op on the core will wait until its exclusive.
39
+
40
+ All other options besides `name` and `key` and `exclusive` will be forwarded to the Hypercore constructor.
38
41
 
39
42
  #### `const stream = store.replicate(optsOrStream)`
40
43
  Creates a replication stream that's capable of replicating all Hypercores that are managed by the Corestore, assuming the remote peer has the correct capabilities.
package/index.js CHANGED
@@ -5,6 +5,7 @@ const Hypercore = require('hypercore')
5
5
  const Xache = require('xache')
6
6
  const b4a = require('b4a')
7
7
  const ReadyResource = require('ready-resource')
8
+ const RW = require('read-write-mutexify')
8
9
 
9
10
  const [NS] = crypto.namespace('corestore', 1)
10
11
  const DEFAULT_NAMESPACE = b4a.alloc(32) // This is meant to be 32 0-bytes
@@ -33,9 +34,11 @@ module.exports = class Corestore extends ReadyResource {
33
34
  this._root = root || this
34
35
  this._replicationStreams = root ? root._replicationStreams : []
35
36
  this._overwrite = opts.overwrite === true
37
+ this._readonly = opts.writable === false
36
38
 
37
39
  this._sessions = new Set() // sessions for THIS namespace
38
40
  this._rootStoreSessions = new Set()
41
+ this._locks = root ? root._locks : new Map()
39
42
 
40
43
  this._findingPeersCount = 0
41
44
  this._findingPeers = []
@@ -171,20 +174,45 @@ module.exports = class Corestore extends ReadyResource {
171
174
  core.writable = true
172
175
  }
173
176
 
177
+ _getLock (id) {
178
+ let rw = this._locks.get(id)
179
+
180
+ if (!rw) {
181
+ rw = new RW()
182
+ this._locks.set(id, rw)
183
+ }
184
+
185
+ return rw
186
+ }
187
+
174
188
  async _preload (opts) {
175
189
  if (!this.primaryKey) await this.ready()
176
190
 
177
191
  const { discoveryKey, keyPair, auth } = await this._generateKeys(opts)
178
192
  const id = b4a.toString(discoveryKey, 'hex')
179
193
 
180
- while (this.cores.has(id)) {
181
- const existing = this.cores.get(id)
182
- if (existing.opened && !existing.closing) return { from: existing, keyPair, auth }
183
- if (existing.closing) {
184
- await existing.close()
185
- } else {
186
- await existing.ready().catch(safetyCatch)
194
+ const rw = (opts && opts.exclusive && opts.writable !== false && keyPair) ? this._getLock(id) : null
195
+
196
+ if (rw) await rw.write.lock()
197
+ const release = () => {
198
+ if (!rw) return
199
+ rw.write.unlock()
200
+ if (rw.write.waiting === 0) this._locks.delete(id)
201
+ }
202
+
203
+ try {
204
+ while (this.cores.has(id)) {
205
+ const existing = this.cores.get(id)
206
+ if (existing.opened && !existing.closing) return { from: existing, keyPair, auth }
207
+ if (existing.closing) {
208
+ await existing.close()
209
+ } else {
210
+ await existing.ready().catch(safetyCatch)
211
+ }
187
212
  }
213
+ } catch (err) {
214
+ release()
215
+ throw err
188
216
  }
189
217
 
190
218
  const userData = {}
@@ -222,10 +250,12 @@ module.exports = class Corestore extends ReadyResource {
222
250
  }
223
251
  }, () => {
224
252
  this.cores.delete(id)
253
+ release()
225
254
  })
226
255
  core.once('close', () => {
227
256
  this._emitCore('core-close', core)
228
257
  this.cores.delete(id)
258
+ release()
229
259
  })
230
260
  core.on('conflict', (len, fork, proof) => {
231
261
  this.emit('conflict', core, len, fork, proof)
@@ -263,6 +293,7 @@ module.exports = class Corestore extends ReadyResource {
263
293
  }
264
294
 
265
295
  const core = new Hypercore(null, {
296
+ writable: !this._readonly,
266
297
  ...opts,
267
298
  name: null,
268
299
  preload: () => this._preload(opts)
@@ -311,17 +342,18 @@ module.exports = class Corestore extends ReadyResource {
311
342
  return stream
312
343
  }
313
344
 
314
- namespace (name) {
345
+ namespace (name, opts) {
315
346
  if (name instanceof Hypercore) {
316
- return this.session({ _bootstrap: name })
347
+ return this.session({ ...opts, _bootstrap: name })
317
348
  }
318
- return this.session({ namespace: generateNamespace(this._namespace, name) })
349
+ return this.session({ ...opts, namespace: generateNamespace(this._namespace, name) })
319
350
  }
320
351
 
321
352
  session (opts) {
322
353
  const session = new Corestore(this.storage, {
323
354
  namespace: this._namespace,
324
355
  cache: this.cache,
356
+ writable: !this._readonly,
325
357
  _root: this._root,
326
358
  ...opts
327
359
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corestore",
3
- "version": "6.6.0",
3
+ "version": "6.8.0",
4
4
  "description": "A Hypercore factory that simplifies managing collections of cores.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -30,8 +30,9 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "b4a": "^1.3.1",
33
- "hypercore": "^10.10.0",
33
+ "hypercore": "^10.12.0",
34
34
  "hypercore-crypto": "^3.2.1",
35
+ "read-write-mutexify": "^2.1.0",
35
36
  "ready-resource": "^1.0.0",
36
37
  "safety-catch": "^1.0.1",
37
38
  "sodium-universal": "^4.0.0",