Skip to content

Commit eeca0e3

Browse files
committed
chore: add simple local stress script (#3013)
1 parent 14b0429 commit eeca0e3

File tree

7 files changed

+157
-10
lines changed

7 files changed

+157
-10
lines changed

docker/dev-host/docker-compose.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ services:
4747
network_mode: host
4848
postgres:
4949
restart: unless-stopped
50-
image: postgres:16-alpine
50+
image: postgres:17-alpine
5151
environment:
5252
- POSTGRES_USER=postgres
5353
- POSTGRES_PASSWORD=postgres
@@ -167,6 +167,7 @@ services:
167167
restart: unless-stopped
168168
environment:
169169
- RIVET_ENDPOINT=http://127.0.0.1:6420
170+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
170171
stop_grace_period: 4s
171172
depends_on:
172173
rivet-engine:

docker/dev-multidc-multinode/docker-compose.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ services:
5454
condition: service_healthy
5555
postgres-dc-a:
5656
restart: unless-stopped
57-
image: postgres:16-alpine
57+
image: postgres:17-alpine
5858
environment:
5959
- POSTGRES_USER=postgres
6060
- POSTGRES_PASSWORD=postgres
@@ -282,6 +282,7 @@ services:
282282
restart: unless-stopped
283283
environment:
284284
- RIVET_ENDPOINT=http://rivet-engine-dc-a-0:6420
285+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
285286
stop_grace_period: 4s
286287
ports:
287288
- '5050:5050'
@@ -298,6 +299,7 @@ services:
298299
restart: unless-stopped
299300
environment:
300301
- RIVET_ENDPOINT=http://rivet-engine-dc-a-0:6420
302+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
301303
stop_grace_period: 4s
302304
depends_on:
303305
rivet-engine-dc-a-0:
@@ -312,6 +314,7 @@ services:
312314
restart: unless-stopped
313315
environment:
314316
- RIVET_ENDPOINT=http://rivet-engine-dc-a-0:6420
317+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
315318
stop_grace_period: 4s
316319
depends_on:
317320
rivet-engine-dc-a-0:
@@ -320,7 +323,7 @@ services:
320323
- rivet-network-dc-a
321324
postgres-dc-b:
322325
restart: unless-stopped
323-
image: postgres:16-alpine
326+
image: postgres:17-alpine
324327
environment:
325328
- POSTGRES_USER=postgres
326329
- POSTGRES_PASSWORD=postgres
@@ -544,6 +547,7 @@ services:
544547
restart: unless-stopped
545548
environment:
546549
- RIVET_ENDPOINT=http://rivet-engine-dc-b-0:6420
550+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
547551
stop_grace_period: 4s
548552
depends_on:
549553
rivet-engine-dc-b-0:
@@ -558,6 +562,7 @@ services:
558562
restart: unless-stopped
559563
environment:
560564
- RIVET_ENDPOINT=http://rivet-engine-dc-b-0:6420
565+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
561566
stop_grace_period: 4s
562567
depends_on:
563568
rivet-engine-dc-b-0:
@@ -572,6 +577,7 @@ services:
572577
restart: unless-stopped
573578
environment:
574579
- RIVET_ENDPOINT=http://rivet-engine-dc-b-0:6420
580+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
575581
stop_grace_period: 4s
576582
depends_on:
577583
rivet-engine-dc-b-0:
@@ -580,7 +586,7 @@ services:
580586
- rivet-network-dc-b
581587
postgres-dc-c:
582588
restart: unless-stopped
583-
image: postgres:16-alpine
589+
image: postgres:17-alpine
584590
environment:
585591
- POSTGRES_USER=postgres
586592
- POSTGRES_PASSWORD=postgres
@@ -804,6 +810,7 @@ services:
804810
restart: unless-stopped
805811
environment:
806812
- RIVET_ENDPOINT=http://rivet-engine-dc-c-0:6420
813+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
807814
stop_grace_period: 4s
808815
depends_on:
809816
rivet-engine-dc-c-0:
@@ -818,6 +825,7 @@ services:
818825
restart: unless-stopped
819826
environment:
820827
- RIVET_ENDPOINT=http://rivet-engine-dc-c-0:6420
828+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
821829
stop_grace_period: 4s
822830
depends_on:
823831
rivet-engine-dc-c-0:
@@ -832,6 +840,7 @@ services:
832840
restart: unless-stopped
833841
environment:
834842
- RIVET_ENDPOINT=http://rivet-engine-dc-c-0:6420
843+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
835844
stop_grace_period: 4s
836845
depends_on:
837846
rivet-engine-dc-c-0:

docker/dev-multidc/docker-compose.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ services:
5454
condition: service_healthy
5555
postgres-dc-a:
5656
restart: unless-stopped
57-
image: postgres:16-alpine
57+
image: postgres:17-alpine
5858
environment:
5959
- POSTGRES_USER=postgres
6060
- POSTGRES_PASSWORD=postgres
@@ -198,6 +198,7 @@ services:
198198
restart: unless-stopped
199199
environment:
200200
- RIVET_ENDPOINT=http://rivet-engine-dc-a:6420
201+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
201202
stop_grace_period: 4s
202203
ports:
203204
- '5050:5050'
@@ -208,7 +209,7 @@ services:
208209
- rivet-network-dc-a
209210
postgres-dc-b:
210211
restart: unless-stopped
211-
image: postgres:16-alpine
212+
image: postgres:17-alpine
212213
environment:
213214
- POSTGRES_USER=postgres
214215
- POSTGRES_PASSWORD=postgres
@@ -348,6 +349,7 @@ services:
348349
restart: unless-stopped
349350
environment:
350351
- RIVET_ENDPOINT=http://rivet-engine-dc-b:6420
352+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
351353
stop_grace_period: 4s
352354
depends_on:
353355
rivet-engine-dc-b:
@@ -356,7 +358,7 @@ services:
356358
- rivet-network-dc-b
357359
postgres-dc-c:
358360
restart: unless-stopped
359-
image: postgres:16-alpine
361+
image: postgres:17-alpine
360362
environment:
361363
- POSTGRES_USER=postgres
362364
- POSTGRES_PASSWORD=postgres
@@ -496,6 +498,7 @@ services:
496498
restart: unless-stopped
497499
environment:
498500
- RIVET_ENDPOINT=http://rivet-engine-dc-c:6420
501+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
499502
stop_grace_period: 4s
500503
depends_on:
501504
rivet-engine-dc-c:

docker/dev-multinode/docker-compose.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ services:
5252
condition: service_healthy
5353
postgres:
5454
restart: unless-stopped
55-
image: postgres:16-alpine
55+
image: postgres:17-alpine
5656
environment:
5757
- POSTGRES_USER=postgres
5858
- POSTGRES_PASSWORD=postgres
@@ -265,6 +265,7 @@ services:
265265
restart: unless-stopped
266266
environment:
267267
- RIVET_ENDPOINT=http://rivet-engine-0:6420
268+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
268269
stop_grace_period: 4s
269270
ports:
270271
- '5050:5050'
@@ -281,6 +282,7 @@ services:
281282
restart: unless-stopped
282283
environment:
283284
- RIVET_ENDPOINT=http://rivet-engine-0:6420
285+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
284286
stop_grace_period: 4s
285287
depends_on:
286288
rivet-engine-0:
@@ -295,6 +297,7 @@ services:
295297
restart: unless-stopped
296298
environment:
297299
- RIVET_ENDPOINT=http://rivet-engine-0:6420
300+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
298301
stop_grace_period: 4s
299302
depends_on:
300303
rivet-engine-0:

docker/dev/docker-compose.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ services:
5252
condition: service_healthy
5353
postgres:
5454
restart: unless-stopped
55-
image: postgres:16-alpine
55+
image: postgres:17-alpine
5656
environment:
5757
- POSTGRES_USER=postgres
5858
- POSTGRES_PASSWORD=postgres
@@ -189,6 +189,7 @@ services:
189189
restart: unless-stopped
190190
environment:
191191
- RIVET_ENDPOINT=http://rivet-engine:6420
192+
- RIVET_RUNNER_TOTAL_SLOTS=1000000
192193
stop_grace_period: 4s
193194
ports:
194195
- '5050:5050'

docker/template/src/docker-compose.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export function generateDockerCompose(context: TemplateContext) {
148148
);
149149
services[postgresServiceName] = {
150150
restart: "unless-stopped",
151-
image: "postgres:16-alpine",
151+
image: "postgres:17-alpine",
152152
environment: [
153153
"POSTGRES_USER=postgres",
154154
"POSTGRES_PASSWORD=postgres",
@@ -325,6 +325,7 @@ export function generateDockerCompose(context: TemplateContext) {
325325
restart: "unless-stopped",
326326
environment: [
327327
`RIVET_ENDPOINT=http://${context.getServiceHost("rivet-engine", datacenter.name, 0)}:6420`,
328+
`RIVET_RUNNER_TOTAL_SLOTS=1000000`,
328329
],
329330
stop_grace_period: "4s",
330331
ports: isPrimary && i === 0 ? [`5050:5050`] : undefined,

scripts/tests/actor_stress.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#!/usr/bin/env tsx
2+
3+
import { RIVET_ENDPOINT, createActor, destroyActor } from "./utils";
4+
5+
const PARALLEL_WORKERS = 20;
6+
const TEST_DURATION_MS = 15000;
7+
8+
let activeActors: Set<string> = new Set();
9+
let shouldExit = false;
10+
let completedLoops = 0;
11+
let totalLoopDuration = 0;
12+
let startTime = Date.now();
13+
14+
async function actorLoop(workerId: number): Promise<void> {
15+
while (!shouldExit) {
16+
const loopStart = Date.now();
17+
let actorId: string | undefined;
18+
19+
try {
20+
const actorResponse = await createActor("default", "test-runner");
21+
actorId = actorResponse.actor.actor_id;
22+
activeActors.add(actorId);
23+
24+
const actorPingResponse = await fetch(`${RIVET_ENDPOINT}/ping`, {
25+
method: "GET",
26+
headers: {
27+
"X-Rivet-Target": "actor",
28+
"X-Rivet-Actor": actorId,
29+
},
30+
});
31+
32+
if (!actorPingResponse.ok) {
33+
throw new Error(`Ping failed: ${actorPingResponse.status}`);
34+
}
35+
36+
await destroyActor("default", actorId);
37+
activeActors.delete(actorId);
38+
39+
const loopDuration = Date.now() - loopStart;
40+
completedLoops++;
41+
totalLoopDuration += loopDuration;
42+
43+
} catch (error) {
44+
console.error(`Worker ${workerId} error:`, error);
45+
if (actorId) {
46+
try {
47+
await destroyActor("default", actorId);
48+
activeActors.delete(actorId);
49+
} catch {}
50+
}
51+
}
52+
}
53+
}
54+
55+
function printProgress() {
56+
const elapsed = (Date.now() - startTime) / 1000;
57+
const actorsPerSecond = completedLoops / elapsed;
58+
const avgLoopDuration = completedLoops > 0 ? totalLoopDuration / completedLoops : 0;
59+
60+
process.stdout.write(
61+
`\rElapsed: ${elapsed.toFixed(1)}s | ` +
62+
`Completed: ${completedLoops} | ` +
63+
`Actors/sec: ${actorsPerSecond.toFixed(2)} | ` +
64+
`Avg loop: ${avgLoopDuration.toFixed(0)}ms | ` +
65+
`Active: ${activeActors.size}`
66+
);
67+
}
68+
69+
async function cleanup() {
70+
console.log("\n\nCleaning up active actors...");
71+
shouldExit = true;
72+
73+
const cleanupPromises = Array.from(activeActors).map(async (actorId) => {
74+
try {
75+
await destroyActor("default", actorId);
76+
console.log(`Cleaned up actor: ${actorId}`);
77+
} catch (error) {
78+
console.error(`Failed to cleanup actor ${actorId}:`, error);
79+
}
80+
});
81+
82+
await Promise.all(cleanupPromises);
83+
console.log("Cleanup complete");
84+
}
85+
86+
async function main() {
87+
console.log(`Starting actor stress test...`);
88+
console.log(`Running ${PARALLEL_WORKERS} workers for ${TEST_DURATION_MS / 1000} seconds\n`);
89+
90+
process.on("SIGINT", async () => {
91+
console.log("\nReceived SIGINT");
92+
await cleanup();
93+
process.exit(0);
94+
});
95+
96+
process.on("SIGTERM", async () => {
97+
console.log("\nReceived SIGTERM");
98+
await cleanup();
99+
process.exit(0);
100+
});
101+
102+
const progressInterval = setInterval(printProgress, 100);
103+
104+
const workers = Array.from({ length: PARALLEL_WORKERS }, (_, i) => actorLoop(i));
105+
106+
setTimeout(async () => {
107+
shouldExit = true;
108+
clearInterval(progressInterval);
109+
printProgress();
110+
console.log("\n\nTest duration complete, waiting for workers to finish...");
111+
await Promise.all(workers);
112+
113+
const elapsed = (Date.now() - startTime) / 1000;
114+
console.log("\n=== Final Results ===");
115+
console.log(`Total runtime: ${elapsed.toFixed(2)}s`);
116+
console.log(`Total completed loops: ${completedLoops}`);
117+
console.log(`Average actors/second: ${(completedLoops / elapsed).toFixed(2)}`);
118+
console.log(`Average loop duration: ${(totalLoopDuration / completedLoops).toFixed(0)}ms`);
119+
120+
process.exit(0);
121+
}, TEST_DURATION_MS);
122+
123+
await Promise.all(workers);
124+
}
125+
126+
main().catch((error) => {
127+
console.error("Fatal error:", error);
128+
cleanup().then(() => process.exit(1));
129+
});

0 commit comments

Comments
 (0)