Repository navigation
Stop reconnect storms when the web socket is rate limited - #226
Merged
Merged
Conversation
- A monitor with nothing subscribed stops instead of reconnecting forever, and a failed subscribe closes it, so a client left behind (e.g. by a failed Home Assistant setup) doesn't keep the rate limit active - Share backoff state per user session, so a new client waits out another's backoff instead of starting over at the first attempt - Log why a subscription failed instead of a blank error Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Record the backoff as soon as its reason is known, so closing the monitor after a failed subscribe can't lose it - End the subscribe wait as soon as the connection closes, and report why (e.g. "the web socket connection was rate limited") - Add Rivian.ws_backoff_remaining and Rivian.ws_rate_limited - Close the connection when its last subscription is removed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The monitor sleeps for the remaining backoff, which can fall just under 30 seconds when the jitter is small, so the fake sleep missed it and the test timed out. Treat any sleep longer than the 1 second poll as a backoff, and allow for elapsed time in the delay assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…koffs - Log a subscription callback's exception instead of letting it end the receiver, and only clear the ack when the socket has closed, so a failing callback no longer makes a healthy connection back off - Only hold off new connections during a backoff, so another client's rate limit on the same session doesn't block subscribing on an open connection - Re-check the shared backoff after waiting, in case it was pushed back Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Keep the server's close reason, report it when a subscribe fails, and add Rivian.ws_unauthenticated so integrations can trigger a reauth - Track whether the latest backoff was a rate limit per monitor, so another client's healthy connection on the same session can't clear it - Log subscribe failures caused by a backoff as warnings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Share whether the current backoff is for a rate limit, and report it only while that backoff lasts, so a new client created for a retry sees it and another client's healthy connection can't clear it early. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only move the shared retry time later, so a missing ack on one client can't shorten another's rate-limit backoff or clear its rate-limit flag. Co-Authored-By: Claude Opus 5.5 <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.
Summary
Fixes the library side of bretterer/home-assistant-rivian#305. After a restart, setup kept failing because the web socket was closed with 1013 "Rate limited". Each failed retry left a client reconnecting, and each new client restarted its backoff, so the limit never cleared until a fresh login.
Changes
connection_ack), soclose()can't drop it.Unauthenticated). Failures caused by a backoff are warnings; others are errors.Rivian:ws_backoff_remaining: seconds until the web socket may reconnect;ws_rate_limited: whether the web socket is backing off after a rate limit, for any client on the session;ws_unauthenticated: whether the server closed the socket as unauthenticated.Behavior changes for callers
Nonewithout connecting.ws_unauthenticatedandws_rate_limitedinstead of reading_ws_monitor.Tests
tests/test_ws_monitor.pycovers:close();The backoff fixture uses a fake clock, so the tests don't depend on the random part of the delay.
🤖 Generated with Claude Code