Spaces:
Sleeping
Sleeping
File size: 4,799 Bytes
9d76e23 ca2bd00 9d76e23 ca2bd00 9d76e23 ca2bd00 9d76e23 ca2bd00 9d76e23 ca2bd00 9d76e23 ca2bd00 9d76e23 ca2bd00 9d76e23 ca2bd00 9d76e23 ca2bd00 9d76e23 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# 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
@property
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
@property
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]
@property
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]
@property
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() |