phase2b: Auftraege ueberleben einen Neustart von MC2

- jobengine: jeder Auftrag laeuft als eigene systemd-Einheit mc2-job-<id> (systemd-run,
  RuntimeMaxSec als Zeitlimit); Akte, Protokoll und Exit-Code liegen unter
  <Datenordner>/mc2-jobs; MC2 nimmt laufende Auftraege beim Start wieder auf
- Geheimnisse (HF_TOKEN) ueber eine nur fuer den Nutzer lesbare Umgebungsdatei, die der
  Auftrag beim Start liest und loescht; nichts davon in Befehlszeile oder Einheit
- benannte Nacharbeiten (wartung:nach_update, modell:rolle) statt Closures, laufen auch
  nach einem Neustart
- ohne systemd (PC, Tests) weiter als Kindprozess
- deploy.sh wartet nur noch auf Update-Auftraege; Downloads laufen weiter
- 14 neue Tests; systemd-Weg auf der Box echt geprueft (Neustart, Abbruch, Zeitlimit,
  Geheimnis nicht sichtbar)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-24 17:41:26 +02:00
co-authored by Claude Opus 5.5
parent 75611be9a9
commit e1d7d499f8
7 changed files with 657 additions and 177 deletions
+5 -3
View File
@@ -37,19 +37,21 @@ SKILLS_ALT="autonomie konzept-fliessband llm-wiki morning-report orchestrator pr
review trend-radar wartung konzept_fliessband llm_wiki morning_report projekt_start
trend_radar betrieb-playbook pc-pfad-cache"
# Laufende Update-Aufträge (Gruppe maintenance). Seit Phase 2 überleben Aufträge den Neustart von
# MC2 (eigene systemd-Einheiten) — ein Download darf also weiterlaufen. Ein Update aber führt
# Skripte aus diesem Checkout aus; die darf der Deploy nicht mitten im Lauf austauschen.
laufende_jobs() {
curl -sf -m 5 "$API/api/jobs" 2>/dev/null \
| python3 -c 'import json,sys; print(sum(1 for j in json.load(sys.stdin).get("jobs", []) if j.get("state") in ("running", "queued")))' \
| python3 -c 'import json,sys; print(sum(1 for j in json.load(sys.stdin).get("jobs", []) if j.get("group") == "maintenance" and j.get("state") in ("running", "queued")))' \
2>/dev/null || echo 0
}
stufe1() {
exec 9>"${XDG_RUNTIME_DIR}/mc2-deploy.lock"
flock -n 9 || { echo "Es läuft schon ein Deploy."; exit 1; }
# Update- und Download-Jobs leben (noch) im MC2-Prozess: ein Neustart würde sie abwürgen.
local n; n="$(laufende_jobs)"
if [ "${n:-0}" -gt 0 ] && [ "${MC_DEPLOY_TROTZDEM:-0}" != "1" ]; then
echo "Es laufen $n Job(s) (Update oder Download). Deploy verschoben — später erneut, oder MC_DEPLOY_TROTZDEM=1."
echo "Es läuft ein Update-Auftrag. Deploy verschoben — später erneut, oder MC_DEPLOY_TROTZDEM=1."
exit 1
fi
local vorher; vorher="$(git rev-parse HEAD)"