test(scheduler): nail H7 progress keep + H8 deferred task:state

Address Michał NEED-CHANGES on !7 tip f408da93: fail/defer omit-progress
preserves progress/stat_date; seed + quiet-window defer assert
status=deferred and future due_at on task:state. Soft: seeded due≠wall;
cleanup failure reads task:state.
This commit is contained in:
bot-ci committed 2026-11-03 01:59:18 +08:00
1 parent f408da93c2
commit dcf37c4a1d
2 files changed
+124 -5

No files matched your search

+56 -3
View File
@@ -15,12 +15,14 @@ from reaction_board.database import Database # noqa: E402
from reaction_board.repository import Repository # noqa: E402
from reaction_board.scheduler import ScheduledTask, Scheduler # noqa: E402
from reaction_board.task_state import ( # noqa: E402
STATUS_DEFERRED,
STATUS_DONE,
STATUS_FAILED,
STATUS_PENDING,
STATUS_RUNNING,
ensure_pending,
load_state,
mark_deferred,
mark_done,
mark_failed,
mark_running,
@@ -65,22 +67,26 @@ def test_restart_mid_run_resumes_same_stat_date():
def test_seeded_before_snapshot_at_does_not_force_run():
"""seed 后挂 pending due_at=当晚;白天重启 next_run 未到,不跑。"""
"""seed 后挂 pending;白天重启认落盘 due_at(刻意 ≠ 墙钟)且未到不跑。"""
with tempfile.TemporaryDirectory() as tmp:
db, repo = _repo(tmp)
try:
now = datetime(2026, 11, 3, 10, 30, tzinfo=SHANGHAI_TZ).timestamp()
slot = datetime(2026, 11, 3, 23, 15, tzinfo=SHANGHAI_TZ).timestamp()
# 刻意偏离墙钟 23:15,证明认落盘而非 fallback
slot = datetime(2026, 11, 3, 22, 0, tzinfo=SHANGHAI_TZ).timestamp()
wall = next_daily_run(now, "23:15")
assert slot != wall
ensure_pending(
repo, "snapshot", due_at=slot, stat_date="2026-11-03", now=now,
)
repo.kv_set("snapshot:seeded:2026-11-03", "1")
nxt = startup_next_run(
repo, "snapshot",
wall_due_at=next_daily_run(now, "23:15"),
wall_due_at=wall,
now=now,
)
assert nxt == slot
assert nxt != wall
assert nxt > now
calls = []
@@ -199,6 +205,52 @@ def test_no_state_falls_back_to_wall_clock():
db.close()
def test_fail_or_defer_preserves_progress():
"""H7: mark_failed / mark_deferred 不传 progress 时保留已有 progress 与 stat_date。"""
with tempfile.TemporaryDirectory() as tmp:
db, repo = _repo(tmp)
try:
now = datetime(2026, 11, 3, 12, 0, tzinfo=SHANGHAI_TZ).timestamp()
progress = {"done": 42, "total": 100, "cursor": "aid:99"}
mark_running(
repo, "snapshot", stat_date="2026-11-03", now=now,
progress=progress,
)
before = load_state(repo, "snapshot")
assert before is not None
assert before.progress == progress
assert before.stat_date == "2026-11-03"
due_fail = now + 300
mark_failed(
repo, "snapshot", due_at=due_fail, now=now + 1,
progress=None, error="boom",
)
failed = load_state(repo, "snapshot")
assert failed is not None
assert failed.status == STATUS_FAILED
assert failed.due_at == due_fail
assert failed.progress == progress
assert failed.stat_date == "2026-11-03"
assert failed.error == "boom"
due_defer = now + 600
mark_deferred(
repo, "snapshot", due_at=due_defer, now=now + 2,
progress=None, error="snapshot_quiet_window",
)
deferred = load_state(repo, "snapshot")
assert deferred is not None
assert deferred.status == STATUS_DEFERRED
assert deferred.due_at == due_defer
assert deferred.progress == progress
assert deferred.stat_date == "2026-11-03"
assert deferred.error == "snapshot_quiet_window"
finally:
db.close()
def main_test():
test_restart_mid_run_resumes_same_stat_date()
test_seeded_before_snapshot_at_does_not_force_run()
@@ -206,6 +258,7 @@ def main_test():
test_due_at_passed_runs_including_failed_retry()
test_done_writes_next_due_and_blocks_until_then()
test_no_state_falls_back_to_wall_clock()
test_fail_or_defer_preserves_progress()
print("OK: task_state persistence / resume / due_at gates")