Skip to content
This repository was archived by the owner on Jan 7, 2022. It is now read-only.

Commit 07838f3

Browse files
author
Joe Hand
authored
Improved Peer stats (#120)
* add peers to stats * start adding network tests * fix for unopen archives * more explicit testing of each stage * fix rest of tests * add three peer test * allow 1 or 2 for sending/active * standard mmm * turn off tcp/dht to avoid duplicate connections * run onconnect after next tick * a bit more fuzz room on the complete * use getter * add docs
1 parent be33628 commit 07838f3

File tree

4 files changed

+285
-3
lines changed

4 files changed

+285
-3
lines changed

lib/stats.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,28 @@ module.exports = function (archive, db) {
1414
})
1515
stats.network = networkSpeed(archive, {timeout: 2000})
1616

17+
Object.defineProperties(stats, {
18+
peers: {
19+
enumerable: true,
20+
get: function () {
21+
if (!archive.content || !archive.content.peers) return {} // TODO: how to handle this?
22+
var peers = archive.content.peers
23+
var total = peers.length
24+
var downloadingFrom = peers.filter(function (peer) {
25+
return peer.downloaded
26+
}).length
27+
var complete = peers.filter(function (peer) {
28+
return peer.remoteLength === archive.content.blocks
29+
}).length
30+
31+
return {
32+
total: total,
33+
downloadingFrom: downloadingFrom,
34+
complete: complete
35+
}
36+
}
37+
}
38+
})
39+
1740
return stats
1841
}

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
"xtend": "^4.0.1"
3838
},
3939
"devDependencies": {
40-
"anymatch": "^1.3.0",
41-
"dat-encoding": "^3.0.1",
4240
"dependency-check": "^2.8.0",
4341
"memdb": "^1.3.1",
4442
"memdown": "^1.2.4",
@@ -47,7 +45,8 @@
4745
"rimraf": "^2.5.4",
4846
"standard": "^8.6.0",
4947
"tap-spec": "^4.1.1",
50-
"tape": "^4.6.3"
48+
"tape": "^4.6.3",
49+
"temporary-directory": "^1.0.2"
5150
},
5251
"keywords": [
5352
"data",

readme.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,12 @@ Additionally, you can use a `.datignore` file to ignore any the user specifies.
255255

256256
Get upload and download speeds: `stats.network.uploadSpeed` or `stats.network.downloadSpeed`. Transfer speeds are tracked using [hyperdrive-network-speed](https://github.com/joehand/hyperdrive-network-speed/).
257257

258+
##### `var peers = stats.peers`
259+
260+
* `peers.total` - total number of connected peers
261+
* `peers.complete` - connected peers with all the content data
262+
* `peers.downloadingFrom` - connected peers the user has downloaded data from
263+
258264
#### `dat.pause()`
259265

260266
Pause all upload & downloads. Currently, this is the same as `dat.leaveNetwork()`, which leaves the network and destroys the swarm. Discovery will happen again on `resume()`.

test/network.js

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
var path = require('path')
2+
var test = require('tape')
3+
var memdb = require('memdb')
4+
var tmp = require('temporary-directory')
5+
6+
var Dat = require('..')
7+
var shareFolder = path.join(__dirname, 'fixtures')
8+
9+
test('peer connection information between two peers', function (t) {
10+
var srcDat
11+
var clientDat
12+
var clientClean
13+
14+
Dat(shareFolder, { db: memdb() }, function (err, dat) {
15+
srcDat = dat
16+
t.error(err, 'no error')
17+
var sourceStats
18+
var clientStats
19+
20+
tmp(function (err, dir, cleanup) {
21+
if (err) throw err
22+
Dat(dir, { key: dat.key }, function (err, dat) {
23+
clientDat = dat
24+
clientClean = cleanup
25+
t.error(err, 'no error')
26+
clientStats = clientDat.trackStats()
27+
28+
beforeConnect(function () {
29+
var network = clientDat.joinNetwork({dht: false, tcp: false})
30+
network.once('connection', function () {
31+
clientDat.archive.open(function () {
32+
onConnect(function () {
33+
clientDat.archive.content.once('download', onTransfer)
34+
})
35+
})
36+
})
37+
})
38+
})
39+
})
40+
41+
sourceStats = srcDat.trackStats()
42+
srcDat.importFiles(function () {
43+
srcDat.joinNetwork({dht: false, tcp: false})
44+
})
45+
46+
function beforeConnect (cb) {
47+
var sPeers = sourceStats.peers
48+
var cPeers = clientStats.peers
49+
t.same(sPeers.total, 0, 'beforeConnect: source has zero total peers')
50+
t.same(sPeers.downloadingFrom, 0, 'beforeConnect: source has zero sending peer')
51+
t.same(sPeers.complete, 0, 'beforeConnect: source has zero complete peer')
52+
t.notOk(cPeers.total, 'beforeConnect: client total undefined')
53+
cb()
54+
}
55+
56+
function onConnect (cb) {
57+
var sPeers = sourceStats.peers
58+
var cPeers = clientStats.peers
59+
t.ok(sPeers.total >= 1, 'onConnect: source has 1 (or more) total peers')
60+
t.same(sPeers.downloadingFrom, 0, 'onConnect: source has zero sending peer')
61+
t.same(sPeers.complete, 0, 'onConnect: source has zero complete peer')
62+
t.ok(cPeers.total >= 1, 'onConnect: client has 1 (or more) total peers')
63+
t.same(cPeers.downloadingFrom, 0, 'onConnect: client has zero sending peer')
64+
t.ok(cPeers.complete >= 1, 'onConnect: client has >=1 complete peer')
65+
cb()
66+
}
67+
68+
function onTransfer () {
69+
var sPeers = sourceStats.peers
70+
var cPeers = clientStats.peers
71+
t.ok(sPeers.total >= 1, 'onTransfer: source has 1 (or more) total peers')
72+
t.same(sPeers.downloadingFrom, 0, 'onTransfer: source has zero sending peer')
73+
t.ok(cPeers.total >= 1, 'onTransfer: client has 1 (or more) total peers')
74+
t.same(cPeers.downloadingFrom, 1, 'onTransfer: client has 1 sending peer')
75+
t.ok(cPeers.complete >= 1, 'onTransfer: client has >=1 complete peer')
76+
77+
// Check for completion
78+
var stats = clientStats.get()
79+
if (stats.blocksProgress === stats.blocksTotal) return next()
80+
clientStats.on('update', function () {
81+
var stats = clientStats.get()
82+
if (stats.blocksProgress === stats.blocksTotal) return next()
83+
})
84+
85+
function next () {
86+
setTimeout(onComplete, 100) // download blocks take some time to clear
87+
}
88+
}
89+
90+
function onComplete () {
91+
var sPeers = sourceStats.peers
92+
var cPeers = clientStats.peers
93+
t.ok(sPeers.total >= 1, 'onComplete: source has 1 (or more) total peers')
94+
t.same(sPeers.downloadingFrom, 0, 'onComplete: source has zero sending peer')
95+
t.same(sPeers.complete, 1, 'onComplete: source has 1 complete peer')
96+
t.ok(cPeers.total >= 1, 'onComplete: client has 1 (or more) total peers')
97+
t.same(cPeers.downloadingFrom, 1, 'onComplete: client has 1 sending peer')
98+
t.ok(cPeers.complete >= 1, 'onComplete: client has >=1 complete peer')
99+
onDisconnect()
100+
}
101+
102+
function onDisconnect () {
103+
// disconnect peers
104+
clientDat.close(function () {
105+
var sPeers = sourceStats.peers
106+
var cPeers = clientStats.peers
107+
t.same(sPeers.downloadingFrom, 0, 'onDisconnect: source has zero sending peer')
108+
t.same(sPeers.complete, 0, 'onDisconnect: source has zero complete peer')
109+
t.same(cPeers.downloadingFrom, 0, 'onDisconnect: client has 0 sending peer')
110+
t.same(cPeers.complete, 0, 'onDisconnect: client has 0 complete peer')
111+
done()
112+
})
113+
}
114+
115+
function done () {
116+
dat.close(function () {
117+
clientClean()
118+
t.end()
119+
})
120+
}
121+
})
122+
})
123+
124+
test('peer connection information between 3 peers', function (t) {
125+
var srcDat
126+
var clientDat
127+
var clientDat1
128+
var client1Clean
129+
var client2Clean
130+
131+
Dat(shareFolder, { db: memdb() }, function (err, dat) {
132+
srcDat = dat
133+
t.error(err, 'no error')
134+
var sourceStats
135+
var clientStats
136+
137+
tmp(function (err, dir, cleanup) {
138+
if (err) throw err
139+
Dat(dir, { key: dat.key }, function (err, dat) {
140+
clientDat1 = dat
141+
client1Clean = cleanup
142+
t.error(err, 'no error')
143+
dat.trackStats()
144+
dat.joinNetwork({dht: false, tcp: false})
145+
})
146+
})
147+
148+
tmp(function (err, dir, cleanup) {
149+
if (err) throw err
150+
Dat(dir, { key: dat.key }, function (err, dat) {
151+
clientDat = dat
152+
client2Clean = cleanup
153+
t.error(err, 'no error')
154+
clientStats = clientDat.trackStats()
155+
156+
beforeConnect(function () {
157+
var network = clientDat.joinNetwork({dht: false, tcp: false})
158+
network.once('connection', function () {
159+
clientDat.archive.open(function () {
160+
process.nextTick(function () {
161+
onConnect(function () {
162+
clientDat.archive.content.once('download', onTransfer)
163+
})
164+
})
165+
})
166+
})
167+
})
168+
})
169+
})
170+
171+
sourceStats = srcDat.trackStats()
172+
srcDat.importFiles(function () {
173+
srcDat.joinNetwork({dht: false, tcp: false})
174+
})
175+
176+
function beforeConnect (cb) {
177+
var sPeers = sourceStats.peers
178+
var cPeers = clientStats.peers
179+
t.same(sPeers.total, 0, 'beforeConnect: source has zero total peers')
180+
t.same(sPeers.downloadingFrom, 0, 'beforeConnect: source has zero sending peer')
181+
t.same(sPeers.complete, 0, 'beforeConnect: source has zero complete peer')
182+
t.notOk(cPeers.total, 'beforeConnect: client total undefined')
183+
cb()
184+
}
185+
186+
function onConnect (cb) {
187+
var sPeers = sourceStats.peers
188+
var cPeers = clientStats.peers
189+
t.ok(sPeers.total >= 1, 'onConnect: source has 1 (or more) total peers')
190+
t.same(sPeers.downloadingFrom, 0, 'onConnect: source has zero sending peer')
191+
t.same(sPeers.complete, 0, 'onConnect: source has zero complete peer')
192+
t.ok(cPeers.total >= 1, 'onConnect: client has 1 (or more) total peers')
193+
t.same(cPeers.downloadingFrom, 0, 'onConnect: client has zero sending peer')
194+
t.ok(cPeers.complete >= 1, 'onConnect: client has >=1 complete peer')
195+
cb()
196+
}
197+
198+
function onTransfer () {
199+
var sPeers = sourceStats.peers
200+
var cPeers = clientStats.peers
201+
t.ok(sPeers.total >= 1, 'onTransfer: source has 1 (or more) total peers')
202+
t.same(sPeers.downloadingFrom, 0, 'onTransfer: source has zero sending peer')
203+
t.ok(cPeers.total >= 1, 'onTransfer: client has 1 (or more) total peers')
204+
t.same(cPeers.downloadingFrom, 1, 'onTransfer: client has 1 sending peer')
205+
t.ok(cPeers.complete >= 1, 'onTransfer: client has >=1 complete peer')
206+
207+
// Check for completion
208+
var stats = clientStats.get()
209+
if (stats.blocksProgress === stats.blocksTotal) return next()
210+
clientStats.on('update', function () {
211+
var stats = clientStats.get()
212+
if (stats.blocksProgress === stats.blocksTotal) return next()
213+
})
214+
215+
function next () {
216+
setTimeout(onComplete, 200) // download blocks take some time to clear
217+
}
218+
}
219+
220+
function onComplete () {
221+
var sPeers = sourceStats.peers
222+
var cPeers = clientStats.peers
223+
t.ok(sPeers.total >= 1, 'onComplete: source has 1 (or more) total peers')
224+
t.same(sPeers.downloadingFrom, 0, 'onComplete: source has zero sending peer')
225+
t.same(sPeers.complete, 2, 'onComplete: source has 2 complete peer')
226+
t.ok(cPeers.total >= 1, 'onComplete: client has 1 (or more) total peers')
227+
t.ok(cPeers.downloadingFrom >= 1, 'onComplete: client has 1 sending peer')
228+
t.ok(cPeers.complete >= 1, 'onComplete: client has >=1 complete peer')
229+
onDisconnect()
230+
}
231+
232+
function onDisconnect () {
233+
// disconnect peers
234+
clientDat1.close()
235+
clientDat.close(function () {
236+
var sPeers = sourceStats.peers
237+
var cPeers = clientStats.peers
238+
t.same(sPeers.downloadingFrom, 0, 'onDisconnect: source has zero sending peer')
239+
t.same(sPeers.complete, 0, 'onDisconnect: source has zero complete peer')
240+
t.same(cPeers.downloadingFrom, 0, 'onDisconnect: client has 0 sending peer')
241+
t.same(cPeers.complete, 0, 'onDisconnect: client has 0 complete peer')
242+
done()
243+
})
244+
}
245+
246+
function done () {
247+
dat.close(function () {
248+
client1Clean()
249+
client2Clean()
250+
t.end()
251+
})
252+
}
253+
})
254+
})

0 commit comments

Comments
 (0)