fix: harden calendar freshness endpoints
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user