""" MongoDB database connection management. This module handles MongoDB connection with fail-fast approach. The application will terminate if MongoDB is not accessible at startup. """ import sys from typing import Optional from pymongo import MongoClient from pymongo.database import Database from pymongo.errors import ConnectionFailure, ServerSelectionTimeoutError from ..config.settings import get_mongodb_url, get_mongodb_database_name # Global variables for singleton pattern _client: Optional[MongoClient] = None _database: Optional[Database] = None def create_mongodb_client() -> MongoClient: """ Create MongoDB client with connection validation. Returns: MongoClient: Connected MongoDB client Raises: SystemExit: If connection fails (fail-fast approach) """ mongodb_url = get_mongodb_url() try: # Create client with short timeout for fail-fast behavior client = MongoClient( mongodb_url, serverSelectionTimeoutMS=5000, # 5 seconds timeout connectTimeoutMS=5000, socketTimeoutMS=5000 ) # Test connection by running admin command client.admin.command('ping') print(f"Successfully connected to MongoDB at {mongodb_url}") return client except (ConnectionFailure, ServerSelectionTimeoutError) as e: print(f"ERROR: Failed to connect to MongoDB at {mongodb_url}") print(f"Connection error: {str(e)}") print("MongoDB is required for this application. Please ensure MongoDB is running and accessible.") sys.exit(1) except Exception as e: print(f"ERROR: Unexpected error connecting to MongoDB: {str(e)}") sys.exit(1) def get_database() -> Database: """ Get MongoDB database instance (singleton pattern). Returns: Database: MongoDB database instance This function implements singleton pattern to ensure only one database connection is created throughout the application lifecycle. """ global _client, _database if _database is None: if _client is None: _client = create_mongodb_client() database_name = get_mongodb_database_name() _database = _client[database_name] print(f"Connected to database: {database_name}") return _database def close_database_connection(): """ Close MongoDB database connection. This function should be called during application shutdown to properly close the database connection. """ global _client, _database if _client is not None: _client.close() _client = None _database = None print("MongoDB connection closed") def get_mongodb_client() -> Optional[MongoClient]: """ Get the raw MongoDB client instance. Returns: MongoClient or None: MongoDB client instance if connected This is primarily for testing purposes or advanced use cases where direct client access is needed. """ return _client def test_database_connection() -> bool: """ Test if database connection is working. Returns: bool: True if connection is working, False otherwise This function can be used for health checks. """ try: db = get_database() # Simple operation to test connection db.command('ping') return True except Exception: return False