Skip to content

Commit 66f4181

Browse files
committed
test: add metrics interval test
1 parent 570f2dc commit 66f4181

1 file changed

Lines changed: 128 additions & 0 deletions

File tree

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Flags: --expose-internals
2+
import { mustSucceed } from '../common/index.mjs';
3+
import assert from 'node:assert';
4+
import { setTimeout as delay } from 'node:timers/promises';
5+
import {
6+
GRPCServer,
7+
TestClient,
8+
} from '../common/nsolid-grpc-agent/index.js';
9+
10+
const INITIAL_INTERVAL = 600;
11+
const UPDATED_INTERVAL = 100;
12+
const FAST_INTERVAL_UPPER_BOUND = 300;
13+
const METRICS_TIMEOUT_MS = 1500;
14+
15+
function waitForMetricsEvent(grpcServer, timeoutMs = METRICS_TIMEOUT_MS) {
16+
return new Promise((resolve, reject) => {
17+
const timer = setTimeout(() => {
18+
grpcServer.off('metrics', onMetrics);
19+
reject(new Error(`Timed out waiting for metrics event after ${timeoutMs}ms`));
20+
}, timeoutMs);
21+
22+
function onMetrics() {
23+
clearTimeout(timer);
24+
grpcServer.off('metrics', onMetrics);
25+
resolve(Date.now());
26+
}
27+
28+
grpcServer.on('metrics', onMetrics);
29+
});
30+
}
31+
32+
async function collectMetricsEventTimestamps(grpcServer,
33+
count,
34+
timeoutMs = METRICS_TIMEOUT_MS) {
35+
const timestamps = [];
36+
const deadline = Date.now() + timeoutMs;
37+
38+
while (timestamps.length < count) {
39+
const remaining = deadline - Date.now();
40+
if (remaining <= 0) {
41+
break;
42+
}
43+
44+
timestamps.push(await waitForMetricsEvent(grpcServer, remaining));
45+
}
46+
47+
return timestamps;
48+
}
49+
50+
async function runTest({ getEnv }) {
51+
return new Promise((resolve) => {
52+
const grpcServer = new GRPCServer();
53+
grpcServer.start(mustSucceed(async (port) => {
54+
const env = getEnv(port);
55+
const opts = {
56+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
57+
env,
58+
};
59+
const child = new TestClient([], opts);
60+
const agentId = await child.id();
61+
const initialConfig = await child.config({ interval: INITIAL_INTERVAL });
62+
assert.strictEqual(initialConfig.interval, INITIAL_INTERVAL);
63+
64+
// Wait for one periodic metrics push so the next interval boundary is
65+
// well-defined before reconfiguring.
66+
await waitForMetricsEvent(grpcServer, INITIAL_INTERVAL * 3);
67+
68+
const { data, requestId } = await grpcServer.reconfigure(agentId, {
69+
interval: UPDATED_INTERVAL,
70+
});
71+
assert.strictEqual(data.msg.common.requestId, requestId);
72+
assert.strictEqual(Number(data.msg.body.interval), UPDATED_INTERVAL);
73+
74+
const updatedConfig = await child.config();
75+
assert.strictEqual(updatedConfig.interval, UPDATED_INTERVAL);
76+
77+
const timestamps = await collectMetricsEventTimestamps(grpcServer,
78+
3,
79+
METRICS_TIMEOUT_MS);
80+
assert.strictEqual(
81+
timestamps.length,
82+
3,
83+
`Expected 3 metrics events after reconfigure, got ${timestamps.length}`,
84+
);
85+
86+
const deltas = [
87+
timestamps[1] - timestamps[0],
88+
timestamps[2] - timestamps[1],
89+
];
90+
for (const delta of deltas) {
91+
assert.ok(
92+
delta < FAST_INTERVAL_UPPER_BOUND,
93+
`Expected fast metrics cadence after reconfigure, got ${delta}ms`,
94+
);
95+
}
96+
97+
await child.shutdown(0);
98+
grpcServer.close();
99+
resolve();
100+
}));
101+
});
102+
}
103+
104+
const testConfigs = [
105+
{
106+
getEnv: (port) => {
107+
return {
108+
NODE_DEBUG_NATIVE: 'nsolid_grpc_agent',
109+
NSOLID_GRPC_INSECURE: 1,
110+
NSOLID_GRPC: `localhost:${port}`,
111+
};
112+
},
113+
},
114+
{
115+
getEnv: (port) => {
116+
return {
117+
NODE_DEBUG_NATIVE: 'nsolid_grpc_agent',
118+
NSOLID_GRPC_INSECURE: 1,
119+
NSOLID_SAAS: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbtesting.localhost:${port}`,
120+
};
121+
},
122+
},
123+
];
124+
125+
for (const testConfig of testConfigs) {
126+
await runTest(testConfig);
127+
await delay(100);
128+
}

0 commit comments

Comments
 (0)