diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index f0ccbc4522..baf19ecf97 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -16,7 +16,7 @@ "human-crypto-keys": "^0.1.4", "ipfs": "^0.55.2", "ipfs-http-client": "^50.1.0", - "ipfs-utils": "^7.0.0", + "ipfs-utils": "^8.1.2", "ipns": "^0.11.0", "it-last": "^1.0.4", "p-retry": "^4.2.0", diff --git a/examples/custom-libp2p/package.json b/examples/custom-libp2p/package.json index bed6d6d071..b291af6b29 100644 --- a/examples/custom-libp2p/package.json +++ b/examples/custom-libp2p/package.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "ipfs": "^0.55.2", - "libp2p": "^0.31.5", + "libp2p": "^0.31.6", "libp2p-bootstrap": "^0.12.3", "libp2p-kad-dht": "^0.22.0", "libp2p-mdns": "^0.16.0", diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 44aa3d74d3..c87c8e807a 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -47,7 +47,7 @@ "err-code": "^3.0.1", "ipfs-unixfs": "^4.0.3", "ipfs-unixfs-importer": "^7.0.3", - "ipfs-utils": "^7.0.0", + "ipfs-utils": "^8.1.2", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", diff --git a/packages/ipfs-cli/package.json b/packages/ipfs-cli/package.json index ddadda3ecd..d2030eb572 100644 --- a/packages/ipfs-cli/package.json +++ b/packages/ipfs-cli/package.json @@ -43,7 +43,7 @@ "ipfs-daemon": "^0.7.0", "ipfs-http-client": "^50.1.0", "ipfs-repo": "^9.1.6", - "ipfs-utils": "^7.0.0", + "ipfs-utils": "^8.1.2", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", "it-all": "^1.0.4", diff --git a/packages/ipfs-core-utils/package.json b/packages/ipfs-core-utils/package.json index dc81bf7bc5..b565b442b9 100644 --- a/packages/ipfs-core-utils/package.json +++ b/packages/ipfs-core-utils/package.json @@ -48,7 +48,7 @@ "err-code": "^3.0.1", "ipfs-core-types": "^0.5.0", "ipfs-unixfs": "^4.0.3", - "ipfs-utils": "^7.0.0", + "ipfs-utils": "^8.1.2", "it-all": "^1.0.4", "it-map": "^1.0.4", "it-peekable": "^1.0.1", diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index b14e942e63..4ea0e42590 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -78,7 +78,7 @@ "ipfs-unixfs": "^4.0.3", "ipfs-unixfs-exporter": "^5.0.3", "ipfs-unixfs-importer": "^7.0.3", - "ipfs-utils": "^7.0.0", + "ipfs-utils": "^8.1.2", "ipld": "^0.30.0", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^1.0.0", @@ -94,11 +94,11 @@ "it-map": "^1.0.4", "it-pipe": "^1.1.0", "just-safe-set": "^2.2.1", - "libp2p": "^0.31.5", + "libp2p": "^0.31.6", "libp2p-bootstrap": "^0.12.3", "libp2p-crypto": "^0.19.3", "libp2p-floodsub": "^0.25.1", - "libp2p-gossipsub": "^0.9.0", + "libp2p-gossipsub": "^0.9.2", "libp2p-kad-dht": "^0.22.0", "libp2p-mdns": "^0.16.0", "libp2p-mplex": "^0.10.2", diff --git a/packages/ipfs-daemon/package.json b/packages/ipfs-daemon/package.json index 6bea16f294..1ee6b51ccc 100644 --- a/packages/ipfs-daemon/package.json +++ b/packages/ipfs-daemon/package.json @@ -38,9 +38,9 @@ "ipfs-http-client": "^50.1.0", "ipfs-http-gateway": "^0.4.1", "ipfs-http-server": "^0.5.0", - "ipfs-utils": "^7.0.0", + "ipfs-utils": "^8.1.2", "just-safe-set": "^2.2.1", - "libp2p": "^0.31.5", + "libp2p": "^0.31.6", "libp2p-delegated-content-routing": "^0.10.0", "libp2p-delegated-peer-routing": "^0.9.0", "libp2p-webrtc-star": "^0.22.2", @@ -48,7 +48,7 @@ }, "devDependencies": { "aegir": "^33.0.0", - "node-fetch": "^2.6.1", + "node-fetch": "npm:@achingbrain/node-fetch@^2.6.4", "ws": "^7.3.1" }, "optionalDependencies": { diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index e32db95c8f..17eca3b0f5 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -52,7 +52,7 @@ "ipfs-core-types": "^0.5.0", "ipfs-core-utils": "^0.8.1", "ipfs-unixfs": "^4.0.3", - "ipfs-utils": "^7.0.0", + "ipfs-utils": "^8.1.2", "ipld-block": "^0.11.0", "ipld-dag-cbor": "^1.0.0", "ipld-dag-pb": "^0.22.1", diff --git a/packages/ipfs-http-client/src/pubsub/subscribe.js b/packages/ipfs-http-client/src/pubsub/subscribe.js index 83db478e4e..1348117455 100644 --- a/packages/ipfs-http-client/src/pubsub/subscribe.js +++ b/packages/ipfs-http-client/src/pubsub/subscribe.js @@ -62,7 +62,7 @@ module.exports = configure((api, options) => { return } - readMessages(response.ndjson(), { + readMessages(response, { onMessage: handler, onEnd: () => subsTracker.unsubscribe(topic, handler), onError: options.onError @@ -78,17 +78,17 @@ module.exports = configure((api, options) => { }) /** - * @param {*} msgStream + * @param {import('ipfs-utils/src/types').ExtendedResponse} response * @param {object} options * @param {(message: Message) => void} options.onMessage * @param {() => void} options.onEnd * @param {ErrorHandlerFn} [options.onError] */ -async function readMessages (msgStream, { onMessage, onEnd, onError }) { +async function readMessages (response, { onMessage, onEnd, onError }) { onError = onError || log try { - for await (const msg of msgStream) { + for await (const msg of response.ndjson()) { try { if (!msg.from) { continue @@ -106,12 +106,28 @@ async function readMessages (msgStream, { onMessage, onEnd, onError }) { } } } catch (err) { - // FIXME: In testing with Chrome, err.type is undefined (should not be!) - // Temporarily use the name property instead. - if (err.type !== 'aborted' && err.name !== 'AbortError') { + if (!isAbortError(err)) { onError(err, true) // Fatal } } finally { onEnd() } } + +/** + * @param {Error & {type?:string}} error + * @returns {boolean} + */ +const isAbortError = error => { + switch (error.type) { + case 'aborted': + return true + // It is `abort` in Electron instead of `aborted` + case 'abort': + return true + default: + // FIXME: In testing with Chrome, err.type is undefined (should not be!) + // Temporarily use the name property instead. + return error.name === 'AbortError' + } +} diff --git a/packages/ipfs-http-client/test/pubsub.spec.js b/packages/ipfs-http-client/test/pubsub.spec.js new file mode 100644 index 0000000000..8e6320fe99 --- /dev/null +++ b/packages/ipfs-http-client/test/pubsub.spec.js @@ -0,0 +1,84 @@ +/* eslint-env mocha */ +'use strict' + +const { expect } = require('aegir/utils/chai') +const { AbortController } = require('native-abort-controller') + +const f = require('./utils/factory')() + +describe('.pubsub', function () { + this.timeout(20 * 1000) + describe('.subscribe', () => { + let ipfs + let ctl + + beforeEach(async function () { + this.timeout(30 * 1000) // slow CI + + ctl = await await f.spawn({ + args: '--enable-pubsub-experiment' + }) + + ipfs = ctl.api + }) + + afterEach(() => f.clean()) + + it('.onError when connection is closed', async () => { + const topic = 'gossipboom' + let messageCount = 0 + let onError + const error = new Promise(resolve => { onError = resolve }) + + await ipfs.pubsub.subscribe(topic, message => { + messageCount++ + + if (messageCount === 2) { + // Stop the daemon + ctl.stop().catch() + } + }, { + onError + }) + + await ipfs.pubsub.publish(topic, 'hello') + await ipfs.pubsub.publish(topic, 'bye') + + await expect(error).to.eventually.be.fulfilled().and.to.be.instanceOf(Error) + }) + + it('does not call onError when aborted', async () => { + const controller = new AbortController() + const topic = 'gossipabort' + const messages = [] + let onError + let onReceived + + const received = new Promise(resolve => { onReceived = resolve }) + const error = new Promise(resolve => { onError = resolve }) + + await ipfs.pubsub.subscribe(topic, message => { + messages.push(message) + if (messages.length === 2) { + onReceived() + } + }, { + onError, + signal: controller.signal + }) + + await ipfs.pubsub.publish(topic, 'hello') + await ipfs.pubsub.publish(topic, 'bye') + + await received + controller.abort() + + // Stop the daemon + await ctl.stop() + // Just to make sure no error is caused by above line + setTimeout(onError, 200, 'aborted') + + await expect(error).to.eventually.be.fulfilled().and.to.equal('aborted') + }) + }) +}) diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index 2909ed6dd1..dcc6be591a 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -57,7 +57,7 @@ "ipfs-core-types": "^0.5.0", "ipfs-http-client": "^50.1.0", "ipfs-interop": "^5.0.2", - "ipfs-utils": "^7.0.0", + "ipfs-utils": "^8.1.2", "ipfsd-ctl": "^8.0.1", "iso-url": "^1.0.0", "libp2p-webrtc-star": "^0.22.2",