Skip to content

Commit 2fc7023

Browse files
authored
fix: survive bad network requests (#222)
* fix: survive not being able to send messages to peers Builds on the work in #221 I see intermittant but frequent CI errors with js-ipfs, usually after a test has finished and the ndoes are being torn down. Getting it to do some additional logging reveals bitswap is crashing when it cannot send a message to a remote peer due to the libp2p dial failing: ```console ipfs: [stdout] Error: stream ended before 1 bytes became available ipfs: at /home/travis/build/ipfs/js-ipfs/node_modules/it-reader/index.js:37:9 ipfs: at processTicksAndRejections (internal/process/task_queues.js:97:5) ipfs: at async /home/travis/build/ipfs/js-ipfs/node_modules/it-length-prefixed/src/decode.js:80:20 ipfs: at async oneChunk (/home/travis/build/ipfs/js-ipfs/node_modules/multistream-select/src/multistream.js:12:20) ipfs: at async Object.exports.read (/home/travis/build/ipfs/js-ipfs/node_modules/multistream-select/src/multistream.js:34:15) ipfs: at async module.exports (/home/travis/build/ipfs/js-ipfs/node_modules/multistream-select/src/select.js:21:19) ipfs: at async ClassIsWrapper.newStream [as _newStream] (/home/travis/build/ipfs/js-ipfs/node_modules/libp2p/src/upgrader.js:251:40) ipfs: at async ClassIsWrapper.newStream (/home/travis/build/ipfs/js-ipfs/node_modules/libp2p-interfaces/src/connection/connection.js:172:34) ipfs: at async Network.sendMessage (/home/travis/build/ipfs/js-ipfs/node_modules/ipfs-bitswap/src/network.js:147:34) ipfs: at async DecisionEngine._processTasks (/home/travis/build/ipfs/js-ipfs/node_modules/ipfs-bitswap/src/decision-engine/index.js:124:5) { ipfs: code: 'ERR_UNSUPPORTED_PROTOCOL', ipfs: buffer: BufferList { _bufs: [], length: 0 } ipfs: } ``` This PR adds a try/catch around network send operations. At the moment it just dumps the request, I'm not sure if we want to add a retry in there or something.
1 parent 1a5ed4a commit 2fc7023

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

src/decision-engine/index.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,21 @@ class DecisionEngine {
120120
return
121121
}
122122

123-
// Send the message
124-
await this.network.sendMessage(peerId, msg)
123+
try {
124+
// Send the message
125+
await this.network.sendMessage(peerId, msg)
126+
127+
// Peform sent message accounting
128+
for (const block of blocks.values()) {
129+
this.messageSent(peerId, block)
130+
}
131+
} catch (err) {
132+
this._log.error(err)
133+
}
125134

126135
// Free the tasks up from the request queue
127136
this._requestQueue.tasksDone(peerId, tasks)
128137

129-
// Peform sent message accounting
130-
for (const block of blocks.values()) {
131-
this.messageSent(peerId, block)
132-
}
133-
134138
// Trigger the next round of task processing
135139
this._scheduleProcessTasks()
136140
}

test/decision-engine/decision-engine.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,4 +683,50 @@ describe('Engine', () => {
683683
}
684684
}
685685
})
686+
687+
it('survives not being able to send a message to peer', async () => {
688+
let r
689+
const failToSendPromise = new Promise((resolve) => {
690+
r = resolve
691+
})
692+
693+
const network = mockNetwork()
694+
network.sendMessage = () => {
695+
r()
696+
throw new Error('Something is b0rken')
697+
}
698+
699+
// who is in the network
700+
const us = await newEngine(network)
701+
const them = await newEngine()
702+
703+
// add a block to our blockstore
704+
const data = Buffer.from(`this is message ${Date.now()}`)
705+
const hash = await multihashing(data, 'sha2-256')
706+
const cid = new CID(hash)
707+
const block = new Block(data, cid)
708+
await us.engine.blockstore.put(block)
709+
710+
// receive a message with a want for our block
711+
await us.engine.messageReceived(them.peer, {
712+
blocks: [],
713+
wantlist: [{
714+
cid,
715+
priority: 1,
716+
wantType: 'wanty'
717+
}]
718+
})
719+
720+
// should have added a task for the remote peer
721+
const tasks = us.engine._requestQueue._byPeer.get(them.peer.toB58String())
722+
723+
expect(tasks).to.have.property('_pending').that.has.property('length', 1)
724+
725+
// wait for us.network.sendMessage to be called
726+
await failToSendPromise
727+
728+
// should be done processing
729+
expect(tasks).to.have.property('_pending').that.has.property('length', 0)
730+
expect(tasks).to.have.property('_active').that.has.property('size', 0)
731+
})
686732
})

0 commit comments

Comments
 (0)