Skip to content

test(mongo): add join-churn write-load test - #81

Open
Harxhit wants to merge 1 commit into
mainfrom
test/mongo-write-load
Open

test(mongo): add join-churn write-load test#81
Harxhit wants to merge 1 commit into
mainfrom
test/mongo-write-load

Conversation

@Harxhit

@Harxhit Harxhit commented Aug 27, 2026

Copy link
Copy Markdown
Owner

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.


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

  • Each join triggers a Viewer insert plus a LiveRoom $inc update, so churn sustains write-heavy load.
  • A worker pool runs connect → join → disconnect cycles and reports join-ack percentiles plus joins/sec.
  • MONGO-WRITE-LOAD.md documents the writes triggered per join, Mongo-side sampling commands, and interpretation guidance.

Written for commit a68cb9d. Summary will update on new commits.

Review in cubic

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>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cd82389f-563c-4b36-b62f-fe6e38594dc0


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
17.3% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Suggested change
node /tmp/cs-tests/mongo-write-load/mongo-write-load.js \
node load-test/mongo-write-load.js \

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant