Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions cron/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,28 +429,43 @@ def load_jobs() -> List[Dict[str, Any]]:
if not JOBS_FILE.exists():
return []

_strict_retry = False # track whether we used the strict=False fallback

try:
with open(JOBS_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
return data.get("jobs", [])
except json.JSONDecodeError:
# Retry with strict=False to handle bare control chars in string values
_strict_retry = True
try:
with open(JOBS_FILE, 'r', encoding='utf-8') as f:
data = json.loads(f.read(), strict=False)
jobs = data.get("jobs", [])
if jobs:
# Auto-repair: rewrite with proper escaping
save_jobs(jobs)
logger.warning("Auto-repaired jobs.json (had invalid control characters)")
return jobs
except Exception as e:
logger.error("Failed to auto-repair jobs.json: %s", e)
raise RuntimeError(f"Cron database corrupted and unrepairable: {e}") from e
except IOError as e:
logger.error("IOError reading jobs.json: %s", e)
raise RuntimeError(f"Failed to read cron database: {e}") from e

# Validate top-level JSON shape: accept dict (expected) or bare list (auto-repair).
if isinstance(data, dict):
jobs = data.get("jobs", [])
if _strict_retry and jobs:
# We hit control-character corruption; rewrite with proper escaping
save_jobs(jobs)
logger.warning("Auto-repaired jobs.json (had invalid control characters)")
return jobs
if isinstance(data, list):
# Bare array — likely saved/edited outside save_jobs(). Auto-repair.
if data:
save_jobs(data)
logger.warning("Auto-repaired jobs.json (bare list → wrapped as dict)")
return data

raise RuntimeError(
f"Cron database corrupted: expected {{'jobs': [...]}}, got {type(data).__name__}"
)


def save_jobs(jobs: List[Dict[str, Any]]):
"""Save all jobs to storage."""
Expand Down