Skip to content

Transactions

Every repository method (get_items, create_item, etc.) wraps its operation in a transaction via self.transaction(). self.transaction() reuses an existing session from the context if one exists, otherwise creates a new one.

Explicit transaction

You can open an explicit transaction when you need to group several operations:

async with repository.transaction():
    product1 = await repository.create_item(ProductTable(name="Laptop", price=999.99))
    product2 = await repository.create_item(ProductTable(name="Mouse", price=29.99))

If any operation raises an exception, the entire transaction is rolled back.

Reusing an existing session

Nested transaction() calls yield the same session — no new savepoint is created:

async with repository.transaction(), repository.transaction():
    items = [item async for item in repository.get_items()]

Nested transactions (savepoints)

nested_transaction() creates a SQLAlchemy savepoint. When no outer session exists it starts a new session with a savepoint. On exception the savepoint is rolled back, leaving any outer transaction unaffected:

try:
    async with repository.nested_transaction():
        await repository.create_item(ProductTable(name="Keyboard", price=79.99))
        raise ValueError("Rollback nested")
except ValueError:
    pass

# Keyboard was rolled back; previous items remain

This is useful for partial rollback inside a larger transaction. See Multi-Repo Transactions for container-level savepoints.