Add watchdog for missed launchd runs, add backup retention

Mirrors the same fix on the Lotto sibling project. watchdog.py
(com.eurojackpot.watchdog.plist, daily 09:00) checks whether the
latest draw or trained models are older than the launchd schedule
allows and alerts via EurojackpotNotifier.send_error() - catches a
silently-missed StartCalendarInterval run (e.g. Mac asleep at the
scheduled time) that launchd itself never retries.

EurojackpotAPIUpdater.create_backup() didn't have Lotto's path bug,
but had the same unbounded growth (85 backups, 2.4MB accumulated).
Adds retention (keep last 30) and prunes the existing backlog.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
cbazzaandClaude Sonnet 5 committed 2026-09-12 10:02:40 +02:00
1 parent c39babade4
commit 416c646fd9
12 files changed
+144 -7306

No files matched your search

+17 -1
View File
@@ -91,7 +91,7 @@ class EurojackpotAPIUpdater:
return False
def create_backup(self) -> bool:
"""Erstellt Backup."""
"""Erstellt Backup und behält nur die letzten KEEP_BACKUPS Stück."""
if not os.path.exists(self.data_file):
return True
@@ -108,12 +108,28 @@ class EurojackpotAPIUpdater:
shutil.copy2(self.data_file, self.backup_file)
print(f" ✅ Backup: {os.path.basename(self.backup_file)}")
self._prune_old_backups(backup_dir, filename)
return True
except Exception as e:
print(f" ⚠️ Backup-Fehler: {e}")
return False
@staticmethod
def _prune_old_backups(backup_dir: str, filename: str, keep: int = 30) -> None:
"""Behält nur die KEEP neuesten Backups, löscht den Rest."""
pattern = f"{filename}.backup_"
backups = sorted(
(f for f in os.listdir(backup_dir) if f.startswith(pattern)),
reverse=True,
)
for old in backups[keep:]:
try:
os.remove(os.path.join(backup_dir, old))
except OSError:
pass
def fetch_from_api(self, api_name: str) -> List[Dict]:
"""
Holt Daten von spezifischer API.