Ruby retry docs from ground truth; TS docstring examples typecheck - #519
Merged
Merged
Conversation
…ments The Retry Behavior section was wrong twice over (#510): it listed the retryable statuses as "429, 502, 503, 504" when the transport keys off the error's retryable? classification -- 500 and every other 5xx retry on GET, as do connection-level network errors -- and it described max_retries as "max retry attempts" when it is the TOTAL attempt budget: 3 means one initial attempt plus two retries, and max_retries: 0 sends zero requests and raises "Request failed after 0 attempts". Rewrite the section from the transport's ground truth: GET-only scope with the raw-path carve-outs; classification-based statuses including the read-timeout exception (Faraday maps read timeouts to a status-less non-retryable ApiError, not NetworkError -- only connect-phase timeouts retry); total-attempts semantics; uncapped exponential backoff; Retry-After only via 429; the one-shot 401 refresh replay outside the budget; per-operation retry metadata being inert; and retryable? as the actual transport predicate rather than a hint. Align the config comment, options table, and env-var table (adding the missing BASECAMP_TIMEOUT / BASECAMP_MAX_RETRIES rows), and the same misstatement in config.rb's doc comments. Fixes #510.
The fetchAllPages/paginateAll @example blocks use bare (r) => r.json(), which is Promise<unknown> under Node fetch types and fails against the parse callback's Promise<T[]> in any strict/NodeNext project configured like this repo -- the same defect #507 fixed in the README. Mirror the README's proven form: (r) => r.json() as Promise<any[]>. Fixes #511.
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 #510. Fixes #511.
Ruby — Retry Behavior rewritten from the transport's ground truth
The old section was wrong twice over, both proven by driving the real
request_with_retryloop with onlysingle_requeststubbed:retryable?, which is true for 500 and every other 5xx. Proof: a stubbed 500 on GET undermax_retries: 3produced exactly 3 invocations.max_retriesdocumented as "max retry attempts" — it is the total attempt budget. Proof:Config.new(max_retries: 0)→ zero HTTP calls, raisingBasecamp::ApiError: Request failed after 0 attempts.The rewrite also covers the contract corners the old text ignored: GET-only scope with the raw-path carve-outs; the read-timeout exception (Faraday maps read timeouts to
Faraday::TimeoutError < ServerError, caught ahead of theNetworkErrorrescue and classified as a status-less,retryable? == falseApiError— proven empirically: stubbed read timeout → 1 attempt, no retry, vsConnectionFailed→NetworkError, 3 attempts); uncapped exponential backoff;Retry-Afteronly via 429; the one-shot 401 refresh replay for all methods outside the budget; per-operation retry metadata being inert in Ruby; andretryable?as the actual transport predicate (the inverse of Python's "classification is only a hint" framing). Config comment, options table, env-var table (adding the missingBASECAMP_TIMEOUT/BASECAMP_MAX_RETRIESrows), and the same misstatements inconfig.rb's doc comments all aligned.Ruby suite: 908 runs, 2079 assertions, 0 failures; rubocop clean.
TypeScript — docstring examples pass strict typecheck
fetchAllPages/paginateAll@exampleblocks used bare(r) => r.json()—Promise<unknown>under Node fetch types, failing the parse callback'sPromise<T[]>in any strict/NodeNext project configured like this repo (the defect #507 fixed in the README, still present in source). Red proof, the extracted examples verbatim under the repo-shaped harness:Green with the README's proven form
(r) => r.json() as Promise<any[]>;tsc --noEmitclean; vitest 979 passed (local count).These are the only two bare
r.json()docstring sites intypescript/src(verified by grep — everything else is real code operating under the SDK's own types).Summary by cubic
Updates Ruby retry docs to match the actual transport behavior and fixes TypeScript pagination examples to pass strict typecheck. Clarifies
max_retriessemantics to prevent misleading guidance.retryable?-based (429, all 5xx, network); no retry on read timeouts/4xx;max_retries= total attempts (0 sends none); exponential backoff with jitter and 429Retry-After; one-shot 401 refresh; raw upload/download carve-outs; per-operation retry metadata ignored. Also alignconfig.rbcomments and README tables, addingBASECAMP_TIMEOUTandBASECAMP_MAX_RETRIES.fetchAllPages/paginateAll@exampleblocks typecheck by castingr.json()toPromise<any[]>.Written for commit 572bce9. Summary will update on new commits.