jobengine: Nacharbeit laeuft vor dem Endzustand (Wettlauf, auf der Box sichtbar)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-24 17:42:42 +02:00
co-authored by Claude Opus 5.5
parent e1d7d499f8
commit b1bc9395cf
+20 -17
View File
@@ -96,7 +96,7 @@ def _pfad(job_id: str, endung: str) -> Path:
def _speichern(job: dict) -> None:
"""Akte ohne Laufzeitfelder atomar schreiben."""
daten = {k: v for k, v in job.items() if k not in _LAUFZEIT}
daten = {k: v for k, v in job.items() if k not in _LAUFZEIT and not k.startswith("_")}
try:
_jobs_dir().mkdir(parents=True, exist_ok=True)
tmp = _pfad(job["id"], ".json.tmp")
@@ -256,25 +256,28 @@ def _beende_gruppe(proc: subprocess.Popen) -> None:
def _abschliessen(job: dict, code: int | None) -> None:
"""Endzustand festhalten (genau einmal) und, wenn erfolgreich, die Nacharbeit ausführen."""
"""Endzustand festhalten (genau einmal). Bei Erfolg läuft die Nacharbeit VOR dem Endzustand:
Wer „done“ sieht, sieht auch schon ihre Wirkung (gesetzte Rolle, geleerte Zwischenspeicher)."""
with _LOCK:
if job["state"] in _ENDE:
if job["state"] in _ENDE or job.get("_schliesst"):
return
job["returncode"] = code
job["finished_at"] = time.time()
if job.get("canceled"):
job["state"] = "canceled"
elif job.get("zeitlimit") or (code is None and time.time() - job["started_at"] >= job["zeitlimit_s"] - 5):
job.update(state="failed", zeitlimit=True, error="Zeitlimit überschritten")
elif code is None:
job["state"] = "failed"
job.setdefault("error", "Der Auftrag endete ohne Rückmeldung.")
else:
job["state"] = "done" if code == 0 else "failed"
job["_schliesst"] = True
felder: dict = {"returncode": code}
if job.get("canceled"):
felder["state"] = "canceled"
elif job.get("zeitlimit") or (code is None and time.time() - job["started_at"] >= job["zeitlimit_s"] - 5):
felder.update(state="failed", zeitlimit=True, error="Zeitlimit überschritten")
elif code is None:
felder.update(state="failed", error=job.get("error") or "Der Auftrag endete ohne Rückmeldung.")
else:
felder["state"] = "done" if code == 0 else "failed"
if felder["state"] == "done":
_nacharbeit_ausfuehren(job)
with _LOCK:
job.update(felder, finished_at=time.time())
job.pop("_schliesst", None)
_PROCS.pop(job["id"], None)
_speichern(job)
if job["state"] == "done":
_nacharbeit_ausfuehren(job)
def _nacharbeit_ausfuehren(job: dict) -> None:
@@ -523,7 +526,7 @@ def public_jobs(mit_log: bool = True) -> list[dict]:
with _LOCK:
_laden()
_aufraeumen()
jobs = [{k: v for k, v in j.items() if k not in _INTERN} for j in JOBS.values()]
jobs = [{k: v for k, v in j.items() if k not in _INTERN and not k.startswith("_")} for j in JOBS.values()]
for j in jobs:
j["log"] = _protokoll_lesen(j["id"]) if mit_log else []
return sorted(jobs, key=lambda j: j.get("started_at") or 0)