blind-peer 0.0.4 → 2.7.5
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/README.md +70 -2
- package/bin.js +151 -21
- package/index.js +462 -94
- package/lib/db.js +170 -0
- package/package.json +39 -14
- package/.github/workflows/test-node.yml +0 -23
- package/build.js +0 -102
- package/client.js +0 -31
- package/example/autobase.mjs +0 -66
- package/example/blind-peer.mjs +0 -6
- package/example/post.mjs +0 -25
- package/spec/hyperdb/db.json +0 -19
- package/spec/hyperdb/index.js +0 -83
- package/spec/hyperdb/messages.js +0 -234
- package/spec/hyperschema/index.js +0 -199
- package/spec/hyperschema/schema.json +0 -107
package/index.js
CHANGED
|
@@ -1,146 +1,514 @@
|
|
|
1
|
-
const { EventEmitter } = require('events')
|
|
2
|
-
const AutobaseLightWriter = require('autobase-light-writer')
|
|
3
|
-
const HyperDB = require('hyperdb')
|
|
4
1
|
const Corestore = require('corestore')
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
2
|
+
const Hypercore = require('hypercore')
|
|
3
|
+
const RocksDB = require('rocksdb-native')
|
|
4
|
+
const ReadyResource = require('ready-resource')
|
|
8
5
|
const Hyperswarm = require('hyperswarm')
|
|
9
6
|
const ProtomuxRPC = require('protomux-rpc')
|
|
10
7
|
const c = require('compact-encoding')
|
|
8
|
+
const b4a = require('b4a')
|
|
9
|
+
const crypto = require('hypercore-crypto')
|
|
10
|
+
const safetyCatch = require('safety-catch')
|
|
11
|
+
const Wakeup = require('protomux-wakeup')
|
|
12
|
+
const ScopeLock = require('scope-lock')
|
|
13
|
+
const IdEnc = require('hypercore-id-encoding')
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
const BlindPeerDB = require('./lib/db.js')
|
|
16
|
+
|
|
17
|
+
const { AddCoreEncoding } = require('blind-peer-encodings')
|
|
18
|
+
|
|
19
|
+
class CoreTracker {
|
|
20
|
+
constructor (blindPeer, core) {
|
|
21
|
+
this.blindPeer = blindPeer
|
|
22
|
+
this.core = core
|
|
23
|
+
this.destroyed = false
|
|
24
|
+
this.record = null
|
|
25
|
+
this.activated = false
|
|
26
|
+
this.updated = false
|
|
27
|
+
this.id = null
|
|
28
|
+
this.referrerDiscoveryKey = null
|
|
29
|
+
this.channel = null
|
|
30
|
+
this.downloadRange = null
|
|
31
|
+
this.announceToReferrerBound = this.announceToReferrer.bind(this)
|
|
15
32
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.
|
|
33
|
+
const onupdate = this._onupdate.bind(this)
|
|
34
|
+
const onactive = this._onactive.bind(this)
|
|
35
|
+
|
|
36
|
+
this.core.on('upload', onactive)
|
|
37
|
+
this.core.on('download', onactive)
|
|
38
|
+
this.core.on('truncate', onupdate)
|
|
39
|
+
this.core.on('append', onupdate)
|
|
20
40
|
}
|
|
21
41
|
|
|
22
|
-
|
|
23
|
-
this.
|
|
42
|
+
_onupdate () {
|
|
43
|
+
this.updated = true
|
|
44
|
+
if (!this.record) return
|
|
24
45
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
46
|
+
this.record.length = this.core.length
|
|
47
|
+
this.record.bytesAllocated = this.core.byteLength - this.record.bytesCleared
|
|
48
|
+
this.blindPeer.db.updateCore(this.record, this.id)
|
|
49
|
+
this.blindPeer.flush().then(this.announceToReferrerBound, safetyCatch)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
_onactive () {
|
|
53
|
+
this.activated = true
|
|
29
54
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}, this._onrpcadd.bind(this))
|
|
55
|
+
if (this.record) {
|
|
56
|
+
this.blindPeer.db.updateCore(this.record, this.id)
|
|
57
|
+
}
|
|
34
58
|
|
|
35
|
-
|
|
36
|
-
requestEncoding: schema.resolveStruct('@blind-peer/request-post'),
|
|
37
|
-
responseEncoding: schema.resolveStruct('@blind-peer/response-post')
|
|
38
|
-
}, this._onrpcpost.bind(this))
|
|
59
|
+
this.blindPeer.emit('core-activity', this.core, this.record)
|
|
39
60
|
}
|
|
40
61
|
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
const
|
|
44
|
-
this.
|
|
62
|
+
gc () { // TODO: support gc-ing till less than last block (required hypercore to support getting byteLength at arbitrary versions)
|
|
63
|
+
const bytesCleared = this.core.byteLength
|
|
64
|
+
const blocksCleared = this.core.length
|
|
65
|
+
this.record.bytesAllocated = this.core.byteLength - bytesCleared
|
|
66
|
+
this.record.blocksCleared = blocksCleared
|
|
67
|
+
this.record.bytesCleared = bytesCleared
|
|
68
|
+
|
|
69
|
+
if (this.downloadRange) this.downloadRange.destroy()
|
|
70
|
+
this.downloadRange = this.core.download({ start: this.record.blocksCleared, end: -1 })
|
|
71
|
+
|
|
72
|
+
this.core.clear(0, blocksCleared).catch(safetyCatch)
|
|
73
|
+
this.blindPeer.db.updateCore(this.record, this.id)
|
|
74
|
+
|
|
75
|
+
return bytesCleared
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async refresh () {
|
|
79
|
+
await this.core.ready()
|
|
80
|
+
if (this.destroyed) return
|
|
81
|
+
|
|
82
|
+
this.id = this.core.id
|
|
83
|
+
this.channel = 'hypercore/alpha##' + b4a.toString(this.core.discoveryKey, 'hex')
|
|
84
|
+
|
|
85
|
+
const record = await this.blindPeer.db.get('@blind-peer/cores', { key: this.core.key })
|
|
86
|
+
if (this.destroyed || this.record || !record) return
|
|
87
|
+
|
|
88
|
+
this.record = record
|
|
89
|
+
this.core.download({ start: this.record.blocksCleared, end: -1 })
|
|
45
90
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
91
|
+
if (this.updated) this._onupdate()
|
|
92
|
+
if (this.activated) this._onactive()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
announceToReferrer () {
|
|
96
|
+
if (!this.record || !this.record.referrer) return
|
|
97
|
+
if (!this.referrerDiscoveryKey) this.referrerDiscoveryKey = crypto.discoveryKey(this.record.referrer)
|
|
98
|
+
|
|
99
|
+
const sessions = this.blindPeer.wakeup.getSessions(null, { discoveryKey: this.referrerDiscoveryKey })
|
|
100
|
+
if (sessions.length === 0) return
|
|
101
|
+
|
|
102
|
+
const wakeup = [{ key: this.core.key, length: this.core.length }]
|
|
103
|
+
|
|
104
|
+
for (const s of sessions) {
|
|
105
|
+
for (const peer of s.peers) {
|
|
106
|
+
const mux = peer.stream.userData
|
|
107
|
+
|
|
108
|
+
// already replicating with that peer
|
|
109
|
+
if (mux._infos.get(this.channel)) {
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
s.announceByStream(peer.stream, wakeup)
|
|
114
|
+
}
|
|
50
115
|
}
|
|
51
116
|
}
|
|
52
117
|
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
|
|
56
|
-
|
|
118
|
+
destroy () {
|
|
119
|
+
if (this.destroyed) return
|
|
120
|
+
this.destroyed = true
|
|
121
|
+
}
|
|
122
|
+
}
|
|
57
123
|
|
|
58
|
-
|
|
124
|
+
class WakeupHandler {
|
|
125
|
+
constructor (db, key, discoveryKey) {
|
|
126
|
+
this.db = db
|
|
127
|
+
this.key = key
|
|
128
|
+
this.discoveryKey = discoveryKey
|
|
129
|
+
this.active = false
|
|
59
130
|
}
|
|
60
131
|
|
|
61
|
-
async
|
|
132
|
+
async onpeeractive (peer, session) {
|
|
133
|
+
const referrer = this.key
|
|
134
|
+
const query = {
|
|
135
|
+
gte: { referrer },
|
|
136
|
+
lte: { referrer },
|
|
137
|
+
reverse: true,
|
|
138
|
+
limit: 32
|
|
139
|
+
}
|
|
140
|
+
|
|
62
141
|
try {
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
142
|
+
const latest = await this.db.find('@blind-peer/cores-by-referrer', query).toArray()
|
|
143
|
+
if (peer.removed) return
|
|
144
|
+
session.announce(peer, latest)
|
|
145
|
+
} catch {
|
|
146
|
+
// do nothing
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
65
150
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
})
|
|
151
|
+
class BlindPeer extends ReadyResource {
|
|
152
|
+
constructor (rocks, { swarm, store, wakeup, maxBytes = 100_000_000_000, enableGc = true, trustedPubKeys, port } = {}) {
|
|
153
|
+
super()
|
|
70
154
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
155
|
+
this.rocks = typeof rocks === 'string' ? new RocksDB(rocks) : rocks
|
|
156
|
+
this.store = store || new Corestore(this.rocks, { active: false })
|
|
157
|
+
this.swarm = swarm || null
|
|
158
|
+
this._port = port || null
|
|
159
|
+
this.trustedPubKeys = new Set()
|
|
160
|
+
for (const k of trustedPubKeys || []) this.addTrustedPubKey(k)
|
|
74
161
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
162
|
+
this.wakeup = wakeup || new Wakeup(this._onwakeup.bind(this))
|
|
163
|
+
this.ownsWakeup = !wakeup
|
|
164
|
+
this.ownsSwarm = !swarm
|
|
165
|
+
this.ownsStore = !store
|
|
166
|
+
this.db = null
|
|
167
|
+
this.activeReplication = new Map()
|
|
168
|
+
this.activeWakeup = new Map()
|
|
169
|
+
this.flushInterval = null
|
|
170
|
+
this.maxBytes = maxBytes
|
|
171
|
+
this.enableGc = enableGc
|
|
172
|
+
this.lock = new ScopeLock({ debounce: true })
|
|
173
|
+
this.announcedCores = new Map()
|
|
78
174
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
175
|
+
this.stats = {
|
|
176
|
+
bytesGcd: 0,
|
|
177
|
+
coresAdded: 0,
|
|
178
|
+
activations: 0,
|
|
179
|
+
wakeups: 0
|
|
84
180
|
}
|
|
85
181
|
}
|
|
86
182
|
|
|
183
|
+
get encryptionPublicKey () {
|
|
184
|
+
return this.db.encryptionKeyPair.publicKey
|
|
185
|
+
}
|
|
186
|
+
|
|
87
187
|
get publicKey () {
|
|
88
|
-
return this.swarm.
|
|
188
|
+
return this.swarm.keyPair.publicKey
|
|
89
189
|
}
|
|
90
190
|
|
|
91
|
-
|
|
92
|
-
this.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
191
|
+
get digest () {
|
|
192
|
+
return this.db.digest
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
addTrustedPubKey (key) {
|
|
196
|
+
this.trustedPubKeys.add(IdEnc.normalize(key))
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
_isTrustedPeer (key) {
|
|
200
|
+
return this.trustedPubKeys.has(IdEnc.normalize(key))
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async _open () {
|
|
204
|
+
await this.store.ready()
|
|
205
|
+
// legacy, we can remove once current ones are upgraded
|
|
206
|
+
const { secretKey } = await this.store.createKeyPair('blind-mirror-swarm')
|
|
207
|
+
this.db = new BlindPeerDB(this.rocks.session(), { swarming: secretKey.subarray(0, 32), encryption: null })
|
|
208
|
+
await this.db.ready()
|
|
209
|
+
|
|
210
|
+
if (this.swarm === null) {
|
|
211
|
+
const swarmOpts = { keyPair: this.db.swarmingKeyPair }
|
|
212
|
+
if (this._port) swarmOpts.port = this._port
|
|
213
|
+
this.swarm = new Hyperswarm(swarmOpts)
|
|
214
|
+
}
|
|
96
215
|
this.swarm.on('connection', this._onconnection.bind(this))
|
|
216
|
+
|
|
217
|
+
const announceProms = []
|
|
218
|
+
for await (const record of this.db.createAnnouncingCoresStream()) {
|
|
219
|
+
announceProms.push(this._announceCore(record.key))
|
|
220
|
+
}
|
|
221
|
+
await Promise.all(announceProms)
|
|
222
|
+
|
|
223
|
+
this.store.watch(this._oncoreopen.bind(this))
|
|
224
|
+
|
|
225
|
+
this.flushInterval = setInterval(this.flush.bind(this), 10_000)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async _onwakeup (discoveryKey, muxer) {
|
|
229
|
+
this.stats.wakeups++
|
|
230
|
+
|
|
231
|
+
const auth = await this.store.storage.getAuth(discoveryKey)
|
|
232
|
+
if (!auth) return
|
|
233
|
+
|
|
234
|
+
const stream = muxer.stream
|
|
235
|
+
const handler = new WakeupHandler(this.db, auth.key, discoveryKey)
|
|
236
|
+
const w = this.wakeup.session(auth.key, handler)
|
|
237
|
+
|
|
238
|
+
if (w.getPeer(stream)) {
|
|
239
|
+
w.destroy()
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
w.addStream(stream)
|
|
244
|
+
|
|
245
|
+
for (const peer of w.peers) {
|
|
246
|
+
if (peer.active) handler.onpeeractive(peer, w)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
stream.setMaxListeners(0)
|
|
250
|
+
stream.once('close', () => w.destroy())
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async listen () {
|
|
254
|
+
if (!this.opened) await this.ready()
|
|
97
255
|
return this.swarm.listen()
|
|
98
256
|
}
|
|
99
257
|
|
|
100
|
-
|
|
101
|
-
return
|
|
258
|
+
needsGc () {
|
|
259
|
+
return this.digest.bytesAllocated >= this.maxBytes
|
|
102
260
|
}
|
|
103
261
|
|
|
104
|
-
async
|
|
105
|
-
|
|
262
|
+
async _gc () { // Do not call directly (assumes lock)
|
|
263
|
+
if (!this.needsGc()) return
|
|
106
264
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return
|
|
265
|
+
const bytesToClear = this.digest.bytesAllocated - this.maxBytes
|
|
266
|
+
let bytesCleared = 0
|
|
267
|
+
this.emit('gc-start', { bytesToClear })
|
|
268
|
+
|
|
269
|
+
for await (const record of this.db.createGcCandidateReadStream()) {
|
|
270
|
+
if (this.closing) return
|
|
271
|
+
if (bytesCleared >= bytesToClear) break
|
|
272
|
+
if (record.bytesAllocated === 0) continue
|
|
273
|
+
if (record.announce) continue // We never clear these ATM, since we do no book keeping on the cleared length of announced cores
|
|
274
|
+
|
|
275
|
+
const { key } = record
|
|
276
|
+
|
|
277
|
+
// Explicitly opening the core ensures an active replication
|
|
278
|
+
// session exists
|
|
279
|
+
const core = this.store.get({ key })
|
|
280
|
+
await core.ready()
|
|
281
|
+
if (this.closing) return
|
|
282
|
+
const id = b4a.toString(core.discoveryKey, 'hex')
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
const tracker = this.activeReplication.get(id)
|
|
286
|
+
const coreBytesCleared = tracker.gc()
|
|
287
|
+
bytesCleared += coreBytesCleared
|
|
288
|
+
} finally {
|
|
289
|
+
await core.close().catch(safetyCatch)
|
|
290
|
+
}
|
|
113
291
|
}
|
|
114
292
|
|
|
115
|
-
const w = new AutobaseLightWriter(this.store.namespace(autobase), autobase, { active: false })
|
|
116
|
-
await w.ready()
|
|
117
|
-
const entry = { autobase, writer: w.local.key, blockEncryptionKey }
|
|
118
|
-
await this.db.insert('@blind-peer/mailbox', entry)
|
|
119
293
|
await this.db.flush()
|
|
120
|
-
|
|
294
|
+
if (this.closing) return
|
|
295
|
+
this.stats.bytesGcd += bytesCleared
|
|
296
|
+
this.emit('gc-done', { bytesCleared })
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
_onreferrerupdates (updates) {
|
|
300
|
+
const pending = new Set()
|
|
301
|
+
|
|
302
|
+
for (const u of updates) {
|
|
303
|
+
const id = b4a.toString(u.referrer, 'hex')
|
|
304
|
+
const w = this.activeWakeup.get(id)
|
|
305
|
+
if (!w) continue
|
|
121
306
|
|
|
122
|
-
|
|
307
|
+
w.queued.push(u)
|
|
308
|
+
pending.add(w)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
for (const w of pending) {
|
|
312
|
+
w.flush()
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
_oncoreopen (core) {
|
|
317
|
+
const session = new Hypercore({ core, weak: true })
|
|
318
|
+
const id = b4a.toString(core.discoveryKey, 'hex')
|
|
319
|
+
const tracker = new CoreTracker(this, session)
|
|
320
|
+
|
|
321
|
+
this.activeReplication.set(id, tracker)
|
|
322
|
+
tracker.refresh().catch(safetyCatch)
|
|
323
|
+
|
|
324
|
+
session.on('close', () => {
|
|
325
|
+
tracker.destroy()
|
|
326
|
+
if (this.activeReplication.get(id) === tracker) {
|
|
327
|
+
this.activeReplication.delete(id)
|
|
328
|
+
}
|
|
329
|
+
})
|
|
123
330
|
}
|
|
124
331
|
|
|
125
|
-
async
|
|
126
|
-
|
|
127
|
-
|
|
332
|
+
async flush () { // not allowed to throw
|
|
333
|
+
if (!(await this.lock.lock())) return
|
|
334
|
+
try {
|
|
335
|
+
if (this.enableGc && this.needsGc()) await this._gc()
|
|
336
|
+
if (this.db.updated()) await this.db.flush()
|
|
337
|
+
} catch (e) {
|
|
338
|
+
this.emit('flush-error', e)
|
|
339
|
+
safetyCatch(e)
|
|
340
|
+
} finally {
|
|
341
|
+
this.lock.unlock()
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
_onconnection (conn) {
|
|
346
|
+
if (this.closing) {
|
|
347
|
+
conn.destroy()
|
|
348
|
+
return
|
|
349
|
+
}
|
|
128
350
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
351
|
+
if (this.ownsStore) this.store.replicate(conn)
|
|
352
|
+
if (this.ownsWakeup) this.wakeup.addStream(conn)
|
|
353
|
+
|
|
354
|
+
const rpc = new ProtomuxRPC(conn, {
|
|
355
|
+
id: this.swarm.keyPair.publicKey,
|
|
356
|
+
valueEncoding: c.none
|
|
132
357
|
})
|
|
133
|
-
await w.append(message)
|
|
134
|
-
const length = w.local.length
|
|
135
|
-
await w.close()
|
|
136
358
|
|
|
137
|
-
|
|
359
|
+
rpc.respond('add-core', AddCoreEncoding, this._onaddcore.bind(this, conn))
|
|
138
360
|
}
|
|
139
361
|
|
|
140
|
-
async
|
|
141
|
-
|
|
142
|
-
|
|
362
|
+
async _activateCore (stream, record) {
|
|
363
|
+
this.stats.activations++
|
|
364
|
+
|
|
365
|
+
const core = this.store.get({ key: record.key })
|
|
366
|
+
await core.ready()
|
|
367
|
+
|
|
368
|
+
const tracker = this.activeReplication.get(b4a.toString(core.discoveryKey, 'hex'))
|
|
369
|
+
if (tracker && !tracker.record) await tracker.refresh()
|
|
370
|
+
|
|
371
|
+
if (record.announce) {
|
|
372
|
+
await this._announceCore(core.key)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (stream.destroying) {
|
|
376
|
+
await core.close()
|
|
377
|
+
return
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
core.replicate(stream)
|
|
381
|
+
stream.on('close', () => core.close().catch(safetyCatch))
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
async _announceCore (key) {
|
|
385
|
+
const coreId = IdEnc.normalize(key)
|
|
386
|
+
if (this.announcedCores.has(coreId)) return
|
|
387
|
+
|
|
388
|
+
const core = this.store.get({ key })
|
|
389
|
+
this.announcedCores.set(coreId, core)
|
|
390
|
+
|
|
391
|
+
core.on('append', () => {
|
|
392
|
+
this.emit('core-append', core)
|
|
393
|
+
})
|
|
394
|
+
core.on('download', () => {
|
|
395
|
+
if (core.length === core.contiguousLength) {
|
|
396
|
+
this.emit('core-downloaded', core)
|
|
397
|
+
}
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
await core.ready()
|
|
401
|
+
this.swarm.join(core.discoveryKey, { server: true, client: false })
|
|
402
|
+
|
|
403
|
+
// WARNING: we do not yet handle the case where
|
|
404
|
+
// data of an announced core is cleared
|
|
405
|
+
core.download({ start: 0, end: -1 })
|
|
406
|
+
|
|
407
|
+
this.emit('announce-core', core)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
async _onaddcore (stream, record) {
|
|
411
|
+
if (!this.opened) await this.ready()
|
|
412
|
+
|
|
413
|
+
record.priority = Math.min(record.priority, 1) // 2 is reserved for trusted peers
|
|
414
|
+
if (record.announce !== false && !this._isTrustedPeer(stream.remotePublicKey)) {
|
|
415
|
+
this.emit('downgrade-announce', { record, remotePublicKey: stream.remotePublicKey })
|
|
416
|
+
record.announce = false
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
this.db.addCore(record)
|
|
420
|
+
await this.flush() // flush now as important data
|
|
421
|
+
|
|
422
|
+
if (record.referrer) {
|
|
423
|
+
// ensure referrer is allocated...
|
|
424
|
+
// TODO: move to a dedicated wakeup collection, insted of using a core since we moved away from that
|
|
425
|
+
// still works atm, cause dkey
|
|
426
|
+
const muxer = stream.userData
|
|
427
|
+
const core = this.store.get({ key: record.referrer })
|
|
428
|
+
await core.ready()
|
|
429
|
+
const discoveryKey = core.discoveryKey
|
|
430
|
+
await core.close()
|
|
431
|
+
|
|
432
|
+
await this._onwakeup(discoveryKey, muxer)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
this.stats.coresAdded++
|
|
436
|
+
this.emit('add-core', record, true)
|
|
437
|
+
|
|
438
|
+
await this._activateCore(stream, record)
|
|
439
|
+
|
|
440
|
+
const coreRecord = await this.db.getCoreRecord(record.key)
|
|
441
|
+
return coreRecord
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
async _close () {
|
|
445
|
+
clearInterval(this.flushInterval)
|
|
446
|
+
if (this.ownsWakeup) this.wakeup.destroy()
|
|
447
|
+
if (this.ownsSwarm) await this.swarm.destroy()
|
|
448
|
+
await this.flush()
|
|
449
|
+
await this.db.close()
|
|
450
|
+
if (this.ownsStore) await this.store.close()
|
|
451
|
+
await this.rocks.close()
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
registerMetrics (promClient) {
|
|
455
|
+
const self = this
|
|
456
|
+
new promClient.Gauge({ // eslint-disable-line no-new
|
|
457
|
+
name: 'blind_peer_bytes_allocated',
|
|
458
|
+
help: 'The amount of bytes allocated by the hyperdb (as reported in its digest)',
|
|
459
|
+
collect () {
|
|
460
|
+
this.set(self.digest.bytesAllocated)
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
new promClient.Gauge({ // eslint-disable-line no-new
|
|
465
|
+
name: 'blind_peer_cores',
|
|
466
|
+
help: 'The amount of cores (as reported in its digest)',
|
|
467
|
+
collect () {
|
|
468
|
+
this.set(self.digest.cores)
|
|
469
|
+
}
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
new promClient.Gauge({ // eslint-disable-line no-new
|
|
473
|
+
name: 'blind_peer_cores_added',
|
|
474
|
+
help: 'The total amount of add-core RPC requests that have been processed',
|
|
475
|
+
collect () {
|
|
476
|
+
this.set(self.stats.coresAdded)
|
|
477
|
+
}
|
|
478
|
+
})
|
|
479
|
+
|
|
480
|
+
new promClient.Gauge({ // eslint-disable-line no-new
|
|
481
|
+
name: 'blind_peer_bytes_gcd',
|
|
482
|
+
help: 'The total amount of bytes garbage collected since the process started',
|
|
483
|
+
collect () {
|
|
484
|
+
this.set(self.stats.bytesGcd)
|
|
485
|
+
}
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
new promClient.Gauge({ // eslint-disable-line no-new
|
|
489
|
+
name: 'blind_peer_core_activations',
|
|
490
|
+
help: 'The total amount of hypercore activations since the process started',
|
|
491
|
+
collect () {
|
|
492
|
+
this.set(self.stats.activations)
|
|
493
|
+
}
|
|
494
|
+
})
|
|
495
|
+
|
|
496
|
+
new promClient.Gauge({ // eslint-disable-line no-new
|
|
497
|
+
name: 'blind_peer_wakeups',
|
|
498
|
+
help: 'The total amount of hypercore wakeups since the process started',
|
|
499
|
+
collect () {
|
|
500
|
+
this.set(self.stats.wakeups)
|
|
501
|
+
}
|
|
502
|
+
})
|
|
503
|
+
|
|
504
|
+
new promClient.Gauge({ // eslint-disable-line no-new
|
|
505
|
+
name: 'blind_peer_db_flushes',
|
|
506
|
+
help: 'The total amount of database flushes since the process started',
|
|
507
|
+
collect () {
|
|
508
|
+
this.set(self.db.stats.flushes)
|
|
509
|
+
}
|
|
510
|
+
})
|
|
143
511
|
}
|
|
144
512
|
}
|
|
145
513
|
|
|
146
|
-
|
|
514
|
+
module.exports = BlindPeer
|