diff --git a/api/app/database.py b/api/app/database.py index 8505025..cc72d14 100644 --- a/api/app/database.py +++ b/api/app/database.py @@ -1,22 +1,62 @@ """MongoDB connection management using Beanie ODM.""" +import asyncio + +import structlog from beanie import init_beanie from pymongo import AsyncMongoClient from app.config import settings +logger = structlog.get_logger() + client: AsyncMongoClient | None = None +MAX_RETRIES = 10 +RETRY_DELAY = 3 # seconds + async def init_db() -> None: - """Initialize MongoDB connection and Beanie ODM.""" + """Initialize MongoDB connection and Beanie ODM with retry logic.""" global client - client = AsyncMongoClient(settings.mongo_uri) - db = client[settings.mongo_db] - from app.models import ALL_MODELS - await init_beanie(database=db, document_models=ALL_MODELS) + for attempt in range(1, MAX_RETRIES + 1): + try: + client = AsyncMongoClient( + settings.mongo_uri, + serverSelectionTimeoutMS=5000, + connectTimeoutMS=5000, + socketTimeoutMS=10000, + ) + db = client[settings.mongo_db] + await init_beanie(database=db, document_models=ALL_MODELS) + if attempt > 1: + logger.info("Database connected after retry", attempt=attempt) + return + except Exception as exc: + if attempt == MAX_RETRIES: + logger.error( + "Database connection failed after all retries", + attempts=MAX_RETRIES, + error=str(exc), + ) + raise + logger.warning( + "Database not ready, retrying...", + attempt=attempt, + max_retries=MAX_RETRIES, + delay=RETRY_DELAY, + error=str(exc), + ) + # Close failed client before retrying + if client: + try: + await client.close() + except Exception: + pass + client = None + await asyncio.sleep(RETRY_DELAY) async def close_db() -> None: