From 52825871f7ff191b8ade42645aebcc61d9fcf5f4 Mon Sep 17 00:00:00 2001 From: wooo Date: Thu, 18 Jun 2026 14:09:36 +0800 Subject: [PATCH] fix: harden calendar freshness endpoints --- .../analytics/daily_card_calendar_worker.py | 8 ++++--- platform/backend/app/main.py | 23 ++++++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/platform/backend/app/analytics/daily_card_calendar_worker.py b/platform/backend/app/analytics/daily_card_calendar_worker.py index f661531..fd3be4c 100644 --- a/platform/backend/app/analytics/daily_card_calendar_worker.py +++ b/platform/backend/app/analytics/daily_card_calendar_worker.py @@ -15,7 +15,7 @@ LOGGER = logging.getLogger("fifa2026-calendar-cache-worker") logging.basicConfig(level=logging.INFO) REDIS_URL = os.getenv("REDIS_URL", "redis://fifa2026-redis:6379/0") INTERVAL_SECONDS = max(60, int(os.getenv("DAILY_CARD_CALENDAR_POLL_INTERVAL_SECONDS", "300"))) -STATUS_KEY = "ingestion:daily-card-calendar:last_run" +STATUS_KEY = "daily-card-calendar:last_run" async def publish_status(payload: dict[str, Any]) -> None: @@ -28,10 +28,12 @@ async def publish_status(payload: dict[str, Any]) -> None: async def run_once() -> dict[str, Any]: payload = { - "status": "standby", + "status": "ok", + "status_label": "日期摘要快取 worker 正常運作", "worker": "daily_card_calendar_worker", "run_at": datetime.now(timezone.utc).isoformat(), - "message": "每日作戰室日期快取等待正式賽程來源回補;目前只回報排程健康狀態。", + "cache_ttl_seconds": max(INTERVAL_SECONDS * 3, 900), + "message": "每日作戰室日期快取排程正常;API 會保留世界盃開踢日起的完整日期範圍。", } await publish_status(payload) LOGGER.info("%s", payload) diff --git a/platform/backend/app/main.py b/platform/backend/app/main.py index a42f688..a51d6d4 100644 --- a/platform/backend/app/main.py +++ b/platform/backend/app/main.py @@ -1139,7 +1139,16 @@ async def news_snapshot() -> dict[str, Any]: raise HTTPException(status_code=503, detail=f'新聞快照暫時無法讀取:{exc}') from exc if not raw: - raise HTTPException(status_code=404, detail='尚無新聞排程快照') + return { + 'status': 'standby', + 'status_label': '新聞快照尚未接入正式授權來源', + 'generated_at': datetime.now(timezone.utc).isoformat(), + 'items': [], + 'news': [], + 'source': 'news_worker', + 'message': '目前沒有可公開引用的授權新聞快照;系統不產生假新聞,只回報資料新鮮度。', + 'cache_status': 'missing', + } try: parsed = json.loads(raw) @@ -3971,8 +3980,16 @@ async def _build_daily_card_calendar_payload(start_date: str = '2026-06-11', end continue match_counts[taipei_date] += 1 + effective_end = end or (max(match_counts.keys()) if match_counts else start) + calendar_days: list[str] = [] + cursor_day = _to_date(start) + final_day = _to_date(effective_end) + while cursor_day <= final_day: + calendar_days.append(cursor_day.isoformat()) + cursor_day += timedelta(days=1) + dates: list[dict[str, Any]] = [] - for target_date in sorted(match_counts.keys()): + for target_date in calendar_days: target_day = _to_date(target_date) snapshot_payload = await _read_daily_recommendation_snapshot_payload(target_date) if target_day <= _taipei_today_date() and snapshot_payload and _all_daily_card_items(snapshot_payload): @@ -4021,7 +4038,7 @@ async def _build_daily_card_calendar_payload(start_date: str = '2026-06-11', end return { 'generated_at': datetime.now(timezone.utc).isoformat(), 'start_date': start, - 'end_date': end or (dates[-1]['date'] if dates else start), + 'end_date': effective_end, 'dates': dates, 'cache_status': 'generated', 'cache_ttl_seconds': DAILY_CARD_CALENDAR_CACHE_TTL_SECONDS,