From 89dffcabbdb9d6152a3e43975c9f2ad4a16a3ef6 Mon Sep 17 00:00:00 2001 From: doas root Date: Wed, 12 Nov 2025 00:10:58 +0300 Subject: [PATCH] fix(): add flush to uow.add to ensure db sync --- src/template_project/adapters/unit_of_work.py | 3 +- .../application/common/unit_of_work.py | 2 +- .../application/user/interactors/sign_up.py | 4 +- .../migrations/versions/__init__.py | 0 .../migrations/versions/ad80834713c3_.py | 51 +++++++++++++++++++ src/template_project/web_api/entry_point.py | 1 - src/template_project/web_api/routes/user.py | 2 - 7 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 src/template_project/migrations/versions/__init__.py create mode 100644 src/template_project/migrations/versions/ad80834713c3_.py diff --git a/src/template_project/adapters/unit_of_work.py b/src/template_project/adapters/unit_of_work.py index f3b94ed..a37e6da 100644 --- a/src/template_project/adapters/unit_of_work.py +++ b/src/template_project/adapters/unit_of_work.py @@ -10,8 +10,9 @@ class DefaultUnitOfWork(UnitOfWork): self._session = session @override - def add(self, *entities: Any) -> None: + async def add(self, *entities: Any) -> None: self._session.add_all(entities) + await self._session.flush() @override async def commit(self) -> None: diff --git a/src/template_project/application/common/unit_of_work.py b/src/template_project/application/common/unit_of_work.py index ab6bdfe..f366b2e 100644 --- a/src/template_project/application/common/unit_of_work.py +++ b/src/template_project/application/common/unit_of_work.py @@ -4,7 +4,7 @@ from typing import Any, Protocol class UnitOfWork(Protocol): @abstractmethod - def add(self, *entities: Any) -> None: + async def add(self, *entities: Any) -> None: raise NotImplementedError @abstractmethod diff --git a/src/template_project/application/user/interactors/sign_up.py b/src/template_project/application/user/interactors/sign_up.py index 2e7dac2..de4f7c5 100644 --- a/src/template_project/application/user/interactors/sign_up.py +++ b/src/template_project/application/user/interactors/sign_up.py @@ -43,7 +43,9 @@ class UserSignUpInteractor: response = UserSignUpResponse(access_token=crypted_access_token) - self.unit_of_work.add(user, access_token) + for entity in (user, access_token): # preserve creation order + await self.unit_of_work.add(entity) + await self.unit_of_work.commit() return response diff --git a/src/template_project/migrations/versions/__init__.py b/src/template_project/migrations/versions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/template_project/migrations/versions/ad80834713c3_.py b/src/template_project/migrations/versions/ad80834713c3_.py new file mode 100644 index 0000000..aad5347 --- /dev/null +++ b/src/template_project/migrations/versions/ad80834713c3_.py @@ -0,0 +1,51 @@ +"""empty message + +Revision ID: ad80834713c3 +Revises: +Create Date: 2025-11-12 00:03:31.080899 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'ad80834713c3' +down_revision: Union[str, Sequence[str], None] = None +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('users', + sa.Column('id', sa.UUID(), nullable=False), + sa.Column('email', sa.String(), nullable=False), + sa.Column('hashed_password', sa.String(), nullable=False), + sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('email') + ) + op.create_table('access_token', + sa.Column('id', sa.UUID(), nullable=False), + sa.Column('user_id', sa.UUID(), nullable=False), + sa.Column('revoked', sa.Boolean(), nullable=False), + sa.Column('expires_in', sa.DateTime(timezone=True), nullable=False), + sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('access_token') + op.drop_table('users') + # ### end Alembic commands ### diff --git a/src/template_project/web_api/entry_point.py b/src/template_project/web_api/entry_point.py index e2a01df..4ed8c51 100644 --- a/src/template_project/web_api/entry_point.py +++ b/src/template_project/web_api/entry_point.py @@ -1,7 +1,6 @@ import argparse import asyncio import os -import selectors import sys from collections.abc import AsyncIterator from contextlib import asynccontextmanager diff --git a/src/template_project/web_api/routes/user.py b/src/template_project/web_api/routes/user.py index 42af749..cc98a95 100644 --- a/src/template_project/web_api/routes/user.py +++ b/src/template_project/web_api/routes/user.py @@ -1,5 +1,3 @@ -import asyncio - from dishka import FromDishka from dishka.integrations.fastapi import DishkaRoute from fastapi import APIRouter