4 Commits

Author SHA1 Message Date
gx 543b7c9508 pipeline_monitor: 2 bug fixes — stall detection + lost MQTT event
Bug #1: _check_stall возвращался early если alive=False (pipeline ZMQ dead).
Но pipeline может hung без exit'а (ffmpeg process жив но encoder deadlock):
ZMQ не отвечает (alive=False), при этом encoder не emit'ит frames в
mediamtx. Wrapper script не retry'ит (process не exited), никто не
поднимает алерт. Fix: stall check работает ВНЕ зависимости от alive.

Bug #2: _check_stall возвращался early если /live publish session
отсутствует в mediamtx /v3/rtspsessions/list. Pipeline мог никогда
не подключиться (или TCP push session дропнулся). Treat as "frozen
at 0 bytes" — stall alert fire'ится через N polls.

Bug #3 (bonus): _check_instance логировал "lost" но не emit'ил MQTT
event. HA не видела алертов. Fix: добавлен on_event call для pipeline_lost
и pipeline_restored (paired с уже существующими pipeline_stalled /
pipeline_unstalled).

Verified на сегодняшнем incident: pipeline encoder hung 4 hours,
никто не реагировал. После fix monitor emit'ит lost+stalled события
через 12 секунд → MQTT-listener (HA automation) может сделать
docker restart cuda-grid-pipeline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 15:57:21 +01:00
gx d29f3f96e5 pipeline_monitor: + stall watchdog (mediamtx bytes-based detect)
Resilience improvement — раньше pipeline mог hung без exit (NVENC stuck,
output broken pipe), Docker restart policy не triggered. Никакой alert.

Now: poll mediamtx /v3/rtspsessions/list каждые N sec, track publish session
inboundBytes. Не растёт 3 polls (~9 sec) → emit MQTT 'pipeline_stalled' event
(через dispatcher.on_event = mqtt.publish_event). User / Home Assistant
automation решает что делать (restart container, notify).

Wired:
  pipeline_monitor.on_event = mqtt.publish_event  # __main__.py

Bytes started growing again → emit 'pipeline_unstalled'.

Alert single-shot: пока stalled flag set, no dup alerts. Reset когда
bytes counter растёт.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 10:03:41 +01:00
gx 110b77899f pipeline_monitor: 2-sec wait перед restore — fix overlay loss race
Bug: restore триггерился сразу после detected "ZMQ ping success", но
filter graph внутри ffmpeg ещё в startup phase — accepts ZMQ commands
но overlay add не fully apply'ются. Часть overlays lost silently.

Симптом: monitor logs "restore_done overlays=6", но pipeline ZMQ probe
показывает filter имеет только 2-3 overlays. Grafana / alerts_chat /
frigate event overlays отсутствуют → user sees пустые cells / strip.

Fix: asyncio.sleep(2.0) перед re-pushing layout + overlays. Pipeline
filter всегда успевает finish init за 2 sec (verified повторными
restart tests).

Cost: 2-sec задержка между detect + visible restore. Acceptable —
total recovery time pipeline crash → fully visible на TV ≈ 5-7 sec.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 08:06:40 +01:00
gx 6081e33e5a controller: PipelineMonitor — auto-restore overlay state после pipeline restart
Pipeline filter state (overlays, layout, cell_map, audio) живёт в RAM
ffmpeg process. При recreate container (compose up, OOM, NVENC crash,
config change) state lost — controller'у нужно re-push.

Раньше user'у приходилось вручную:
  curl POST /layout/.../set
  docker restart cuda-grid-controller  # для browser/dynamic re-register

Теперь автоматизировано:
  PipelineMonitor polls ZMQ каждые 3 sec (no-op set_layout).
  On timeout/error → mark instance lost.
  First success after lost → trigger restore:
    1. set_layout к state.active_layout
    2. set_audio_output_enabled к state.audio_output_enabled
    3. re-push все overlays из state.overlays
    4. browser/dynamic/frigate hooks: mark_all_unregistered() —
       их loops автоматически re-add на next iteration

Verified test: docker restart cuda-grid-pipeline → 10 sec downtime →
monitor logs lost+restored+restore_done с count=6 overlays.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 07:35:27 +01:00