48 lines
1.7 KiB
Python
48 lines
1.7 KiB
Python
"""Pure scheduling helpers for the admin leaderboard daily snapshots.
|
|
|
|
Kept import-light on purpose (only stdlib ``datetime``) so the decision logic
|
|
is unit-testable without standing up the FastAPI app, the DB engine, or the
|
|
ORM. The background scheduler in ``app/gateway/app.py`` wires this to the real
|
|
snapshot rows.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
def should_finalize_previous_day(
|
|
*,
|
|
status: str | None,
|
|
generated_at: datetime | None,
|
|
now: datetime,
|
|
finalize_hour: int,
|
|
) -> bool:
|
|
"""Decide whether *yesterday's* snapshot should be force-recomputed once.
|
|
|
|
The previous day's snapshot is normally built before midnight, so it can
|
|
miss runs / tool calls whose rows only land in the database shortly before
|
|
or after the day boundary. Once per day, on/after ``finalize_hour`` (local
|
|
Beijing time), we recompute it a single time so the full day is captured.
|
|
|
|
``now`` and ``generated_at`` are expected to be timezone-aware Beijing
|
|
datetimes (``generated_at`` may be ``None`` for legacy rows).
|
|
|
|
Returns ``True`` only when all hold:
|
|
- it is already on/after ``finalize_hour`` today;
|
|
- a snapshot row exists (``status`` is not ``None`` — a missing day is
|
|
left to the normal prewarm/queue path);
|
|
- that snapshot is not already ``queued``/``running`` (a finalize already
|
|
in flight, or normal processing);
|
|
- it was generated before today (i.e. not yet finalized for this day).
|
|
"""
|
|
if status is None:
|
|
return False
|
|
if now.hour < finalize_hour:
|
|
return False
|
|
if status in ("queued", "running"):
|
|
return False
|
|
if generated_at is not None and generated_at.date() >= now.date():
|
|
return False
|
|
return True
|