database fix
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# STAGE 1: BUILDER
|
||||
# This stage installs build tools and Python dependencies
|
||||
FROM python:3.13.7-slim AS builder
|
||||
FROM python:3.12.11-slim AS builder
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
DEBIAN_FRONTEND=noninteractive
|
||||
@@ -23,7 +23,7 @@ RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# STAGE 2: FINAL
|
||||
# This is the lean, final image for running the application
|
||||
FROM python:3.13.7-slim
|
||||
FROM python:3.12.11-slim
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
DEBIAN_FRONTEND=noninteractive
|
||||
@@ -49,6 +49,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
jpegoptim \
|
||||
libsox-fmt-mp3 \
|
||||
lame \
|
||||
libportaudio2 \
|
||||
libportaudiocpp0 \
|
||||
portaudio19-dev \
|
||||
# Runtime libraries for Python packages
|
||||
libxml2 \
|
||||
# Process manager
|
||||
@@ -59,7 +62,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
WORKDIR /app
|
||||
|
||||
# Copy installed Python packages from the builder stage
|
||||
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
|
||||
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
|
||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
||||
|
||||
# Copy supervisor config and application code
|
||||
|
||||
35
main.py
35
main.py
@@ -22,7 +22,7 @@ import sys
|
||||
import re
|
||||
import importlib
|
||||
import collections.abc
|
||||
|
||||
import time
|
||||
import ocrmypdf
|
||||
import pypdf
|
||||
import pytesseract
|
||||
@@ -40,6 +40,7 @@ from sqlalchemy import (Column, DateTime, Integer, String, Text,
|
||||
create_engine, delete, event)
|
||||
from sqlalchemy.orm import Session, declarative_base, sessionmaker
|
||||
from sqlalchemy.pool import NullPool
|
||||
from sqlalchemy.exc import OperationalError
|
||||
from string import Formatter
|
||||
from werkzeug.utils import secure_filename
|
||||
from typing import List as TypingList
|
||||
@@ -1250,7 +1251,37 @@ async def download_kokoro_models_if_missing():
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
logger.info("Application starting up...")
|
||||
Base.metadata.create_all(bind=engine)
|
||||
# Base.metadata.create_all(bind=engine)
|
||||
|
||||
create_attempts = 3
|
||||
for attempt in range(1, create_attempts + 1):
|
||||
try:
|
||||
# use engine.begin() to ensure the DDL runs in a connection/transaction context
|
||||
with engine.begin() as conn:
|
||||
Base.metadata.create_all(bind=conn)
|
||||
logger.info("Database tables ensured (create_all succeeded).")
|
||||
break
|
||||
except OperationalError as oe:
|
||||
# Some SQLite drivers raise an OperationalError when two processes try to create the same table at once.
|
||||
msg = str(oe).lower()
|
||||
# If we see "already exists" we treat this as a race and retry briefly.
|
||||
if "already exists" in msg or ("table" in msg and "already exists" in msg):
|
||||
logger.warning(
|
||||
"Database table creation race detected (attempt %d/%d): %s. Retrying...",
|
||||
attempt,
|
||||
create_attempts,
|
||||
oe,
|
||||
)
|
||||
time.sleep(0.5)
|
||||
continue
|
||||
else:
|
||||
logger.exception("Database initialization failed with OperationalError.")
|
||||
raise
|
||||
except Exception:
|
||||
logger.exception("Unexpected error during DB initialization.")
|
||||
raise
|
||||
|
||||
|
||||
load_app_config()
|
||||
|
||||
# Download required models on startup
|
||||
|
||||
Reference in New Issue
Block a user