Skip to content

Commit 0b8936f

Browse files
feat: ConnectionManager extends EventEmitter & exposed on the Waku interface (& minor improvements) (#1447)
* move KeepAliveOptions to dedicated interface file * update export for KeepAlive * expose `ConnectionManager` on the waku node * update ConnectionManager test to use the exposed API * rm: only for the test
1 parent 30fcace commit 0b8936f

8 files changed

+46
-35
lines changed

packages/core/src/index.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,4 @@ export { waitForRemotePeer } from "./lib/wait_for_remote_peer.js";
2929

3030
export { ConnectionManager } from "./lib/connection_manager.js";
3131

32-
export {
33-
KeepAliveManager,
34-
KeepAliveOptions,
35-
} from "./lib/keep_alive_manager.js";
32+
export { KeepAliveManager } from "./lib/keep_alive_manager.js";

packages/core/src/lib/connection_manager.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,27 @@ import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events";
55
import {
66
ConnectionManagerOptions,
77
EPeersByDiscoveryEvents,
8+
IConnectionManager,
89
IPeersByDiscoveryEvents,
910
IRelay,
11+
KeepAliveOptions,
1012
PeersByDiscoveryResult,
1113
} from "@waku/interfaces";
1214
import { Libp2p, Tags } from "@waku/interfaces";
1315
import debug from "debug";
1416

15-
import { KeepAliveManager, KeepAliveOptions } from "./keep_alive_manager.js";
17+
import { KeepAliveManager } from "./keep_alive_manager.js";
1618

1719
const log = debug("waku:connection-manager");
1820

1921
export const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
2022
export const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
2123
export const DEFAULT_MAX_PARALLEL_DIALS = 3;
2224

23-
export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
25+
export class ConnectionManager
26+
extends EventEmitter<IPeersByDiscoveryEvents>
27+
implements IConnectionManager
28+
{
2429
private static instances = new Map<string, ConnectionManager>();
2530
private keepAliveManager: KeepAliveManager;
2631
private options: ConnectionManagerOptions;
@@ -217,7 +222,7 @@ export class ConnectionManager extends EventEmitter<IPeersByDiscoveryEvents> {
217222
}
218223
}
219224

220-
async dropConnection(peerId: PeerId): Promise<void> {
225+
private async dropConnection(peerId: PeerId): Promise<void> {
221226
try {
222227
this.keepAliveManager.stop(peerId);
223228
await this.libp2p.hangUp(peerId);

packages/core/src/lib/keep_alive_manager.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { PeerId } from "@libp2p/interface-peer-id";
22
import type { IRelay } from "@waku/interfaces";
3+
import type { KeepAliveOptions } from "@waku/interfaces";
34
import debug from "debug";
45
import type { PingService } from "libp2p/ping";
56

@@ -8,11 +9,6 @@ import { createEncoder } from "../index.js";
89
export const RelayPingContentTopic = "/relay-ping/1/ping/null";
910
const log = debug("waku:keep-alive");
1011

11-
export interface KeepAliveOptions {
12-
pingKeepAlive: number;
13-
relayKeepAlive: number;
14-
}
15-
1612
export class KeepAliveManager {
1713
private pingKeepAliveTimers: Map<string, ReturnType<typeof setInterval>>;
1814
private relayKeepAliveTimers: Map<PeerId, ReturnType<typeof setInterval>>;

packages/interfaces/src/connection_manager.ts

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { PeerId } from "@libp2p/interface-peer-id";
22
import type { Peer } from "@libp2p/interface-peer-store";
3+
import type { EventEmitter } from "@libp2p/interfaces/events";
34

45
export enum Tags {
56
BOOTSTRAP = "bootstrap",
@@ -47,3 +48,9 @@ export interface PeersByDiscoveryResult {
4748
[Tags.PEER_EXCHANGE]: Peer[];
4849
};
4950
}
51+
52+
export interface IConnectionManager
53+
extends EventEmitter<IPeersByDiscoveryEvents> {
54+
getPeersByDiscovery(): Promise<PeersByDiscoveryResult>;
55+
stop(): void;
56+
}

packages/interfaces/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export * from "./sender.js";
1212
export * from "./receiver.js";
1313
export * from "./misc.js";
1414
export * from "./libp2p.js";
15+
export * from "./keep_alive_manager.js";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface KeepAliveOptions {
2+
pingKeepAlive: number;
3+
relayKeepAlive: number;
4+
}

packages/interfaces/src/waku.ts

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Stream } from "@libp2p/interface-connection";
22
import type { PeerId } from "@libp2p/interface-peer-id";
33
import type { Multiaddr } from "@multiformats/multiaddr";
44

5+
import { IConnectionManager } from "./connection_manager.js";
56
import type { IFilter } from "./filter.js";
67
import type { Libp2p } from "./libp2p.js";
78
import type { ILightPush } from "./light_push.js";
@@ -16,6 +17,8 @@ export interface Waku {
1617
filter?: IFilter;
1718
lightPush?: ILightPush;
1819

20+
connectionManager: IConnectionManager;
21+
1922
dial(peer: PeerId | Multiaddr, protocols?: Protocols[]): Promise<Stream>;
2023

2124
start(): Promise<void>;

packages/tests/tests/connection_manager.spec.ts

+21-23
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,20 @@
11
import { CustomEvent } from "@libp2p/interfaces/events";
22
import { createSecp256k1PeerId } from "@libp2p/peer-id-factory";
3-
import { ConnectionManager, KeepAliveOptions } from "@waku/core";
43
import { EPeersByDiscoveryEvents, LightNode, Tags } from "@waku/interfaces";
54
import { createLightNode } from "@waku/sdk";
65
import { expect } from "chai";
76
import sinon, { SinonSpy, SinonStub } from "sinon";
87

98
import { delay } from "../dist/delay.js";
109

11-
const KEEP_ALIVE_OPTIONS: KeepAliveOptions = {
12-
pingKeepAlive: 0,
13-
relayKeepAlive: 5 * 1000,
14-
};
1510
const TEST_TIMEOUT = 10_000;
1611
const DELAY_MS = 1_000;
1712

1813
describe("ConnectionManager", function () {
19-
let connectionManager: ConnectionManager | undefined;
2014
let waku: LightNode;
21-
let peerId: string;
2215

2316
beforeEach(async function () {
2417
waku = await createLightNode();
25-
peerId = Math.random().toString(36).substring(7);
26-
connectionManager = ConnectionManager.create(
27-
peerId,
28-
waku.libp2p,
29-
KEEP_ALIVE_OPTIONS
30-
);
3118
});
3219

3320
afterEach(async () => {
@@ -51,15 +38,17 @@ describe("ConnectionManager", function () {
5138
});
5239

5340
const peerDiscoveryBootstrap = new Promise<boolean>((resolve) => {
54-
connectionManager!.addEventListener(
41+
waku.connectionManager.addEventListener(
5542
EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP,
5643
({ detail: receivedPeerId }) => {
5744
resolve(receivedPeerId.toString() === peerIdBootstrap.toString());
5845
}
5946
);
6047
});
6148

62-
waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerId }));
49+
waku.libp2p.dispatchEvent(
50+
new CustomEvent("peer", { detail: await createSecp256k1PeerId() })
51+
);
6352

6453
expect(await peerDiscoveryBootstrap).to.eq(true);
6554
});
@@ -77,7 +66,7 @@ describe("ConnectionManager", function () {
7766
});
7867

7968
const peerDiscoveryPeerExchange = new Promise<boolean>((resolve) => {
80-
connectionManager!.addEventListener(
69+
waku.connectionManager.addEventListener(
8170
EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE,
8271
({ detail: receivedPeerId }) => {
8372
resolve(receivedPeerId.toString() === peerIdPx.toString());
@@ -109,7 +98,7 @@ describe("ConnectionManager", function () {
10998
});
11099

111100
const peerConnectedBootstrap = new Promise<boolean>((resolve) => {
112-
connectionManager!.addEventListener(
101+
waku.connectionManager.addEventListener(
113102
EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP,
114103
({ detail: receivedPeerId }) => {
115104
resolve(receivedPeerId.toString() === peerIdBootstrap.toString());
@@ -136,7 +125,7 @@ describe("ConnectionManager", function () {
136125
});
137126

138127
const peerConnectedPeerExchange = new Promise<boolean>((resolve) => {
139-
connectionManager!.addEventListener(
128+
waku.connectionManager.addEventListener(
140129
EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE,
141130
({ detail: receivedPeerId }) => {
142131
resolve(receivedPeerId.toString() === peerIdPx.toString());
@@ -157,16 +146,25 @@ describe("ConnectionManager", function () {
157146
let dialPeerStub: SinonStub;
158147
let getConnectionsStub: SinonStub;
159148
let getTagNamesForPeerStub: SinonStub;
149+
let waku: LightNode;
160150

161-
afterEach(() => {
151+
this.beforeEach(async function () {
152+
waku = await createLightNode();
153+
});
154+
155+
afterEach(async () => {
156+
await waku.stop();
162157
sinon.restore();
163158
});
164159

165160
describe("attemptDial method", function () {
166161
let attemptDialSpy: SinonSpy;
167162

168163
beforeEach(function () {
169-
attemptDialSpy = sinon.spy(connectionManager as any, "attemptDial");
164+
attemptDialSpy = sinon.spy(
165+
waku.connectionManager as any,
166+
"attemptDial"
167+
);
170168
});
171169

172170
afterEach(function () {
@@ -196,14 +194,14 @@ describe("ConnectionManager", function () {
196194
describe("dialPeer method", function () {
197195
beforeEach(function () {
198196
getConnectionsStub = sinon.stub(
199-
(connectionManager as any).libp2p,
197+
(waku.connectionManager as any).libp2p,
200198
"getConnections"
201199
);
202200
getTagNamesForPeerStub = sinon.stub(
203-
connectionManager as any,
201+
waku.connectionManager as any,
204202
"getTagNamesForPeer"
205203
);
206-
dialPeerStub = sinon.stub(connectionManager as any, "dialPeer");
204+
dialPeerStub = sinon.stub(waku.connectionManager as any, "dialPeer");
207205
});
208206

209207
afterEach(function () {

0 commit comments

Comments
 (0)