autobee 2.2.0 → 2.2.2
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 +25 -1
- package/lib/writers.js +64 -33
- package/package.json +2 -1
package/index.js
CHANGED
|
@@ -344,6 +344,29 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
344
344
|
async _close() {
|
|
345
345
|
this._interrupting = true
|
|
346
346
|
|
|
347
|
+
// the local core holds the exclusive lock but the local writer closes it
|
|
348
|
+
// early in the teardown, so hand the lock to a detached session that
|
|
349
|
+
// outlives the teardown and only release it once everything is down
|
|
350
|
+
let lock = null
|
|
351
|
+
|
|
352
|
+
if (this.local.exclusive) {
|
|
353
|
+
lock = this.store.session()
|
|
354
|
+
const local = lock.get({ key: this.local.key, active: false })
|
|
355
|
+
await local.ready()
|
|
356
|
+
|
|
357
|
+
// transfer exclusiveness, the detached session now unlocks on close
|
|
358
|
+
local.exclusive = true
|
|
359
|
+
this.local.exclusive = false
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
await this._teardown()
|
|
364
|
+
} finally {
|
|
365
|
+
if (lock) await lock.close()
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async _teardown() {
|
|
347
370
|
try {
|
|
348
371
|
await ApplyView.close(this.view, this)
|
|
349
372
|
} catch (err) {
|
|
@@ -351,7 +374,6 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
351
374
|
}
|
|
352
375
|
|
|
353
376
|
if (this.writers) await this.writers.close()
|
|
354
|
-
await this.local.close()
|
|
355
377
|
await this.system.close()
|
|
356
378
|
await this._wakeup.close()
|
|
357
379
|
if (this.bootstrap) await this.bootstrap.close()
|
|
@@ -366,6 +388,8 @@ module.exports = class Autobee extends ReadyResource {
|
|
|
366
388
|
// don't rely on the store teardown to stop the notify watcher
|
|
367
389
|
if (this._notifyHandler) this._notifyHandler.destroy()
|
|
368
390
|
|
|
391
|
+
await this.local.close()
|
|
392
|
+
|
|
369
393
|
// rugpull the rest
|
|
370
394
|
await this.store.close()
|
|
371
395
|
|
package/lib/writers.js
CHANGED
|
@@ -4,6 +4,7 @@ const Triggers = require('./triggers.js')
|
|
|
4
4
|
const { LEGACY_OPLOG_VERSION } = require('./constants.js')
|
|
5
5
|
const { resolveWeight } = require('./witness.js')
|
|
6
6
|
const { WriterEncryption } = require('autobee-encryption')
|
|
7
|
+
const ReadWriteLock = require('read-write-mutexify')
|
|
7
8
|
|
|
8
9
|
const WRITER_PREFETCH = 10
|
|
9
10
|
|
|
@@ -25,6 +26,7 @@ class ActiveWriters {
|
|
|
25
26
|
|
|
26
27
|
this._pendingBuffer = new Map()
|
|
27
28
|
this._adding = new Map()
|
|
29
|
+
this._lock = new ReadWriteLock()
|
|
28
30
|
|
|
29
31
|
this.localWriter = new Writer(this, auto.system, true, local, b4a.toString(local.key, 'hex'))
|
|
30
32
|
this.localWriter.attach()
|
|
@@ -89,14 +91,27 @@ class ActiveWriters {
|
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
async rotateLocalWriter(core) {
|
|
92
|
-
this.
|
|
93
|
-
await this.localWriter.detachAndClose()
|
|
94
|
+
await this._lock.write.lock()
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
try {
|
|
97
|
+
this.clearLocal()
|
|
98
|
+
await this.localWriter.detachAndClose()
|
|
99
|
+
|
|
100
|
+
const id = b4a.toString(core.key, 'hex')
|
|
101
|
+
|
|
102
|
+
// a peer may already have announced this core (wakeup hint / link), in which
|
|
103
|
+
// case an external writer tracks it - drop it so only one writer owns the key
|
|
104
|
+
const existing = this.active.get(id)
|
|
105
|
+
if (existing) await existing.detachAndClose()
|
|
98
106
|
|
|
99
|
-
|
|
107
|
+
this.localWriter = new Writer(this, this.auto.system, true, core, id)
|
|
108
|
+
// register in active like the constructor does, so add() finds it
|
|
109
|
+
this.localWriter.attach()
|
|
110
|
+
|
|
111
|
+
await this.updateLocalState()
|
|
112
|
+
} finally {
|
|
113
|
+
this._lock.write.unlock()
|
|
114
|
+
}
|
|
100
115
|
}
|
|
101
116
|
|
|
102
117
|
clearLocal() {
|
|
@@ -178,7 +193,7 @@ class ActiveWriters {
|
|
|
178
193
|
return !!this.active.get(id)
|
|
179
194
|
}
|
|
180
195
|
|
|
181
|
-
add(key) {
|
|
196
|
+
async add(key) {
|
|
182
197
|
const id = b4a.toString(key, 'hex')
|
|
183
198
|
|
|
184
199
|
let adding = this._adding.get(id)
|
|
@@ -187,44 +202,60 @@ class ActiveWriters {
|
|
|
187
202
|
adding = this._add(key, id)
|
|
188
203
|
this._adding.set(id, adding)
|
|
189
204
|
|
|
190
|
-
|
|
205
|
+
try {
|
|
206
|
+
return await adding
|
|
207
|
+
} finally {
|
|
191
208
|
this._adding.delete(id)
|
|
192
|
-
}
|
|
209
|
+
}
|
|
193
210
|
}
|
|
194
211
|
|
|
195
|
-
// TODO: correct fix is writer as ReadyResource
|
|
196
212
|
async _add(key, id) {
|
|
197
|
-
|
|
198
|
-
if (local) await this.updateLocalState()
|
|
213
|
+
await this._lock.read.lock()
|
|
199
214
|
|
|
200
|
-
|
|
201
|
-
|
|
215
|
+
try {
|
|
216
|
+
if (this.auto._interrupting) return null
|
|
217
|
+
|
|
218
|
+
// judged against the writer we own, not auto.local - that flips before the
|
|
219
|
+
// rotation takes the write lock. an add that beats the rotation onto its
|
|
220
|
+
// key just makes an external writer, which the rotation then evicts
|
|
221
|
+
if (b4a.equals(key, this.localWriter.core.key)) {
|
|
222
|
+
await this.updateLocalState()
|
|
223
|
+
if (this.auto._interrupting) return null
|
|
224
|
+
// never track the local core with a second writer - reattach it if it
|
|
225
|
+
// was detached (i.e. removed earlier and now re-added)
|
|
226
|
+
this.localWriter.attach()
|
|
227
|
+
return this.localWriter
|
|
228
|
+
}
|
|
202
229
|
|
|
203
|
-
|
|
204
|
-
|
|
230
|
+
let w = this.active.get(id)
|
|
231
|
+
if (w) return w
|
|
205
232
|
|
|
206
|
-
|
|
233
|
+
const local = b4a.equals(key, this.auto.local.key)
|
|
234
|
+
const encryption = this.auto.encryptionKey ? new WriterEncryption(this.auto) : null
|
|
207
235
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
236
|
+
const core = this.auto.store.get({
|
|
237
|
+
active: false,
|
|
238
|
+
key,
|
|
239
|
+
encryption,
|
|
240
|
+
group: local || !this.auto.wakeupCapability ? null : this.auto.wakeupCapability.discoveryKey
|
|
241
|
+
})
|
|
214
242
|
|
|
215
|
-
|
|
216
|
-
|
|
243
|
+
await core.ready()
|
|
244
|
+
await core.setUserData('referrer', this.auto.key)
|
|
217
245
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
246
|
+
// teardown may have started underneath us
|
|
247
|
+
if (this.auto._interrupting) {
|
|
248
|
+
await core.close()
|
|
249
|
+
return null
|
|
250
|
+
}
|
|
223
251
|
|
|
224
|
-
|
|
225
|
-
|
|
252
|
+
w = new Writer(this, this.auto.system, false, core, id)
|
|
253
|
+
w.attach()
|
|
226
254
|
|
|
227
|
-
|
|
255
|
+
return w
|
|
256
|
+
} finally {
|
|
257
|
+
this._lock.read.unlock()
|
|
258
|
+
}
|
|
228
259
|
}
|
|
229
260
|
|
|
230
261
|
async remove(key) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autobee",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "Bee based autobase",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Holepunch Inc.",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"hypercore": "^11.33.2",
|
|
32
32
|
"hypercore-id-encoding": "^1.3.0",
|
|
33
33
|
"hyperschema": "^1.20.1",
|
|
34
|
+
"read-write-mutexify": "^2.1.0",
|
|
34
35
|
"ready-guard": "^1.0.0",
|
|
35
36
|
"ready-resource": "^1.2.0",
|
|
36
37
|
"resolve-reject-promise": "^1.1.0",
|