From 07cc9e1886d24a81fb159855230d6508aec78361 Mon Sep 17 00:00:00 2001 From: Vansh-Sharma27 Date: Sun, 26 Jul 2026 19:27:54 +0530 Subject: [PATCH] fix(embedding): run warmup in a worker thread to avoid blocking the event loop warmup() can download an hf: tokenizer, which is blocking network I/O. Both call sites live in async functions (the API lifespan and run_deriver), so a slow download would stall the event loop during startup, delaying telemetry tasks and signal handling. Wrap both calls in asyncio.to_thread; warmup itself synchronizes via the singleton lock, so running it in a worker thread is safe. --- src/deriver/__main__.py | 4 +++- src/main.py | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/deriver/__main__.py b/src/deriver/__main__.py index 4a904092..5ff09af2 100644 --- a/src/deriver/__main__.py +++ b/src/deriver/__main__.py @@ -73,9 +73,11 @@ async def run_deriver(): await validate_embedding_schema(engine) # Eagerly build the embedding client so an hf: tokenizer download # happens here, not on the first reconciler call under the lock. + # Run it in a worker thread so the blocking download doesn't stall + # the event loop. from src.embedding_client import embedding_client - embedding_client.warmup() + await asyncio.to_thread(embedding_client.warmup) await main() finally: # Shutdown telemetry (flush CloudEvents buffer) diff --git a/src/main.py b/src/main.py index 4fa65819..a15bc691 100644 --- a/src/main.py +++ b/src/main.py @@ -1,3 +1,4 @@ +import asyncio import logging import re import time @@ -118,8 +119,10 @@ async def lifespan(_: FastAPI): await validate_embedding_schema(engine) # Eagerly build the embedding client so an hf: tokenizer download happens - # here, not on the first request under the singleton lock. - embedding_client.warmup() + # here, not on the first request under the singleton lock. Run it in a + # worker thread: the download is blocking network I/O and would otherwise + # stall the event loop (signal handling, telemetry) during startup. + await asyncio.to_thread(embedding_client.warmup) try: await init_cache()