fix(system): three next-runs, completed-date data_date, running mark

Split /system schedule into fans / snapshot+UP / discovery next-runs.
Drive data_date and snapshot_days from fully completed video snapshots
only, keep prior success date on failure, show task failure records, and
mark in-progress tasks as 运行中 without wall-clock next-run jumps.
This commit is contained in:
bot-ci committed 2026-11-02 00:46:20 +08:00
1 parent 0b92e10317
commit af90ce8f87
9 files changed
+411 -52

No files matched your search

+7 -1
View File
@@ -256,13 +256,19 @@ def test_fan_failure_placeholder():
transport = SnapshotTransport({}, fan={"code": -500, "message": "x", "data": None})
db, repo, service = make_service(tmp, transport, retries=2)
try:
# 合并跑:视频完成日不受粉丝失败影响
result = service.run(date=DATE)
assert result.total == 0
assert result.fans_failed == 1
assert result.completed is False
assert result.completed is True
assert repo.kv_get("snapshot:last_completed") == DATE
row = repo.get_up_stat(DATE, 37754047)
assert row["ok"] == 0
assert row["follower"] is None and row["following"] is None
fans_only = service.run_fans(date=DATE, force=True)
assert fans_only.fans_failed == 1
assert fans_only.completed is False
finally:
db.close()
+89 -1
View File
@@ -357,10 +357,14 @@ def test_fans_candidates_system_and_export():
assert system["snapshot_days"] == 3
assert system["blacklist"][0]["video_count"] == 1
assert system["tasks"]["snapshot"]["ok"] is True
assert system["tasks"]["fans"]["ok"] is True
assert system["errors"] == []
assert system["preview"] is False
assert system["running"] == {}
assert set(system["next_runs"]) >= {"fans", "snapshot", "discover"}
assert system["next_runs"]["snapshot"] > 0
assert system["next_runs"]["discover"] > FIXED_NOW
assert system["next_runs"]["fans"] > 0
assert system["next_runs"]["discover"] > 0
finally:
db.close()
@@ -562,8 +566,92 @@ def main_test():
test_stats_query()
test_fans_custom_range_modes()
test_fans_candidates_system_and_export()
test_system_status_uses_completed_date_and_running_flags()
test_system_next_runs_follow_last_completion_not_wall_clock()
print("OK: Web 查询层总览/榜单/详情/UP/时长效率/粉丝/候选/系统/访问统计测试全部通过")
def test_system_status_uses_completed_date_and_running_flags():
"""采集中途的 ok=1 不得抢跑数据日期;running 显示三任务。"""
import json
with tempfile.TemporaryDirectory() as tmp:
db, q = setup(tmp)
try:
repo = Repository(db)
# 模拟今日部分写入成功,但完成日仍停在前一天
today = "2026-11-01"
repo.upsert_snapshot(
today, 101,
metrics={"view": 1, "like": 0, "coin": 0, "favorite": 0,
"share": 0, "reply": 0, "danmaku": 0},
ok=True, err=None, captured_at=FIXED_NOW,
)
assert repo.kv_get("snapshot:last_completed") == DATES[-1]
system = q.system()
overview = q.overview()
assert system["data_date"] == DATES[-1]
assert overview["data_date"] == DATES[-1]
assert system["snapshot_days"] == 3
# 三个下次运行字段;标记 snapshot 运行中
repo.kv_set(
"task:running:snapshot",
json.dumps({"name": "snapshot", "started_at": FIXED_NOW}),
)
DASHBOARD_CACHE.clear()
system = q.system()
assert "snapshot" in system["running"]
assert system["running"]["snapshot"]["running"] is True
assert set(system["next_runs"]) >= {"fans", "snapshot", "discover"}
# 失败记录保留,完成日不变
repo.kv_set(
"task:last:snapshot",
json.dumps({
"name": "snapshot", "ok": False,
"started_at": FIXED_NOW - 10, "finished_at": FIXED_NOW,
"error": "boom", "summary": None,
}),
)
repo.kv_delete("task:running:snapshot")
DASHBOARD_CACHE.clear()
system = q.system()
assert system["data_date"] == DATES[-1]
assert overview["data_date"] == DATES[-1]
assert any(err["task"] == "snapshot" for err in system["errors"])
assert system["tasks"]["snapshot"]["ok"] is False
finally:
db.close()
def test_system_next_runs_follow_last_completion_not_wall_clock():
import json
with tempfile.TemporaryDirectory() as tmp:
db, q = setup(tmp)
try:
repo = Repository(db)
# 发现任务刚完成不久:下次 = finished + 60min,即使 now 已超过也不跳档
finished = FIXED_NOW - 30
repo.kv_set(
"task:last:discovery",
json.dumps({
"name": "discovery", "ok": True,
"started_at": finished - 5, "finished_at": finished,
"error": None, "summary": {},
}),
)
DASHBOARD_CACHE.clear()
system = q.system()
assert system["next_runs"]["discover"] == finished + 3600
# 仍小于/等于 now 也可以(表示本轮后的下一档已到期或未到),但绝不能跳到 +7200
assert system["next_runs"]["discover"] != finished + 7200
finally:
db.close()
if __name__ == "__main__":
main_test()
+18
View File
@@ -166,6 +166,8 @@ def build_db(tmp: str | Path) -> Path:
repo.mark_candidate_decision(202, "rejected", now=ts("2026-10-30"))
repo.finish_folder_sync(FOLDER, media_count=3, full_refresh=True)
repo.kv_set("snapshot:last_completed", DATES[-1])
for day in DATES:
repo.kv_set(f"snapshot:completed:{day}", "1")
repo.kv_set("auth:ok", "1")
repo.kv_set("auth:message", "OK")
repo.kv_set(
@@ -176,6 +178,22 @@ def build_db(tmp: str | Path) -> Path:
"error": None, "summary": {"completed": True},
}),
)
repo.kv_set(
"task:last:fans",
json.dumps({
"name": "fans", "ok": True,
"started_at": ts(DATES[-1]) + 60, "finished_at": ts(DATES[-1]) + 90,
"error": None, "summary": {"fans_ok": 1, "fans_failed": 0},
}),
)
repo.kv_set(
"task:last:discovery",
json.dumps({
"name": "discovery", "ok": True,
"started_at": ts(DATES[-1]) - 3600, "finished_at": ts(DATES[-1]) - 3500,
"error": None, "summary": {"candidates": 0},
}),
)
finally:
db.close()
return path