import asyncio from contextlib import asynccontextmanager, suppress import os import time from multiprocessing import freeze_support import uvicorn from fastapi import FastAPI from api.core import Exceptions, Gzip, Middleware from api.core.RedisPreheat import preheat_redis_cache from api.main import api_router from config.main import config async def _run_redis_preheat_background(): print('Redis 缓存预热中(后台)...') start = time.perf_counter() try: warmed_keys = await asyncio.to_thread(preheat_redis_cache) duration = time.perf_counter() - start print(f'Redis 缓存预热完成: {len(warmed_keys)} keys, {duration:.2f}s') except Exception as exc: print(f'Redis 缓存预热失败: {exc}') @asynccontextmanager async def lifespan(app: FastAPI): print('dcalc is starting...') print('Application starting...') app.state.redis_preheat_task = asyncio.create_task(_run_redis_preheat_background()) print('Application startup complete.') yield preheat_task = getattr(app.state, 'redis_preheat_task', None) if preheat_task and not preheat_task.done(): preheat_task.cancel() with suppress(asyncio.CancelledError): await preheat_task application = FastAPI(docs_url='/doc', redoc_url=None, lifespan=lifespan) application.add_exception_handler(Exception, Exceptions.all_exception_handler) Middleware.register_cors(application) Gzip.register_gzip_response(application) application.include_router(api_router) if __name__ == '__main__': freeze_support() os.environ['TZ'] = 'Asia/Shanghai' if os.name != 'nt': # Only call tzset on Unix-like systems, not on Windows time.tzset() uvicorn.run(app='main:application', host='0.0.0.0', port=config.PORT, workers=config.WORKERS, reload=False)