buildable docker compose
This commit is contained in:
@@ -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
|
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):
|
def _migrate_add_missing_columns(sync_conn):
|
||||||
"""Add missing columns to existing tables (startup migration — no Alembic).
|
"""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):
|
async def lifespan(app: FastAPI):
|
||||||
# Create tables on startup, then patch any missing columns
|
# Create tables on startup, then patch any missing columns
|
||||||
async with engine.begin() as conn:
|
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(Base.metadata.create_all)
|
||||||
await conn.run_sync(_migrate_add_missing_columns)
|
await conn.run_sync(_migrate_add_missing_columns)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Render config templates with environment variables, then start nginx.
|
# Render config templates with environment variables, then start nginx.
|
||||||
set -e
|
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
|
envsubst '${API_PUBLIC_URL}' < /usr/share/nginx/html/config.json.template > /usr/share/nginx/html/config.json
|
||||||
|
|
||||||
exec nginx -g 'daemon off;'
|
exec nginx -g 'daemon off;'
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
# Map ISO timestamp to date-only string for daily log rotation
|
# Map ISO timestamp to date-only string for daily log rotation
|
||||||
map $time_iso8601 $log_date {
|
map $time_iso8601 $log_date {
|
||||||
~^(?<date>\d{4}-\d{2}-\d{2}) $date;
|
"~^(?<date>\d{4}-\d{2}-\d{2})" $date;
|
||||||
default "unknown";
|
default "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ server {
|
|||||||
|
|
||||||
# Proxy API calls to the backend service
|
# Proxy API calls to the backend service
|
||||||
location /api/ {
|
location /api/ {
|
||||||
proxy_pass ${API_UPSTREAM};
|
proxy_pass __API_UPSTREAM__;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header Origin $http_origin;
|
proxy_set_header Origin $http_origin;
|
||||||
proxy_set_header Referer $http_referer;
|
proxy_set_header Referer $http_referer;
|
||||||
|
|||||||
Reference in New Issue
Block a user