Fix the blocking call scan for async handlers

Review the AI's codeEasy10 min

Your task

An AI wrote a FastAPI quote endpoint as async def and called requests.get inside it. That call blocks, and an async def handler runs on the event loop, the one thread that runs every coroutine. Under load, every endpoint in the service stalled behind it. Your team now scans the route table for async handlers that call a blocking library.

An assistant wrote find_blocking_async_handlers(handlers). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • handlers: one record per route handler, in the form "name|kind|calls", like "get_quote|async|requests.get,resp.json". The kind is normally async (declared async def) or sync (a plain def, which FastAPI runs in a thread pool). The calls are a comma separated list of what the handler calls, possibly empty. handlers itself can be empty.
  • Return the names of the handlers that block the event loop.

Rules the tests check:

  • Split each record on |. Skip a record that does not have exactly 3 parts.
  • Trim whitespace at both ends of the name, the kind and the calls. Skip a record whose name is empty after trimming.
  • Only async handlers count. The kind compares without case, so ASYNC is async. Skip every other kind.
  • Split the calls on , and trim each call. Ignore empty calls.
  • A call blocks when it is exactly time.sleep or exactly open, or when it starts with requests., urllib., psycopg2. or socket., the dot included. Calls compare with case. No other call blocks.
  • Report a handler once when at least one of its calls blocks.
  • Return the names in input order. A name on two flagged records appears twice.

Examples

find_blocking_async_handlers(handlers: list[str]) -> list[str]
Example 1
Inputfind_blocking_async_handlers(["get_quote|async|requests.get,resp.json", "healthz|async|", "list_items|sync|requests.post"])
Output["get_quote"]
Example 2
Inputfind_blocking_async_handlers(["get_quote|async|httpx.AsyncClient.get,resp.json", "sleeper|async|time.sleep,log.info"])
Output["sleeper"]
Example 3
Inputfind_blocking_async_handlers(["a|async|requests.get", "b|async|urllib.request.urlopen", "c|async|psycopg2.connect", "d|async|socket.recv"])
Output["a", "b", "c", "d"]