Skip to content

Commit

Permalink
chore: avoid artificially induced async
Browse files Browse the repository at this point in the history
  • Loading branch information
achingbrain committed May 26, 2020
1 parent d5d81fc commit bd676f0
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 38 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
"cids": "~0.8.0",
"debug": "^4.1.0",
"ipld-block": "^0.9.1",
"it-first": "^1.0.2",
"it-length-prefixed": "^3.0.0",
"it-pipe": "^1.1.0",
"just-debounce-it": "^1.1.0",
Expand Down
72 changes: 36 additions & 36 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const DecisionEngine = require('./decision-engine')
const Notifications = require('./notifications')
const logger = require('./utils').logger
const Stats = require('./stats')
const first = require('it-first')
const AbortController = require('abort-controller')
const anySignal = require('any-signal')

Expand Down Expand Up @@ -188,20 +187,7 @@ class Bitswap {
* @param {AbortSignal} options.abortSignal
* @returns {Promise<Block>}
*/
async get (cid, options) { // eslint-disable-line require-await
return first(this.getMany([cid], options))
}

/**
* Fetch a a list of blocks by cid. If the blocks are in the local
* blockstore they are returned, otherwise the blocks are added to the wantlist and returned once another node sends them to us.
*
* @param {AsyncIterator<CID>} cids
* @param {Object} options
* @param {AbortSignal} options.abortSignal
* @returns {Promise<AsyncIterator<Block>>}
*/
async * getMany (cids, options = {}) {
async get (cid, options = {}) { // eslint-disable-line require-await
const fetchFromNetwork = (cid, options) => {
// add it to the want list - n.b. later we will abort the AbortSignal
// so no need to remove the blocks from the wantlist after we have it
Expand Down Expand Up @@ -235,27 +221,40 @@ class Bitswap {
}
}

for (const cid of cids) {
// depending on implementation it's possible for blocks to come in while
// we do the async operations to get them from the blockstore leading to
// a race condition, so register for incoming block notifications as well
// as trying to get it from the datastore
const controller = new AbortController()
const signal = anySignal([options.signal, controller.signal])

const block = await Promise.race([
this.notifications.wantBlock(cid, {
signal
}),
loadOrFetchFromNetwork(cid, {
signal
})
])

// since we have the block we can now remove our listener
controller.abort()
// depending on implementation it's possible for blocks to come in while
// we do the async operations to get them from the blockstore leading to
// a race condition, so register for incoming block notifications as well
// as trying to get it from the datastore
const controller = new AbortController()
const signal = anySignal([options.signal, controller.signal])

const block = await Promise.race([
this.notifications.wantBlock(cid, {
signal
}),
loadOrFetchFromNetwork(cid, {
signal
})
])

// since we have the block we can now remove our listener
controller.abort()

return block
}

yield block
/**
* Fetch a a list of blocks by cid. If the blocks are in the local
* blockstore they are returned, otherwise the blocks are added to the wantlist and returned once another node sends them to us.
*
* @param {AsyncIterator<CID>} cids
* @param {Object} options
* @param {AbortSignal} options.abortSignal
* @returns {Promise<AsyncIterator<Block>>}
*/
async * getMany (cids, options = {}) {
for await (const cid of cids) {
yield this.get(cid, options)
}
}

Expand Down Expand Up @@ -302,7 +301,8 @@ class Bitswap {
* @returns {Promise<void>}
*/
async put (block) { // eslint-disable-line require-await
return first(this.putMany([block]))
await this.blockstore.put(block)
this._sendHaveBlockNotifications(block)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion test/bitswap.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe('bitswap without DHT', function () {
nodes[0].bitswap.blockstore = {
get: sinon.stub().withArgs(block.cid).throws({ code: 'ERR_NOT_FOUND' }),
has: sinon.stub().withArgs(block.cid).returns(false),
putMany: sinon.stub().returns([])
put: sinon.stub()
}

// add the block to our want list
Expand Down

0 comments on commit bd676f0

Please sign in to comment.