Spaces:
Sleeping
Sleeping
| # Import required MongoDB libraries and utilities | |
| from pymongo import MongoClient | |
| from pymongo.database import Database | |
| from pymongo.collection import Collection | |
| from pymongo.errors import ConnectionFailure, ConfigurationError, OperationFailure | |
| import logging | |
| from typing import Optional | |
| from src.config.settings import ( | |
| MONGO_URI, MONGO_DB_NAME, MONGO_NEWS_COLLECTION_NAME, | |
| MONGO_SESSIONS_COLLECTION_NAME, MONGO_TRACKING_COLLECTION_NAME | |
| ) | |
| # Set up logger for this module | |
| logger = logging.getLogger(__name__) | |
| class MongoDB: | |
| """ | |
| MongoDB connection handler implementing the Singleton pattern. | |
| This class manages the connection to MongoDB Atlas and provides access to collections. | |
| """ | |
| # Class variables to store singleton instance and connection details | |
| _instance: Optional['MongoDB'] = None | |
| _client: Optional[MongoClient] = None | |
| _db: Optional[Database] = None | |
| def __new__(cls): | |
| """ | |
| Implements the Singleton pattern by ensuring only one instance of MongoDB class exists. | |
| Returns the existing instance if it exists, otherwise creates a new one. | |
| """ | |
| if cls._instance is None: | |
| cls._instance = super(MongoDB, cls).__new__(cls) | |
| return cls._instance | |
| def __init__(self): | |
| """ | |
| Initialize the MongoDB connection if it hasn't been established yet. | |
| Only creates a new connection if _client is None. | |
| """ | |
| if self._client is None: | |
| self._connect() | |
| def _connect(self): | |
| """ | |
| Establishes connection to MongoDB Atlas. | |
| Handles connection errors and sets up the database instance. | |
| Does not raise exceptions if connection fails - allows graceful degradation. | |
| """ | |
| try: | |
| logger.info(f"Connecting to MongoDB Atlas: DB='{MONGO_DB_NAME}'") | |
| # Create MongoDB client with 5 second timeout for server selection | |
| self._client = MongoClient(MONGO_URI, serverSelectionTimeoutMS=5000) | |
| # Verify connection by running a simple command | |
| self._client.admin.command('ismaster') | |
| # Set up database instance | |
| self._db = self._client[MONGO_DB_NAME] | |
| logger.info("Successfully connected to MongoDB.") | |
| except (ConnectionFailure, ConfigurationError) as e: | |
| logger.warning(f"MongoDB connection failed: {e}") | |
| self._client = None | |
| self._db = None | |
| # Don't raise the exception - allow the application to continue without MongoDB | |
| except Exception as e: | |
| logger.warning(f"An unexpected error occurred during MongoDB connection: {e}") | |
| self._client = None | |
| self._db = None | |
| # Don't raise the exception - allow the application to continue without MongoDB | |
| def db(self) -> Optional[Database]: | |
| """ | |
| Property to get the database instance. | |
| Returns None if the connection is not available. | |
| Returns: | |
| Database: MongoDB database instance or None if not connected | |
| """ | |
| if self._db is None: | |
| # Try to connect once, but don't keep retrying | |
| try: | |
| self._connect() | |
| except Exception as e: | |
| logger.warning(f"Failed to establish MongoDB connection: {e}") | |
| return None | |
| return self._db | |
| def news_collection(self) -> Collection: | |
| """ | |
| Property to get the news collection. | |
| Returns: | |
| Collection: MongoDB collection for news data | |
| """ | |
| return self.db[MONGO_NEWS_COLLECTION_NAME] | |
| def sessions_collection(self) -> Collection: | |
| """ | |
| Property to get the sessions collection. | |
| Returns: | |
| Collection: MongoDB collection for session data | |
| """ | |
| return self.db[MONGO_SESSIONS_COLLECTION_NAME] | |
| def tracking_collection(self) -> Collection: | |
| """ | |
| Property to get the tracking collection. | |
| Returns: | |
| Collection: MongoDB collection for user feedback/tracking data | |
| """ | |
| return self.db[MONGO_TRACKING_COLLECTION_NAME] | |
| def close(self): | |
| """ | |
| Closes the MongoDB connection and cleans up resources. | |
| Handles any errors during connection closure. | |
| """ | |
| if self._client: | |
| try: | |
| self._client.close() | |
| logger.info("MongoDB connection closed.") | |
| except Exception as e: | |
| logger.error(f"Error closing MongoDB connection: {e}", exc_info=True) | |
| finally: | |
| self._client = None | |
| self._db = None | |
| # Create a singleton instance of MongoDB for use throughout the application | |
| mongodb = MongoDB() |