Repository navigation
Negotiate heart-beats as STOMP 1.2 specifies - #216
Merged
vrslev merged 6 commits intoNov 10, 2026
Merged
Conversation
The client sent heart-beats at the server's wanted interval alone, so a server
answering "heart-beat:x,0" (it wants none) made the client send them in a loop
that never sleeps. The aliveness check read the server's interval alone too, so
a server sending none ("heart-beat:0,y") made every connection look dead, and a
CONNECTED frame without a heart-beat header raised KeyError.
STOMP 1.2, Heart-beating: client heart-beats come every MAX(cx, sy) ms, and
none if cx or sy is 0; server heart-beats every MAX(sx, cy) ms, the same way;
a missing heart-beat header is "heart-beat:0,0". AgreedHeartbeat.negotiate does
exactly that once, in the connection lifespan. The heart-beat task starts only
when the client sends any, and is_alive waits on the agreed server interval and
holds the connection alive when none is agreed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vrslev
reviewed
Nov 10, 2026
|
|
||
|
|
||
| @dataclass(frozen=True, slots=True) | ||
| class AgreedHeartbeat: |
Collaborator
There was a problem hiding this comment.
I'd prefer updating Heartbeat instead of adding new class
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.
Fixes #213.
Why
STOMP 1.2, Heart-beating: from
CONNECT'sheart-beat:<cx>,<cy>andCONNECTED'sheart-beat:<sx>,<sy>, the client sends every MAX(cx, sy) ms, and none if cx or sy is 0; the server sends every MAX(sx, cy) ms, the same way; a missing header is treated asheart-beat:0,0.stompman used the server's values alone:
sy. Withsy = 0(the server wants none), the heart-beat loop slept 0 s and sent EOLs continuously.is_aliveused the server'ssx. Withsx = 0(the server sends none), every connection counted as dead.CONNECTEDframe withoutheart-beatraisedKeyError.Summary
stompman.config.AgreedHeartbeat, withnegotiate(client=…, server=…): the rule above, written once.ConnectionLifespan.enterreads a missing header as0,0, negotiates, and passes theAgreedHeartbeattoset_heartbeat_interval.EstablishedConnectionResultandActiveConnectionStatecarry it in place of the raw serverHeartbeat.ConnectionManager._restart_background_tasksstarts the heart-beat task only when the send interval is above 0.ActiveConnectionState.is_alivewaits on the agreed receive interval timescheck_server_alive_interval_factor, and returns true when no server heart-beats are agreed.Compatibility:
EstablishedConnectionResult.server_heartbeatandActiveConnectionState.server_heartbeatbecomeheartbeat: AgreedHeartbeat, andset_heartbeat_intervaltakes anAgreedHeartbeat. None of them is exported fromstompman, but a customConnectionLifespanFactorywould need the new type. Behaviour is unchanged whenever both sides send and want heart-beats at the same interval:test_client_heartbeats_okpasses as before.Validation
just lintjust check-typesjust test-fast: 458 passed. New tests:test_agreed_heartbeat_negotiate: one case per branch of the rule, both directions;test_client_sends_no_heartbeats_the_server_does_not_want:heart-beat:1000,0and a missing header; no heart-beat is written and nothing loops on a 0 s interval. It fails without the change;test_is_alive_waits_on_the_agreed_interval(MAX(sx, cy)) andtest_is_alive_when_no_server_heartbeats_are_agreed.just test(integration) not run.