fix(signalr): don't panic on non-feed SignalR Core frames#317
Merged
Conversation
F1's livetiming signalrcore endpoint interleaves ping frames (`{"type":6}`)
and completion frames among the `feed` invocations. listen() unwrapped every
frame into FeedMessage (which requires `target`), so the first ping panicked
the tokio ingest worker and silently killed all live data while the HTTP
server kept serving empty connections.
- listen(): skip frames that don't deserialize as a feed invocation instead
of unwrapping (logs at debug).
- subscribe(): read until the Completion matching our invocation id, skipping
ping/other frames that may arrive first, instead of assuming the next frame
is the Completion.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
After F1's live timing moved to the SignalR Core endpoint (
livetiming.formula1.com/signalrcore), therealtimeservice crashes its ingest task within ~15s of connecting, on every published image I tested (4.0.4, 4.0.5,develop, andlatestrebuilt after the recentfix: invocation_id missingcommit). The HTTP/SSE server keeps running, so the dashboard loads but shows no live data — the failure is silent.Root cause
SignalR Core interleaves protocol frames among the
feedinvocations — most commonly ping frames{"type":6}(exactly the 10-char message in the panic above), plus completion/close frames. Two places assume a stricter frame shape:listen().unwrap()s every frame intoFeedMessage, which requires atargetfield. The first ping panics the worker and kills all live data.subscribe()assumes the immediate next frame after the Subscribe invocation is the Completion, so a ping arriving first breaks subscription.Fix
listen(): skip frames that don't deserialize as a feed invocation instead of unwrapping (logged atdebug).subscribe(): read until the Completion whoseinvocationIdmatches ours, skipping ping/other frames that may arrive first.No protocol or struct changes — purely defensive parsing.
Validation
Built from this branch and run against the live endpoint during an active session:
wss://livetiming.formula1.com/signalrcore, handshake + subscribe succeed./api/currentserves real session state (full 44-driver list, weather, timing,ExtrapolatedClock/Heartbeat).skipping non-feed signalr frameat debug and ignored.🤖 Generated with Claude Code