Integrate scheduler service into FastAPI lifespan

- Start scheduler service during app startup
- Gracefully stop scheduler during app shutdown
- Track scheduler in initialized services
- Scheduler starts after background loader
- Scheduler shutdown with 5s timeout
This commit is contained in:
2026-01-31 15:10:42 +01:00
parent 63da2daa53
commit eb0f6cdc85

View File

@@ -117,7 +117,8 @@ async def lifespan(_application: FastAPI):
initialized = {
'database': False,
'services': False,
'background_loader': False
'background_loader': False,
'scheduler': False
}
# Startup
@@ -265,6 +266,18 @@ async def lifespan(_application: FastAPI):
initialized['background_loader'] = True
logger.info("Background loader service started")
# Initialize and start scheduler service
from src.server.services.scheduler_service import get_scheduler_service
scheduler_service = get_scheduler_service()
try:
await scheduler_service.start()
initialized['scheduler'] = True
logger.info("Scheduler service started")
except Exception as e:
logger.warning("Failed to start scheduler service: %s", e)
# Continue - scheduler is optional
# Run media scan only on first run
await perform_media_scan_if_needed(background_loader)
else:
@@ -322,7 +335,23 @@ async def lifespan(_application: FastAPI):
elapsed = time.monotonic() - shutdown_start
return max(0.0, SHUTDOWN_TIMEOUT - elapsed)
# 1. Stop background loader service (only if initialized)
# 1. Stop scheduler service (only if initialized)
if initialized['scheduler']:
try:
from src.server.services.scheduler_service import get_scheduler_service
scheduler_service = get_scheduler_service()
logger.info("Stopping scheduler service...")
await asyncio.wait_for(
scheduler_service.stop(),
timeout=min(5.0, remaining_time())
)
logger.info("Scheduler service stopped")
except asyncio.TimeoutError:
logger.warning("Scheduler service shutdown timed out")
except Exception as e: # pylint: disable=broad-exception-caught
logger.error("Error stopping scheduler service: %s", e, exc_info=True)
# 2. Stop background loader service (only if initialized)
if initialized['background_loader']:
try:
from src.server.utils.dependencies import _background_loader_service
@@ -338,7 +367,7 @@ async def lifespan(_application: FastAPI):
except Exception as e: # pylint: disable=broad-exception-caught
logger.error("Error stopping background loader service: %s", e, exc_info=True)
# 2. Broadcast shutdown notification via WebSocket
# 3. Broadcast shutdown notification via WebSocket
try:
ws_service = get_websocket_service()
logger.info("Broadcasting shutdown notification to WebSocket clients...")
@@ -352,7 +381,7 @@ async def lifespan(_application: FastAPI):
except Exception as e: # pylint: disable=broad-exception-caught
logger.error("Error during WebSocket shutdown: %s", e, exc_info=True)
# 3. Shutdown download service and persist active downloads
# 4. Shutdown download service and persist active downloads
try:
from src.server.services.download_service import ( # noqa: E501
_download_service_instance,