(app: FastAPI)
| 54 | |
| 55 | @asynccontextmanager |
| 56 | async def lifespan(app: FastAPI): |
| 57 | import asyncio |
| 58 | |
| 59 | from ..core.auto_registration import ( |
| 60 | AutoRegistrationCoordinator, |
| 61 | register_auto_registration_coordinator, |
| 62 | ) |
| 63 | from ..core.db_logs import cleanup_database_logs |
| 64 | from ..database.init_db import initialize_database |
| 65 | from .auto_quick_refresh_scheduler import auto_quick_refresh_scheduler |
| 66 | from .routes.registration import run_auto_registration_batch, recover_interrupted_registration_tasks |
| 67 | |
| 68 | try: |
| 69 | initialize_database() |
| 70 | except Exception as exc: |
| 71 | logger.warning("Database init failed: %s", exc) |
| 72 | |
| 73 | loop = asyncio.get_running_loop() |
| 74 | task_manager.set_loop(loop) |
| 75 | |
| 76 | recovered_registration_tasks = await asyncio.to_thread(recover_interrupted_registration_tasks) |
| 77 | if recovered_registration_tasks.get("running_recovered") or recovered_registration_tasks.get("pending_recovered"): |
| 78 | logger.warning( |
| 79 | "Recovered interrupted registration tasks on startup: running=%s pending=%s", |
| 80 | recovered_registration_tasks.get("running_recovered", 0), |
| 81 | recovered_registration_tasks.get("pending_recovered", 0), |
| 82 | ) |
| 83 | |
| 84 | global auto_registration_coordinator |
| 85 | auto_registration_coordinator = AutoRegistrationCoordinator( |
| 86 | trigger_callback=run_auto_registration_batch, |
| 87 | ) |
| 88 | register_auto_registration_coordinator(auto_registration_coordinator) |
| 89 | auto_registration_coordinator.start() |
| 90 | |
| 91 | async def run_log_cleanup_once() -> None: |
| 92 | try: |
| 93 | result = await asyncio.to_thread(cleanup_database_logs) |
| 94 | logger.info( |
| 95 | "Log cleanup done: deleted=%s remaining=%s", |
| 96 | result.get("deleted_total", 0), |
| 97 | result.get("remaining", 0), |
| 98 | ) |
| 99 | except Exception as exc: |
| 100 | logger.warning("Log cleanup failed: %s", exc) |
| 101 | |
| 102 | async def periodic_log_cleanup() -> None: |
| 103 | while True: |
| 104 | try: |
| 105 | await asyncio.sleep(3600) |
| 106 | await run_log_cleanup_once() |
| 107 | except asyncio.CancelledError: |
| 108 | break |
| 109 | except Exception as exc: |
| 110 | logger.warning("Periodic log cleanup failed: %s", exc) |
| 111 | |
| 112 | await run_log_cleanup_once() |
| 113 | app.state.log_cleanup_task = asyncio.create_task(periodic_log_cleanup()) |
nothing calls this directly
no test coverage detected