fix(cron): coerce null runHistory ms fields from jobs.json

Explicit JSON null for runAtMs/durationMs bypassed the missing-key
default and raised TypeError on load. Treat null/blank like missing.
This commit is contained in:
santhreal
2026-07-21 13:45:02 +08:00
committed by Xubin Ren
parent dfc3919b52
commit 0b1b02f187
2 changed files with 50 additions and 2 deletions
+39
View File
@@ -1007,3 +1007,42 @@ async def test_list_jobs_during_on_job_does_not_cause_stale_reload(tmp_path) ->
next_run = j["state"]["nextRunAtMs"]
assert next_run is not None
assert next_run > now_ms, f"Job '{j['name']}' next_run should be in the future"
def test_load_jobs_accepts_null_run_history_ms(tmp_path) -> None:
store_path = tmp_path / "cron" / "jobs.json"
store_path.parent.mkdir(parents=True)
store_path.write_text(
json.dumps(
{
"version": 1,
"jobs": [
{
"id": "j1",
"name": "t",
"enabled": True,
"schedule": {"kind": "every", "everyMs": 60_000},
"payload": {
"kind": "agent_turn",
"message": "hi",
"sessionKey": "websocket:chat-1",
},
"state": {
"runHistory": [
{"runAtMs": None, "status": "ok", "durationMs": None},
],
},
"createdAtMs": 0,
"updatedAtMs": 0,
}
],
}
),
encoding="utf-8",
)
jobs, _version = CronService(store_path)._load_jobs()
assert jobs is not None
assert jobs[0].state.run_history[0].run_at_ms == 0
assert jobs[0].state.run_history[0].duration_ms == 0
assert jobs[0].state.run_history[0].status == "ok"