Skip to content

fix: prevent status update flooding from stderr#172

Open
anchallll02 wants to merge 1 commit into
SamXop123:mainfrom
anchallll02:fix-stderr-status-flood
Open

fix: prevent status update flooding from stderr#172
anchallll02 wants to merge 1 commit into
SamXop123:mainfrom
anchallll02:fix-stderr-status-flood

Conversation

@anchallll02
Copy link
Copy Markdown

@anchallll02 anchallll02 commented Jun 2, 2026

Fix: Prevent status update flooding from stderr

Changes

  • Added deduplication in updateStatus to avoid identical state updates
  • Added 1000ms throttle for stderr-based UI updates
  • Kept console.error for real-time debugging logs

Impact

  • Prevents UI flickering caused by stderr spam
  • Improves performance during helper error floods

Summary by CodeRabbit

  • Bug Fixes

    • Eliminated duplicate status notifications from repeated updates.
    • Improved error handling to warn instead of silently failing on parsing issues.
  • Improvements

    • Enhanced debugging capabilities with better logging of diagnostic information.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 2, 2026

@anchallll02 is attempting to deploy a commit to the Dot_NotSam's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

createAudioBridge now prevents redundant status updates by deduplicating identical { mode, reason } payloads and throttles stderr-driven status changes to once per 1000ms. Helper stdout parsing buffers incoming data, splits into lines, and gates the ready state transition. Helper stderr is logged for debugging, and invalid JSON messages emit warnings instead of silent failures.

Changes

Helper Communication & Error Handling

Layer / File(s) Summary
Status update throttling and deduplication
audioBridge.js
lastStatusUpdate tracks the last throttle boundary; updateStatus skips callback invocation when mode and reason match the current helperStatus, eliminating duplicate state notifications and establishing the throttle mechanism for stderr updates.
Helper stdout, stderr, and JSON parsing
audioBridge.js
Stdout buffering and line-by-line processing with blank-line filtering and ready-state gating; JSON parsing emits console warnings and continues on errors; stderr output is logged to console.error and throttled helper-error status updates reuse the lastStatusUpdate mechanism; minor formatting adjustments at lines 130 and 170.

🎯 2 (Simple) | ⏱️ ~12 minutes

🐰 A bridge grows stronger with patient throttling,
No spam of status, no state from recoil—
Each message flows once per thousand bright ticks,
And when JSON fails, we warn with a hop! 🎵

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly matches the main objective of the PR: preventing status update flooding from stderr through throttling and deduplication mechanisms.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@audioBridge.js`:
- Around line 68-76: The handler attached to helperProcess.stdout.on("data")
currently sets helperReady and calls updateStatus prematurely on the first
chunk; change it so helperReady = true and updateStatus({mode: "helper", reason:
"C# helper process connected."}) are executed only after you successfully parse
a complete helper JSON message (use your existing buffer accumulation and
JSON.parse inside a try/catch), i.e., move the helperReady/updateStatus block to
the branch that runs after a successful parse of a valid helper message/type,
and apply the same change to the other stdout handling block that mirrors this
logic (the other occurrence around the helper message parsing code).
- Line 13: The stderr throttling in audioBridge.js is advancing
`lastStatusUpdate` even when `updateStatus(...)` drops a duplicate status, which
can suppress a different message that follows and can also carry stale throttle
state across helper restarts. Update the logic around `lastStatusUpdate` and
`updateStatus` so the timestamp is only recorded after a status actually
changes, and reset that throttle state whenever the helper lifecycle is reset or
restarted. Use the `lastStatusUpdate` variable and the `updateStatus` flow as
the main points to adjust.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 828eb9eb-47f1-4bd2-a2b7-983909d1d6c9

📥 Commits

Reviewing files that changed from the base of the PR and between 2db55a0 and 6acce23.

📒 Files selected for processing (1)
  • audioBridge.js

Comment thread audioBridge.js
reason: "Helper not started yet."
};

let lastStatusUpdate = 0; // FIX: used for throttling stderr updates
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't advance the stderr throttle window for dropped updates.

lastStatusUpdate is set before updateStatus(...), so a duplicate helper-error still refreshes the throttle bucket even though updateStatus short-circuits. That means a new, different stderr message that arrives right after can be hidden for up to 1s. Because this timestamp also survives helper restarts, the first error from a new process can be suppressed too. Only stamp the time after a status actually changes, and reset it when the helper lifecycle resets.

Proposed fix
   function updateStatus(nextStatus) {
     // FIX: prevent identical state spam
     if (
       helperStatus.mode === nextStatus.mode &&
       helperStatus.reason === nextStatus.reason
     ) {
-      return;
+      return false;
     }

     helperStatus = nextStatus;
     onStatusChange(helperStatus);
+    return true;
   }
   function start() {
+    lastStatusUpdate = 0;
     const helperBinary = findHelperBinary();
       // FIX: throttle UI updates to avoid flood (max 1 per 1000ms)
       if (now - lastStatusUpdate < 1000) {
         return;
       }
-
-      lastStatusUpdate = now;
-
-      updateStatus({
+      if (updateStatus({
         mode: "helper-error",
         reason: [
           "Audio helper error: ",
           errorMessage || "Helper reported an error.",
           "\n",
           "Troubleshooting:",
           "\n- Check if your audio device is in use by another app.",
           "\n- Try restarting Paraline or your computer.",
           "\n- If this continues, rebuild the helper binary."
         ].join("")
-      });
+      })) {
+        lastStatusUpdate = now;
+      }
   function stop() {
     if (helperProcess) {
       helperProcess.kill();
       helperProcess = null;
     }
+    lastStatusUpdate = 0;

Also applies to: 105-125

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@audioBridge.js` at line 13, The stderr throttling in audioBridge.js is
advancing `lastStatusUpdate` even when `updateStatus(...)` drops a duplicate
status, which can suppress a different message that follows and can also carry
stale throttle state across helper restarts. Update the logic around
`lastStatusUpdate` and `updateStatus` so the timestamp is only recorded after a
status actually changes, and reset that throttle state whenever the helper
lifecycle is reset or restarted. Use the `lastStatusUpdate` variable and the
`updateStatus` flow as the main points to adjust.

Comment thread audioBridge.js
Comment on lines 68 to +76
helperProcess.stdout.on("data", (chunk) => {
if (!helperReady) {
helperReady = true;
helperReady = true;

updateStatus({
mode: "helper",
reason: "C# helper process connected."
});
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Delay the ready transition until a valid helper message is parsed.

Right now any first stdout chunk flips the bridge to "helper", even if that chunk is only partial JSON or malformed output. That can leave the UI showing a connected helper before the protocol has actually produced a valid message. Move the helperReady/updateStatus(...) block to after the first successfully parsed helper message instead of before buffering/parsing.

Proposed fix
     helperProcess.stdout.on("data", (chunk) => {
-      if (!helperReady) {
-        helperReady = true;
-
-        updateStatus({
-          mode: "helper",
-          reason: "C# helper process connected."
-        });
-      }
-
       stdoutBuffer += chunk.toString();

       const lines = stdoutBuffer.split(/\r?\n/);
       stdoutBuffer = lines.pop() || "";

       for (const line of lines) {
         if (!line.trim()) continue;

         try {
           const message = JSON.parse(line);
+
+          if (!helperReady) {
+            helperReady = true;
+            updateStatus({
+              mode: "helper",
+              reason: "C# helper process connected."
+            });
+          }

           if (message.type === "level" && typeof message.value === "number") {
             sendLevel(message.value);
           }
         } catch (_error) {

Also applies to: 80-95

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@audioBridge.js` around lines 68 - 76, The handler attached to
helperProcess.stdout.on("data") currently sets helperReady and calls
updateStatus prematurely on the first chunk; change it so helperReady = true and
updateStatus({mode: "helper", reason: "C# helper process connected."}) are
executed only after you successfully parse a complete helper JSON message (use
your existing buffer accumulation and JSON.parse inside a try/catch), i.e., move
the helperReady/updateStatus block to the branch that runs after a successful
parse of a valid helper message/type, and apply the same change to the other
stdout handling block that mirrors this logic (the other occurrence around the
helper message parsing code).

@Karanjot786
Copy link
Copy Markdown

Hey @anchallll02! Saw your work on GSSoC 2026.

We are building TermUI, a TypeScript terminal UI framework with React-style hooks and JSX, rendered entirely in the terminal.

We have 74 unassigned GSSoC issues open across widgets, hooks, adapters, and CLI tooling. Your JavaScript background transfers directly.

Karanjot, TermUI maintainer

@SamXop123
Copy link
Copy Markdown
Owner

@anchallll02 Please fix the coderabbit review comments as suggested

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

Labels

gssoc26 GirlScript Summer of Code 2026 type:bug type:performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants