antragstracker/scripts/check-background-jobs.sh
Dotty Dotter f87ab389aa feat: Nutzungsanleitung + Legende auf /anleitung (#18)
- Neue Route /anleitung mit vollständiger Dokumentation
- 6 Abschnitte: Was ist der Tracker, Verfahrensstränge, Ampel-Legende,
  KI-Bewertung, konkrete Szenarien, Fristen-Tracking
- Lädt Strang-Definitionen von /api/ampel/definition
- Ampel-Beispiele inline mit Mock-Daten (inkl. Abzweigungen)
- Farbige Strang-Kästen, Inhaltsverzeichnis mit Sprungmarken
- Navigation in Desktop- und Mobile-Menü ergänzt
2026-04-02 23:09:44 +02:00

84 lines
2.6 KiB
Bash
Executable File

#!/bin/bash
# Prüft Background-Jobs anhand ihrer Heartbeat-Dateien.
# Per Cron alle 5 Minuten aufrufen:
# */5 * * * * /path/to/antragstracker/scripts/check-background-jobs.sh >> /path/to/antragstracker/data/job-checker.log 2>&1
set -euo pipefail
cd "$(dirname "$0")/.."
DATA_DIR="data"
MAX_STALE_SECONDS=1800 # 30 Minuten ohne Update = stale
now=$(date +%s)
check_job() {
local name="$1"
local heartbeat_file="$2"
local restart_cmd="$3"
if [ ! -f "$heartbeat_file" ]; then
return 0 # Kein Heartbeat = Job nicht aktiv, OK
fi
local status=$(python3 -c "import json; d=json.load(open('$heartbeat_file')); print(d.get('status','unknown'))" 2>/dev/null || echo "error")
if [ "$status" = "completed" ]; then
echo "[$(date)] ✅ $name: fertig"
return 0
fi
# PID prüfen
local pid=$(python3 -c "import json; d=json.load(open('$heartbeat_file')); print(d.get('pid',''))" 2>/dev/null || echo "")
if [ -n "$pid" ] && [ "$pid" != "null" ] && [ "$pid" != "None" ]; then
if ! kill -0 "$pid" 2>/dev/null; then
echo "[$(date)] ❌ $name: Prozess $pid tot → Neustart"
eval "$restart_cmd"
return 0
fi
fi
# Timestamp prüfen
local last_batch=$(python3 -c "
import json, datetime
d = json.load(open('$heartbeat_file'))
ts = d.get('last_batch_at') or d.get('started_at') or ''
if ts:
dt = datetime.datetime.fromisoformat(ts.replace('Z', '+00:00'))
print(int(dt.timestamp()))
else:
print(0)
" 2>/dev/null || echo "0")
if [ "$last_batch" != "0" ]; then
local age=$((now - last_batch))
if [ "$age" -gt "$MAX_STALE_SECONDS" ]; then
echo "[$(date)] ⚠️ $name: Heartbeat ${age}s alt (max ${MAX_STALE_SECONDS}s) → Neustart"
# Kill alten Prozess
[ -n "$pid" ] && [ "$pid" != "null" ] && kill "$pid" 2>/dev/null || true
sleep 2
eval "$restart_cmd"
return 0
fi
fi
# Alles gut
local progress=$(python3 -c "
import json
d = json.load(open('$heartbeat_file'))
done = d.get('total_geocoded', d.get('total_done', '?'))
pending = d.get('total_pending', '?')
print(f'{done} done, {pending} pending')
" 2>/dev/null || echo "?")
echo "[$(date)] ✓ $name: läuft (PID $pid, $progress)"
}
# === Jobs registrieren ===
PROJ_DIR="$(pwd)"
check_job "Geocoding" \
"$DATA_DIR/geocode-heartbeat.json" \
"cd '$PROJ_DIR' && nohup bash scripts/geocode_background.sh >> data/geocode.log 2>&1 &"
# Weitere Jobs hier eintragen:
# check_job "OParl-Sync" "$DATA_DIR/sync-heartbeat.json" "..."