test(mongo): add join-churn write-load test - #81
Conversation
socket.io-client test that drives high join/leave churn — each join triggers a Viewer insert + a LiveRoom \$inc — to measure how join-ack latency degrades under MongoDB write pressure. - load-test/mongo-write-load.js — worker-pool join/leave churn; join-ack percentiles + joins/sec - load-test/results/MONGO-WRITE-LOAD.md — writes triggered, mongostat/serverStatus sampling Authored by Claude (Anthropic) via Claude Code. Not executed against a live backend — results are placeholders, not fabricated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
There was a problem hiding this comment.
5 issues found across 2 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="load-test/results/MONGO-WRITE-LOAD.md">
<violation number="1" location="load-test/results/MONGO-WRITE-LOAD.md:31">
P2: The test's central premise is wrong: join-ack latency cannot reflect Mongo write pressure. In registerViewer.handler.ts the ack({success:true}) is emitted before Viewer.create and LiveRoom.updateOne are dispatched, and both are non-awaited `void` calls (fire-and-forget). joinAsViewer only does Redis work, so ack latency measures the Redis/signaling join path, not DB write time. Consequently the Interpretation guidance (p99 climbing => Mongo write ceiling) is invalid — this test cannot detect a DB write bottleneck via ack latency. Either have the server await the writes before acking, or reframe the doc to measure client-observed throughput / server-side write duration instead of ack latency.</violation>
<violation number="2" location="load-test/results/MONGO-WRITE-LOAD.md:57">
P3: The documented run command points to /tmp/cs-tests/mongo-write-load/mongo-write-load.js, but the script lives at load-test/mongo-write-load.js. Running the command verbatim fails because that path does not exist, and it contradicts the instruction to run from the load-test folder. Use the in-repo path so the command works as written.</violation>
</file>
<file name="load-test/mongo-write-load.js">
<violation number="1" location="load-test/mongo-write-load.js:37">
P2: When `--timeout` is non-numeric or negative, the run reports mass timeouts instead of rejecting the configuration, while invalid hold/ramp values silently disable those controls. Validate every duration as a finite non-negative integer and require integer counts.</violation>
<violation number="2" location="load-test/mongo-write-load.js:172">
P2: With the default `HOLD_MS=0`, this disconnect races the server’s fire-and-forget persistence. Under write pressure cleanup can miss the insert or reorder the counter decrement, leaving orphan viewer documents and invalidating the churn results; wait for a persistence-complete barrier before disconnecting.</violation>
<violation number="3" location="load-test/mongo-write-load.js:282">
P2: The reported `~2 * joins/sec` is not the total Mongo write rate for this churn, because disconnect cleanup adds a delete and a counter update. Label this as join-write rate or include cleanup operations before comparing it with `mongostat`.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| session-lifecycle persistence on join/leave. High connect/join/disconnect churn therefore | ||
| produces sustained, mostly write-heavy DB load — which is what this generator is for. | ||
|
|
||
| The client measures **`joinRoom` ack latency** (the round trip the real viewer feels) and |
There was a problem hiding this comment.
P2: The test's central premise is wrong: join-ack latency cannot reflect Mongo write pressure. In registerViewer.handler.ts the ack({success:true}) is emitted before Viewer.create and LiveRoom.updateOne are dispatched, and both are non-awaited void calls (fire-and-forget). joinAsViewer only does Redis work, so ack latency measures the Redis/signaling join path, not DB write time. Consequently the Interpretation guidance (p99 climbing => Mongo write ceiling) is invalid — this test cannot detect a DB write bottleneck via ack latency. Either have the server await the writes before acking, or reframe the doc to measure client-observed throughput / server-side write duration instead of ack latency.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/results/MONGO-WRITE-LOAD.md, line 31:
<comment>The test's central premise is wrong: join-ack latency cannot reflect Mongo write pressure. In registerViewer.handler.ts the ack({success:true}) is emitted before Viewer.create and LiveRoom.updateOne are dispatched, and both are non-awaited `void` calls (fire-and-forget). joinAsViewer only does Redis work, so ack latency measures the Redis/signaling join path, not DB write time. Consequently the Interpretation guidance (p99 climbing => Mongo write ceiling) is invalid — this test cannot detect a DB write bottleneck via ack latency. Either have the server await the writes before acking, or reframe the doc to measure client-observed throughput / server-side write duration instead of ack latency.</comment>
<file context>
@@ -0,0 +1,179 @@
+session-lifecycle persistence on join/leave. High connect/join/disconnect churn therefore
+produces sustained, mostly write-heavy DB load — which is what this generator is for.
+
+The client measures **`joinRoom` ack latency** (the round trip the real viewer feels) and
+reports its distribution alongside join throughput. Because throughput of successful joins
+maps directly onto insert+update volume, joins/sec is a proxy for write pressure.
</file context>
|
|
||
| console.log( | ||
| `throughput: ${joinsPerSec.toFixed(1)} joins/sec ` + | ||
| `(~${(joinsPerSec * 2).toFixed(1)} Mongo writes/sec: insert + $inc)` |
There was a problem hiding this comment.
P2: The reported ~2 * joins/sec is not the total Mongo write rate for this churn, because disconnect cleanup adds a delete and a counter update. Label this as join-write rate or include cleanup operations before comparing it with mongostat.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/mongo-write-load.js, line 282:
<comment>The reported `~2 * joins/sec` is not the total Mongo write rate for this churn, because disconnect cleanup adds a delete and a counter update. Label this as join-write rate or include cleanup operations before comparing it with `mongostat`.</comment>
<file context>
@@ -0,0 +1,299 @@
+
+ console.log(
+ `throughput: ${joinsPerSec.toFixed(1)} joins/sec ` +
+ `(~${(joinsPerSec * 2).toFixed(1)} Mongo writes/sec: insert + $inc)`
+ );
+
</file context>
| results.errors.push( | ||
| `cycle ${cycleIdx}: connect: ${err?.message || String(err)}` | ||
| ); | ||
| socket.disconnect(); |
There was a problem hiding this comment.
P2: With the default HOLD_MS=0, this disconnect races the server’s fire-and-forget persistence. Under write pressure cleanup can miss the insert or reorder the counter decrement, leaving orphan viewer documents and invalidating the churn results; wait for a persistence-complete barrier before disconnecting.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/mongo-write-load.js, line 172:
<comment>With the default `HOLD_MS=0`, this disconnect races the server’s fire-and-forget persistence. Under write pressure cleanup can miss the insert or reorder the counter decrement, leaving orphan viewer documents and invalidating the churn results; wait for a persistence-complete barrier before disconnecting.</comment>
<file context>
@@ -0,0 +1,299 @@
+ results.errors.push(
+ `cycle ${cycleIdx}: connect: ${err?.message || String(err)}`
+ );
+ socket.disconnect();
+ return;
+ }
</file context>
| const CONCURRENCY = parseInt(arg("concurrency", "50"), 10); | ||
| const HOLD_MS = parseInt(arg("holdMs", "0"), 10); | ||
| const RAMP_MS = parseInt(arg("rampMs", "0"), 10); | ||
| const ACK_TIMEOUT_MS = parseInt(arg("timeout", "8000"), 10); |
There was a problem hiding this comment.
P2: When --timeout is non-numeric or negative, the run reports mass timeouts instead of rejecting the configuration, while invalid hold/ramp values silently disable those controls. Validate every duration as a finite non-negative integer and require integer counts.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/mongo-write-load.js, line 37:
<comment>When `--timeout` is non-numeric or negative, the run reports mass timeouts instead of rejecting the configuration, while invalid hold/ramp values silently disable those controls. Validate every duration as a finite non-negative integer and require integer counts.</comment>
<file context>
@@ -0,0 +1,299 @@
+const CONCURRENCY = parseInt(arg("concurrency", "50"), 10);
+const HOLD_MS = parseInt(arg("holdMs", "0"), 10);
+const RAMP_MS = parseInt(arg("rampMs", "0"), 10);
+const ACK_TIMEOUT_MS = parseInt(arg("timeout", "8000"), 10);
+
+// ---------- arg validation ----------
</file context>
|
|
||
| ```bash | ||
| # from a directory where socket.io-client resolves (e.g. the load-test/ folder) | ||
| node /tmp/cs-tests/mongo-write-load/mongo-write-load.js \ |
There was a problem hiding this comment.
P3: The documented run command points to /tmp/cs-tests/mongo-write-load/mongo-write-load.js, but the script lives at load-test/mongo-write-load.js. Running the command verbatim fails because that path does not exist, and it contradicts the instruction to run from the load-test folder. Use the in-repo path so the command works as written.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At load-test/results/MONGO-WRITE-LOAD.md, line 57:
<comment>The documented run command points to /tmp/cs-tests/mongo-write-load/mongo-write-load.js, but the script lives at load-test/mongo-write-load.js. Running the command verbatim fails because that path does not exist, and it contradicts the instruction to run from the load-test folder. Use the in-repo path so the command works as written.</comment>
<file context>
@@ -0,0 +1,179 @@
+
+```bash
+# from a directory where socket.io-client resolves (e.g. the load-test/ folder)
+node /tmp/cs-tests/mongo-write-load/mongo-write-load.js \
+ --url http://localhost:3000 \
+ --token "$ACCESS_TOKEN" \
</file context>
| node /tmp/cs-tests/mongo-write-load/mongo-write-load.js \ | |
| node load-test/mongo-write-load.js \ |


socket.io-client test that drives high join/leave churn — each join triggers a Viewer insert + a LiveRoom $inc — to measure how join-ack latency degrades under MongoDB write pressure.
Authored by Claude (Anthropic) via Claude Code. Not executed against a live backend — results are placeholders, not fabricated.
Summary by cubic
Adds a Socket.IO load generator that drives high join/leave churn to measure how join-ack latency degrades under MongoDB write pressure. The test hasn't been run against a live backend, so results in the results doc are placeholders.
What the test does
Viewerinsert plus aLiveRoom$incupdate, so churn sustains write-heavy load.MONGO-WRITE-LOAD.mddocuments the writes triggered per join, Mongo-side sampling commands, and interpretation guidance.Written for commit a68cb9d. Summary will update on new commits.