并发与异步执行
FastAPI relies on an asynchronous event loop (asyncio). Blocking operations—such as CPU-heavy pandas calculations, synchronous database ORM calls, or synchronous network requests (yfinance, requests)—must never be executed directly on the main event loop thread.
The run_sync Helper (concurrency.py)
Fonrex provides run_sync() in concurrency.py as a unified abstraction for executing blocking synchronous code safely inside worker threads:
from concurrency import run_sync
# Offloads a synchronous blocking function to the default ThreadPoolExecutor
result = await run_sync(sync_blocking_function, arg1, arg2, kwarg=value)
Internal Architecture
FastAPI Event Loop (Async)
│
├─► Async HTTP Router Endpoint (async def)
│ │
│ ├─► Calls run_sync(DatabaseService.get_asset, ticker)
│ │ │
│ │ ▼
│ │ ThreadPoolExecutor Worker Thread
│ │ (执行同步 SQLAlchemy ORM 查询)
│ │ │
│ │ ◄─────┘
│ │
│ ◄─────┘ Event Loop remains unblocked for other requests!
│
└─► Processes other concurrent HTTP / WS connections
Guidelines for Developers
- Async Routers: Define router functions with
async def. - Synchronous Services: If a service method interacts with
DatabaseServiceoryfinance, invoke it viaawait run_sync(service.method, ...)from the router. - Async Services: Services that utilize
redis.asyncioorhttpx.AsyncClient(NewsService,CanaryMonitor) can be awaited directly withoutrun_sync.