Commit 2ac2998
authored
fix: schedule reconnect after parse error during streaming (#134)
## Summary
Every error path in `ReconnectingRequest::poll_next` during the
`Connected` state sets state to `WaitingToReconnect` before returning
the error — except for parser errors propagated through
`process_bytes(...)?`. After a parse error, the state stayed at
`Connected` and the next poll continued draining the (already-broken)
response body before finally hitting end-of-body and emitting a spurious
`UnexpectedEof` before the reconnect actually kicked in.
This PR schedules a reconnect on parse errors when reconnect is enabled,
matching the pattern used by every other error path. The error is still
returned to the caller; the only behavioral change is that the next poll
cleanly transitions to reconnect rather than draining the broken body.
**Before:** `Connected`, `Err(InvalidLine)`, `Err(UnexpectedEof)`,
`Connected`, …
**After:** `Connected`, `Err(InvalidLine)`, `Connected`, …
## Context
Surfaced while investigating
[launchdarkly/rust-server-sdk#116](launchdarkly/rust-server-sdk#116)
(`StreamingDataSource` silently shuts down on stream errors). That
report has two contributing bugs; this PR addresses the
rust-eventsource-client side. The rust-server-sdk side will be fixed in
a follow-up PR — together they restore the reconnection contract: the
eventsource-client owns reconnection, the SDK keeps polling and trusts
it.
Tracked in
[SDK-2345](https://launchdarkly.atlassian.net/browse/SDK-2345).
## Test plan
- [x] New test `parser_error_schedules_reconnect_immediately`
(`eventsource-client/src/client.rs`) — verifies the next stream item
after a parse error is `Connected` from the reconnect, not a spurious
`UnexpectedEof`.
- [x] `cargo test` — 60 lib tests + 2 doc tests pass; no regressions.
[SDK-2345]:
https://launchdarkly.atlassian.net/browse/SDK-2345?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes streaming error-handling semantics by scheduling reconnects on
parser failures, which can affect how downstream consumers observe
errors and reconnect timing. Scope is small and covered by a new
integration-style test, but touches core stream state transitions.
>
> **Overview**
> **Fixes reconnection behavior after SSE parse errors during
streaming.** When `EventParser::process_bytes` fails in the `Connected`
state, the client now (when `ReconnectOptions::reconnect` is enabled)
transitions to `WaitingToReconnect` before yielding the parse error,
avoiding continued draining of a broken response body and the resulting
follow-on errors.
>
> Updates `Client::stream` docs to clarify that stream errors are
non-terminal and that the stream only ends on `Poll::Ready(None)`, and
adds a new test (`parser_error_schedules_reconnect_immediately`)
asserting the sequence `Connected -> Err(InvalidLine) -> Connected`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ddea87d. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 53e64f7 commit 2ac2998
1 file changed
Lines changed: 91 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
199 | 199 | | |
200 | 200 | | |
201 | 201 | | |
202 | | - | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
203 | 206 | | |
204 | | - | |
205 | | - | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
206 | 216 | | |
207 | 217 | | |
208 | 218 | | |
| |||
495 | 505 | | |
496 | 506 | | |
497 | 507 | | |
498 | | - | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
499 | 523 | | |
500 | 524 | | |
501 | 525 | | |
| |||
712 | 736 | | |
713 | 737 | | |
714 | 738 | | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
715 | 802 | | |
0 commit comments