Interview question
Fetch URLs concurrently with a bound, timeout, and structured cleanup
Implements bounded asyncio HTTP concurrency with one client, per-call deadlines, TaskGroup ownership, and deterministic cleanup.
TL;DR
Implements bounded asyncio HTTP concurrency with one client, per-call deadlines, TaskGroup ownership, and deterministic cleanup.
asyncio Semaphore, TaskGroup, timeout ownership, shared client lifetime, result ordering, cancellation, and bounded resource use.
Practice the problem like a real interview: restate, reason, implement, and test.
Implement fetch_all(urls, limit, timeout_seconds) using one httpx.AsyncClient. Run at most limit requests at once, keep results in input order, fail the operation when any request fails, and ensure all sibling tasks and the client are cleaned up. Do not create every connection without a concurrency bound.
Next in Python Backend Practical Labs: Validated FastAPI create
urls=[A,B,C], limit=2 -> at most two client.get calls active
B fails -> siblings are cancelled and awaited
results -> returned in A,B,C input order
asyncio.timeout and raise_for_status inside the owned task.import asyncio
import httpx
async def fetch_all(
urls: list[str], limit: int, timeout_seconds: float
) -> list[bytes]:
if limit <= 0:
raise ValueError("limit must be positive")
semaphore = asyncio.Semaphore(limit)
results: list[bytes | None] = [None] * len(urls)
async with httpx.AsyncClient() as client:
async def fetch(index: int, url: str) -> None:
async with semaphore:
async with asyncio.timeout(timeout_seconds):
response = await client.get(url)
response.raise_for_status()
results[index] = response.content
async with asyncio.TaskGroup() as group:
for index, url in enumerate(urls):
group.create_task(fetch(index, url))
return [value for value in results if value is not None]
The work is O(n) requests with O(n) task and result bookkeeping, while active remote calls are bounded by limit.
gather over unbounded coroutines can overwhelm sockets and the dependency.create_task calls can outlive the operation.Spot a weak answer, missing edge case, or clearer explanation? Send it in.
Say thanks with a standalone, one-time $5 contribution. No account required.