From 6fb9179d5b0373e85eecd172aa472cd1df688dc1 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 2 Jul 2018 09:42:04 +0100 Subject: [PATCH 1/3] fix: re-serialise operations that were serial before refactor During the refactor I took the opportunity to parallelise some pubsub operations that didn't explicitly depend on each other. This worked perfectly while testing locally, but on CI it is a different story. I found that tests for js-ipfs-api (which are run against go-ipfs) failed for seemingly random reasons. After much investigation I finally tried re-serialising the operations I had refactored to be parallel and the tests started to pass. It seems that the pubsub implementation in go-ipfs has some issues with concurrency. I also found two intermittent issues with `swarm.connect` in go-ipfs (seen significantly more often on CI): 1. Issuing two calls to this function from the same node might end up in the second not actually creating a connection and no error message reported to the user 2. Even after the response to the user it takes a few milliseconds for a connection to actually be connected I intend to open issues on go-ipfs and write examples demonstrating these problems. I created a utility function `connect` to temporarily mitigate these issues in one place. The utility serialises calls from a single node to another and pauses after each to allow the connection to properly establish. License: MIT Signed-off-by: Alan Shaw --- js/src/bitswap/unwant.js | 3 +- js/src/bitswap/wantlist.js | 3 +- js/src/dht/findpeer.js | 3 +- js/src/dht/findprovs.js | 3 +- js/src/dht/get.js | 3 +- js/src/dht/provide.js | 3 +- js/src/dht/query.js | 3 +- js/src/key/list.js | 4 +- js/src/ping/ping-pull-stream.js | 3 +- js/src/ping/ping-readable-stream.js | 3 +- js/src/ping/ping.js | 3 +- js/src/pubsub/ls.js | 3 +- js/src/pubsub/peers.js | 46 +++++++++++------------ js/src/pubsub/publish.js | 4 +- js/src/pubsub/subscribe.js | 58 +++++++++++++---------------- js/src/pubsub/unsubscribe.js | 4 +- js/src/pubsub/utils.js | 8 +++- js/src/utils/swarm.js | 16 ++++++++ 18 files changed, 97 insertions(+), 76 deletions(-) create mode 100644 js/src/utils/swarm.js diff --git a/js/src/bitswap/unwant.js b/js/src/bitswap/unwant.js index b16be1d8..41157daf 100644 --- a/js/src/bitswap/unwant.js +++ b/js/src/bitswap/unwant.js @@ -5,6 +5,7 @@ const waterfall = require('async/waterfall') const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') const { waitForWantlistKey } = require('./utils') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -33,7 +34,7 @@ module.exports = (createCommon, options) => { // Add key to the wantlist for ipfsB ipfsB.block.get(key, () => {}) - ipfsA.swarm.connect(ipfsB.peerId.addresses[0], done) + connect(ipfsA, ipfsB.peerId.addresses[0], done) }) }) }) diff --git a/js/src/bitswap/wantlist.js b/js/src/bitswap/wantlist.js index 0606b175..da16804f 100644 --- a/js/src/bitswap/wantlist.js +++ b/js/src/bitswap/wantlist.js @@ -5,6 +5,7 @@ const waterfall = require('async/waterfall') const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') const { waitForWantlistKey } = require('./utils') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -33,7 +34,7 @@ module.exports = (createCommon, options) => { // Add key to the wantlist for ipfsB ipfsB.block.get(key, () => {}) - ipfsA.swarm.connect(ipfsB.peerId.addresses[0], done) + connect(ipfsA, ipfsB.peerId.addresses[0], done) }) }) }) diff --git a/js/src/dht/findpeer.js b/js/src/dht/findpeer.js index daae871a..f1537f6b 100644 --- a/js/src/dht/findpeer.js +++ b/js/src/dht/findpeer.js @@ -3,6 +3,7 @@ const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -29,7 +30,7 @@ module.exports = (createCommon, options) => { nodeA = nodes[0] nodeB = nodes[1] - nodeB.swarm.connect(nodeA.peerId.addresses[0], done) + connect(nodeB, nodeA.peerId.addresses[0], done) }) }) }) diff --git a/js/src/dht/findprovs.js b/js/src/dht/findprovs.js index 98f962af..04e6385c 100644 --- a/js/src/dht/findprovs.js +++ b/js/src/dht/findprovs.js @@ -5,6 +5,7 @@ const waterfall = require('async/waterfall') const CID = require('cids') const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -29,7 +30,7 @@ module.exports = (createCommon, options) => { nodeA = nodes[0] nodeB = nodes[1] - nodeB.swarm.connect(nodeA.peerId.addresses[0], done) + connect(nodeB, nodeA.peerId.addresses[0], done) }) }) }) diff --git a/js/src/dht/get.js b/js/src/dht/get.js index 317ace93..ccaec962 100644 --- a/js/src/dht/get.js +++ b/js/src/dht/get.js @@ -4,6 +4,7 @@ const waterfall = require('async/waterfall') const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -30,7 +31,7 @@ module.exports = (createCommon, options) => { nodeA = nodes[0] nodeB = nodes[1] - nodeA.swarm.connect(nodeB.peerId.addresses[0], done) + connect(nodeA, nodeB.peerId.addresses[0], done) }) }) }) diff --git a/js/src/dht/provide.js b/js/src/dht/provide.js index 91c71f8e..917c5a72 100644 --- a/js/src/dht/provide.js +++ b/js/src/dht/provide.js @@ -4,6 +4,7 @@ const CID = require('cids') const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -26,7 +27,7 @@ module.exports = (createCommon, options) => { spawnNodesWithId(2, factory, (err, nodes) => { expect(err).to.not.exist() ipfs = nodes[0] - ipfs.swarm.connect(nodes[1].peerId.addresses[0], done) + connect(ipfs, nodes[1].peerId.addresses[0], done) }) }) }) diff --git a/js/src/dht/query.js b/js/src/dht/query.js index c0ee95c1..f7ac8f9f 100644 --- a/js/src/dht/query.js +++ b/js/src/dht/query.js @@ -3,6 +3,7 @@ const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -29,7 +30,7 @@ module.exports = (createCommon, options) => { nodeA = nodes[0] nodeB = nodes[1] - nodeB.swarm.connect(nodeA.peerId.addresses[0], done) + connect(nodeB, nodeA.peerId.addresses[0], done) }) }) }) diff --git a/js/src/key/list.js b/js/src/key/list.js index 705576da..ff39b4cc 100644 --- a/js/src/key/list.js +++ b/js/src/key/list.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict' -const times = require('async/times') +const timesSeries = require('async/timesSeries') const hat = require('hat') const { getDescribe, getIt, expect } = require('../utils/mocha') @@ -33,7 +33,7 @@ module.exports = (createCommon, options) => { it('should list all the keys', function (done) { this.timeout(60 * 1000) - times(3, (n, cb) => { + timesSeries(3, (n, cb) => { ipfs.key.gen(hat(), { type: 'rsa', size: 2048 }, cb) }, (err, keys) => { expect(err).to.not.exist() diff --git a/js/src/ping/ping-pull-stream.js b/js/src/ping/ping-pull-stream.js index e51c4e95..104e26c0 100644 --- a/js/src/ping/ping-pull-stream.js +++ b/js/src/ping/ping-pull-stream.js @@ -6,6 +6,7 @@ const series = require('async/series') const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') const { expectIsPingResponse, isPong } = require('./utils') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -33,7 +34,7 @@ module.exports = (createCommon, options) => { cb() }) }, - (cb) => ipfsA.swarm.connect(ipfsB.peerId.addresses[0], cb) + (cb) => connect(ipfsA, ipfsB.peerId.addresses[0], cb) ], done) }) }) diff --git a/js/src/ping/ping-readable-stream.js b/js/src/ping/ping-readable-stream.js index aad13bee..9ca063c6 100644 --- a/js/src/ping/ping-readable-stream.js +++ b/js/src/ping/ping-readable-stream.js @@ -7,6 +7,7 @@ const series = require('async/series') const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') const { expectIsPingResponse, isPong } = require('./utils') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -34,7 +35,7 @@ module.exports = (createCommon, options) => { cb() }) }, - (cb) => ipfsA.swarm.connect(ipfsB.peerId.addresses[0], cb) + (cb) => connect(ipfsA, ipfsB.peerId.addresses[0], cb) ], done) }) }) diff --git a/js/src/ping/ping.js b/js/src/ping/ping.js index df58b5a5..8a758041 100644 --- a/js/src/ping/ping.js +++ b/js/src/ping/ping.js @@ -5,6 +5,7 @@ const series = require('async/series') const { spawnNodesWithId } = require('../utils/spawn') const { getDescribe, getIt, expect } = require('../utils/mocha') const { expectIsPingResponse, isPong } = require('./utils') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -32,7 +33,7 @@ module.exports = (createCommon, options) => { cb() }) }, - (cb) => ipfsA.swarm.connect(ipfsB.peerId.addresses[0], cb) + (cb) => connect(ipfsA, ipfsB.peerId.addresses[0], cb) ], done) }) }) diff --git a/js/src/pubsub/ls.js b/js/src/pubsub/ls.js index 2b716227..900ec17e 100644 --- a/js/src/pubsub/ls.js +++ b/js/src/pubsub/ls.js @@ -2,6 +2,7 @@ 'use strict' const each = require('async/each') +const eachSeries = require('async/eachSeries') const { getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') @@ -68,7 +69,7 @@ module.exports = (createCommon, options) => { handler () {} }] - each(topics, (t, cb) => { + eachSeries(topics, (t, cb) => { ipfs.pubsub.subscribe(t.name, t.handler, cb) }, (err) => { expect(err).to.not.exist() diff --git a/js/src/pubsub/peers.js b/js/src/pubsub/peers.js index 7b6576f4..16bcba4c 100644 --- a/js/src/pubsub/peers.js +++ b/js/src/pubsub/peers.js @@ -2,10 +2,11 @@ 'use strict' const parallel = require('async/parallel') -const auto = require('async/auto') +const series = require('async/series') const { spawnNodesWithId } = require('../utils/spawn') const { waitForPeers, getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -13,7 +14,7 @@ module.exports = (createCommon, options) => { const common = createCommon() describe('.pubsub.peers', function () { - this.timeout(80 * 1000) + this.timeout(120 * 1000) let ipfs1 let ipfs2 @@ -46,9 +47,8 @@ module.exports = (createCommon, options) => { const ipfs3Addr = ipfs3.peerId.addresses.find((a) => a.includes('127.0.0.1')) parallel([ - (cb) => ipfs1.swarm.connect(ipfs2Addr, cb), - (cb) => ipfs1.swarm.connect(ipfs3Addr, cb), - (cb) => ipfs2.swarm.connect(ipfs3Addr, cb) + (cb) => connect(ipfs1, [ipfs2Addr, ipfs3Addr], cb), + (cb) => connect(ipfs2, ipfs3Addr, cb) ], done) }) @@ -73,7 +73,7 @@ module.exports = (createCommon, options) => { const topic = getTopic() const topicOther = topic + 'different topic' - parallel([ + series([ (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), (cb) => ipfs2.pubsub.subscribe(topicOther, sub2, cb), (cb) => ipfs3.pubsub.subscribe(topicOther, sub3, cb) @@ -101,14 +101,12 @@ module.exports = (createCommon, options) => { const sub3 = (msg) => {} const topic = getTopic() - auto({ - sub1: (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), - sub2: (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), - sub3: (cb) => ipfs3.pubsub.subscribe(topic, sub3, cb), - peers: ['sub1', 'sub2', 'sub3', (_, cb) => { - waitForPeers(ipfs1, topic, [ipfs2.peerId.id], cb) - }] - }, (err) => { + series([ + (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), + (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), + (cb) => ipfs3.pubsub.subscribe(topic, sub3, cb), + (cb) => waitForPeers(ipfs1, topic, [ipfs2.peerId.id], 30000, cb) + ], (err) => { expect(err).to.not.exist() parallel([ @@ -125,17 +123,15 @@ module.exports = (createCommon, options) => { const sub3 = (msg) => {} const topic = getTopic() - auto({ - sub1: (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), - sub2: (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), - sub3: (cb) => ipfs3.pubsub.subscribe(topic, sub3, cb), - peers: ['sub1', 'sub2', 'sub3', (_, cb) => { - waitForPeers(ipfs1, topic, [ - ipfs2.peerId.id, - ipfs3.peerId.id - ], cb) - }] - }, (err) => { + series([ + (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), + (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), + (cb) => ipfs3.pubsub.subscribe(topic, sub3, cb), + (cb) => waitForPeers(ipfs1, topic, [ + ipfs2.peerId.id, + ipfs3.peerId.id + ], 30000, cb) + ], (err) => { expect(err).to.not.exist() parallel([ diff --git a/js/src/pubsub/publish.js b/js/src/pubsub/publish.js index 17522d08..79620005 100644 --- a/js/src/pubsub/publish.js +++ b/js/src/pubsub/publish.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict' -const times = require('async/times') +const timesSeries = require('async/timesSeries') const hat = require('hat') const { getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') @@ -50,7 +50,7 @@ module.exports = (createCommon, options) => { const count = 10 const topic = getTopic() - times(count, (_, cb) => { + timesSeries(count, (_, cb) => { ipfs.pubsub.publish(topic, Buffer.from(hat()), cb) }, done) }) diff --git a/js/src/pubsub/subscribe.js b/js/src/pubsub/subscribe.js index fc726d4e..70e695af 100644 --- a/js/src/pubsub/subscribe.js +++ b/js/src/pubsub/subscribe.js @@ -3,11 +3,11 @@ const series = require('async/series') const parallel = require('async/parallel') -const times = require('async/times') -const auto = require('async/auto') +const timesSeries = require('async/timesSeries') const { spawnNodesWithId } = require('../utils/spawn') const { waitForPeers, makeCheck, getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') +const { connect } = require('../utils/swarm') module.exports = (createCommon, options) => { const describe = getDescribe(options) @@ -182,7 +182,7 @@ module.exports = (createCommon, options) => { check() } - parallel([ + series([ (cb) => ipfs1.pubsub.subscribe(topic, handler1, cb), (cb) => ipfs1.pubsub.subscribe(topic, handler2, cb) ], (err) => { @@ -218,7 +218,7 @@ module.exports = (createCommon, options) => { } const ipfs2Addr = ipfs2.peerId.addresses.find((a) => a.includes('127.0.0.1')) - ipfs1.swarm.connect(ipfs2Addr, done) + connect(ipfs1, ipfs2Addr, done) }) let topic @@ -252,13 +252,11 @@ module.exports = (createCommon, options) => { check() } - auto({ - sub1: (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), - sub2: (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), - peers: ['sub1', 'sub2', (_, cb) => { - waitForPeers(ipfs2, topic, [ipfs1.peerId.id], cb) - }] - }, (err) => { + series([ + (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), + (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), + (cb) => waitForPeers(ipfs2, topic, [ipfs1.peerId.id], 30000, cb) + ], (err) => { expect(err).to.not.exist() ipfs2.pubsub.publish(topic, Buffer.from(expectedString), check) @@ -290,13 +288,11 @@ module.exports = (createCommon, options) => { } } - auto({ - sub1: (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), - sub2: (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), - peers: ['sub1', 'sub2', (_, cb) => { - waitForPeers(ipfs2, topic, [ipfs1.peerId.id], cb) - }] - }, (err) => { + series([ + (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), + (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), + (cb) => waitForPeers(ipfs2, topic, [ipfs1.peerId.id], 30000, cb) + ], (err) => { expect(err).to.not.exist() ipfs2.pubsub.publish(topic, buffer, check) @@ -327,13 +323,11 @@ module.exports = (createCommon, options) => { check() } - auto({ - sub1: (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), - sub2: (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), - peers: ['sub1', 'sub2', (_, cb) => { - waitForPeers(ipfs2, topic, [ipfs1.peerId.id], cb) - }] - }, (err) => { + series([ + (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), + (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), + (cb) => waitForPeers(ipfs2, topic, [ipfs1.peerId.id], 30000, cb) + ], (err) => { expect(err).to.not.exist() outbox.forEach((msg) => { @@ -379,17 +373,15 @@ module.exports = (createCommon, options) => { } } - auto({ - sub1: (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), - sub2: (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), - peers: ['sub1', 'sub2', (_, cb) => { - waitForPeers(ipfs1, topic, [ipfs2.peerId.id], cb) - }] - }, (err) => { + series([ + (cb) => ipfs1.pubsub.subscribe(topic, sub1, cb), + (cb) => ipfs2.pubsub.subscribe(topic, sub2, cb), + (cb) => waitForPeers(ipfs1, topic, [ipfs2.peerId.id], 30000, cb) + ], (err) => { expect(err).to.not.exist() startTime = new Date().getTime() - times(count, (sendCount, cb) => { + timesSeries(count, (sendCount, cb) => { const msgData = Buffer.from(msgBase + sendCount) ipfs2.pubsub.publish(topic, msgData, cb) }, check) diff --git a/js/src/pubsub/unsubscribe.js b/js/src/pubsub/unsubscribe.js index 70fcea30..a7f74d96 100644 --- a/js/src/pubsub/unsubscribe.js +++ b/js/src/pubsub/unsubscribe.js @@ -2,7 +2,7 @@ 'use strict' const each = require('async/each') -const times = require('async/times') +const timesSeries = require('async/timesSeries') const { getTopic } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') @@ -37,7 +37,7 @@ module.exports = (createCommon, options) => { const count = 10 const someTopic = getTopic() - times(count, (_, cb) => { + timesSeries(count, (_, cb) => { const handler = (msg) => {} ipfs.pubsub.subscribe(someTopic, handler, (err) => cb(err, handler)) }, (err, handlers) => { diff --git a/js/src/pubsub/utils.js b/js/src/pubsub/utils.js index 03c8d346..2f8efde2 100644 --- a/js/src/pubsub/utils.js +++ b/js/src/pubsub/utils.js @@ -2,7 +2,9 @@ const hat = require('hat') -function waitForPeers (ipfs, topic, peersToWait, callback) { +function waitForPeers (ipfs, topic, peersToWait, waitForMs, callback) { + const start = Date.now() + const checkPeers = () => { ipfs.pubsub.peers(topic, (err, peers) => { if (err) { @@ -17,6 +19,10 @@ function waitForPeers (ipfs, topic, peersToWait, callback) { return callback() } + if (Date.now() > start + waitForMs) { + return callback(new Error('Timed out waiting for peers')) + } + setTimeout(checkPeers, 10) }) } diff --git a/js/src/utils/swarm.js b/js/src/utils/swarm.js new file mode 100644 index 00000000..6e7119bd --- /dev/null +++ b/js/src/utils/swarm.js @@ -0,0 +1,16 @@ +const eachSeries = require('async/eachSeries') + +function connect (fromNode, toAddrs, cb) { + if (!Array.isArray(toAddrs)) toAddrs = [toAddrs] + + // FIXME ??? quick connections to different nodes sometimes cause no + // connection and no error, hence serialize connections and pause between + eachSeries(toAddrs, (toAddr, cb) => { + fromNode.swarm.connect(toAddr, (err) => { + if (err) return cb(err) + setTimeout(cb, 300) + }) + }, cb) +} + +module.exports.connect = connect From ad3e9d2a5b4cd5854d042a96f88c5fa4b80ee3ab Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 2 Jul 2018 09:57:04 +0100 Subject: [PATCH 2/3] fix: revert timout increase License: MIT Signed-off-by: Alan Shaw --- js/src/pubsub/peers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/pubsub/peers.js b/js/src/pubsub/peers.js index 16bcba4c..7f5684d8 100644 --- a/js/src/pubsub/peers.js +++ b/js/src/pubsub/peers.js @@ -14,7 +14,7 @@ module.exports = (createCommon, options) => { const common = createCommon() describe('.pubsub.peers', function () { - this.timeout(120 * 1000) + this.timeout(80 * 1000) let ipfs1 let ipfs2 From 3c0778cbaa5867e015722c425175d526336c33fb Mon Sep 17 00:00:00 2001 From: David Dias Date: Tue, 3 Jul 2018 17:02:21 +0200 Subject: [PATCH 3/3] Update swarm.js --- js/src/utils/swarm.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/src/utils/swarm.js b/js/src/utils/swarm.js index 6e7119bd..368151b4 100644 --- a/js/src/utils/swarm.js +++ b/js/src/utils/swarm.js @@ -1,7 +1,9 @@ const eachSeries = require('async/eachSeries') function connect (fromNode, toAddrs, cb) { - if (!Array.isArray(toAddrs)) toAddrs = [toAddrs] + if (!Array.isArray(toAddrs)) { + toAddrs = [toAddrs] + } // FIXME ??? quick connections to different nodes sometimes cause no // connection and no error, hence serialize connections and pause between