Skip to content

fix(relay): log every connection's close from Connection::run - #5602

Merged
kixelated merged 1 commit into
mainfrom
fix/relay-ws-close-log
Oct 15, 2026
Merged

kixelated merged 1 commit into
mainfrom
fix/relay-ws-close-log

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Problem

Interop has failed on every PR since #5568 with relay connection N (subscriber) idled out instead of closing (open). Every flagged connection is transport=websocket.

The harness runs the relay with RUST_LOG=<inherited>,moq_relay::connection=info,moq_relay::relay=info (#5215) and pairs each conn{id=N} with a connection closed id=N line. #5568 numbered WebSocket sessions on the cluster counter and added their close log, but from target moq_relay::websocket, which that filter drops. The relay did close these sessions; the harness just never saw it. Before #5568, WebSocket ids came from a separate counter that collided with already-closed QUIC ids, which hid the same gap.

The 13:07Z scheduled red run was unrelated: its failure was the wire-compat step's stale planned break, fixed separately.

Approach

Connection::run logs its own close, inside its conn span and under moq_relay::connection, for every transport. The QUIC and WebSocket accept loops and moq-cli's LAN path stop logging it themselves. One log site, one target, so a new transport can't drift again.

The harness check is unchanged. quest/m1/interop-close-log.md is deleted: it pinned the harness filter to the close-log target and was only waiting on a green Interop run.

Public API / wire impact

  • moq_relay::Connection::run now returns () instead of anyhow::Result<()>, since it reports the outcome itself. Every in-tree caller discarded or only logged the result. Breaking for embedders on main.
  • QUIC close lines move from moq_relay::relay to moq_relay::connection and now carry the conn{...} span prefix. The connection closed id=N [err=...] text is unchanged.
  • No wire change.

Validation

  • Reproduced locally on unmodified main with just test interop --all: rust round failed on WebSocket connections 6 and 7. With the fix, the full matrix passes ("interop: all checks passed").
  • Regression test: relay_websocket_logs_its_close_under_a_cluster_id now captures logs through a filter that keeps only moq_relay::connection, matching the harness. It fails without the fix ("the WebSocket session's close was not logged") and passes with it.
  • just check passes. One earlier run timed out in bursts_cross_a_transport_peer::impaired under full parallel load. It passed 3/3 alone and in the rerun.

Follow-ups

  • The io_uring accept path (rs/moq-relay/src/uring.rs) doesn't go through Connection::run, so it logs negotiated and its close under moq_relay::uring with no conn span. Interop doesn't run it today.

🤖 Generated with Claude Code

The interop harness keeps only the relay's `moq_relay::connection` and
`moq_relay::relay` log targets. #5568 logged a WebSocket session's close from
`moq_relay::websocket`, so the harness saw each WebSocket `conn{id=N}` open
but never its close and failed the round as an idle-out.

`Connection::run` now logs the close itself, in its own span and target, for
every transport, and returns nothing; the QUIC, WebSocket, and moq-cli LAN
accept loops stop logging it separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T19:18:11.974324Z b7152b2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed commit: b7152b2.

No actionable bugs found. Keeping the close event in Connection::run fixes the target/filter mismatch at its source, rather than requiring the harness to know each transport's logging target. The stricter WebSocket regression covers the missed close, and the unchanged parser accepts the added span prefix. Panic isolation and success/error log levels remain equivalent; in-tree callers no longer duplicate the close.

The Result-to-unit API change is intentional and documented. io_uring remains outside this path as described, so this does not establish uniform logging for that backend.

Verification limits: static source, caller and harness review through GitHub. No tests, builds or interop runs executed by me.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Summary: the Interop idle-outs since #5568 came from a log filter, not from stuck sessions. The harness keeps only moq_relay::connection and moq_relay::relay, and #5568 logged WebSocket closes from moq_relay::websocket, so every WebSocket conn{id=N} looked open. Connection::run now logs every transport's close under moq_relay::connection.

  • Reproduced on unmodified main with just test interop --all (WebSocket connections 6 and 7 in the rust round). With this PR the full matrix passes.
  • The regression smoke test now filters to the harness's target. It fails without the fix and passes with it.
  • just check passes.
  • Codex reviewed b7152b2 with no findings.
  • deps: adopt the iroh HTTP/3 close capsule fix #5591 (iroh capsule bump) does not touch this path.

(Written by Claude Opus 5.5)

@kixelated
kixelated enabled auto-merge October 15, 2026 19:18
@coderabbitai

coderabbitai Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3e6f098c-94bb-4049-b620-141ffa38bc5d
📥 Commits

Reviewing files that changed from the base of the PR and between 0653643 and b7152b2.

📒 Files selected for processing: 14
  • quest/m1/README.md
  • quest/m1/interop-close-log.md
  • rs/moq-cli/src/main.rs
  • rs/moq-relay/benches/auth.rs
  • rs/moq-relay/src/cluster.rs
  • rs/moq-relay/src/connection.rs
  • rs/moq-relay/src/relay.rs
  • rs/moq-relay/src/websocket.rs
  • rs/moq-relay/tests/auth_lifetime.rs
  • rs/moq-relay/tests/goaway_cluster.rs
  • rs/moq-relay/tests/session_revalidate.rs
  • rs/moq-relay/tests/smoke.rs
  • rs/moq-relay/tests/upstream_links.rs
  • test/interop/relay-log.sh
💤 Files with no reviewable changes: 2
  • quest/m1/README.md
  • quest/m1/interop-close-log.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.

Walkthrough

Connection::run now returns unit and logs successful closure at info level and errors at warn level. Relay connection call sites and tests use the updated method. The smoke test captures info-level connection events. The Interop close-log quest entry and document were removed, and the relay-log comment now points to the connection module.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to b7152

Close logging is centralized, and the regression test checks the WebSocket close event. No actionable merge-blocking impact is established.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 68.75% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 12 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly describes the primary change: centralized close logging in Connection::run for every connection.
Description check Passed The description is directly related to the changes. It explains the WebSocket logging issue, the centralized logging approach, API impact, validation, and follow-up scope.
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.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
✨ Simplify code
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 Clippy (1.98.1)

Clippy execution timed out

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.

@kixelated
kixelated added this pull request to the merge queue Oct 15, 2026
Merged via the queue into main with commit de6c273 Oct 15, 2026
9 checks passed
@kixelated
kixelated deleted the fix/relay-ws-close-log branch October 15, 2026 19:47
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