Proven
Manual transaction handling creates inconsistent data states and error-prone code. When operations involve multiple database changes, ensuring atomicity and proper rollback on failure becomes critical. The Transaction Management Pattern addresses:
The Transaction Management Pattern ensures consistent transaction handling with automatic commit/rollback, eliminating manual transaction management and reducing data consistency errors.
Core concept:
from contextlib import asynccontextmanager
from services.database.session_factory import AsyncSessionFactory
@asynccontextmanager
async def transaction_scope():
"""Context manager for automatic transaction handling"""
async with AsyncSessionFactory.session_scope() as session:
try:
async with session.begin():
yield session
# Automatic commit on successful exit
except Exception:
# Automatic rollback on exception
raise
class BaseRepository:
"""Repository with integrated transaction handling"""
def __init__(self, session: AsyncSession):
self.session = session
async def create(self, **kwargs) -> Any:
"""Create with automatic transaction handling"""
async with self.session.begin():
instance = self.model(**kwargs)
self.session.add(instance)
# Automatic commit via context manager
return instance
async def update(self, id: str, **kwargs) -> Optional[Any]:
"""Update with transaction safety"""
async with self.session.begin():
result = await self.session.execute(
select(self.model).where(self.model.id == id)
)
instance = result.scalar_one_or_none()
if instance:
for key, value in kwargs.items():
setattr(instance, key, value)
# Automatic commit via context manager
return instance
class ProjectService:
"""Service with transaction management for complex operations"""
def __init__(self, project_repo: ProjectRepository, workflow_repo: WorkflowRepository):
self.project_repo = project_repo
self.workflow_repo = workflow_repo
async def create_project_with_workflows(self, project_data: dict, workflows: List[dict]) -> Project:
"""Complex operation requiring transaction coordination"""
async with AsyncSessionFactory.session_scope() as session:
async with session.begin():
# Create project
project = await self.project_repo.create(**project_data)
# Create associated workflows
for workflow_data in workflows:
workflow_data['project_id'] = project.id
await self.workflow_repo.create(**workflow_data)
# All operations commit together or rollback together
return project
async def safe_operation_with_transaction():
"""Example of proper transaction error handling"""
try:
async with AsyncSessionFactory.session_scope() as session:
async with session.begin():
# Perform operations
project = await project_repo.create(name="Test Project")
await workflow_repo.create(project_id=project.id, name="Test Workflow")
# Operations committed automatically on success
return project
except IntegrityError as e:
logger.error(f"Database integrity violation: {e}")
raise ProjectCreationError("Project creation failed due to data constraints")
except Exception as e:
logger.error(f"Unexpected error in transaction: {e}")
raise ProjectCreationError("Project creation failed")
AsyncSessionFactory.session_scope() for session managementsession.begin() contextsession.commit() or session.rollback() manuallysession.commit() callsservices/database/repositories.pyConsolidated from:
archive/PATTERN-INDEX-legacy.md#transaction-management-pattern - Status and location information