Skip to content

fix: default timeout on outbound fetch calls - #91

Open
hugo-ccabral wants to merge 2 commits into
mainfrom
fix/fetch-default-timeout
Open

fix: default timeout on outbound fetch calls#91
hugo-ccabral wants to merge 2 commits into
mainfrom
fix/fetch-default-timeout

Conversation

@hugo-ccabral

@hugo-ccabral hugo-ccabral commented Jul 24, 2026

Copy link
Copy Markdown

Summary

  • Mirrors fix: default timeout on outbound fetch calls blocks#392. Nothing bounded how long an outbound fetch() could hang — a stuck upstream connection (VTEX/CDN holding a TCP connection open) pins request context in memory until the runtime kills the isolate.
  • Adds commerce/utils/fetchTimeout.ts: withFetchTimeout() / withTimeoutSignal(), native AbortSignal.timeout() composed with AbortSignal.any() so a caller-supplied signal is never dropped. Default 10s.
  • Wires it into the VTEX _fetch fallback + fetchSafe/fetchAPI, Magento's magentoFetch, Resend's sendEmail, Shopify's createGraphqlClient fallback, and the Google Fonts loader.
  • This repo pins @decocms/start@6.6.1, which predates the equivalent export in blocks, so the helper is duplicated locally for now. Once the dependency bumps past the version shipping sdk/fetchTimeout, replace this file with a re-export and delete the copy.

Test plan

  • Manually verified against the identical, already-tested implementation in fix: default timeout on outbound fetch calls blocks#392 (all touched files there are byte-identical mirrors of this repo's)
  • Could not run this repo's test/typecheck locally (no node_modules installed in this environment) — recommend CI confirms magento/client.ts, resend/tests/send.test.ts, vtex/client.ts, vtex/utils/fetch.ts, shopify/utils/graphql.ts, website/loaders/fonts/googleFonts.ts all still pass

🤖 Generated with Claude Code


Summary by cubic

Add a default 10s timeout to all outbound fetch() calls to stop hung upstreams from pinning request context. Ban bare fetch to enforce the wrapper; the timeout helper is duplicated locally until @decocms/start exposes it.

  • Bug Fixes

    • Added commerce/utils/fetchTimeout.ts with withFetchTimeout() and withTimeoutSignal() (10s default).
    • Applied to VTEX (client default, fetchSafe, sitemap proxy), Magento (magentoFetch), Resend (sendEmail), Shopify (GraphQL client fallback), and the Google Fonts loader.
    • Updated Resend tests to expect an AbortSignal in requests.
  • Refactors

    • Added Biome noRestrictedGlobals rule to ban bare fetch in vtex/**, magento/**, resend/**, shopify/**, and website/** (excluding hooks/tests); use the wrapped clients or withFetchTimeout.
    • Introduced a FetchFn alias and replaced typeof fetch annotations to satisfy the lint rule.

Written for commit cbf588e. Summary will update on new commits.

Review in cubic

Mirrors decocms/blocks#392. Nothing bounded how long an outbound fetch
could hang, letting a stuck upstream connection pin request context in
memory until the runtime kills the isolate. Adds commerce/utils/fetchTimeout.ts
(AbortSignal.timeout composed with any caller signal via AbortSignal.any,
10s default) and wires it into VTEX, Magento, Resend, Shopify, and the
Google Fonts loader's raw fetch call sites.

This repo pins @decocms/start@6.6.1, which predates the equivalent export
in blocks, so the helper is duplicated here for now -- replace with a
re-export from @decocms/start/sdk/fetchTimeout once that dependency is
bumped past the version shipping it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@hugo-ccabral
hugo-ccabral requested a review from a team July 24, 2026 14:33
…apper

A future dev can still bypass fetchSafe/vtexFetch/magentoFetch/etc. by typing
bare fetch(), silently losing the timeout. Adds a Biome noRestrictedGlobals
override banning the fetch global in vtex/magento/resend/shopify/website
(excluding client-side hooks and tests), pointing at the sanctioned client.

The ban also catches `typeof fetch` in type positions, so introduces a
FetchFn alias (commerce/utils/fetchTimeout.ts) to replace those annotations.
Also fixes a real gap the rule caught: vtex/utils/sitemap.ts's fetchImpl
defaulted to raw fetch, same unbounded-hang risk as the other call sites.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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