Skip to content

fix(ws_highway): swallow a mid-stream WebSocketDisconnect quietly - #845

Merged
byrongamatos merged 2 commits into
mainfrom
fix/ws-highway-disconnect
Jul 10, 2026
Merged

fix(ws_highway): swallow a mid-stream WebSocketDisconnect quietly#845
byrongamatos merged 2 commits into
mainfrom
fix/ws-highway-disconnect

Conversation

@byrongamatos

@byrongamatos byrongamatos commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #844, fixing the disconnect-logging issue CodeRabbit flagged there. Pre-existing (byte-identical to origin/main), so it correctly wasn't touched in the verbatim move.

The issue

The outer try in highway_ws had only except Exception as e: log.exception("highway_ws unhandled error"). The inner except WebSocketDisconnect covers only the post-ready keep-alive loop, and drum_tab/notation have localized guards — but the ~13 other streamed sends (beats, sections, notes, chords, anchors, …) fall through to the blanket handler. Since WebSocketDisconnect is an Exception subclass, a routine tab-close mid-load was logged as an error.

Fix

A dedicated except WebSocketDisconnect: return before the blanket handler — matching the two localized guards and the lib/** coding guideline ("Handle WebSocket disconnects with try/except WebSocketDisconnect").

Test

tests/test_ws_highway_disconnect.py drives highway_ws with a fake websocket that raises WebSocketDisconnect on the first streamed send (loading), over a real minimal sloppak. Negative-checked: removing the guard fails the test (disconnect logged as highway_ws unhandled error); the fix passes. It uses a raw handler on feedBack.server rather than caplog, because configure_logging() reroutes that logger through structlog where caplog doesn't observe it.

Full suite 2401 passed; Codex 0 findings. Closes the review thread on #844.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Prevented WebSocket disconnects during live streaming from falling through to the generic error-handling path, avoiding unnecessary error logging and error responses.
  • Tests
    • Added a new test module to confirm mid-stream client disconnects are handled quietly (no exceptions, only expected streaming output, and no “unhandled error” logs).

Pre-existing (byte-identical to origin/main), flagged by CodeRabbit on #844: the
outer try's only guard was `except Exception as e: log.exception("highway_ws
unhandled error")`. The inner `except WebSocketDisconnect` covers ONLY the
post-`ready` keep-alive loop, and the drum_tab/notation sends have their own
localized guards — but the ~13 other streamed sends (beats, sections, notes,
chords, anchors, …) fall through to the blanket handler. Since
WebSocketDisconnect is an Exception subclass, a routine tab-close mid-load was
logged as an error at whichever send was in flight.

Fix: a dedicated `except WebSocketDisconnect: return` before the blanket handler,
matching the two localized guards and the lib/ coding guideline.

tests/test_ws_highway_disconnect.py drives highway_ws with a fake websocket that
raises WebSocketDisconnect on the first streamed send (`loading`), over a real
minimal sloppak. Negative-checked: removing the guard makes it fail (the
disconnect is logged as `highway_ws unhandled error`); the fix passes. Uses a
raw handler on `feedBack.server` rather than caplog, since configure_logging()
reroutes that logger through structlog where caplog doesn't observe it.

Full suite green. Closes the review thread on #844.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 151866c9-7cbd-46c4-8ce7-e96d657f9af2

📥 Commits

Reviewing files that changed from the base of the PR and between a1775e9 and 0d66c01.

📒 Files selected for processing (1)
  • tests/test_ws_highway_disconnect.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_ws_highway_disconnect.py

📝 Walkthrough

Walkthrough

The highway WebSocket handler now returns immediately on client disconnect during streaming. A regression test simulates the disconnect in a minimal runtime environment and verifies that no unhandled highway WebSocket error is logged.

Changes

WebSocket disconnect handling

Layer / File(s) Summary
Return on routine disconnect
lib/routers/ws_highway.py
The outer WebSocketDisconnect handler returns immediately, preventing routine disconnects from reaching blanket error handling.
Mid-stream disconnect regression test
tests/test_ws_highway_disconnect.py
A disconnecting WebSocket stub, runtime fixture, and logging capture verify that a mid-stream disconnect completes without an unhandled-error log.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% 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 clearly and concisely describes the main change: handling mid-stream WebSocketDisconnects quietly in ws_highway.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ws-highway-disconnect

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 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 `@tests/test_ws_highway_disconnect.py`:
- Around line 37-48: Update _DisconnectingWS.send_json to raise
WebSocketDisconnect only on its first invocation and allow subsequent calls to
complete, then change the related assertion to require exactly one send so
handlers that continue streaming after the disconnect fail the test.
🪄 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 Plus

Run ID: 8debcbe4-826d-4779-8947-328a6174b47f

📥 Commits

Reviewing files that changed from the base of the PR and between 5144611 and a1775e9.

📒 Files selected for processing (2)
  • lib/routers/ws_highway.py
  • tests/test_ws_highway_disconnect.py

Comment thread tests/test_ws_highway_disconnect.py Outdated
…e send) — CodeRabbit

The stub now raises only on the first send and the test asserts ws.sends == 1,
so a handler that caught the disconnect and kept streaming would fail. Still
negative-checked: removing the guard fails the test.
@byrongamatos
byrongamatos merged commit c870199 into main Jul 10, 2026
5 checks passed
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