馃 New version release - #125
Merged
Merged
Conversation
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.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@smooai/fetch@4.0.0
Major Changes
1a84633: SMOODEV-3375: Retries never duplicate a side effect: they now check the HTTP method, and timeouts cancel the attempt. This changes a default, so it is a major release.
What was wrong. Retries ignored the HTTP method. A
POSTthat timed out or got a 429/5xx was sent again, up to twice more. In TypeScript the per-attempt timeout (mollitia'sTimeoutmodule) did not stop the losing request, so the first attempt kept running on the server while the retry sent it again. Image generation takes 20-50s against the 10s default timeout, so it billed three images and returned nothing. Any non-idempotent call (CRM writes, message sends, payments) could run its side effect more than once.New default, in all five languages:
GET,HEAD,OPTIONS,TRACE,PUTandDELETE(RFC 9110 搂9.2.2).POST,PATCHand any other method make exactly one attempt. You get that attempt's own error (HTTPResponseError/TimeoutErrorand the equivalents in other languages), not the retries-exhausted wrapper.Retry-Afteron aPOSTis not retried either.onRejectionis never called for these requests, so it cannot turn their retries back on.There are two ways to opt back in:
Idempotency-Keyheader, in any casing. The server then deduplicates.retry: { allowNonIdempotent: true }. The name in each language:allowNonIdempotentallow_non_idempotentAllowNonIdempotentEligibility is checked after the pre-request hooks and the auth provider run, so a hook can add the key. The client-side rate limiter's retry loop is unchanged, because it rejects requests before anything is sent.
Timeouts cancel the attempt. TypeScript now aborts each attempt with an
AbortController, combined with the caller's ownsignal, so the connection is closed before any retry. Afetchthat ignoressignalstill times out on schedule. Rust, Go, Python and .NET already cancelled the attempt. A new test in every language proves the first attempt's connection closes. Go now also waits for the cancelled attempt to finish before it retries. Python now puts a hard deadline on each attempt withasyncio.timeout. Before, httpx only had per-phase timeouts, so a server that kept sending bytes slowly never timed out.Also fixed: in TypeScript, a request the caller aborted is no longer retried.
Other API changes:
isIdempotentMethod,isRetryEligible,IDEMPOTENCY_KEY_HEADERand theRetryOptionstype.options.retryandFetchBuilder.withRetrynow take a partial. It is merged over the defaults, soretry: { allowNonIdempotent: true }keeps every other default.signalthatfetchreceives now combines the caller's signal with the timeout's. It is no longer the caller's own object.RetryOptionsgainsallow_non_idempotent. This breaks existingRetryOptions { .. }struct literals.RetryOptionsnow implementsDefault, so literals can end with..Default::default()from now on.is_idempotent_method,is_retry_eligibleandIDEMPOTENCY_KEY_HEADER.RetryOptions.AllowNonIdempotent,IsIdempotentMethodandIdempotencyKeyHeader./v4.RetryOptions.allow_non_idempotent.is_idempotent_methodandIDEMPOTENCY_KEY_HEADERare exported.RetryPolicy:AllowNonIdempotent,IsIdempotentMethod,IsRetryEligibleandIdempotencyKeyHeader.Microsoft.SourceLink.GitHubgoes to 10.0.303. 8.0.0 pulls inMicrosoft.Build.Tasks.Git8.0.0, which has an advisory against it (GHSA-23fw-v26w-5fgq), and a clean restore now fails with NU1902.Why a major version:
POSTretries quietly loses them.The shared
spec/retry-idempotency-corpus.jsonpins the rule. Each language's tests run it against a real local server and count the requests the server received.