diff --git a/platform/backend/app/main.py b/platform/backend/app/main.py index f5e6414..9e84522 100644 --- a/platform/backend/app/main.py +++ b/platform/backend/app/main.py @@ -10,7 +10,7 @@ from typing import Any, Mapping from uuid import uuid4 import httpx -from sqlalchemy import asc, desc, select, func +from sqlalchemy import asc, desc, select, func, text from sqlalchemy.orm import aliased from sqlalchemy.exc import SQLAlchemyError @@ -25,7 +25,6 @@ from .analytics.daily_card_generator import ( recalibrate_daily_card_confidence_payload, update_runtime_market_calibration, ) -from .analytics.worldcup_seed import seed_venues from .analytics.localization import ( localize_city, localize_country, @@ -3669,10 +3668,40 @@ async def relay_redis_events() -> None: await redis.close() +async def ensure_daily_recommendation_snapshot_schema() -> None: + """確保每日作戰室快照表存在,避免正式資料庫漏 migration 時造成推薦 API 500。""" + + async with SessionFactory() as session: + await session.execute( + text( + ''' + CREATE TABLE IF NOT EXISTS daily_recommendation_snapshots ( + id VARCHAR(64) PRIMARY KEY, + target_date VARCHAR(10) NOT NULL, + generated_at TIMESTAMPTZ NOT NULL, + items_count INTEGER NOT NULL DEFAULT 0, + live_market_count INTEGER NOT NULL DEFAULT 0, + pre_market_count INTEGER NOT NULL DEFAULT 0, + payload JSONB NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() + ) + ''' + ) + ) + await session.execute( + text( + 'CREATE INDEX IF NOT EXISTS idx_daily_recommendation_snapshots_target_date ' + 'ON daily_recommendation_snapshots (target_date)' + ) + ) + await session.commit() + logger.info('Daily recommendation snapshot schema bootstrap completed.') + + @app.on_event('startup') async def on_startup() -> None: - seed_summary = await seed_venues() - logger.info('World Cup seed/schema bootstrap completed: %s', seed_summary) + await ensure_daily_recommendation_snapshot_schema() app.state.redis_listener = asyncio.create_task(relay_redis_events())