Add a timeout to `waitForRemotePeer`

This commit is contained in:
Franck Royer 2022-05-18 15:55:08 +10:00
parent 06930c15dc
commit aad678a708
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
3 changed files with 59 additions and 8 deletions

View File

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added
- `waitForRemotePeer` now accepts a `timeoutMs` parameter that rejects the promise if it is reached. By default, no timeout is applied.
### Changed ### Changed
- `waitForRemotePeer` waits for a Relay peer by default instead of Relay and Store. - `waitForRemotePeer` waits for a Relay peer by default instead of Relay and Store.

View File

@ -166,10 +166,13 @@ describe("Decryption Keys", () => {
describe("Wait for remote peer / get peers", function () { describe("Wait for remote peer / get peers", function () {
let waku: Waku; let waku: Waku;
let nwaku: Nwaku; let nwaku: Nwaku | undefined;
afterEach(async function () { afterEach(async function () {
!!nwaku && nwaku.stop(); if (nwaku) {
nwaku.stop();
nwaku = undefined;
}
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e)); !!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
}); });
@ -214,6 +217,23 @@ describe("Wait for remote peer / get peers", function () {
expect(peers.has(nimPeerId as string)).to.be.true; expect(peers.has(nimPeerId as string)).to.be.true;
}); });
it("Relay - times out", function (done) {
this.timeout(5000);
Waku.create({
staticNoiseKey: NOISE_KEY_1,
}).then((waku) => {
waku.waitForRemotePeer([Protocols.Relay], 200).then(
() => {
throw "Promise expected to reject on time out";
},
(reason) => {
expect(reason).to.eq("Timed out waiting for a remote peer.");
done();
}
);
});
});
it("Store - dialed first", async function () { it("Store - dialed first", async function () {
this.timeout(20_000); this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this)); nwaku = new Nwaku(makeLogFileName(this));
@ -238,7 +258,7 @@ describe("Wait for remote peer / get peers", function () {
expect(peers.includes(nimPeerId as string)).to.be.true; expect(peers.includes(nimPeerId as string)).to.be.true;
}); });
it("Store - dialed after", async function () { it("Store - dialed after - with timeout", async function () {
this.timeout(20_000); this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this)); nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({ persistMessages: true }); await nwaku.start({ persistMessages: true });
@ -247,7 +267,7 @@ describe("Wait for remote peer / get peers", function () {
waku = await Waku.create({ waku = await Waku.create({
staticNoiseKey: NOISE_KEY_1, staticNoiseKey: NOISE_KEY_1,
}); });
const waitPromise = waku.waitForRemotePeer([Protocols.Store]); const waitPromise = waku.waitForRemotePeer([Protocols.Store], 2000);
await delay(1000); await delay(1000);
await waku.dial(multiAddrWithId); await waku.dial(multiAddrWithId);
await waitPromise; await waitPromise;

View File

@ -329,12 +329,21 @@ export class Waku {
* Wait for a remote peer to be ready given the passed protocols. * Wait for a remote peer to be ready given the passed protocols.
* Useful when using the [[CreateOptions.bootstrap]] with [[Waku.create]]. * Useful when using the [[CreateOptions.bootstrap]] with [[Waku.create]].
* *
* @default Remote peer must have Waku Relay enabled. * @param protocols The protocols that need to be enabled by remote peers.
* @param timeoutMs A timeout value in milliseconds..
*
* @returns A promise that **resolves** if all desired protocols are fulfilled by
* remote nodes, **rejects** if the timeoutMs is reached.
*
* @default Remote peer must have Waku Relay enabled and no time out is applied.
*/ */
async waitForRemotePeer(protocols?: Protocols[]): Promise<void> { async waitForRemotePeer(
protocols?: Protocols[],
timeoutMs?: number
): Promise<void> {
protocols = protocols ?? [Protocols.Relay]; protocols = protocols ?? [Protocols.Relay];
const promises = []; const promises: Promise<void>[] = [];
if (protocols.includes(Protocols.Relay)) { if (protocols.includes(Protocols.Relay)) {
const peers = this.relay.getPeers(); const peers = this.relay.getPeers();
@ -372,7 +381,15 @@ export class Waku {
promises.push(lightPushPromise); promises.push(lightPushPromise);
} }
await Promise.all(promises); if (timeoutMs) {
await rejectOnTimeout(
Promise.all(promises),
timeoutMs,
"Timed out waiting for a remote peer."
);
} else {
await Promise.all(promises);
}
} }
private startKeepAlive( private startKeepAlive(
@ -417,3 +434,13 @@ export class Waku {
} }
} }
} }
const awaitTimeout = (ms: number, rejectReason: string): Promise<void> =>
new Promise((_resolve, reject) => setTimeout(() => reject(rejectReason), ms));
const rejectOnTimeout = (
promise: Promise<any>,
timeoutMs: number,
rejectReason: string
): Promise<void> =>
Promise.race([promise, awaitTimeout(timeoutMs, rejectReason)]);