64 lines
4.1 KiB
Markdown
64 lines
4.1 KiB
Markdown
# A40-Last-Guard fuer Video-Overflow (#96 erweitert) — 2026-07-24
|
||
|
||
**Auftrag:** Bär-Vorgabe 2026-07-24 — der MiniMax/Kling-Video-Failover (#96) griff bisher NUR
|
||
wenn ComfyUI/A40 komplett unerreichbar war. Die A40 darf laut Bär nicht überlastet werden —
|
||
der Überlauf muss schon bei AUSLASTUNG greifen, nicht erst wenn die Karte tot ist.
|
||
|
||
## Was gebaut wurde (additiv, reversibel)
|
||
|
||
Datei: `B:\barby\orchestrator\main.py` (VM302:8197), `B:\barby\orchestrator\routing_tiers.json`
|
||
Backups vor Änderung: `main.py.bak-a40loadguard-20260724-113445`, `routing_tiers.json.bak-a40loadguard-20260724-113445`
|
||
|
||
### 1. Neues Last-Signal: `a40_load_status()`
|
||
Prüft VOR jedem Video-Schritt (`run_video_job`) drei unabhängige, additive Quellen (ODER-verknüpft):
|
||
|
||
| Quelle | Schwelle | Bedeutung |
|
||
|---|---|---|
|
||
| ComfyUI `/system_stats` VRAM | `A40_VRAM_BUSY_PCT` (Default **85%**) | Karte fast voll |
|
||
| nvidia-smi GPU-Util + ComfyUI-`/queue`-Stau | `A40_UTIL_BUSY_PCT` (Default **95%**) UND `queue_pending>=1` | Karte dauerhaft am Limit mit Rückstau |
|
||
| A40-Guard-Semaphore #54 (VM201 `/api/burst/a40-guard/status`) | `busy: true` | Karte hält schon 1 Job fest — laut Bär darf sie nie überbucht werden, das reicht allein |
|
||
|
||
Fail-open: jeder Messfehler → `overloaded=False` (ein kaputtes Signal leitet nie fälschlich extern um).
|
||
|
||
### 2. Überlauf-Entscheidung in `run_video_job`
|
||
- Nicht erreichbar → wie bisher (#96 Basisfall), jetzt über gemeinsamen Helper `_run_minimax_overflow()`.
|
||
- **NEU:** erreichbar aber `overloaded=True` → Job wird NICHT lokal nachgelegt (kein Thrashing/Überbuchung).
|
||
- Wenn Bär den MiniMax-Failover scharf geschaltet hat (`CLOUD_VIDEO_FALLBACK_ENABLED=1` + `MINIMAX_API_KEY`): Überlauf auf Video-Tier 5 (routing_tiers.json).
|
||
- Ohne Freigabe (aktueller Live-Zustand): Job bleibt lokal in der ComfyUI-Queue, das Last-Signal wird trotzdem in `job.plan.overflow.last_signal` dokumentiert — kein Geld ausgegeben ohne Bär-GO.
|
||
- `/health`-Endpoint zeigt jetzt die vollständige Trigger-Logik + den Last-Signal-Endpunkt.
|
||
|
||
### 3. routing_tiers.json
|
||
Neuer Meta-Eintrag `a40_last_signal_baer_2026-07-24` dokumentiert die Schwellen, Quellen und den Verify-Beleg.
|
||
`a40_guard_endpoint` korrigiert auf den echten Pfad `/api/burst/a40-guard/status`.
|
||
|
||
## Verify (Beleg, ohne echten Cloud-Call)
|
||
|
||
Testinstanz: `main.py` als Modul importiert (kein Server-Neustart nötig für den Funktionstest), `a40_load_status()` isoliert aufgerufen.
|
||
|
||
**Test 1 — A40 frei (Live-Zustand, VRAM 25.9/45GB frei = 42.4% belegt):**
|
||
```json
|
||
{"reachable": true, "overloaded": false, "vram_pct": 42.4, "guard_busy": false}
|
||
```
|
||
→ Job würde lokal eingereiht (Headroom vorhanden). **Bestätigt: lokal bleibt Priorität 1 bei Headroom.**
|
||
|
||
**Test 2 — künstlich scharfe VRAM-Schwelle (`A40_VRAM_BUSY_PCT=1`), reale Messwerte unverändert:**
|
||
```json
|
||
{"reachable": true, "overloaded": true, "gruende": ["vram_belegt_42.4pct_ab_1.0pct"]}
|
||
```
|
||
→ Plan-Entscheidung: Job bleibt lokal (kein Bär-GO für MiniMax), Last wird dokumentiert. Mit aktivem Failover wäre der Grund `a40_ueberlastet:vram_belegt_...` an `_run_minimax_overflow()` gegangen.
|
||
|
||
**Test 3 — A40-Guard-Semaphore (#54) isoliert getestet (Mock-Server liefert `{"busy":true,"job":"sim_video_job_123"}`):**
|
||
```json
|
||
{"reachable": true, "overloaded": true, "guard_busy": true, "gruende": ["a40_guard_belegt_job=sim_video_job_123"]}
|
||
```
|
||
→ **Bestätigt: die Guard-Semaphore allein (unabhängig von VRAM/Util) löst das Überlauf-Signal aus.**
|
||
|
||
## Deployment
|
||
- `python -m py_compile main.py` → OK (2×, vor und nach Doku-Ergänzung)
|
||
- Queue vor Neustart geprüft: `laufend=0, warteschlange=0` → kein Job unterbrochen
|
||
- Scheduled Task `BarbyOrchestrator` neu gestartet (Stop/Start), `/health` danach OK, `jobs.gesamt` unverändert (39) → State erhalten
|
||
- Kein echter Cloud-Call ausgelöst, kein Guthaben verbraucht (MiniMax bleibt Default AUS, Bär-GO weiterhin nötig für den ersten echten Testclip)
|
||
|
||
## Rollback
|
||
`Copy-Item main.py.bak-a40loadguard-20260724-113445 main.py -Force` + `Copy-Item routing_tiers.json.bak-a40loadguard-20260724-113445 routing_tiers.json -Force`, dann Scheduled Task `BarbyOrchestrator` neu starten.
|