Skip to content

feat(sdk): act on s2s reconnect advice in append and read sessions - #703

Open
infiniteregrets wants to merge 13 commits into
mainfrom
m/sdk-reconnect-advice
Open

feat(sdk): act on s2s reconnect advice in append and read sessions#703
infiniteregrets wants to merge 13 commits into
mainfrom
m/sdk-reconnect-advice

Conversation

@infiniteregrets

@infiniteregrets infiniteregrets commented Aug 17, 2026

Copy link
Copy Markdown
Member

No description provided.

@infiniteregrets
infiniteregrets force-pushed the m/sdk-reconnect-advice branch 4 times, most recently from f667d83 to 54c3568 Compare August 18, 2026 03:42
@infiniteregrets
infiniteregrets marked this pull request as ready for review August 18, 2026 03:43
@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR propagates S2S reconnect advice into append and read session control flow so sessions can hand over proactively without consuming retry budget.

  • Adds a per-connection atomic reconnect signal shared between frame decoders and session loops.
  • Half-closes and drains advised append connections before reconnecting.
  • Resumes advised read connections after the last delivered batch and paces repeated no-progress reconnects.

Confidence Score: 5/5

The PR appears safe to merge; no actionable correctness, security, or compatibility failures were identified.

Append advice drains the active acknowledgement stream before handoff, while read advice advances the resume position before reconnecting, preserving append ambiguity guarantees and read continuity.

Important Files Changed

Filename Overview
sdk/src/api.rs Detects reconnect advice on regular append and read frames and propagates it through a per-attempt signal.
sdk/src/reconnect.rs Introduces the shared reconnect flag and constants used to pace repeated no-progress handovers.
sdk/src/session/append.rs Stops new input on advice, half-closes and drains acknowledgements, then reconnects while preserving retry-policy behavior.
sdk/src/session/read.rs Emits an internal advice outcome after the associated batch, resumes from the updated sequence, and preserves bounded-read termination.
sdk/src/lib.rs Registers the new private reconnect module without changing the public API.

Sequence Diagram

sequenceDiagram
    participant Server
    participant Decoder
    participant Session
    participant Replacement as New connection
    Server-->>Decoder: Regular S2S frame with reconnect flag
    Decoder->>Session: Decoded ack or read batch
    Decoder->>Session: Set per-connection advice signal
    alt Append session
        Session->>Server: Half-close request body
        Server-->>Session: Drain remaining acknowledgements and EOF
    else Read session
        Session->>Session: Advance resume sequence past delivered batch
    end
    Session->>Replacement: Reconnect without consuming retry budget
Loading

Reviews (1): Last reviewed commit: "feat(sdk): act on s2s reconnect advice i..." | Re-trigger Greptile

A server that is about to terminate sets the reconnect-advised bit on
the regular frames it sends. Sessions now finish the current connection
cleanly and move to a fresh one, rather than staying attached until the
terminal server_draining error arrives.

An append session stops admitting inputs, half-closes so the server can
acknowledge everything it accepted, drains those acknowledgements, and
then reconnects. Because the whole request body is already on the wire
before the half-close, a clean end means nothing is left unacknowledged,
so this holds even under AppendRetryPolicy::NoSideEffects. A read
session finishes the batch the advice arrived on and resumes from the
position after it.

Neither path is treated as a failure, so no retry budget is consumed,
and both pace themselves if advice repeats without progress.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread sdk/src/session/append.rs Outdated
Comment thread sdk/src/session/append.rs Outdated
Comment thread sdk/src/session/read.rs Outdated
.await?;
Ok(Box::pin(try_stream! {
loop {
match timeout(Duration::from_secs(20), batches.next()).await {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a part of this PR I know, but lets move this duration into a const with a comment, so its less magic-y and clearly related to the document s2s heartbeat max https://s2.dev/docs/api/protocol#data-flow (plus some buffer)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, please check!

Comment thread sdk/src/session/read.rs Outdated
Some(Ok(batch)) => {
Some(Ok(ReadItem::ReconnectAdvised)) => {
batches = None;
if end.count == Some(0) || end.bytes == Some(0) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is confusing -- maybe lets have a util fn that clarifies that we are checking if the read end condition is already satisfied, like read_limits_exhausted(&end) or something, and maybe a comment stating that this is an optimization, to avoid a useless reconnect for a read that was already satisfied at the moment we received the reconnect signal

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PTAL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants