refactor: migrate to keyword-based repository config, add nested transactions and tests
This commit is contained in:
64
examples/nested_transactions.py
Normal file
64
examples/nested_transactions.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import asyncio
|
||||
|
||||
from metaorm import BaseFilter, BaseRepository, BaseTable, Field, RepositorySettings
|
||||
|
||||
|
||||
class ProductTable(BaseTable, table=True):
|
||||
__tablename__ = "products"
|
||||
|
||||
id: int | None = Field(default=None, primary_key=True)
|
||||
name: str
|
||||
price: float
|
||||
|
||||
|
||||
class ProductFilter(BaseFilter):
|
||||
name: str | None = None
|
||||
|
||||
|
||||
class ProductRepository(BaseRepository, table=ProductTable, filter_=ProductFilter):
|
||||
pass
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
settings = RepositorySettings(dsn="sqlite+aiosqlite:///:memory:")
|
||||
repository = ProductRepository(settings=settings)
|
||||
|
||||
await repository.create_tables()
|
||||
|
||||
# Standalone nested transaction: rollback only the inner scope
|
||||
try:
|
||||
async with repository.nested_transaction():
|
||||
await repository.create_item(ProductTable(name="Laptop", price=999.99))
|
||||
await repository.create_item(ProductTable(name="Mouse", price=29.99))
|
||||
raise ValueError("Simulated error inside nested transaction")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
count = await repository.get_items_count()
|
||||
print(f"Items after standalone nested rollback: {count}") # 0
|
||||
|
||||
# Nested transaction inside an outer transaction
|
||||
async with repository.transaction():
|
||||
await repository.create_item(ProductTable(name="Keyboard", price=79.99))
|
||||
|
||||
try:
|
||||
async with repository.nested_transaction():
|
||||
await repository.create_item(
|
||||
ProductTable(name="Monitor", price=299.99),
|
||||
)
|
||||
raise ValueError("Nested rollback")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Monitor is rolled back, Keyboard stays in the outer transaction
|
||||
items = [item async for item in repository.get_items()]
|
||||
print(f"Items after partial rollback: {len(items)}") # 1
|
||||
print(items[0].name) # Keyboard
|
||||
|
||||
# Verify committed results
|
||||
all_items = [item async for item in repository.get_items()]
|
||||
print(f"Final items: {[item.name for item in all_items]}") # ["Keyboard"]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user