From 621e8bd7b6804abf60893668939e69929448a8c0 Mon Sep 17 00:00:00 2001 From: kfj001 Date: Sun, 28 Jun 2026 13:23:00 -0700 Subject: [PATCH] buildable docker compose --- backend/app/main.py | 24 ++++++++++++++++++++++++ docker-entrypoint.sh | 2 +- nginx.conf.template | 4 ++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/backend/app/main.py b/backend/app/main.py index e6564b6..cc4701f 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -13,6 +13,29 @@ from app.user_models import User from app.api import events, auth, station_config, history, team, community, shows, storage, underwriters, stats +def _cleanup_orphaned_sequences(sync_conn): + """Drop model sequences whose backing table no longer exists. + + Prevents 'duplicate key value violates unique constraint' errors when + create_all() tries to recreate a SERIAL-backed sequence for a table + whose original sequence was left behind after a drop/recreate cycle. + Only runs on PostgreSQL; no-op for SQLite. + """ + import sqlalchemy as sa + + if sync_conn.dialect.name != "postgresql": + return + + inspector = sa.inspect(sync_conn) + existing_tables = set(inspector.get_table_names()) + + for table in Base.metadata.tables.values(): + expected_seq = f"{table.name}_id_seq" + if table.name not in existing_tables: + sync_conn.execute(sa.text(f"DROP SEQUENCE IF EXISTS {expected_seq}")) + print(f" → Dropped orphaned sequence {expected_seq}") + + def _migrate_add_missing_columns(sync_conn): """Add missing columns to existing tables (startup migration — no Alembic). @@ -82,6 +105,7 @@ async def _ensure_station_config(session): async def lifespan(app: FastAPI): # Create tables on startup, then patch any missing columns async with engine.begin() as conn: + await conn.run_sync(_cleanup_orphaned_sequences) await conn.run_sync(Base.metadata.create_all) await conn.run_sync(_migrate_add_missing_columns) diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index df72a93..dfdb8fc 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -2,7 +2,7 @@ # Render config templates with environment variables, then start nginx. set -e -envsubst '${API_UPSTREAM}' < /etc/nginx/conf.d/nginx.conf.template > /etc/nginx/conf.d/default.conf +sed "s|__API_UPSTREAM__|${API_UPSTREAM}|g" /etc/nginx/conf.d/nginx.conf.template > /etc/nginx/conf.d/default.conf envsubst '${API_PUBLIC_URL}' < /usr/share/nginx/html/config.json.template > /usr/share/nginx/html/config.json exec nginx -g 'daemon off;' diff --git a/nginx.conf.template b/nginx.conf.template index deec1ff..65ac465 100644 --- a/nginx.conf.template +++ b/nginx.conf.template @@ -1,6 +1,6 @@ # Map ISO timestamp to date-only string for daily log rotation map $time_iso8601 $log_date { - ~^(?\d{4}-\d{2}-\d{2}) $date; + "~^(?\d{4}-\d{2}-\d{2})" $date; default "unknown"; } @@ -26,7 +26,7 @@ server { # Proxy API calls to the backend service location /api/ { - proxy_pass ${API_UPSTREAM}; + proxy_pass __API_UPSTREAM__; proxy_set_header Host $host; proxy_set_header Origin $http_origin; proxy_set_header Referer $http_referer;