feat: allow request timeouts to be configured via ClientOptions - #339
Open
cheekychops wants to merge 1 commit into
Open
feat: allow request timeouts to be configured via ClientOptions#339cheekychops wants to merge 1 commit into
cheekychops wants to merge 1 commit into
Conversation
BaseClient builds its OkHttpClient with no timeout overrides, so every caller gets the OkHttp defaults of 10s connect, 10s read and 10s write, with no way to change them: Client exposes only (apiKey) and (apiKey, ClientOptions), ClientOptions carries the region, newHttpClient is private static, and the BaseClient constructors that accept an OkHttpClient are protected and unreachable from a Client subclass. For an integration whose calls are mostly writes, a 10s read timeout turns a slow-but-successful Recurly response into a failure whose outcome the caller cannot determine. A subscription create that times out may well have been applied, so the caller has to reconcile by reading back rather than retrying, and the safest version of that is a lot of machinery to carry for something a timeout setting would avoid. ClientOptions now takes optional connect, read, write and call timeouts, and newHttpClient applies each one that is set. Anything left unset keeps the current behaviour exactly, so this is source and behaviour compatible; the existing tests are unchanged and still pass. newHttpClient becomes package-private so the tests can assert on the client it builds. Four cases: defaults unchanged when nothing is configured, all four timeouts applied when set, timeouts applied individually without disturbing the others, and a configured timeout surviving construction through the public Client constructor.
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.
Problem
BaseClientbuilds itsOkHttpClientwith no timeout overrides, so every caller gets the OkHttp defaults — 10s connect, 10s read, 10s write, and no overall call timeout — with no supported way to change them:Clientexposes onlyClient(apiKey)andClient(apiKey, ClientOptions)ClientOptionscarries the region and nothing elsenewHttpClientisprivate staticBaseClientconstructors that do accept anOkHttpClientareprotected, and aClientsubclass cannot reach them throughsuper(...)So the only routes available today are reflection over
BaseClient'sprivate final OkHttpClient clientfield, or vendoring the SDK. Neither is something we want in a payments integration.Why 10s read is the painful one
For an integration whose Recurly calls are mostly writes, a 10s read timeout converts a slow-but-successful response into a failure whose outcome the caller cannot determine. A
createSubscriptionthat times out at 10s may well have been applied at Recurly — so the caller cannot simply retry, and instead has to reconcile by reading back the account's subscriptions and matching them against what it asked for.We have production evidence of exactly that: a recent burst of timed-out subscription creates all took 10.7–10.8s, and in every case the write had in fact landed — confirmed by Recurly's own
new_subscriptionandsuccessful_paymentwebhooks arriving seconds later. The customer was charged and shown an error. Being able to raise the read timeout is a far smaller thing to own than the reconciliation logic it forces.Change
ClientOptionsgains optionalconnectTimeout,readTimeout,writeTimeoutandcallTimeout(java.time.Duration), andnewHttpClientapplies each one that is set:Anything left unset behaves exactly as before, so this is source- and behaviour-compatible.
newHttpClientbecomes package-private so the tests can assert on the client it builds; it is not part of the public surface either way.Tests
Four new cases in
BaseClientTest:Client(apiKey, ClientOptions)constructormvn testis green: 48 tests, 0 failures, with the existing 26BaseClientTestcases untouched. Reverting the wiring innewHttpClientfails exactly the three tests that assert configured values, so they do bind to the change.I could not run
./scripts/format—bin/google-java-format-1.35.0-all-deps.jaris not present in the repo — so the new code follows the surrounding style by hand and stays within 100 columns. Happy to reformat if CI disagrees.Notes
ClientOptions.javaandBaseClient.javaboth lack the "automatically created by Recurly's OpenAPI generation process" banner, so I have taken them to be hand-written and in scope for a PR per CONTRIBUTING.