"""video-render FastAPI entry — health + lifespan (worker loop spawn).""" from __future__ import annotations import asyncio import logging import os from contextlib import asynccontextmanager import redis.asyncio as aioredis from fastapi import FastAPI import worker from _shared.heartbeat import heartbeat_loop logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s %(message)s") logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): worker_task = asyncio.create_task(worker.worker_loop()) hb_redis = aioredis.from_url(os.getenv("REDIS_URL", "redis://192.168.45.54:6379"), decode_responses=False) hb_task = asyncio.create_task(heartbeat_loop(hb_redis, "video-render", "render", worker.stats)) logger.info("video-render lifespan 시작") try: yield finally: for t in (worker_task, hb_task): t.cancel() try: await t except asyncio.CancelledError: pass await hb_redis.aclose() logger.info("video-render lifespan 종료") app = FastAPI(lifespan=lifespan) @app.get("/health") def health(): return {"ok": True, "service": "video-render"}