fix(cron): persist the junk-entry repair when no valid job remains; log types only
An all-invalid list filtered to [] skipped save_jobs (the 'if jobs and repair' guard), so every tick repeated the warning. Save whenever a repair ran (the shrink-merge still keeps concurrent valid jobs), and log the dropped entries' types instead of their raw values. (cherry picked from commit 3b5b1aa61332cf79554fc2a24ae925908c37fe5d)
This commit is contained in:
committed by
kshitij
parent
695766e3f9
commit
e66e351cf5
10
cron/jobs.py
10
cron/jobs.py
@@ -1377,13 +1377,17 @@ def load_jobs() -> List[Dict[str, Any]]:
|
||||
if isinstance(jobs, list) and not all(isinstance(j, dict) for j in jobs):
|
||||
# Every reader and the due scan index records as dicts: one junk entry would crash the
|
||||
# whole tick and freeze every healthy sibling job, so skip it like the id-keyed map does.
|
||||
# Types only: the raw values are arbitrary file content and must not reach the logs.
|
||||
junk = [j for j in jobs if not isinstance(j, dict)]
|
||||
logger.warning(
|
||||
"Skipping %d non-object entr%s in jobs.json: %s",
|
||||
len(junk), "y" if len(junk) == 1 else "ies", ", ".join(map(repr, junk[:5])))
|
||||
"Skipping %d non-object entr%s in jobs.json (types: %s)",
|
||||
len(junk), "y" if len(junk) == 1 else "ies",
|
||||
", ".join(sorted({type(j).__name__ for j in junk})))
|
||||
jobs = [j for j in jobs if isinstance(j, dict)]
|
||||
repair = repair or "non-object entries dropped"
|
||||
if jobs and repair:
|
||||
# Persist even an empty result, or an all-junk store repeats the repair on every tick; the
|
||||
# save's shrink-merge still keeps any valid job a sibling wrote meanwhile.
|
||||
if repair:
|
||||
save_jobs(jobs)
|
||||
logger.warning("Auto-repaired jobs.json (%s)", repair)
|
||||
_record_load_stamp(pre_read_stamp)
|
||||
|
||||
@@ -1735,6 +1735,20 @@ class TestJobsJsonIdKeyedMap:
|
||||
on_disk = json.loads(JOBS_FILE.read_text(encoding="utf-8"))
|
||||
assert [j["id"] for j in on_disk["jobs"]] == [job["id"]]
|
||||
|
||||
def test_all_junk_list_is_repaired_on_disk_without_logging_values(self, tmp_cron_dir, caplog):
|
||||
"""With no valid job left the repair must still persist (else every tick repeats it), and
|
||||
the warning must not copy raw file content into the logs."""
|
||||
import json
|
||||
from cron.jobs import JOBS_FILE, ensure_dirs
|
||||
|
||||
ensure_dirs()
|
||||
JOBS_FILE.write_text(json.dumps({"jobs": [None, "sk-leaked-value", 42]}), encoding="utf-8")
|
||||
|
||||
with caplog.at_level("WARNING", logger="cron.jobs"):
|
||||
assert list_jobs(include_disabled=True) == []
|
||||
assert json.loads(JOBS_FILE.read_text(encoding="utf-8"))["jobs"] == []
|
||||
assert "sk-leaked-value" not in caplog.text
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user