codejump
MediumPro challengeJavaScriptTypeScript

Node.js — Cancel Slow Work with AbortController

Node.jsBackendPromisesCancellation

tinyserve can fetch an update from several mirrors. Asking all of them and keeping the fastest is
easy; what separates a robust version from a leaky one is cancelling the others, and giving
up when everyone is too slow. Node uses the web's
[`AbortController`](https://nodejs.org/api/globals.html#class-abortcontroller) for that:
fetch, fs.readFile, timers/promises, child_process, streams and events.once all
accept a signal.

Your task

Write async fastestMirror(mirrors, timeoutMs, download):

  • Call download(mirror, { signal }) for every mirror at once. It returns a promise of the

mirror's data, rejects if the mirror is down, and rejects with an AbortError as soon as
signal aborts.

  • Resolve with the first successful download. A mirror that is down does not win.
  • Once there is a winner, abort every download still running.
  • If nothing succeeded after timeoutMs, abort everything and reject with a TimeoutError

(error.name === 'TimeoutError').

  • If every mirror fails before the deadline, reject with the AggregateError of

[`Promise.any`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/any).

The driver reports the result (or the error's name) and which downloads were aborted while
still running.

Tools

  • AbortSignal.timeout(ms) — a signal that aborts by itself with a TimeoutError.
  • AbortSignal.any([a, b]) — aborts when any of the signals aborts (Node 20.3+).
  • signal.reason — what it was aborted with.

Sample tests

Test #1Fastest wins, the other is cancelled
Input: [[{"name":"eu","delay":10},{"name":"us","delay":400}],1000]
Output: {"result":"data from eu","aborted":["us"]}
Test #2Deadline
Input: [[{"name":"eu","delay":400},{"name":"us","delay":500}],100]
Output: {"error":"TimeoutError","aborted":["eu","us"]}
Test #3A quick failure does not win
Input: [[{"name":"eu","delay":5,"fails":true},{"name":"us","delay":50}],1000]
Output: {"result":"data from us","aborted":[]}
Test #4Every mirror is down
Input: [[{"name":"eu","delay":5,"fails":true},{"name":"us","delay":10,"fails":true}],1000]
Output: {"error":"AggregateError","aborted":[]}