feat(compute): Redundanz-Routing per targetInstance (Stage 3)

Mehrere Instanzen pro Dienst nutzbar: Anfragen werden gezielt an eine freie
Instanz adressiert statt an alle gebroadcastet. Mehrere f5tts → naechstes
freies; mehrere LLM → parallele Turns (Multitasking); STT-Redundanz ueber
mehrere Apps via Lease.

- Worker (alle vier): filtern am Loop-Eingang — targetInstance gesetzt und
  != eigener INSTANCE_ID → Nachricht ignorieren. Feld fehlt → wie bisher.
- bridge (TTS/LLM, emittiert die Bridge selbst): _pick_worker() waehlt eine
  online+freie Instanz (Round-Robin), stempelt targetInstance auf
  xtts_request / llm_request. Keine Instanz bekannt → Broadcast.
- bridge (STT-Lease, emittiert die App): neuer stt_lease_request-Handler →
  _pick_stt_worker() (voxtral vor whisper) → stt_lease {instanceId}.
- app (audio.ts): requestSttLease() vor dem Stream, stempelt targetInstance
  auf stt_stream_start / stt_audio_chunk / stt_stream_end (+cancel). Kurzer
  Timeout → '' (Broadcast), Aufnahme haengt nie.

Voll rueckwaertskompatibel: Routing aktiviert sich erst, wenn Worker sich per
worker_hello (Stage 2) registriert haben — sonst bleibt alles Broadcast.
Braucht APK-Rebuild fuer die STT-Lease-Seite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 12:27:51 +02:00
co-authored by Claude Opus 4.8
parent f2ead1242f
commit ec78eb8efe
6 changed files with 118 additions and 14 deletions
+5
View File
@@ -246,6 +246,11 @@ async def _run() -> None:
if msg.get("type") != "llm_request":
continue
payload = msg.get("payload", {}) or {}
# Redundanz-Routing: gezielt an eine andere Instanz adressiert
# → ignorieren. Ohne targetInstance → wie bisher (jeder nimmt).
tgt = payload.get("targetInstance")
if tgt and tgt != INSTANCE_ID:
continue
# Jede Anfrage nebenlaeufig — llama.cpp serialisiert intern,
# aber wir blockieren so nicht den Empfang weiterer Messages.
asyncio.create_task(_handle_llm_request(ws, payload))