~/problems / Async

Async fetcher with limits

On a phone? Coding is easier on a laptop: email this problem to yourself . Meanwhile: fight a boss.

medium assessment 4 levels ~45 min

Level 1 Fetch them all

A price checker calls a dozen shop APIs. Each call spends nearly all its time waiting on the network, so instead of one after another, run them together on one asyncio event loop.

Implement the coroutine async def fetch_all(jobs: list) -> list.

  • Each job is a zero-argument async function: await job() performs one fetch and returns its result.
  • Start every job right away so they all wait on the network at the same time, then return their results in the same order as jobs, whatever order they finish in.
  • fetch_all([]) returns [].
  • Don't block the event loop: no time.sleep, no threads. The tests call asyncio.run(fetch_all(jobs)).
def make(value, delay):
    async def job():
        await asyncio.sleep(delay)
        return value
    return job

jobs = [make("a", 0.03), make("b", 0.01), make("c", 0.02)]
await fetch_all(jobs)     # ["a", "b", "c"] after about 0.03 s, not 0.06 s

The tests also count how many jobs are waiting at the same moment: with 50 jobs, all 50 should be in flight together.

Show hint

asyncio.gather(*coroutines) runs them concurrently and returns the results in the order you passed them.

Level 2 unlocks when level 1 passes.

Level 3 unlocks when level 2 passes.

Level 4 unlocks when level 3 passes.

Topic: Async and await. One thread, many waiting tasks: gather, limits with semaphores, timeouts, cancellation and retries.

Read the visual guide
0:00
Ctrl ' run · Ctrl ↵ submit
esc