Automated Action 025900c849 Fix database migration conflicts and improve migration safety
Changes:
- Enhanced migration 002 with column existence checks to prevent duplicate column errors
- Added comprehensive migration 003 that syncs database with current model state
- Modified application startup to avoid conflicts between create_all() and Alembic
- Added proper table/column existence checking in migrations
- Improved migration safety for production environments
- Removed automatic table creation when database already exists (relies on migrations)

This resolves the 'duplicate column name' error by ensuring migrations
check for existing columns before attempting to add them.
2025-06-24 19:46:05 +00:00

99 lines
3.0 KiB
Python

from pathlib import Path
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
import logging
from app.db.session import engine
from app.db.base import Base
from app.routes import auth, videos, transcription, translation, voice_cloning, video_processing, profile
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
try:
# Create database directory
logger.info("Starting application initialization...")
storage_dir = Path("/app/storage/db")
storage_dir.mkdir(parents=True, exist_ok=True)
logger.info(f"Created storage directory: {storage_dir}")
# Import all models to ensure they're registered with Base
# Only create tables if database doesn't exist (for development)
# In production, use Alembic migrations instead
db_path = storage_dir / "db.sqlite"
if not db_path.exists():
logger.info("Database file doesn't exist, creating initial tables...")
Base.metadata.create_all(bind=engine)
else:
logger.info("Database file exists, skipping table creation (use Alembic for migrations)")
logger.info("Database initialization completed")
yield
except Exception as e:
logger.error(f"Error during application startup: {e}")
raise
app = FastAPI(
title="AI Video Dubbing API",
description="Backend API for AI-powered video dubbing with voice cloning and translation",
version="1.0.0",
lifespan=lifespan
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["*"],
expose_headers=["*"]
)
# Include routers
app.include_router(auth.router, prefix="/auth", tags=["Authentication"])
app.include_router(profile.router, prefix="/profile", tags=["Profile"])
app.include_router(videos.router, prefix="/videos", tags=["Videos"])
app.include_router(transcription.router, prefix="/transcription", tags=["Transcription"])
app.include_router(translation.router, prefix="/translation", tags=["Translation"])
app.include_router(voice_cloning.router, prefix="/voice", tags=["Voice Cloning"])
app.include_router(video_processing.router, prefix="/process", tags=["Video Processing"])
@app.get("/")
async def root():
return {
"title": "AI Video Dubbing API",
"documentation": "/docs",
"health": "/health"
}
@app.get("/health")
async def health_check():
return {
"status": "healthy",
"service": "AI Video Dubbing API",
"database": "connected"
}
@app.get("/test")
async def test_endpoint():
logger.info("Test endpoint called")
return {
"message": "API is working correctly",
"timestamp": "2024-01-01T00:00:00Z",
"status": "success"
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)