2024-10-09 00:43:34 +02:00
|
|
|
import { HealthStatus, IWaku, LightNode, Protocols } from "@waku/interfaces";
|
2024-07-27 18:27:54 +05:30
|
|
|
import { createLightNode } from "@waku/sdk";
|
2024-08-01 14:33:42 +05:30
|
|
|
import { shardInfoToPubsubTopics } from "@waku/utils";
|
2024-07-27 18:27:54 +05:30
|
|
|
import { expect } from "chai";
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
afterEachCustom,
|
|
|
|
|
runMultipleNodes,
|
|
|
|
|
ServiceNode,
|
|
|
|
|
ServiceNodesFleet
|
2024-09-13 14:18:29 +05:30
|
|
|
} from "../../src/index.js";
|
2024-07-27 18:27:54 +05:30
|
|
|
|
2024-08-05 15:52:58 +05:30
|
|
|
import {
|
|
|
|
|
messagePayload,
|
|
|
|
|
TestDecoder,
|
|
|
|
|
TestEncoder,
|
|
|
|
|
TestShardInfo
|
2024-09-13 14:18:29 +05:30
|
|
|
} from "./utils.js";
|
2024-07-27 18:27:54 +05:30
|
|
|
|
|
|
|
|
describe("Node Health Status Matrix Tests", function () {
|
|
|
|
|
let waku: LightNode;
|
|
|
|
|
let serviceNodes: ServiceNode[];
|
|
|
|
|
|
|
|
|
|
afterEachCustom(this, async function () {
|
|
|
|
|
if (waku) {
|
|
|
|
|
await waku.stop();
|
|
|
|
|
}
|
|
|
|
|
if (serviceNodes) {
|
|
|
|
|
await Promise.all(serviceNodes.map((node) => node.stop()));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const peerCounts = [0, 1, 2, 3];
|
|
|
|
|
|
|
|
|
|
peerCounts.forEach((lightPushPeers) => {
|
|
|
|
|
peerCounts.forEach((filterPeers) => {
|
2024-10-04 10:50:58 +02:00
|
|
|
it(`LightPush: ${lightPushPeers} peers, Filter: ${filterPeers} peers`, async function () {
|
2024-07-27 18:27:54 +05:30
|
|
|
this.timeout(10_000);
|
|
|
|
|
|
|
|
|
|
[waku, serviceNodes] = await setupTestEnvironment(
|
|
|
|
|
this.ctx,
|
|
|
|
|
lightPushPeers,
|
|
|
|
|
filterPeers
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (lightPushPeers > 0) {
|
|
|
|
|
await waku.lightPush.send(TestEncoder, messagePayload, {
|
|
|
|
|
forceUseAllPeers: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (filterPeers > 0) {
|
2024-08-05 15:52:58 +05:30
|
|
|
await waku.filter.subscribe([TestDecoder], () => {});
|
2024-07-27 18:27:54 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const lightPushHealth = waku.health.getProtocolStatus(
|
|
|
|
|
Protocols.LightPush
|
|
|
|
|
);
|
|
|
|
|
const filterHealth = waku.health.getProtocolStatus(Protocols.Filter);
|
|
|
|
|
|
2024-10-04 10:50:58 +02:00
|
|
|
lightPushPeers = await getPeerCounBasedOnConnections(
|
|
|
|
|
waku,
|
|
|
|
|
waku.lightPush.protocol.multicodec
|
|
|
|
|
);
|
2024-07-27 18:27:54 +05:30
|
|
|
expect(lightPushHealth?.status).to.equal(
|
|
|
|
|
getExpectedProtocolStatus(lightPushPeers)
|
|
|
|
|
);
|
|
|
|
|
expect(filterHealth?.status).to.equal(
|
|
|
|
|
getExpectedProtocolStatus(filterPeers)
|
|
|
|
|
);
|
|
|
|
|
|
2024-10-04 10:50:58 +02:00
|
|
|
const expectedHealth = getExpectedNodeHealth(
|
|
|
|
|
lightPushPeers,
|
|
|
|
|
filterPeers
|
|
|
|
|
);
|
2024-07-27 18:27:54 +05:30
|
|
|
const nodeHealth = waku.health.getHealthStatus();
|
|
|
|
|
expect(nodeHealth).to.equal(expectedHealth);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function getExpectedProtocolStatus(peerCount: number): HealthStatus {
|
|
|
|
|
if (peerCount === 0) return HealthStatus.Unhealthy;
|
|
|
|
|
if (peerCount === 1) return HealthStatus.MinimallyHealthy;
|
|
|
|
|
return HealthStatus.SufficientlyHealthy;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-04 10:50:58 +02:00
|
|
|
async function getPeerCounBasedOnConnections(
|
2024-10-09 00:43:34 +02:00
|
|
|
waku: IWaku,
|
2024-10-04 10:50:58 +02:00
|
|
|
codec: string
|
|
|
|
|
): Promise<number> {
|
|
|
|
|
const peerIDs = waku.libp2p
|
|
|
|
|
.getConnections()
|
|
|
|
|
.map((c) => c.remotePeer.toString());
|
|
|
|
|
|
|
|
|
|
const peers = await waku.libp2p.peerStore.all();
|
|
|
|
|
|
|
|
|
|
return peers
|
|
|
|
|
.filter((peer) => peerIDs.includes(peer.id.toString()))
|
|
|
|
|
.filter((peer) => peer.protocols.includes(codec)).length;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-27 18:27:54 +05:30
|
|
|
function getExpectedNodeHealth(
|
|
|
|
|
lightPushPeers: number,
|
|
|
|
|
filterPeers: number
|
|
|
|
|
): HealthStatus {
|
|
|
|
|
if (lightPushPeers === 0 || filterPeers === 0) {
|
|
|
|
|
return HealthStatus.Unhealthy;
|
|
|
|
|
} else if (lightPushPeers === 1 || filterPeers === 1) {
|
|
|
|
|
return HealthStatus.MinimallyHealthy;
|
|
|
|
|
} else {
|
|
|
|
|
return HealthStatus.SufficientlyHealthy;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function runNodeWithProtocols(
|
|
|
|
|
lightPush: boolean,
|
|
|
|
|
filter: boolean
|
|
|
|
|
): Promise<ServiceNode> {
|
|
|
|
|
const serviceNode = new ServiceNode(`node-${Date.now()}`);
|
|
|
|
|
await serviceNode.start({
|
|
|
|
|
lightpush: lightPush,
|
|
|
|
|
filter: filter,
|
2024-08-01 14:33:42 +05:30
|
|
|
relay: true,
|
|
|
|
|
clusterId: TestShardInfo.clusterId,
|
|
|
|
|
pubsubTopic: shardInfoToPubsubTopics(TestShardInfo)
|
2024-07-27 18:27:54 +05:30
|
|
|
});
|
|
|
|
|
return serviceNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function setupTestEnvironment(
|
|
|
|
|
context: Mocha.Context,
|
|
|
|
|
lightPushPeers: number,
|
|
|
|
|
filterPeers: number
|
|
|
|
|
): Promise<[LightNode, ServiceNode[]]> {
|
|
|
|
|
let commonPeers: number;
|
|
|
|
|
if (lightPushPeers === 0 || filterPeers === 0) {
|
|
|
|
|
commonPeers = Math.max(lightPushPeers, filterPeers);
|
|
|
|
|
} else {
|
|
|
|
|
commonPeers = Math.min(lightPushPeers, filterPeers);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let waku: LightNode;
|
|
|
|
|
const serviceNodes: ServiceNode[] = [];
|
|
|
|
|
let serviceNodesFleet: ServiceNodesFleet;
|
|
|
|
|
|
|
|
|
|
if (commonPeers > 0) {
|
|
|
|
|
[serviceNodesFleet, waku] = await runMultipleNodes(
|
|
|
|
|
context,
|
|
|
|
|
TestShardInfo,
|
|
|
|
|
{ filter: true, lightpush: true },
|
|
|
|
|
undefined,
|
|
|
|
|
commonPeers
|
|
|
|
|
);
|
|
|
|
|
serviceNodes.push(...serviceNodesFleet.nodes);
|
|
|
|
|
} else {
|
2024-08-13 05:23:20 +05:30
|
|
|
waku = await createLightNode({ networkConfig: TestShardInfo });
|
2024-07-27 18:27:54 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create additional LightPush nodes if needed
|
|
|
|
|
for (let i = commonPeers; i < lightPushPeers; i++) {
|
|
|
|
|
const node = await runNodeWithProtocols(true, false);
|
|
|
|
|
serviceNodes.push(node);
|
|
|
|
|
await waku.dial(await node.getMultiaddrWithId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create additional Filter nodes if needed
|
|
|
|
|
for (let i = commonPeers; i < filterPeers; i++) {
|
|
|
|
|
const node = await runNodeWithProtocols(false, true);
|
|
|
|
|
serviceNodes.push(node);
|
|
|
|
|
await waku.dial(await node.getMultiaddrWithId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [waku, serviceNodes];
|
|
|
|
|
}
|