Current state
io/itunes/fetchItunesItems.ts calls fetch(...) on the iTunes lookup endpoint inside withRetry with no AbortController signal. withRetry only triggers when fetch throws, but a response that stalls mid-stream — connection accepted, data never arrives — never throws. The call blocks indefinitely, bypassing the retry safety net and hanging the entire static site build with no error output or progress indication.
Ideal state
- Each iTunes
fetch call is given an AbortController signal with an explicit deadline (e.g. 30 s).
- When the deadline fires,
fetch throws an AbortError, withRetry treats it as a transient failure, and the retry logic fires as intended.
- A build that cannot receive an iTunes response within the deadline fails with a descriptive error rather than hanging.
Out of scope
- Changing the retry count or backoff strategy in
withRetry (separate concern).
- Adding timeouts to other external fetches (each is a separate issue).
Starting points
io/itunes/fetchItunesItems.ts — the fetch(...) call on the iTunes endpoint (~lines 85–87)
io/utils/retry.ts — withRetry entry point; shows what error types trigger a retry
QA plan
- Read
io/itunes/fetchItunesItems.ts and confirm an AbortController with setTimeout (or equivalent) is created before the fetch call and its signal is passed as a fetch option.
- Confirm the timer is cleared (e.g.
clearTimeout) when the response resolves successfully.
- Confirm the timeout duration is a named constant, not a magic number.
- Run the build (
npm run build or equivalent) — expect it to complete without hanging.
Done when
The iTunes fetch call in fetchItunesItems.ts carries an AbortController signal with an explicit deadline so a stalled response aborts and surfaces as an error rather than silently blocking the build.
Current state
io/itunes/fetchItunesItems.tscallsfetch(...)on the iTunes lookup endpoint insidewithRetrywith noAbortControllersignal.withRetryonly triggers whenfetchthrows, but a response that stalls mid-stream — connection accepted, data never arrives — never throws. The call blocks indefinitely, bypassing the retry safety net and hanging the entire static site build with no error output or progress indication.Ideal state
fetchcall is given anAbortControllersignal with an explicit deadline (e.g. 30 s).fetchthrows anAbortError,withRetrytreats it as a transient failure, and the retry logic fires as intended.Out of scope
withRetry(separate concern).Starting points
io/itunes/fetchItunesItems.ts— thefetch(...)call on the iTunes endpoint (~lines 85–87)io/utils/retry.ts—withRetryentry point; shows what error types trigger a retryQA plan
io/itunes/fetchItunesItems.tsand confirm anAbortControllerwithsetTimeout(or equivalent) is created before thefetchcall and itssignalis passed as a fetch option.clearTimeout) when the response resolves successfully.npm run buildor equivalent) — expect it to complete without hanging.Done when
The iTunes
fetchcall infetchItunesItems.tscarries anAbortControllersignal with an explicit deadline so a stalled response aborts and surfaces as an error rather than silently blocking the build.