Skip to content

[client-resources] Remove terminal requests before reconnect - #24

Open
dearlordylord wants to merge 1 commit into
Platform-Collective:developfrom
dearlordylord:fix/terminal-request-replay
Open

[client-resources] Remove terminal requests before reconnect#24
dearlordylord wants to merge 1 commit into
Platform-Collective:developfrom
dearlordylord:fix/terminal-request-replay

Conversation

@dearlordylord

Copy link
Copy Markdown
Contributor

This part is human-written; the AI disclaimer will be below later ---

Hi, I'm experimenting with finding corner-case bugs in "protocol-like" interactions in code (in this case, with formal methods) and was wondering if you'd be interested in a couple of PRs that close "hard-to-catch sleeper bugs [with very uncommon trigger schedules]". So the ones that may never come out, but if they do, debugging could be troublesome.

In this case, there's also a "non-functional" potential issue of stale requests accumulating indefinitely while the tab is open.

  • And also the potential of a failed request becoming successful/change state much later, when the user doesn't want that anymore

DISCLAIMER: Next is Sol writing, proofread and simplified/humanized. The code is Sol also, self-reviewed.

Summary

After the client reports a request as failed, do not consider that request again during reconnect. Keep the separate rate-limit retry behavior.

What goes wrong

The pending-request map stores unfinished requests. For an error that the client treats as final, the client rejected the caller's promise but left the request in this map. The entry had no automatic expiry. A later successful response could still remove it.

After reconnect, a hello message starts request recovery. The client checks each pending request. Reconnect can then send the failed request again, even though the caller has already received an error.

Why it happens

The success path removed the completed request. The final-error path rejected the promise but did not remove the request.

How I found it

I modeled the request lifecycle in Quint 0.31.0. The model checks one rule: after the client reports a final error, reconnect must not be able to send that request again. The old behavior violates this rule, and that sequence became the regression test.

The model covers request state and reconnect behavior. It does not cover message encoding, payloads, or timing.

flowchart LR
    A[Server returns an error] --> B{Is a rate-limit retry scheduled?}
    B -->|No| C[Report failure and remove request]
    B -->|Yes| D[Keep request pending]
    D --> E[Retry after the server delay]
Loading

What this changes

  • Remove the request before reporting an error as final.
  • Keep a rate-limited request pending while its delayed retry is scheduled.
  • Test both paths.

Result

A request removed after a final error is not considered during reconnect. Rate-limit retries continue to work as before.

@dearlordylord
dearlordylord marked this pull request as ready for review August 11, 2026 18:24
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.

1 participant