"""# Summary MongoDB integer-id repository — the persistent persistence adapter. --- The wire contract declares integer primary keys, while mongo-ops' ``BaseRepository`` allocates ``ObjectId`` keys. This adapter therefore talks to the shared ``MongoConnectionManager`` database directly (the Tier A connection lifecycle is reused; only the id strategy differs) and stores records with auto-incrementing integer ``_id`` values allocated from a ``_counters`` collection. The method surface mirrors the in-memory adapter exactly, so ``CrudsServiceAdaptor`` and the domain services are backend-agnostic. """ from typing import Any from mongo_ops import MongoConnectionManager from pydantic import BaseModel class IntIdMongoRepository: """Motor-backed repository with auto-increment integer ids. Attributes: collection (str): MongoDB collection name. document_cls (type[BaseModel]): Document model bound to this repo. """ def __init__(self, collection: str, document_cls: type[BaseModel]): """Bind the repository to a collection and document model. Args: collection (str): Collection name to operate on. document_cls (type[BaseModel]): Document model persisted here. """ self.collection = collection self.document_cls = document_cls @property def _col(self): """AsyncIOMotorCollection: The live collection handle.""" return MongoConnectionManager._database[self.collection] async def _next_id(self) -> int: """Allocate the next integer id from the shared counters collection. Returns: int: A monotonically increasing identifier. """ counters = MongoConnectionManager._database["_counters"] doc = await counters.find_one_and_update( {"_id": self.collection}, {"$inc": {"seq": 1}}, upsert=True, return_document=True, ) return int(doc["seq"]) def _to_doc(self, data: Any) -> BaseModel: """Coerce ``data`` into a document instance. Args: data (Any): Document instance or field mapping. Returns: BaseModel: Document built from ``data``. """ if isinstance(data, self.document_cls): return data return self.document_cls(**dict(data)) def _to_payload(self, doc: BaseModel, id: int | None = None) -> dict: """Serialize a document into a Mongo-ready payload. Args: doc (BaseModel): Document to serialize. id (int | None): Explicit ``_id``; taken from the doc when omitted. Returns: dict: Mapping with an integer ``_id`` key. """ payload = doc.model_dump() payload.pop("id", None) payload["_id"] = id if id is not None else doc.id return payload async def create(self, data: Any) -> BaseModel: """Persist a new document with a freshly allocated integer id. Args: data (Any): Document instance or field mapping (id ignored). Returns: BaseModel: The stored document with ``id`` assigned. """ doc = self._to_doc(data) new_id = await self._next_id() await self._col.insert_one(self._to_payload(doc, new_id)) doc.id = new_id return doc async def get_by_id(self, id: int) -> BaseModel | None: """Fetch one document by integer id. Args: id (int): Document identifier. Returns: BaseModel | None: The stored document, or ``None`` when absent. """ raw = await self._col.find_one({"_id": int(id)}) return self.document_cls.model_validate(raw) if raw else None async def get_many(self, filter: dict | None = None, **_: Any) -> list[BaseModel]: """List documents, optionally filtered by top-level equality. Args: filter (dict | None): Equality filter on document fields. Returns: list[BaseModel]: Matching documents in insertion order. """ cursor = self._col.find(filter or {}) return [self.document_cls.model_validate(raw) async for raw in cursor] async def update(self, id: int, data: Any) -> BaseModel | None: """Replace a document by integer id. Args: id (int): Document identifier. data (Any): Replacement document or field mapping. Returns: BaseModel | None: The stored document, or ``None`` when absent. """ doc = self._to_doc(data) payload = self._to_payload(doc, int(id)) result = await self._col.replace_one({"_id": int(id)}, payload) if result.matched_count == 0: return None doc.id = int(id) return doc async def patch(self, id: int, data: dict) -> BaseModel | None: """Partially update a document by integer id. Args: id (int): Document identifier. data (dict): Fields to merge into the stored document. Returns: BaseModel | None: The stored document, or ``None`` when absent. """ updates = {k: v for k, v in data.items() if k != "id"} result = await self._col.update_one({"_id": int(id)}, {"$set": updates}) if result.matched_count == 0: return None return await self.get_by_id(id) async def delete(self, id: int) -> bool: """Delete a document by integer id. Args: id (int): Document identifier. Returns: bool: ``True`` when a document was removed. """ result = await self._col.delete_one({"_id": int(id)}) return result.deleted_count > 0 async def delete_many(self, filter: dict | None = None) -> int: """Delete every document (optionally filtered by equality). Args: filter (dict | None): Equality filter on document fields. Returns: int: Number of documents removed. """ result = await self._col.delete_many(filter or {}) return result.deleted_count