Repository navigation
Bound status requests and retry them until the deadline - #201
Merged
Merged
Conversation
Fixes a defect in the status polling of `AssembledTransaction`. Before this change, `pollStatus` sent its status requests through `SorobanServer::getTransaction` without a bound of their own, so a server that accepted the connection and never answered blocked `send` and `signAndSend` indefinitely under the default Guzzle client. A status request that threw ended the call with that exception although the transaction could still complete, and an RPC error response came back as the result with a null status. The waits between requests grew from one second by a factor of 1.5, and the timeout message carried a line break. This change: - Polls every three seconds until `timeoutInSeconds` has elapsed on a monotonic clock, with the first request at once and one last request at the deadline, as js-stellar-sdk does. - Adds `SorobanServer::getTransactionWithTimeout()`, which bounds a status request by the given time and by the client's own `timeout` and `connect_timeout`, and polls through it; `getTransaction` keeps its behavior and shares the request path. - Retries a status request that throws a `GuzzleException`, `RuntimeException` or `InvalidArgumentException` or returns an RPC error until the deadline, and names the last error in the timeout exception, on one line. - Leaves the send step and its PENDING and DUPLICATE handling unchanged. - Adds tests with Guzzle's `MockHandler` for failing, RPC-error and FAILED responses, for the deadline with the last error and the request bounds, for a `timeoutInSeconds` of 0, and for the client-limit clamp of `getTransactionWithTimeout`. The unit suite note in `AGENTS.md` names the ten seconds of real waits these tests add. A `SorobanServer` subclass or test double that customizes the poll's status request overrides `getTransactionWithTimeout()`, because `getTransaction` is no longer on the poll path. The unit suite passes. The integration class `SorobanClientTest` ran against testnet on 2026-11-05 and passes. Closes #200
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #201 +/- ##
============================================
+ Coverage 93.46% 93.47% +0.01%
- Complexity 21609 21621 +12
============================================
Files 1006 1006
Lines 52399 52422 +23
============================================
+ Hits 48974 49001 +27
+ Misses 3425 3421 -4
🚀 New features to boost your workflow:
|
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 a defect in the status polling of
AssembledTransaction. Before this change,pollStatussent its status requests throughSorobanServer::getTransactionwithout a bound of their own, so a server that accepted the connection and never answered blockedsendandsignAndSendindefinitely under the default Guzzle client. A status request that threw ended the call with that exception although the transaction could still complete, and an RPC error response came back as the result with a null status. The waits between requests grew from one second by a factor of 1.5, and the timeout message carried a line break.This change:
timeoutInSecondshas elapsed on a monotonic clock, with the first request at once and one last request at the deadline, as js-stellar-sdk does.SorobanServer::getTransactionWithTimeout(), which bounds a status request by the given time and by the client's owntimeoutandconnect_timeout, and polls through it;getTransactionkeeps its behavior and shares the request path.GuzzleException,RuntimeExceptionorInvalidArgumentExceptionor returns an RPC error until the deadline, and names the last error in the timeout exception, on one line.MockHandlerfor failing, RPC-error and FAILED responses, for the deadline with the last error and the request bounds, for atimeoutInSecondsof 0, and for the client-limit clamp ofgetTransactionWithTimeout. The unit suite note inAGENTS.mdnames the ten seconds of real waits these tests add.A
SorobanServersubclass or test double that customizes the poll's status request overridesgetTransactionWithTimeout(), becausegetTransactionis no longer on the poll path.The unit suite passes. The integration class
SorobanClientTestran against testnet on 2026-11-05 and passes.Closes #200