fix: Geisterzaehler nach Neustart + rkllm-Leck in /api/search/answer

Aufgefallen beim Nachsehen, warum die GUI bei 29:32 Audio 2h34min Analysezeit zeigte.

1. Ein systemctl restart SIGKILLt alle Kindprozesse, die DB-Zeile blieb aber auf
   analysis_status=pending mit gesetztem analysis_started_at. Die GUI zaehlte dadurch
   ewig hoch fuer Arbeit, die es nicht mehr gab. db.failStaleJobs() setzt beim Start
   pending/transcribing auf error - zum Startzeitpunkt kann kein Job legitim laufen.

2. /api/search/answer lud rkllm und gab es nie frei: 1h48min lang 82,6% RAM belegt,
   nur 237 MB verfuegbar. Genau der Zustand, den analyzeRecording und rediarize mit
   llm.stopServer() bewusst vermeiden, weil der TitaNet-Helfer daneben an OOM stirbt
   (auf #71 seinerzeit 48 Rohsprecher). stopServer() jetzt im finally der Route.
This commit is contained in:
2026-07-31 15:25:49 +00:00
parent 914ab2ddc8
commit 963ce427da
3 changed files with 57 additions and 1 deletions
+30
View File
@@ -3,6 +3,36 @@
Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum,
Was, Warum, betroffene Dateien/Backups).
## 2026-07-31 (spät) — Zwei Fehler aus dem Suche-Feature behoben
Beide beim Nachsehen aufgefallen, warum die GUI bei einer 29:32-Aufnahme **2 h 34 min Analysezeit** anzeigte.
### 1. Geisterzähler nach Dienst-Neustart
Ein `systemctl restart` SIGKILLt alle Kindprozesse (whisper, spk_embed, rkllm). Die Datenbankzeile blieb
aber auf `analysis_status='pending'` mit gesetztem `analysis_started_at` stehen — die GUI zeigte darauf
„KI-Analyse läuft… (NPU)" und einen Zähler, der ewig hochlief, für Arbeit die es nicht mehr gab.
Ausgelöst hatte es ein Deploy-Neustart um 13:11 mitten in der laufenden Analyse von #87.
**Fix `db.failStaleJobs()`, aufgerufen beim Start:** `pending` → `error`, `transcribing` → `error`. Zum
Startzeitpunkt kann kein Job legitim laufen, also ist das eindeutig. Der Nutzer sieht jetzt den
Wiederholen-Knopf statt eines Phantomzählers.
### 2. `/api/search/answer` ließ rkllm resident
Die Antwortroute lud rkllm über `llm.askRaw()` und gab es nie frei. Gemessen: **1 h 48 min lang 82,6 % RAM
belegt, nur 237 MB verfügbar.**
Das ist genau der Zustand, den `analyzeRecording` und `rediarize` mit ihrem `llm.stopServer()` bewusst
vermeiden — der TitaNet-Helfer für die Sprecher-Embeddings stirbt neben dem residenten 5,9-GB-Modell an
OOM (auf #71 ergab das seinerzeit 48 Rohsprecher). Die nächste Transkription wäre also mit hoher
Wahrscheinlichkeit fehlgeschlagen.
**Fix:** `llm.stopServer()` im `finally` der Route. Danach wieder 7,3 GB verfügbar.
Dateien: `app/server.js`, `app/db.js`. Board-Backups: `.bak-stalejobs`.
## 2026-07-31 (nachmittags) — Abschnittstitel in der Zusammenfassung fett
Die Section-Zusammenfassung kommt als `Abschnittstitel:\nFließtext…`-Blöcke zurück (llm.js/analyzeLong),