from contextlib import asynccontextmanager from typing import AsyncIterator from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.exc import IntegrityError from fooder.repository.user import UserRepository from fooder.repository.product import ProductRepository from fooder.repository.user_product_usage import UserProductUsageRepository from fooder.repository.user_settings import UserSettingsRepository from fooder.repository.diary import DiaryRepository from fooder.repository.meal import MealRepository from fooder.repository.entry import EntryRepository from fooder.repository.preset import PresetRepository from fooder.repository.preset_entry import PresetEntryRepository from fooder.domain import ( User, Product, UserProductUsage, UserSettings, Diary, Meal, Entry, Preset, PresetEntry, ) from fooder.exc import Conflict class Repository: def __init__(self, session: AsyncSession): self.session = session self.user = UserRepository(User, session) self.product = ProductRepository(Product, session) self.user_product_usage = UserProductUsageRepository(UserProductUsage, session) self.user_settings = UserSettingsRepository(UserSettings, session) self.diary = DiaryRepository(Diary, session) self.meal = MealRepository(Meal, session) self.entry = EntryRepository(Entry, session) self.preset = PresetRepository(Preset, session) self.preset_entry = PresetEntryRepository(PresetEntry, session) async def commit(self) -> None: try: await self.session.commit() except IntegrityError: raise Conflict() async def rollback(self) -> None: await self.session.rollback() @asynccontextmanager async def transaction(self) -> AsyncIterator["Repository"]: try: yield self await self.commit() except Exception: await self.rollback() raise