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()