Improves backpressure resilience and prevents protocol starvation#22
Merged
Conversation
Approved design for issues #3/#9: deliver inbound frames via try_send + a backpressure sub-loop that holds one frame and keeps keepalive/outgoing alive (without reading inbound) so a slow consumer never starves protocol handling. Zero data loss, bounded memory, TCP backpressure to the server. Raises the CHANNEL_SIZE default from 4 to 256 so transient hiccups never trigger it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three TDD tasks: probe mock server + validation test; backpressure-resilient delivery (try_send + sub-loop) with a discriminating test; raise CHANNEL_SIZE default to 256 + docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sends a burst then replies with an 'alive' marker only if it receives a client keepalive ping — the discriminator for protocol-liveness during backpressure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inbound delivery now uses try_send + a backpressure sub-loop that holds one frame and keeps keepalive/outgoing alive (without reading inbound) until the consumer frees capacity. A slow consumer no longer stalls ping/pong and keepalive, so the server no longer drops the connection. Zero data loss, bounded memory, ordering preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A larger default buffer absorbs transient consumer slowdowns so backpressure engages only under sustained overload. Documents that backpressure resilience relies on keepalive being enabled. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- SocketeerRx and ReuniteError CHANNEL_SIZE defaults raised from 4 to 256 to match Socketeer, keeping explicit bare-type usage consistent with reunite compatibility. - Swapped # Errors / # Panics order in backpressure_probe_server to match file convention (Errors first). - Rewrote keepalive_interval disabled-case sentence to accurately describe that the loop stops reading inbound frames when the buffer is full, and that a stalled consumer can park the connection indefinitely. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #22 +/- ##
==========================================
+ Coverage 94.14% 94.64% +0.49%
==========================================
Files 7 7
Lines 564 635 +71
==========================================
+ Hits 531 601 +70
- Misses 33 34 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The send path already funneled through shared helpers (send_confirmed), but the receive path was duplicated: next_message, next_raw_message, and the Stream poll_next impl were reimplemented across Socketeer and SocketeerRx, with the poll_next bodies byte-for-byte identical. Extract recv_raw and poll_recv_raw into socket_loop alongside the send helpers so both the unsplit handle and the split receive half route through one terminal-error-aware receive path. This also makes tracing consistent: all receive paths now emit the "Received message" trace, where previously only Socketeer::next_message did. Pure refactor, no public API change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exercises the no-keepalive arm of deliver_with_backpressure: a small channel (2) under a 5-frame burst forces backpressure with keepalives disabled, the consumer pauses, then drains. Asserts all burst frames arrive in order with zero loss. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exercises the receiver.recv() arm of deliver_with_backpressure: with the loop parked in backpressure (channel full, consumer not reading), a confirmed send still completes, proving a slow receiver does not block the outgoing path. The held burst then drains in full and in order. Co-Authored-By: Claude Opus 4.8 (1M context) <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.
Enhances the socket loop's ability to handle slow message consumers without causing connection drops due to protocol timeouts. Previously, a full receive channel would block the entire loop, preventing keepalives and pongs from being sent, leading to server-side disconnects.
Changes:
ConnectOptionsandSocketeerto clarify the role of keepalives in maintaining connection liveness during backpressure and to reflect the new default channel size.CHANNEL_SIZEdefault value forSocketeerRxandReuniteErrorto 256.backpressure_probe_server) and integration tests to validate that the protocol remains alive and data is delivered in order even when the consumer is backpressured.This ensures a robust connection that adapts gracefully to fluctuating consumer speeds.