From f09aaae8a95ce337485562d56df65ea846124b56 Mon Sep 17 00:00:00 2001 From: alientim Date: Sun, 23 Aug 2026 11:00:15 +0200 Subject: [PATCH] Lizenz: sofortiger erster Heartbeat direkt nach Aktivierung (v1.2.2) Root Cause fuer 'Letzter Heartbeat: noch nie' trotz funktionierender Verbindung (live auf POETEST untersucht und bestaetigt): der Heartbeat- Hintergrund-Thread feuert einmal SOFORT beim Start von tesm.service und danach erst wieder alle 6h. Im realistischen Ablauf (Dienst starten -> danach erst Lizenz hochladen+aktivieren) faellt genau dieser erste, sofortige Versuch immer ins Leere (noch keine Lizenz vorhanden, daher stiller Abbruch ohne Fehlermeldung) -- der naechste ECHTE Versuch waere erst bis zu 6h spaeter gekommen. Manuell nachgestellt: ein direkter Aufruf von _send_heartbeat() nach erfolgter Aktivierung funktioniert einwandfrei (Master verzeichnet den Heartbeat sofort) -- das Protokoll selbst war nie kaputt, nur die Beobachtbarkeit unmittelbar nach der Aktivierung. Fix: beide Aktivierungs-Erfolgspfade (online + Offline-Code-Bestaetigung) loesen jetzt selbst sofort einen ersten Heartbeat aus, statt auf den naechsten planmaessigen 6h-Durchlauf zu warten. Ein Fehlschlag hier (z.B. Kunde tatsaechlich offline) wird wie jeder andere Heartbeat-Fehlschlag behandelt -- rein informativ, schaltet nichts ab. Co-Authored-By: Claude Sonnet 5 --- srv/tesm/VERSION | 2 +- srv/tesm/app.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/srv/tesm/VERSION b/srv/tesm/VERSION index 6085e94..23aa839 100644 --- a/srv/tesm/VERSION +++ b/srv/tesm/VERSION @@ -1 +1 @@ -1.2.1 +1.2.2 diff --git a/srv/tesm/app.py b/srv/tesm/app.py index 0974d42..e60666a 100644 --- a/srv/tesm/app.py +++ b/srv/tesm/app.py @@ -4595,6 +4595,18 @@ def license_activate(): def on_success(): set_setting("license_activation_status", "active") set_setting("license_export_grace", "") + # Sofort einen ersten Heartbeat auslösen, statt bis zu 6h auf den + # nächsten planmäßigen Durchlauf zu warten (siehe + # _license_heartbeat_loop) -- ohne das würde "Letzter Heartbeat" + # direkt nach der Aktivierung fälschlich wie ein Verbindungsproblem + # aussehen ("noch nie"), obwohl schlicht noch keine Zeit vergangen + # ist. Ein Fehlschlag hier (z.B. Kunde offline) wird wie jeder + # andere Heartbeat-Fehlschlag behandelt (nur vermerkt, nichts wird + # deswegen abgeschaltet). + try: + _send_heartbeat() + except Exception: + app.logger.error("Erster Heartbeat nach Aktivierung fehlgeschlagen:\n%s", traceback.format_exc()) return _license_handshake("activate", "/api/activate", on_success, "license.activated", "Lizenz erfolgreich aktiviert.") @@ -4609,6 +4621,18 @@ def license_activate_confirm(): def on_success(): set_setting("license_activation_status", "active") set_setting("license_export_grace", "") + # Sofort einen ersten Heartbeat auslösen, statt bis zu 6h auf den + # nächsten planmäßigen Durchlauf zu warten (siehe + # _license_heartbeat_loop) -- ohne das würde "Letzter Heartbeat" + # direkt nach der Aktivierung fälschlich wie ein Verbindungsproblem + # aussehen ("noch nie"), obwohl schlicht noch keine Zeit vergangen + # ist. Ein Fehlschlag hier (z.B. Kunde offline) wird wie jeder + # andere Heartbeat-Fehlschlag behandelt (nur vermerkt, nichts wird + # deswegen abgeschaltet). + try: + _send_heartbeat() + except Exception: + app.logger.error("Erster Heartbeat nach Aktivierung fehlgeschlagen:\n%s", traceback.format_exc()) return _license_handshake_confirm("activate", on_success, "license.activated", "Lizenz erfolgreich aktiviert.")