feat: home growth auto(7→1) and hourly recent-video snapshot

- Add analytics.home_growth_days (auto|1|7); API growth_days=auto tries 7 then 1
- Homepage shows active window and growth-board link; clearer empty reason
- New snapshot_recent scheduler task (schedule.recent_snapshot_minutes/days)
- run_recent_videos refreshes new aids only; never touches completed/backup
- Full 00:01 job keeps ok=1 skip (covers hourly refresh within 1h); mutex with recent
This commit is contained in:
bot-ci committed 2026-11-02 10:00:02 +08:00
1 parent 04716aec1b
commit 9163f47b76
15 files changed
+496 -22

No files matched your search

+56
View File
@@ -163,6 +163,13 @@ def _clear_task_running(repo: Repository, name: str) -> None:
pass
def _is_task_running(repo: Repository, name: str) -> bool:
try:
return bool(repo.kv_get(_task_running_key(name)))
except Exception: # noqa: BLE001
return False
def _record_task(
repo: Repository,
name: str,
@@ -547,6 +554,16 @@ def cmd_run(args, logger: JsonLogger, *, serve_web: bool = False) -> int:
def run_snapshot():
started = int(time.time())
if _is_task_running(repo, "snapshot_recent"):
logger.info(
"snapshot.skip", reason="snapshot_recent_running",
)
_record_task(
repo, "snapshot", ok=True, started_at=started,
finished_at=int(time.time()),
payload={"skipped": True, "reason": "snapshot_recent_running"},
)
return None
_mark_task_running(repo, "snapshot", started_at=started)
try:
summary = snapshot_service.run_if_needed()
@@ -567,6 +584,39 @@ def cmd_run(args, logger: JsonLogger, *, serve_web: bool = False) -> int:
logger.info("snapshot.summary", **payload)
return summary
def run_snapshot_recent():
started = int(time.time())
if _is_task_running(repo, "snapshot"):
logger.info(
"snapshot.recent_skip", reason="snapshot_running",
)
_record_task(
repo, "snapshot_recent", ok=True, started_at=started,
finished_at=int(time.time()),
payload={"skipped": True, "reason": "snapshot_running"},
)
return None
_mark_task_running(repo, "snapshot_recent", started_at=started)
try:
summary = snapshot_service.run_recent_videos()
except Exception as exc: # noqa: BLE001
_record_task(
repo, "snapshot_recent", ok=False, started_at=started,
finished_at=int(time.time()), error=str(exc),
)
raise
payload = summary.as_dict()
ok = summary.failed == 0
error = ";".join(summary.errors) if summary.errors else None
_record_task(
repo, "snapshot_recent", ok=ok, started_at=summary.started_at,
finished_at=summary.finished_at or int(time.time()),
payload=payload, error=error,
)
last["snapshot_recent"] = summary
logger.info("snapshot.recent_summary", **payload)
return summary
def run_fans():
started = int(time.time())
_mark_task_running(repo, "fans", started_at=started)
@@ -601,6 +651,7 @@ def cmd_run(args, logger: JsonLogger, *, serve_web: bool = False) -> int:
hh, mm = parse_hhmm(cfg.schedule.snapshot_at)
snapshot_at = f"{hh:02d}:{mm:02d}"
recent_minutes = int(store.get().schedule.recent_snapshot_minutes)
scheduler = Scheduler(
[
ScheduledTask(
@@ -617,6 +668,11 @@ def cmd_run(args, logger: JsonLogger, *, serve_web: bool = False) -> int:
next_run=0.0,
next_run_fn=lambda started: next_daily_run(started, snapshot_at),
),
ScheduledTask(
"snapshot_recent",
float(recent_minutes * 60),
run_snapshot_recent,
),
ScheduledTask(
"discovery",
float(cfg.schedule.discover_minutes * 60),