From bfb07a92c3c677a97985c8cf70e0d9e7bbc9f935 Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Wed, 23 Sep 2026 21:40:31 +0200 Subject: [PATCH] umbau(boxwart): Schalter fuer den Probelauf neben dem echten Betrieb MC_WAECHTER_TROCKEN=1: Waechter prueft und fuehrt Hinweise, meldet aber nichts an Telegram/Lucy und repariert nichts selbst. MC_PROBELAUF=1: die Probe-Instanz laesst Erinnerungs-Schleife und Messverlauf aus (sonst zwei Schreiber, doppelte Erinnerungen). Co-Authored-By: Claude Opus 5.5 --- backend/app.py | 11 ++++++++--- backend/services/waechter.py | 10 ++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/backend/app.py b/backend/app.py index c378866..3fea786 100644 --- a/backend/app.py +++ b/backend/app.py @@ -62,9 +62,14 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: "Hirn-Re-Warm-Wächter aktiv (Intervall %ss, Hirn dynamisch aus Hermes-Config)", warmer.INTERVAL, ) - tasks.append(asyncio.create_task(reminders.reminders_loop())) - # 24-h-Metrik-Verlauf (Cockpit-Zeitachse): 10-s-Sampler, Ringpuffer, persistiert. - tasks.append(asyncio.create_task(metrics_history.sampler_loop())) + # Probelauf (neue Fassung neben der laufenden, Box-Wart-Umbau 09/2026): Erinnerungen und + # Messverlauf gehören dem echten MC2 — zwei Schreiber würden Erinnerungen doppelt feuern. + if os.environ.get("MC_PROBELAUF", "") != "1": + tasks.append(asyncio.create_task(reminders.reminders_loop())) + # 24-h-Metrik-Verlauf: 10-s-Sampler, Ringpuffer, persistiert. + tasks.append(asyncio.create_task(metrics_history.sampler_loop())) + else: + log.info("Probelauf: Erinnerungen und Messverlauf bleiben beim echten MC2.") # Geteilter HTTP-Client zur lokalen Engine: Keep-Alive/Connection-Pooling statt neuer Client # pro /v1-Anfrage (spart Sockets/TIME_WAIT unter parallelen Agent-Strömen von Zed/Kilo). app.state.gw_client = httpx.AsyncClient( diff --git a/backend/services/waechter.py b/backend/services/waechter.py index 6771b84..64457fe 100644 --- a/backend/services/waechter.py +++ b/backend/services/waechter.py @@ -58,6 +58,9 @@ DISK_ROT_PCT = float(os.environ.get("MC_WAECHTER_DISK_ROT", "90")) DISK_GELB_PCT = float(os.environ.get("MC_WAECHTER_DISK_GELB", "80")) STORE_PATH = Path(os.environ.get("MC_WAECHTER_STORE", str(MODELS_DIR / "mc2-waechter.json"))) VERLAUF_MAX = 200 +# Trockenlauf (Probelauf neben dem echten Betrieb): prüft und führt Hinweise, meldet aber +# nichts an Telegram/Lucy und repariert nichts selbst — das macht weiter der echte Wächter. +TROCKEN = os.environ.get("MC_WAECHTER_TROCKEN", "") == "1" # Im Steward-Modus beobachtet er auch MC2 selbst und den Gateway (wie der alte Wächter). WATCH_MC2 = os.environ.get("MC_SENTRY_WATCH_MC2", os.environ.get("MC_WAECHTER_WATCH_MC2", "")) == "1" @@ -412,6 +415,9 @@ def _verlauf(art: str, hinweis_id: str, text: str) -> None: def _telegram(betreff: str, text: str) -> None: + if TROCKEN: + log.info("waechter (trocken): würde melden %s %s", betreff, text) + return announce.add(text, subject=betreff, source="waechter") announce.notify_telegram(betreff, text + " (Diese Meldung kam auch an Lucy.)") @@ -425,6 +431,10 @@ def _auto_erlaubt(schluessel: str, jetzt: float) -> bool: def _selbst_beheben(b: Befund, jetzt: float) -> None: if b.auto != "neustart" or not _auto_erlaubt(b.id, jetzt): return + if TROCKEN: + _verlauf("auto", b.id, f"{b.titel}: würde automatisch neu starten (Trockenlauf)") + _stand["auto"][b.id].append(jetzt) + return ergebnis = maintenance.restart_service(b.quelle) _stand["auto"][b.id].append(jetzt) ok = bool(ergebnis.get("ok", ergebnis.get("returncode", 1) == 0))