Pattern-005: Transaction Management Pattern

Status

Proven

Context

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:

Pattern Description

The Transaction Management Pattern ensures consistent transaction handling with automatic commit/rollback, eliminating manual transaction management and reducing data consistency errors.

Core concept:

Implementation

Session Scope Pattern

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

Repository Transaction Integration

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

Service-Level Transaction Management

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

Error Handling with Transactions

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

Usage Guidelines

Benefits

Trade-offs

Anti-patterns to Avoid

References

Migration Notes

Consolidated from: