dht-rpc 6.22.0 → 6.23.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.
- package/index.js +21 -4
- package/lib/health.js +67 -0
- package/lib/query.js +0 -5
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const sodium = require('sodium-universal')
|
|
|
6
6
|
const c = require('compact-encoding')
|
|
7
7
|
const NatSampler = require('nat-sampler')
|
|
8
8
|
const b4a = require('b4a')
|
|
9
|
+
const NetworkHealth = require('./lib/health')
|
|
9
10
|
const IO = require('./lib/io')
|
|
10
11
|
const Query = require('./lib/query')
|
|
11
12
|
const Session = require('./lib/session')
|
|
@@ -24,7 +25,8 @@ const OLD_NODE = 360 // if an node has been around more than 30 min we consider
|
|
|
24
25
|
|
|
25
26
|
const DEFAULTS = {
|
|
26
27
|
concurrency: 10,
|
|
27
|
-
maxWindow: IO.DEFAULT_MAX_WINDOW
|
|
28
|
+
maxWindow: IO.DEFAULT_MAX_WINDOW,
|
|
29
|
+
maxHealthWindow: NetworkHealth.DEFAULT_MAX_HEALTH_WINDOW
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
class DHT extends EventEmitter {
|
|
@@ -41,6 +43,7 @@ class DHT extends EventEmitter {
|
|
|
41
43
|
onresponse: this._onresponse.bind(this),
|
|
42
44
|
ontimeout: this._ontimeout.bind(this)
|
|
43
45
|
})
|
|
46
|
+
this.health = new NetworkHealth(this, opts)
|
|
44
47
|
|
|
45
48
|
this.concurrency = opts.concurrency || DEFAULTS.concurrency
|
|
46
49
|
this.bootstrapped = false
|
|
@@ -50,6 +53,7 @@ class DHT extends EventEmitter {
|
|
|
50
53
|
this.destroyed = false
|
|
51
54
|
this.suspended = false
|
|
52
55
|
this.online = true
|
|
56
|
+
this.degraded = false
|
|
53
57
|
this.stats = {
|
|
54
58
|
queries: { active: 0, total: 0 },
|
|
55
59
|
requests: this.io.stats.requests,
|
|
@@ -158,6 +162,7 @@ class DHT extends EventEmitter {
|
|
|
158
162
|
this._onwakeup()
|
|
159
163
|
log('Resuming io')
|
|
160
164
|
await this.io.resume()
|
|
165
|
+
this.health.reset()
|
|
161
166
|
log('Done, dht resumed')
|
|
162
167
|
this.io.networkInterfaces.on('change', (interfaces) => this._onnetworkchange(interfaces))
|
|
163
168
|
this.refresh()
|
|
@@ -683,6 +688,8 @@ class DHT extends EventEmitter {
|
|
|
683
688
|
) {
|
|
684
689
|
this.refresh()
|
|
685
690
|
}
|
|
691
|
+
|
|
692
|
+
this.health.update()
|
|
686
693
|
}
|
|
687
694
|
|
|
688
695
|
async _updateNetworkState(onlyFirewall = false) {
|
|
@@ -866,17 +873,27 @@ class DHT extends EventEmitter {
|
|
|
866
873
|
return q
|
|
867
874
|
}
|
|
868
875
|
|
|
869
|
-
// called by
|
|
876
|
+
// called by health
|
|
870
877
|
_online() {
|
|
871
|
-
if (this.online) return
|
|
878
|
+
if (this.online && !this.degraded) return
|
|
879
|
+
this.online = true
|
|
880
|
+
this.degraded = false
|
|
881
|
+
this.emit('network-update')
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// called by health
|
|
885
|
+
_degraded() {
|
|
886
|
+
if (this.degraded) return
|
|
872
887
|
this.online = true
|
|
888
|
+
this.degraded = true
|
|
873
889
|
this.emit('network-update')
|
|
874
890
|
}
|
|
875
891
|
|
|
876
|
-
// called by
|
|
892
|
+
// called by health
|
|
877
893
|
_offline() {
|
|
878
894
|
if (!this.online) return
|
|
879
895
|
this.online = false
|
|
896
|
+
this.degraded = false
|
|
880
897
|
this.emit('network-update')
|
|
881
898
|
}
|
|
882
899
|
}
|
package/lib/health.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const MAX_HEALTH_WINDOW = 4
|
|
2
|
+
const RESPONSES_SANITY = 4
|
|
3
|
+
const TIMEOUTS_SANITY = 4
|
|
4
|
+
const TIMEOUTS_THRESHOLD = 0.1
|
|
5
|
+
|
|
6
|
+
module.exports = class NetworkHealth {
|
|
7
|
+
static DEFAULT_MAX_HEALTH_WINDOW = MAX_HEALTH_WINDOW
|
|
8
|
+
|
|
9
|
+
constructor(dht, { maxHealthWindow = MAX_HEALTH_WINDOW } = {}) {
|
|
10
|
+
this._dht = dht
|
|
11
|
+
this._maxHealthWindow = maxHealthWindow
|
|
12
|
+
this._window = []
|
|
13
|
+
this._head = -1
|
|
14
|
+
this.online = true
|
|
15
|
+
this.degraded = false
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get _tail() {
|
|
19
|
+
return (this._head + 1) % this._maxHealthWindow
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get cold() {
|
|
23
|
+
return this._window.length < this._maxHealthWindow
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
reset() {
|
|
27
|
+
this._window = []
|
|
28
|
+
this._head = -1
|
|
29
|
+
this.online = true
|
|
30
|
+
this.degraded = false
|
|
31
|
+
this._dht._online()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
update() {
|
|
35
|
+
this._head = this._tail
|
|
36
|
+
this._window[this._head] = {
|
|
37
|
+
responses: this._dht.stats.requests.responses,
|
|
38
|
+
timeouts: this._dht.stats.requests.timeouts
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (this.cold) return
|
|
42
|
+
|
|
43
|
+
const oldest = this._window[this._tail]
|
|
44
|
+
const newest = this._window[this._head]
|
|
45
|
+
|
|
46
|
+
const responses = newest.responses - oldest.responses
|
|
47
|
+
const timeouts = newest.timeouts - oldest.timeouts
|
|
48
|
+
const timeoutsRate = timeouts / (responses + timeouts)
|
|
49
|
+
|
|
50
|
+
if (responses > 0) {
|
|
51
|
+
this.online = true
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (responses > RESPONSES_SANITY * this._window.length) {
|
|
55
|
+
this.degraded = timeoutsRate > TIMEOUTS_THRESHOLD
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (responses === 0 && timeouts > TIMEOUTS_SANITY * this._window.length) {
|
|
59
|
+
this.online = false
|
|
60
|
+
this.degraded = false
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (this.online && !this.degraded) this._dht._online()
|
|
64
|
+
else if (this.degraded) this._dht._degraded()
|
|
65
|
+
else this._dht._offline()
|
|
66
|
+
}
|
|
67
|
+
}
|
package/lib/query.js
CHANGED
|
@@ -30,7 +30,6 @@ module.exports = class Query extends Readable {
|
|
|
30
30
|
this.closestReplies = []
|
|
31
31
|
|
|
32
32
|
this._slow = 0
|
|
33
|
-
this._online = false
|
|
34
33
|
this._slowdown = false
|
|
35
34
|
this._seen = new Map()
|
|
36
35
|
this._pending = []
|
|
@@ -262,9 +261,6 @@ module.exports = class Query extends Readable {
|
|
|
262
261
|
_onvisit(m, req) {
|
|
263
262
|
this._dec(req)
|
|
264
263
|
|
|
265
|
-
this._online = true
|
|
266
|
-
if (!this.dht.online) this.dht._online()
|
|
267
|
-
|
|
268
264
|
const addr = req.to.host + ':' + req.to.port
|
|
269
265
|
this._seen.set(addr, DONE)
|
|
270
266
|
|
|
@@ -380,7 +376,6 @@ module.exports = class Query extends Readable {
|
|
|
380
376
|
|
|
381
377
|
_destroy(cb) {
|
|
382
378
|
this.dht.stats.queries.active--
|
|
383
|
-
if (!this._online && this.dht.online) this.dht._offline()
|
|
384
379
|
if (this._autoDestroySession) this._session.destroy()
|
|
385
380
|
cb(null)
|
|
386
381
|
}
|