corestore 6.7.0 → 6.8.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.
Files changed (3) hide show
  1. package/README.md +5 -2
  2. package/index.js +37 -7
  3. package/package.json +2 -1
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
@@ -37,6 +38,7 @@ module.exports = class Corestore extends ReadyResource {
37
38
 
38
39
  this._sessions = new Set() // sessions for THIS namespace
39
40
  this._rootStoreSessions = new Set()
41
+ this._locks = root ? root._locks : new Map()
40
42
 
41
43
  this._findingPeersCount = 0
42
44
  this._findingPeers = []
@@ -172,20 +174,46 @@ module.exports = class Corestore extends ReadyResource {
172
174
  core.writable = true
173
175
  }
174
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
+
175
188
  async _preload (opts) {
176
189
  if (!this.primaryKey) await this.ready()
177
190
 
178
191
  const { discoveryKey, keyPair, auth } = await this._generateKeys(opts)
179
192
  const id = b4a.toString(discoveryKey, 'hex')
180
193
 
181
- while (this.cores.has(id)) {
182
- const existing = this.cores.get(id)
183
- if (existing.opened && !existing.closing) return { from: existing, keyPair, auth }
184
- if (existing.closing) {
185
- await existing.close()
186
- } else {
187
- await existing.ready().catch(safetyCatch)
194
+ const readonly = opts.writable === false || this._readonly
195
+ const rw = (opts && opts.exclusive && !readonly && keyPair) ? this._getLock(id) : null
196
+
197
+ if (rw) await rw.write.lock()
198
+ const release = () => {
199
+ if (!rw) return
200
+ rw.write.unlock()
201
+ if (rw.write.waiting === 0) this._locks.delete(id)
202
+ }
203
+
204
+ try {
205
+ while (this.cores.has(id)) {
206
+ const existing = this.cores.get(id)
207
+ if (existing.opened && !existing.closing) return { from: existing, keyPair, auth }
208
+ if (existing.closing) {
209
+ await existing.close()
210
+ } else {
211
+ await existing.ready().catch(safetyCatch)
212
+ }
188
213
  }
214
+ } catch (err) {
215
+ release()
216
+ throw err
189
217
  }
190
218
 
191
219
  const userData = {}
@@ -223,10 +251,12 @@ module.exports = class Corestore extends ReadyResource {
223
251
  }
224
252
  }, () => {
225
253
  this.cores.delete(id)
254
+ release()
226
255
  })
227
256
  core.once('close', () => {
228
257
  this._emitCore('core-close', core)
229
258
  this.cores.delete(id)
259
+ release()
230
260
  })
231
261
  core.on('conflict', (len, fork, proof) => {
232
262
  this.emit('conflict', core, len, fork, proof)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corestore",
3
- "version": "6.7.0",
3
+ "version": "6.8.1",
4
4
  "description": "A Hypercore factory that simplifies managing collections of cores.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -32,6 +32,7 @@
32
32
  "b4a": "^1.3.1",
33
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",