Skip to content

Commit

Permalink
feat: replace waitForRemotePeers() with waku.waitForPeer() method (
Browse files Browse the repository at this point in the history
…#2161)

* fix comment of default number of peers

* export default number of peers from base protocol sdk

* rename to light_push, move class to separate file

* move waitForRemotePeer to sdk package

* add todo to move waitForGossipSubPeerInMesh into @waku/relay

* clean up waitForRemotePeer, split metadata await from event and optimise, decouple from protocol implementations

* simplify and rename ILightPush interface

* use only connected peers in light push based on connections instead of peer renewal mechanism

* improve readability of result processing in light push

* fix check & update tests

* address tests, add new test cases, fix racing condition in StreamManager

* use libp2p.getPeers

* feat: confirm metadata and protocols needed in waitForRemotePeer

* rely on passed protocols and fallback to mounted

* add I prefix to Waku interface

* implement waku.connect method

* add docs to IWaku interface

* remove export and usage of waitForRemotePeer

* move wait for remote peer related to Realy out of @waku/sdk

* change tests to use new API

* fix linting

* update size limit

* rename .connect to .waitForPeer

* export waitForRemotePeer and mark as deprecated

* feat: add mocha tests to @waku/sdk and cover waitForRemotePeer (#2163)

* feat: add mocha tests to @waku/sdk and cover waitForRemotePeer

* add waitForRemote UTs

* remove junk

* feat: expose peerId and protocols from WakuNode (#2166)

* chore: expose peerId and protocols from WakuNode

* remove unused method

* move to private method

* rename to waitForPeers

* up test
  • Loading branch information
weboko authored Oct 8, 2024
1 parent d37e024 commit 75fcca4
Show file tree
Hide file tree
Showing 40 changed files with 713 additions and 193 deletions.
2 changes: 1 addition & 1 deletion .size-limit.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = [
path: ["packages/sdk/bundle/index.js", "packages/core/bundle/index.js"],
import: {
"packages/sdk/bundle/index.js":
"{ createLightNode, waitForRemotePeer, createEncoder, createDecoder, bytesToUtf8, utf8ToBytes, Decoder, Encoder, DecodedMessage, WakuNode }",
"{ createLightNode, createEncoder, createDecoder, bytesToUtf8, utf8ToBytes, Decoder, Encoder, DecodedMessage, WakuNode }",
},
},
{
Expand Down
13 changes: 9 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/interfaces/src/relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface IRelayAPI {
readonly pubsubTopics: Set<PubsubTopic>;
readonly gossipSub: GossipSub;
start: () => Promise<void>;
waitForPeers: () => Promise<void>;
getMeshPeers: (topic?: TopicStr) => PeerIdStr[];
}

Expand Down
101 changes: 96 additions & 5 deletions packages/interfaces/src/waku.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,127 @@ import { Protocols } from "./protocols.js";
import type { IRelay } from "./relay.js";
import type { IStore } from "./store.js";

export interface Waku {
export interface IWaku {
libp2p: Libp2p;
relay?: IRelay;
store?: IStore;
filter?: IFilter;
lightPush?: ILightPush;

health: IHealthManager;
connectionManager: IConnectionManager;

/**
* Returns a unique identifier for a node on the network.
*
* @example
* ```typescript
* console.log(waku.peerId); // 12D3KooWNmk9yXHfHJ4rUduRqD1TCTHkNFMPF9WP2dqWpZDL4aUb
* ```
*/
peerId: PeerId;

/**
* Returns a list of supported protocols.
*
* @example
* ```typescript
* console.log(waku.protocols); // ['/ipfs/id/1.0.0', '/ipfs/ping/1.0.0', '/vac/waku/filter-push/2.0.0-beta1', '/vac/waku/metadata/1.0.0']
* ```
*/
protocols: string[];

/**
* Dials to the provided peer
*
* @param {PeerId | MultiaddrInput} peer information to use for dialing
* @param {Protocols[]} [protocols] array of Waku protocols to be used for dialing. If no provided - will be derived from mounted protocols.
*
* @returns {Promise<Stream>} `Promise` that will resolve to a `Stream` to a dialed peer
*
* @example
* ```typescript
* await waku.dial(remotePeerId, [Protocols.LightPush]);
*
* waku.isConnected() === true;
* ```
*/
dial(peer: PeerId | MultiaddrInput, protocols?: Protocols[]): Promise<Stream>;

/**
* Starts all services and components related to functionality of Waku node.
*
* @returns {Promise<boolean>} `Promise` that will resolve when started.
*
* @example
* ```typescript
* await waku.start();
*
* waku.isStarted() === true;
* ```
*/
start(): Promise<void>;

/**
* Stops all recurring processes and services that are needed for functionality of Waku node.
*
* @returns {Promise<boolean>} `Promise` that resolves when stopped.
*
* @example
* ```typescript
* await waku.stop();
*
* waku.isStarted === false;
* ```
*/
stop(): Promise<void>;

/**
* Resolves when Waku successfully gains connection to a remote peers that fits provided requirements.
* Must be used after attempting to connect to nodes, using {@link IWaku.dial} or
* if was bootstrapped by using {@link IPeerExchange} or {@link DnsDiscoveryComponents}.
*
* @param {Protocols[]} [protocols] Protocols that need to be enabled by remote peers
* @param {number} [timeoutMs] Timeout value in milliseconds after which promise rejects
*
* @returns {Promise<void>} `Promise` that **resolves** if all desired protocols are fulfilled by
* at least one remote peer, **rejects** if the timeoutMs is reached
* @throws If passing a protocol that is not mounted or Waku node is not started
*
* @example
* ```typescript
* try {
* // let's wait for at least one LightPush node and timeout in 1 second
* await waku.waitForPeers([Protocols.LightPush], 1000);
* } catch(e) {
* waku.isConnected() === false;
* console.error("Failed to connect due to", e);
* }
*
* waku.isConnected() === true;
* ```
*/
waitForPeers(protocols?: Protocols[], timeoutMs?: number): Promise<void>;

/**
* @returns {boolean} `true` if the node was started and `false` otherwise
*/
isStarted(): boolean;

/**
* @returns {boolean} `true` if the node has working connection and `false` otherwise
*/
isConnected(): boolean;

health: IHealthManager;
}

export interface LightNode extends Waku {
export interface LightNode extends IWaku {
relay: undefined;
store: IStore;
filter: IFilter;
lightPush: ILightPush;
}

export interface RelayNode extends Waku {
export interface RelayNode extends IWaku {
relay: IRelay;
store: undefined;
filter: undefined;
Expand Down
3 changes: 2 additions & 1 deletion packages/relay/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"@waku/utils": "0.0.20",
"chai": "^4.3.10",
"debug": "^4.3.4",
"fast-check": "^3.19.0"
"fast-check": "^3.19.0",
"p-event": "^6.0.1"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
Expand Down
17 changes: 17 additions & 0 deletions packages/relay/src/relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import { isWireSizeUnderCap, toAsyncIterator } from "@waku/utils";
import { pushOrInitMapSet } from "@waku/utils";
import { Logger } from "@waku/utils";
import { pEvent } from "p-event";

import { RelayCodecs } from "./constants.js";
import { messageValidator } from "./message_validator.js";
Expand Down Expand Up @@ -94,6 +95,22 @@ class Relay implements IRelay {
this.subscribeToAllTopics();
}

/**
* Wait for at least one peer with the given protocol to be connected and in the gossipsub
* mesh for all pubsubTopics.
*/
public async waitForPeers(): Promise<void> {
let peers = this.getMeshPeers();
const pubsubTopics = this.pubsubTopics;

for (const topic of pubsubTopics) {
while (peers.length == 0) {
await pEvent(this.gossipSub, "gossipsub:heartbeat");
peers = this.getMeshPeers(topic);
}
}
}

/**
* Send Waku message.
*/
Expand Down
6 changes: 6 additions & 0 deletions packages/sdk/.mocha.reporters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"reporterEnabled": "spec, allure-mocha",
"allureMochaReporter": {
"outputDir": "allure-results"
}
}
26 changes: 26 additions & 0 deletions packages/sdk/.mocharc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const config = {
extension: ['ts'],
spec: 'src/**/*.spec.ts',
require: ['ts-node/register', 'isomorphic-fetch'],
loader: 'ts-node/esm',
nodeOptions: [
'experimental-specifier-resolution=node',
'loader=ts-node/esm'
],
exit: true
};

if (process.env.CI) {
console.log("Running tests in parallel");
config.parallel = true;
config.jobs = 6;
console.log("Activating allure reporting");
config.reporter = 'mocha-multi-reporters';
config.reporterOptions = {
configFile: '.mocha.reporters.json'
};
} else {
console.log("Running tests serially. To enable parallel execution update mocha config");
}

module.exports = config;
11 changes: 9 additions & 2 deletions packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
"check:lint": "eslint src *.js",
"check:spelling": "cspell \"{README.md,src/**/*.ts}\"",
"check:tsc": "tsc -p tsconfig.dev.json",
"test": "NODE_ENV=test run-s test:*",
"test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha",
"watch:test": "mocha --watch",
"prepublish": "npm run build",
"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build"
},
Expand All @@ -70,15 +73,19 @@
"@waku/proto": "^0.0.8",
"@waku/utils": "0.0.20",
"@waku/message-hash": "0.1.16",
"libp2p": "^1.8.1",
"p-event": "^6.0.1"
"libp2p": "^1.8.1"
},
"devDependencies": {
"@types/mocha": "^10.0.6",
"@types/chai": "^4.3.11",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "^5.0.5",
"@waku/build-utils": "*",
"mocha": "^10.3.0",
"sinon": "^18.0.0",
"chai": "^4.3.10",
"cspell": "^8.6.1",
"interface-datastore": "^8.2.10",
"npm-run-all": "^4.1.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/src/create/create.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type LightNode } from "@waku/interfaces";

import { CreateWakuNodeOptions, WakuNode } from "../waku.js";
import { CreateWakuNodeOptions, WakuNode } from "../waku/index.js";

import { createLibp2pAndUpdateOptions } from "./libp2p.js";

Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/src/create/libp2p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
CreateWakuNodeOptions,
DefaultPingMaxInboundStreams,
DefaultUserAgent
} from "../waku.js";
} from "../waku/index.js";

import { defaultPeerDiscoveries } from "./discovery.js";

Expand Down
4 changes: 1 addition & 3 deletions packages/sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export {

export { utf8ToBytes, bytesToUtf8 } from "@waku/utils/bytes";

export * from "./waku.js";
export * from "./waku/index.js";

export {
createLightNode,
Expand All @@ -18,8 +18,6 @@ export { wakuLightPush } from "./protocols/light_push/index.js";
export { wakuFilter } from "./protocols/filter/index.js";
export { wakuStore } from "./protocols/store/index.js";

export { waitForRemotePeer } from "./wait_for_remote_peer.js";

export * as waku from "@waku/core";
export * as utils from "@waku/utils";
export * from "@waku/interfaces";
2 changes: 2 additions & 0 deletions packages/sdk/src/waku/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./waku.js";
export { waitForRemotePeer } from "./wait_for_remote_peer.js";
Loading

0 comments on commit 75fcca4

Please sign in to comment.