From 9fb54d2bc29653d7f8724bb2126b6ca7435e71fb Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Thu, 14 Mar 2019 18:27:59 -0400 Subject: [PATCH] chore: callbacks -> async / await This is part of the Awesome Endeavour: Async Iterators https://github.com/ipfs/js-ipfs/issues/1670 BREAKING CHANGE: All places in the API that used callbacks are now replaced with async/await --- README.md | 39 ++++------ package.json | 9 +-- src/index.js | 52 ++++++------- test/block-service-test.js | 156 +++++++++++++------------------------ test/browser.js | 22 ++---- test/node.js | 20 ++--- 6 files changed, 113 insertions(+), 185 deletions(-) diff --git a/README.md b/README.md index 19bf33d..5de876f 100644 --- a/README.md +++ b/README.md @@ -72,31 +72,20 @@ const repo = new IPFSRepo('example') // create a block const data = new Buffer('hello world') -multihashing(data, 'sha2-256', (err, multihash) => { - if (err) { - throw err - } - - const cid = new CID(multihash) - const block = new Block(data, cid) - - // create a service - const bs = new BlockService(repo) - - // add the block, then retrieve it - bs.put(block, (err) => { - if (err) { - throw err - } - bs.get(cid, (err, b) => { - if (err) { - throw err - } - console.log(block.data.toString() === b.data.toString()) - // => true - }) - }) -}) +const multihash = await multihashing(data, 'sha2-256') + +const cid = new CID(multihash) +const block = new Block(data, cid) + +// create a service +const service = new BlockService(repo) + +// add the block, then retrieve it +await service.put(block) + +const result = await service.get(cid) +console.log(block.data.toString() === result.data.toString()) +// => true ``` ### Browser: Browserify, Webpack, other bundlers diff --git a/package.json b/package.json index e5f7fab..6ad8ac3 100644 --- a/package.json +++ b/package.json @@ -34,19 +34,18 @@ "chai": "^4.2.0", "cids": "~0.5.7", "dirty-chai": "^2.0.1", + "fs-extra": "^8.0.1", "ipfs-block": "~0.8.0", - "ipfs-repo": "~0.26.2", + "ipfs-repo": "~0.27.0", "lodash": "^4.17.11", - "multihashing-async": "~0.5.2", - "ncp": "^2.0.0", - "rimraf": "^2.6.3" + "multihashing-async": "~0.7.0" }, "engines": { "node": ">=6.0.0", "npm": ">=3.0.0" }, "dependencies": { - "async": "^2.6.2" + "streaming-iterables": "^4.0.2" }, "contributors": [ "David Dias ", diff --git a/src/index.js b/src/index.js index ea282cf..d29beaf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ 'use strict' -const asyncMap = require('async/map') +const { map } = require('streaming-iterables') /** * BlockService is a hybrid block datastore. It stores data in a local @@ -54,14 +54,13 @@ class BlockService { * Put a block to the underlying datastore. * * @param {Block} block - * @param {function(Error)} callback - * @returns {void} + * @returns {Promise} */ - put (block, callback) { + put (block) { if (this.hasExchange()) { - this._bitswap.put(block, callback) + return this._bitswap.put(block) } else { - this._repo.blocks.put(block, callback) + return this._repo.blocks.put(block) } } @@ -69,14 +68,13 @@ class BlockService { * Put a multiple blocks to the underlying datastore. * * @param {Array} blocks - * @param {function(Error)} callback - * @returns {void} + * @returns {Promise} */ - putMany (blocks, callback) { + putMany (blocks) { if (this.hasExchange()) { - this._bitswap.putMany(blocks, callback) + return this._bitswap.putMany(blocks) } else { - this._repo.blocks.putMany(blocks, callback) + return this._repo.blocks.putMany(blocks) } } @@ -84,14 +82,13 @@ class BlockService { * Get a block by cid. * * @param {CID} cid - * @param {function(Error, Block)} callback - * @returns {void} + * @returns {Promise} */ - get (cid, callback) { + get (cid) { if (this.hasExchange()) { - this._bitswap.get(cid, callback) + return this._bitswap.get(cid) } else { - this._repo.blocks.get(cid, callback) + return this._repo.blocks.get(cid) } } @@ -99,16 +96,18 @@ class BlockService { * Get multiple blocks back from an array of cids. * * @param {Array} cids - * @param {function(Error, Block)} callback - * @returns {void} + * @returns {Iterator} */ - getMany (cids, callback) { + getMany (cids) { if (!Array.isArray(cids)) { - callback(new Error('first arg must be an array of cids')) - } else if (this.hasExchange()) { - this._bitswap.getMany(cids, callback) + throw new Error('first arg must be an array of cids') + } + + if (this.hasExchange()) { + return this._bitswap.getMany(cids) } else { - asyncMap(cids, (cid, cb) => this._repo.blocks.get(cid, cb), callback) + const getRepoBlocks = map((cid) => this._repo.blocks.get(cid)) + return getRepoBlocks(cids) } } @@ -116,11 +115,10 @@ class BlockService { * Delete a block from the blockstore. * * @param {CID} cid - * @param {function(Error)} callback - * @return {void} + * @returns {Promise} */ - delete (cid, callback) { - this._repo.blocks.delete(cid, callback) + delete (cid) { + return this._repo.blocks.delete(cid) } } diff --git a/test/block-service-test.js b/test/block-service-test.js index 76936c7..59b8c77 100644 --- a/test/block-service-test.js +++ b/test/block-service-test.js @@ -7,8 +7,7 @@ const expect = chai.expect const Block = require('ipfs-block') const _ = require('lodash') -const map = require('async/map') -const waterfall = require('async/waterfall') +const { collect } = require('streaming-iterables') const CID = require('cids') const multihashing = require('multihashing-async') @@ -19,7 +18,7 @@ module.exports = (repo) => { let bs let testBlocks - before((done) => { + before(async () => { bs = new BlockService(repo) const data = [ @@ -29,108 +28,74 @@ module.exports = (repo) => { Buffer.from('A random data block') ] - map(data, (d, cb) => { - multihashing(d, 'sha2-256', (err, hash) => { - expect(err).to.not.exist() - cb(null, new Block(d, new CID(hash))) - }) - }, (err, blocks) => { - expect(err).to.not.exist() - testBlocks = blocks - done() - }) + testBlocks = await Promise.all(data.map(async (d) => { + const hash = await multihashing(d, 'sha2-256') + return new Block(d, new CID(hash)) + })) }) - describe('fetch only from local Repo', () => { - it('store and get a block', (done) => { + describe('fetch only from local Repo', async () => { + it('store and get a block', async () => { const b = testBlocks[3] - waterfall([ - (cb) => bs.put(b, cb), - (cb) => bs.get(b.cid, cb), - (res, cb) => { - expect(res).to.eql(b) - cb() - } - ], done) + await bs.put(b) + const res = await bs.get(b.cid) + expect(res).to.eql(b) }) - it('get a non stored yet block', (done) => { + it('get a non stored yet block', async () => { const b = testBlocks[2] - bs.get(b.cid, (err, block) => { + try { + await bs.get(b.cid) + } catch (err) { expect(err).to.exist() - expect(block).to.not.exist() - done() - }) + } }) - it('store many blocks', (done) => { - bs.putMany(testBlocks, done) + it('store many blocks', () => { + return bs.putMany(testBlocks) }) - it('get many blocks through .get', (done) => { - map(testBlocks, (b, cb) => bs.get(b.cid, cb), (err, blocks) => { - expect(err).to.not.exist() - expect(blocks).to.eql(testBlocks) - done() - }) + it('get many blocks through .get', async () => { + const blocks = await Promise.all(testBlocks.map(b => bs.get(b.cid))) + expect(blocks).to.eql(testBlocks) }) - it('get many blocks through .getMany', (done) => { - map(testBlocks, (b, cb) => cb(null, b.cid), (err, cids) => { - expect(err).to.not.exist() - bs.getMany(cids, (err, _blocks) => { - expect(err).to.not.exist() - expect(testBlocks).to.eql(_blocks) - done() - }) - }) + it('get many blocks through .getMany', async () => { + const cids = testBlocks.map(b => b.cid) + const blocks = await collect(bs.getMany(cids)) + expect(blocks).to.eql(testBlocks) }) - it('delete a block', (done) => { + it('delete a block', async () => { const data = Buffer.from('Will not live that much') - multihashing(data, 'sha2-256', (err, hash) => { - expect(err).to.not.exist() - const b = new Block(data, new CID(hash)) - - waterfall([ - (cb) => bs.put(b, cb), - (cb) => bs.delete(b.cid, cb), - (cb) => bs._repo.blocks.has(b.cid, cb), - (res, cb) => { - expect(res).to.be.eql(false) - cb() - } - ], done) - }) + const hash = await multihashing(data, 'sha2-256') + const b = new Block(data, new CID(hash)) + + await bs.put(b) + await bs.delete(b.cid) + const res = await bs._repo.blocks.has(b.cid) + expect(res).to.be.eql(false) }) - it('stores and gets lots of blocks', function (done) { + it('stores and gets lots of blocks', async function () { this.timeout(8 * 1000) const data = _.range(1000).map((i) => { return Buffer.from(`hello-${i}-${Math.random()}`) }) - map(data, (d, cb) => { - multihashing(d, 'sha2-256', (err, hash) => { - expect(err).to.not.exist() - cb(null, new Block(d, new CID(hash))) - }) - }, (err, blocks) => { - expect(err).to.not.exist() - bs.putMany(blocks, (err) => { - expect(err).to.not.exist() - - map(blocks, (b, cb) => bs.get(b.cid, cb), (err, res) => { - expect(err).to.not.exist() - expect(res).to.be.eql(blocks) - done() - }) - }) - }) + const blocks = await Promise.all(data.map(async (d) => { + const hash = await multihashing(d, 'sha2-256') + return new Block(d, new CID(hash)) + })) + + await bs.putMany(blocks) + + const res = await Promise.all(blocks.map(b => bs.get(b.cid))) + expect(res).to.be.eql(blocks) }) it('sets and unsets exchange', () => { @@ -152,11 +117,11 @@ module.exports = (repo) => { expect(bs.hasExchange()).to.be.eql(true) }) - it('retrieves a block through bitswap', (done) => { + it('retrieves a block through bitswap', async () => { // returns a block with a value equal to its key const bitswap = { - get (cid, callback) { - callback(null, new Block(Buffer.from('secret'), cid)) + get (cid) { + return new Block(Buffer.from('secret'), cid) } } @@ -164,36 +129,27 @@ module.exports = (repo) => { const data = Buffer.from('secret') - waterfall([ - (cb) => multihashing(data, 'sha2-256', cb), - (hash, cb) => bs.get(new CID(hash), cb), - (block, cb) => { - expect(block.data).to.be.eql(data) - cb() - } - ], done) + const hash = await multihashing(data, 'sha2-256') + const block = await bs.get(new CID(hash)) + + expect(block.data).to.be.eql(data) }) - it('puts the block through bitswap', (done) => { + it('puts the block through bitswap', async () => { const puts = [] const bitswap = { - put (block, callback) { + put (block) { puts.push(block) - callback() } } bs.setExchange(bitswap) const data = Buffer.from('secret sauce') - waterfall([ - (cb) => multihashing(data, 'sha2-256', cb), - (hash, cb) => bs.put(new Block(data, new CID(hash)), cb) - ], (err) => { - expect(err).to.not.exist() - expect(puts).to.have.length(1) - done() - }) + const hash = await multihashing(data, 'sha2-256') + await bs.put(new Block(data, new CID(hash))) + + expect(puts).to.have.length(1) }) }) }) diff --git a/test/browser.js b/test/browser.js index fd60cc4..fa97598 100644 --- a/test/browser.js +++ b/test/browser.js @@ -2,7 +2,6 @@ /* global self */ 'use strict' -const series = require('async/series') const IPFSRepo = require('ipfs-repo') const tests = require('./block-service-test') @@ -18,23 +17,16 @@ idb.deleteDatabase('ipfs/blocks') describe('IPFS Repo Tests on the Browser', () => { const repo = new IPFSRepo('ipfs') - before((done) => { - series([ - (cb) => repo.init({}, cb), - (cb) => repo.open(cb) - ], done) + before(async () => { + await repo.init({}) + await repo.open() }) - after((done) => { - series([ - (cb) => repo.close(cb), - (cb) => { - idb.deleteDatabase('ipfs') - idb.deleteDatabase('ipfs/blocks') + after(async () => { + await repo.close() - cb() - } - ], done) + idb.deleteDatabase('ipfs') + idb.deleteDatabase('ipfs/blocks') }) tests(repo) diff --git a/test/node.js b/test/node.js index f03c709..1d59fb2 100644 --- a/test/node.js +++ b/test/node.js @@ -1,9 +1,7 @@ /* eslint-env mocha */ 'use strict' -const ncp = require('ncp').ncp -const series = require('async/series') -const rimraf = require('rimraf') +const fs = require('fs-extra') const path = require('path') const IPFSRepo = require('ipfs-repo') @@ -15,18 +13,14 @@ describe('IPFS Block Tests on Node.js', () => { const repoPath = testRepoPath + '-for-' + date const repo = new IPFSRepo(repoPath) - before((done) => { - series([ - (cb) => ncp(testRepoPath, repoPath, cb), - (cb) => repo.open(cb) - ], done) + before(async () => { + await fs.copy(testRepoPath, repoPath) + await repo.open() }) - after((done) => { - series([ - (cb) => repo.close(cb), - (cb) => rimraf(repoPath, cb) - ], done) + after(async () => { + await repo.close() + await fs.remove(repoPath) }) tests(repo)