2 / 2
Sep 2024

I don’t understand what going on,I have done exactly what the docs says.
In my app you would see i have two files, main and database, I defined dd() in main which I passed to do_transactions.

The problems

  • 1: The transaction is committed even when that line of code was never executed, query returned None.
  • 2: The transaction is still committed when await session.commit_transaction() is removed or commented, query returned None.

when I comment/removed callback() the transaction does not get committed, what could be the problem?

main.py

import asyncio from motor.motor_asyncio import AsyncIOMotorDatabase async def test(): from .database import do_transactions async def dd(database: AsyncIOMotorDatabase) -> int: comments_collection = database.get_collection("comments") test_collection = database.get_collection("test") await test_collection.delete_many({}) await comments_collection.insert_one({"name": "test"}) return 449 query = await do_transactions(dd, bool) pprint(query) if __name__ == "__main__": asyncio.run(test())

database.py

from motor.motor_asyncio import ( AsyncIOMotorClient, AsyncIOMotorCollection, AsyncIOMotorDatabase, AsyncIOMotorClientSession, ) T = TypeVar("T") async def do_transactions( self, callback: Callable[[AsyncIOMotorDatabase], Coroutine[Any, Any, T]], return_type: Type[T], ) -> T | None: client=AsyncIOMotorClient("uri") async with await client.start_session() as session: db = session.client.get_database(name="database") try: async with session.start_transaction(): result = 777 # this works fine #result = await callback(db) transaction will be committed if this is uncommented if not isinstance(result, return_type): await session.abort_transaction() return None await session.commit_transaction() # removing this still commits the transaction if callback() is uncommented await session.end_session() return result except Exception as e: await session.abort_transaction() return None

session.start_transaction() is a context manager which automatically commits the transaction if the with-block completes without raising an exception. The motor docs don’t explain this well: AsyncIOMotorClientSession – Sequence of operations — Motor 3.5.1 documentation

But the pymongo docs do explain it, here: client_session – Logical sessions for sequential operations - PyMongo 4.9.0.dev0 documentation

Upon normal completion of with session.start_transaction() block, the transaction automatically calls ClientSession.commit_transaction(). If the block exits with an exception, the transaction automatically calls ClientSession.abort_transaction().