diff --git a/IMPLEMENTATION_STATUS.md b/IMPLEMENTATION_STATUS.md index 5e67f65..b256953 100644 --- a/IMPLEMENTATION_STATUS.md +++ b/IMPLEMENTATION_STATUS.md @@ -63,16 +63,12 @@ ## КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ -### Auto-Migration Fix (database.py) -**Проблема**: RuntimeWarning: coroutine 'run_async_migrations' was never awaited -**Причина**: Alembic - синхронная библиотека, но получала async database URL -**Решение**: Конвертация async URL в sync перед передачей в Alembic -- `sqlite+aiosqlite://` → `sqlite:///` -- `postgresql+asyncpg://` → `postgresql://` - +### Migrations Strategy +**Решение**: Миграции запускаются в Dockerfile перед стартом сервера **Файлы**: -- `backend/src/app/infra/database.py:78-80` - URL conversion +- `backend/Dockerfile:34` - `alembic upgrade head` перед uvicorn - `backend/Dockerfile:25-26` - Copy alembic files to container +- Удален `run_migrations()` из кода приложения (clean separation) --- diff --git a/backend/Dockerfile b/backend/Dockerfile index 940590b..2c2390c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -30,4 +30,5 @@ RUN mkdir -p /app/data ENV PYTHONPATH=/app/src -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] +# Run migrations and start server +CMD ["sh", "-c", "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000"] diff --git a/backend/src/app/infra/database.py b/backend/src/app/infra/database.py index 1985628..b8af4b4 100644 --- a/backend/src/app/infra/database.py +++ b/backend/src/app/infra/database.py @@ -54,40 +54,3 @@ async def init_db() -> None: """Initialize database tables.""" async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) - - -def run_migrations() -> None: - """ - Run Alembic migrations synchronously. - - Alembic is sync-only, so we convert async URL to sync URL. - """ - from pathlib import Path - - from alembic import command - from alembic.config import Config - from loguru import logger - - # Find alembic.ini - alembic_ini_path = Path(__file__).parent.parent.parent.parent / "alembic.ini" - - if not alembic_ini_path.exists(): - logger.warning(f"alembic.ini not found at {alembic_ini_path}, skipping migrations") - return - - # Convert async database URL to sync for Alembic - sync_db_url = settings.database_url.replace("sqlite+aiosqlite://", "sqlite:///") - sync_db_url = sync_db_url.replace("postgresql+asyncpg://", "postgresql://") - - # Create Alembic config - alembic_cfg = Config(str(alembic_ini_path)) - alembic_cfg.set_main_option("sqlalchemy.url", sync_db_url) - - # Run migrations synchronously - logger.info("Running Alembic migrations...") - try: - command.upgrade(alembic_cfg, "head") - logger.info("Migrations completed successfully") - except Exception as e: - logger.error(f"Migration failed: {e}") - raise diff --git a/backend/src/app/main.py b/backend/src/app/main.py index 7441627..1aef244 100644 --- a/backend/src/app/main.py +++ b/backend/src/app/main.py @@ -7,7 +7,7 @@ from fastapi.middleware.cors import CORSMiddleware from app.api.v1 import assets, auth, batch, folders, shares, uploads from app.infra.config import get_settings -from app.infra.database import init_db, run_migrations +from app.infra.database import init_db settings = get_settings() @@ -15,8 +15,7 @@ settings = get_settings() @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan handler.""" - # Startup: Run migrations first - run_migrations() + # Startup await init_db() yield # Shutdown