Commit graph

2 commits

Author SHA1 Message Date
oskar dff76ecd30 fix(events): service_healthy tylko na transition + cleanup 358k backlog + retencja — glob zalewu paralizowal reconcile supervisora
- node-agent: service_healthy emitowany tylko przy przejsciu w stan zdrowy
  (per-service in-memory state), nie co cykl dla kazdego zdrowego serwisu.
  To samo dla control-plane HTTP probe. healthcheck_failed/containers_not_running/
  incydenty pozostaja emitowane bez zmian (realne sygnaly).
- node-agent: naprawiono _cleanup_control_plane_fs — istniejaca retencja
  eventow byla martwa od migracji observer_checkpoint.json na epoch-int
  (str(path) <= int rzucal TypeError, lapane cicho przez broad except).
  Teraz porownuje epoch-do-epoch i czysci wylacznie service_healthy/node_health
  starsze niz checkpoint + 3-dniowy bufor; healthcheck_failed/incydenty/ha_*
  zachowane bezterminowo.
- scripts/maintenance/cleanup_event_backlog.py: jednorazowy skrypt do
  bezpiecznego czyszczenia backlogu na VPS (dry-run domyslnie, --apply
  do usuniecia). Ten sam warunek: typ szumu + starsze niz checkpoint + 1h bufor.
2026-07-16 20:20:17 +02:00
oskar 4746ebe0fb fix(node-agent): detect restarting/crash-looping containers — state fell through classification, crash-loops were invisible to monitoring
check_containers() classified only exited/dead, running+unhealthy and running.
Docker's "restarting", "paused", "removing" and any future state matched no
branch, so a crash-looping container (restart policy + continuous crash) emitted
ZERO events and world-state kept showing it "healthy" (observed live:
lustro/pi-watchtower-1). Every Docker state is now handled:

- restarting + RestartCount >= CRASH_LOOP_RESTART_THRESHOLD (default 3):
  reuse containers_not_running (high, crash_loop=true) — parity with exited/dead,
  rides the existing supervisor-wired remediation path.
- restarting below threshold: new observational container_restarting (low),
  visible but non-actionable so benign post-deploy restarts don't alarm.
- paused / unknown-or-future state: new diagnostic container_state_unexpected
  (medium) — no more silent fall-through; new Docker states become visible.
- removing: conscious documented skip (ephemeral teardown).
- created: unchanged skip (compose tracking artifact).

RestartCount (top-level inspect field) distinguishes a crash-loop from a one-off
restart. Adds services/node-agent/tests/test_check_containers.py pinning the full
state table.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 20:11:56 +02:00