Files
docs/standards/mcp/templates/app/infra/db/repos/mongo_int.py
Vishesh 'ironeagle' Bangotra 406affcfcf feat: renumber lib reference into 4-pillar anatomy
Renumber the 15 reference docs into pillar groups (recipe -> anatomy):
- 01 Build Recipe (entry), 02 Composition Root
- domains: 10 Layering Rules
- contract: 20 Spec-First Routing, 21 CRUD Template, 22 Auth Integration
- interfaces/infra: 30 Infra Adapters
- UI: 40 UI: Auto-Rendered Admin & Custom Pages (new; @aetoskia packages,
  client template, x- catalog via react-openapi MCP module)
- pipelines: 50 Pipeline Scaffold, 51 Worker & Progress, 52 Human-in-the-Loop
- delivery/meta: 90 Drone Pipelines, 91 Versioning & Changelog,
  92 Genericity Matrix, 93 Library Registry, 94 Repository Inventory

MCP module names are unchanged (NN_ prefix stripped); all cross-references
(wiki, templates, hooks, registry) updated; lib index rewritten pillar-first;
build recipe bootstraps the client template. Bundle + HTML sites regenerated.
2026-10-19 17:42:55 +05:30

185 lines
6.0 KiB
Python

"""# 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