feat(scheduler): persist task state/progress/due_at across restart (#8)
Replace process-start next_run=0 guesses with kv task:state records (status, due_at, stat_date, progress). Startup recovers stale running, honors future due_at for delayed retries, and resumes the same stat_date. Seed only enqueues evening seal; seal force keeps non-seed ok=1 as progress (keep_scraped). Keeps !7 fail-logging and cleanup retry.
This commit is contained in:
1 parent
51ffa44577
commit
f408da93c2
7 files changed
+1793
-902
No files matched your search
@@ -661,6 +661,50 @@ def test_seeded_day_skips_without_force_and_seals_with_force():
|
||||
db.close()
|
||||
|
||||
|
||||
def test_seal_keep_scraped_skips_view_progress_punches_seed():
|
||||
"""晚间 seal(keep_scraped):已 view 的 ok=1 作进度跳过,seed 壳仍打穿。"""
|
||||
clock = 1_800_000_000
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
transport = SnapshotTransport({
|
||||
1: view_for(1, view=111),
|
||||
2: view_for(2, view=222),
|
||||
})
|
||||
db, repo, service = make_service(tmp, transport)
|
||||
try:
|
||||
add_video(repo, 1)
|
||||
add_video(repo, 2)
|
||||
today = DATE
|
||||
# 两条 seed 壳
|
||||
for aid, view in ((1, 10), (2, 20)):
|
||||
repo.upsert_snapshot(
|
||||
today, aid,
|
||||
metrics={"view": view, "like": 1, "coin": 0, "favorite": 0,
|
||||
"share": 0, "reply": 0, "danmaku": 0},
|
||||
ok=True, err=None, captured_at=clock, src="seed",
|
||||
)
|
||||
# 模拟 seal 中途:aid=1 已真实采集
|
||||
repo.upsert_snapshot(
|
||||
today, 1,
|
||||
metrics={"view": 111, "like": 1, "coin": 0, "favorite": 0,
|
||||
"share": 0, "reply": 0, "danmaku": 0},
|
||||
ok=True, err=None, captured_at=clock + 1, src="view",
|
||||
)
|
||||
repo.kv_set(service.seeded_key(today), "1")
|
||||
|
||||
sealed = service.run_if_needed(date=today, force=True)
|
||||
assert sealed.completed is True
|
||||
assert sealed.skipped >= 1 # aid=1 进度跳过
|
||||
assert sealed.success >= 1 # aid=2 seed 打穿
|
||||
# 只应请求 aid=2 的 view(aid=1 已是 view 进度)
|
||||
assert transport.count("/web-interface/view") == 1
|
||||
assert int(repo.get_snapshot(today, 1)["view"]) == 111
|
||||
assert repo.get_snapshot(today, 1)["src"] == "view"
|
||||
assert int(repo.get_snapshot(today, 2)["view"]) == 222
|
||||
assert repo.get_snapshot(today, 2)["src"] == "view"
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def main():
|
||||
test_snapshot_success_resume_and_force()
|
||||
test_resume_skips_ok_and_retries_failed()
|
||||
@@ -679,6 +723,7 @@ def main():
|
||||
test_seed_same_day_completed_is_already_completed_not_no_source()
|
||||
test_seed_from_last_completed_does_not_mark_completed()
|
||||
test_seeded_day_skips_without_force_and_seals_with_force()
|
||||
test_seal_keep_scraped_skips_view_progress_punches_seed()
|
||||
print("OK: 每日快照、断点续跑、失败占位与粉丝采集测试全部通过")
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user