Fix: sync requests blocking event loop in async webhook/auth handlers#5432
Fix: sync requests blocking event loop in async webhook/auth handlers#5432atlas-agent-omi[bot] wants to merge 1 commit intomainfrom
Conversation
Use asyncio.to_thread() to offload synchronous requests.post/get calls to the thread pool in async webhook, auth, and oauth handlers. Previously these sync calls would block the entire asyncio event loop for up to 15 seconds per call, stalling all concurrent connections. Fixes #5431
Greptile SummaryThis PR correctly addresses the core concurrency problem: 6 synchronous Key changes:
Minor note: The three converted Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant WS as WebSocket Handler (async)
participant WH as webhooks.py
participant TP as Thread Pool (asyncio.to_thread)
participant EXT as External Webhook URL
Note over WS,EXT: After fix — realtime_transcript_webhook & send_audio_bytes_developer_webhook
WS->>WH: await realtime_transcript_webhook(uid, segments)
WH->>TP: asyncio.to_thread(requests.post, webhook_url, ...)
Note over WS: Event loop free to handle other connections
TP-->>EXT: HTTP POST (blocking, in thread)
EXT-->>TP: 200 OK
TP-->>WH: response
WH-->>WS: return
Last reviewed commit: 1b73b0b |
| } | ||
|
|
||
| token_response = requests.post(token_url, data=token_data) | ||
| token_response = await asyncio.to_thread(requests.post, token_url, data=token_data) |
There was a problem hiding this comment.
The three requests.post calls converted to asyncio.to_thread in this file (Google token exchange, Apple token exchange, and Firebase sign-in) lack timeout parameters. While these calls no longer block the event loop directly, they still consume thread-pool slots. Without a timeout, a slow or unresponsive endpoint could hang indefinitely. Consider adding a reasonable timeout (e.g., timeout=10) to match the pattern already established in webhooks.py:
| token_response = await asyncio.to_thread(requests.post, token_url, data=token_data) | |
| token_response = await asyncio.to_thread(requests.post, token_url, data=token_data, timeout=10) |
The same applies to the Apple token exchange at line 344 and Firebase sign-in at line 412.
Problem
Fixes #5431
6 synchronous
requests.post()/requests.get()calls insideasync deffunctions block the asyncio event loop for up to 15 seconds each. This stalls all concurrent WebSocket connections and HTTP handlers while waiting for external endpoints to respond.Critical path (webhooks — called during real-time transcription):
realtime_transcript_webhook()— called on every transcript segmentsend_audio_bytes_developer_webhook()— called for audio streamingLower priority (auth — one-time flows):
_exchange_google_code_for_oauth_credentials()— Google token exchange_exchange_apple_code_for_oauth_credentials()— Apple token exchange_generate_custom_token()— Firebase sign-inoauth_token()— external app setup checkFix
Wrapped all sync
requestscalls withasyncio.to_thread()to offload to the thread pool:Files Changed
backend/utils/webhooks.py— 2 calls fixedbackend/routers/auth.py— 3 calls fixedbackend/routers/oauth.py— 1 call fixedTesting
asyncio.to_thread()is stdlib (Python 3.9+), no new dependencies