From 5e62b3d308d7202cf80e94b53d0ded15444f888d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=91=D0=BB=D0=B8?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2?= Date: Fri, 29 May 2026 12:30:39 +0300 Subject: [PATCH] Fix worker startup via FastAPI lifespan, remove manual start from server script --- backend/main.py | 40 +++++++++++++++++++++++++++++----------- backend/queue.py | 9 ++++++--- start_server.py | 7 +------ 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/backend/main.py b/backend/main.py index 62e5baa..d6721ba 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,6 +1,7 @@ """FastAPI backend для сервиса транскрибации.""" import json +from contextlib import asynccontextmanager from pathlib import Path from typing import List, Optional @@ -18,17 +19,8 @@ from backend.queue import ( get_processed_tree, read_file_content, set_progress_callback, -) - -app = FastAPI(title="Transcription Service", version="1.0.0") - -# CORS -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], + start_workers, + stop_workers, ) # WebSocket менеджер @@ -57,6 +49,32 @@ manager = ConnectionManager() set_progress_callback(manager.broadcast) +@asynccontextmanager +async def lifespan(app: FastAPI): + """Управление жизненным циклом приложения.""" + print("🚀 Запуск рабочих процессов...") + start_workers(num_workers=1) + yield + print("🛑 Остановка рабочих процессов...") + stop_workers() + + +app = FastAPI( + title="Transcription Service", + version="1.0.0", + lifespan=lifespan, +) + +# CORS +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + # === API Endpoints === @app.get("/", response_class=HTMLResponse) diff --git a/backend/queue.py b/backend/queue.py index 521d36c..87e3921 100644 --- a/backend/queue.py +++ b/backend/queue.py @@ -138,23 +138,26 @@ _workers: List[asyncio.Task] = [] async def _worker_loop(): """Рабочий цикл обработки.""" + print("[Worker] Рабочий процесс запущен и ждёт задачи...") while True: try: task_id, file_path = await _queue.get() + print(f"[Worker] Получена задача: {task_id}") await process_file(file_path, task_id) _queue.task_done() + print(f"[Worker] Задача завершена: {task_id}") except asyncio.CancelledError: + print("[Worker] Остановка рабочего процесса") break except Exception as e: print(f"[Worker Error] {e}") def start_workers(num_workers: int = 1): - """Запускает рабочих.""" + """Запускает рабочих в текущем event loop.""" global _workers - loop = asyncio.get_event_loop() for i in range(num_workers): - task = loop.create_task(_worker_loop()) + task = asyncio.create_task(_worker_loop()) _workers.append(task) diff --git a/start_server.py b/start_server.py index 99bf969..a3edb6d 100644 --- a/start_server.py +++ b/start_server.py @@ -7,18 +7,13 @@ from pathlib import Path sys.path.insert(0, str(Path(__file__).parent)) import uvicorn -from backend.main import app -from backend.queue import start_workers if __name__ == "__main__": print("🚀 Запуск сервиса транскрибации...") print("📡 Сервер: http://localhost:8000") print("") - # Запускаем фоновых рабочих - start_workers(num_workers=1) - - # Запускаем сервер + # Запускаем сервер (рабочие запускаются через lifespan в backend/main.py) uvicorn.run( "backend.main:app", host="0.0.0.0",