fix(scheduler): daily slot off-plan + cross-midnight resume (#8)

- Cross-midnight: unfinished yesterday seals ASAP with yesterday's stat_date;
  force seal ignores today's snapshot_at gate when stat_date < today.
- Off-plan already_completed: compare completion started_at (not finished_at)
  to today's planned slot; earlier → still run at slot for all daily tasks.
- Cold start: bootstrap task:state from task:last / seed markers.
- ensure_pending: do not glue new due onto a different day's unfinished state.
- run_if_needed(force): keep_scraped True for seal, False for CLI --force.
- Scheduler due_reader: pick up disk due_at each loop (seed→evening seal).
This commit is contained in:
bot-ci committed 2026-11-03 02:35:13 +08:00
1 parent dcf37c4a1d
commit f6bef59e07
7 files changed
+630 -24

No files matched your search

+11 -3
View File
@@ -142,12 +142,20 @@ class SnapshotService:
return f"fans:seeded:{stat_date}"
def run_if_needed(
self, *, date: str | None = None, force: bool = False
self,
*,
date: str | None = None,
force: bool = False,
keep_scraped: bool | None = None,
) -> SnapshotSummary:
"""视频快照(含 UP 头像补齐);粉丝采集请用 ``run_fans_if_needed``。
当日若仅有午夜 seed 壳且未 ``force``,直接返回等待晚间落盘,
避免把「全员 skip」误标成 completed。
``force`` + ``keep_scraped``:
- 晚间 seal / 断点续跑:``keep_scraped=True``(默认)保留已采 ok=1;
- CLI ``--force``:显式 ``keep_scraped=False`` 全量重采。
"""
now = self._now()
stat_date = date or shanghai_date(now)
@@ -155,9 +163,9 @@ class SnapshotService:
raise ValueError(f"日期格式必须是 YYYY-MM-DD: {stat_date!r}")
seeded = self.repo.kv_get(self.seeded_key(stat_date)) == "1"
if force:
# 晚间 seal / 续跑:打穿 seed,保留已真实采集的 ok=1 作为进度。
ks = True if keep_scraped is None else bool(keep_scraped)
return self.run_videos(
date=stat_date, force=True, keep_scraped=True,
date=stat_date, force=True, keep_scraped=ks,
)
completed = self.repo.kv_get(self.completed_key(stat_date)) == "1"