new api service and logic implemented
This commit is contained in:
192
Services/MongoDb/database.py
Normal file
192
Services/MongoDb/database.py
Normal file
@@ -0,0 +1,192 @@
|
||||
"""
|
||||
MongoDB database connection and operations.
|
||||
|
||||
This module provides MongoDB connection management with:
|
||||
1. Connection pooling
|
||||
2. Lifecycle management
|
||||
3. Error handling
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any, List, Union, Callable
|
||||
from contextlib import contextmanager
|
||||
from pymongo import MongoClient
|
||||
from pymongo.results import InsertOneResult, DeleteResult, UpdateResult
|
||||
from pymongo.cursor import Cursor
|
||||
from functools import wraps
|
||||
|
||||
from AllConfigs.NoSqlDatabase.configs import MongoConfig
|
||||
|
||||
|
||||
class MongoInsertMixin:
|
||||
"""Mixin for MongoDB insert operations."""
|
||||
|
||||
def insert_one(self, document: Dict[str, Any]) -> InsertOneResult:
|
||||
"""Insert a single document."""
|
||||
return self.collection.insert_one(document)
|
||||
|
||||
def insert_many(self, documents: List[Dict[str, Any]]) -> List[InsertOneResult]:
|
||||
"""Insert multiple documents."""
|
||||
return self.collection.insert_many(documents)
|
||||
|
||||
|
||||
class MongoFindMixin:
|
||||
"""Mixin for MongoDB find operations."""
|
||||
|
||||
def find_one(self, filter_query: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""Find a single document."""
|
||||
return self.collection.find_one(filter_query)
|
||||
|
||||
def find_many(self, filter_query: Dict[str, Any]) -> Cursor:
|
||||
"""Find multiple documents."""
|
||||
return self.collection.find(filter_query)
|
||||
|
||||
|
||||
class MongoUpdateMixin:
|
||||
"""Mixin for MongoDB update operations."""
|
||||
|
||||
def update_one(
|
||||
self, filter_query: Dict[str, Any], update: Dict[str, Any]
|
||||
) -> UpdateResult:
|
||||
"""Update a single document."""
|
||||
return self.collection.update_one(filter_query, update)
|
||||
|
||||
def update_many(
|
||||
self, filter_query: Dict[str, Any], update: Dict[str, Any]
|
||||
) -> UpdateResult:
|
||||
"""Update multiple documents."""
|
||||
return self.collection.update_many(filter_query, update)
|
||||
|
||||
|
||||
class MongoDeleteMixin:
|
||||
"""Mixin for MongoDB delete operations."""
|
||||
|
||||
def delete_one(self, filter_query: Dict[str, Any]) -> DeleteResult:
|
||||
"""Delete a single document."""
|
||||
return self.collection.delete_one(filter_query)
|
||||
|
||||
def delete_many(self, filter_query: Dict[str, Any]) -> DeleteResult:
|
||||
"""Delete multiple documents."""
|
||||
return self.collection.delete_many(filter_query)
|
||||
|
||||
|
||||
class MongoAggregateMixin:
|
||||
"""Mixin for MongoDB aggregate operations."""
|
||||
|
||||
def aggregate(self, pipeline: List[Dict[str, Any]]) -> Cursor:
|
||||
"""Execute an aggregation pipeline."""
|
||||
return self.collection.aggregate(pipeline)
|
||||
|
||||
|
||||
class MongoDBHandler(
|
||||
MongoInsertMixin,
|
||||
MongoFindMixin,
|
||||
MongoUpdateMixin,
|
||||
MongoDeleteMixin,
|
||||
MongoAggregateMixin,
|
||||
):
|
||||
"""Handler for MongoDB operations with connection management."""
|
||||
|
||||
_instance = None
|
||||
_client: Optional[MongoClient] = None
|
||||
|
||||
def __new__(cls):
|
||||
"""Implement singleton pattern for database connection."""
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize MongoDB connection if not already initialized."""
|
||||
if not self._client:
|
||||
# Build connection options
|
||||
connection_kwargs = {
|
||||
"host": MongoConfig.URL,
|
||||
"maxPoolSize": 50, # Maximum number of connections in the pool
|
||||
"minPoolSize": 10, # Minimum number of connections in the pool
|
||||
"maxIdleTimeMS": 30000, # Maximum time a connection can be idle (30 seconds)
|
||||
"waitQueueTimeoutMS": 2000, # How long a thread will wait for a connection
|
||||
"serverSelectionTimeoutMS": 5000, # How long to wait for server selection
|
||||
}
|
||||
self._client = MongoClient(**connection_kwargs)
|
||||
|
||||
# Test connection
|
||||
self._client.admin.command("ping")
|
||||
|
||||
def __enter__(self):
|
||||
"""Context manager entry point."""
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
"""Context manager exit point - ensures connection is properly closed."""
|
||||
try:
|
||||
if self._client:
|
||||
self._client.close()
|
||||
self._client = None
|
||||
except Exception:
|
||||
# Silently pass any errors during shutdown
|
||||
pass
|
||||
return False # Don't suppress any exceptions
|
||||
|
||||
def close(self):
|
||||
"""Close MongoDB connection."""
|
||||
try:
|
||||
if self._client:
|
||||
self._client.close()
|
||||
self._client = None
|
||||
except Exception:
|
||||
# Silently pass any errors during shutdown
|
||||
pass
|
||||
|
||||
@property
|
||||
def client(self) -> MongoClient:
|
||||
"""Get MongoDB client."""
|
||||
return self._client
|
||||
|
||||
def get_database(self, database_name: str = None):
|
||||
"""Get MongoDB database."""
|
||||
db_name = database_name or MongoConfig.DATABASE_NAME
|
||||
return self._client[db_name]
|
||||
|
||||
def get_collection(self, collection_name: str, database_name: str = None):
|
||||
"""Get MongoDB collection."""
|
||||
database = self.get_database(database_name)
|
||||
return database[collection_name]
|
||||
|
||||
# Create a function to get the singleton instance
|
||||
@classmethod
|
||||
@contextmanager
|
||||
def get_mongodb(cls):
|
||||
"""Get or create the MongoDB singleton instance as a context manager."""
|
||||
instance = cls()
|
||||
try:
|
||||
yield instance
|
||||
finally:
|
||||
try:
|
||||
if instance._client:
|
||||
instance._client.close()
|
||||
instance._client = None
|
||||
except Exception:
|
||||
# Silently pass any errors during shutdown
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def with_mongodb(cls, func: Callable):
|
||||
"""Decorator to automatically handle MongoDB connection context.
|
||||
|
||||
Usage:
|
||||
@MongoDBHandler.with_mongodb
|
||||
def my_function(db, *args, **kwargs):
|
||||
# db is the MongoDB instance
|
||||
pass
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
with cls.get_mongodb() as db:
|
||||
return func(db, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
# Create a singleton instance for backward compatibility
|
||||
mongodb = MongoDBHandler()
|
||||
Reference in New Issue
Block a user