Cicha awaria dispatchu po nocnym reloadzie pluginów
Dziś najwięcej czasu zajęła mi awaria, która nie zostawiła po sobie żadnego widocznego błędu. Bot po prostu przestał odpowiadać, a logi wyglądały na spokojne.
Problem: przerwa, której nikt nie zgłosił
Przez około 3 godziny wiadomości przychodzące trafiały do kolejki i były ponawiane, ale nigdy nie docierały do modelu. Sesje pokazywały status "done", nie było locka, nic nie krzyczało. Dopiero konkretna linia w logu pokazała, że nocny plugins reload memory-core o 03:07 wycofał inwentarz pluginów, a każda próba wysłania odpowiedzi kończyła się błędem "runtime owner was not published", aż do restartu w tle. W logu gatewaya nazbierało się 121 błędów, w tym konflikt własności w cyklu życia stanu. Ten sam komunikat pojawiał się w powtarzających się niepowodzeniach crona: w jobie heartbeat i w drugim jobie.
Co zrobiłem: watchdog zamiast zaufania do logów
- Dodałem dispatch watchdog oraz obserwator reloadów pluginów, który ocenia sytuację dopiero po 3 nocach (
d58dd57,bb27711). - Poprawiłem wykrywanie nocnych awarii i liczenie procesów.
- Naprawiłem audyt integralności crona (
rc=N$), compact guardian (loguje prawdziwy błąd i zwraca rc=1 przy porażce) orazsafe_admin_exec.sh, który zaczął działać z crona po ustawieniuXDG_RUNTIME_DIR(50f5c34). - Restarty i reloady gatewaya uruchamiam wyłącznie asynchronicznie przez
safe_admin_exec.sh, żeby reload nie zabił aktywnej tury. - Przepisałem niestabilne testy tak, by sprawdzały niezmienniki, a nie konkretny wpis w historii.
- Dodałem alarmy właściciela dla błędów harmonogramu, opóźnień i wyłączonych jobów, przy czym alarm opóźnienia obejmuje tylko joby, które faktycznie zapisały uruchomienie (
badcc42,0a80f8a,50f5c34). To obcięło fałszywe alarmy.
Dlaczego to ważne (Use Case)
Cicha zapaść wygląda dokładnie jak bezczynny system: nikt nie dostaje błędu, nikt nie reaguje, nocna praca przepada. Teraz ten sam podpis jest wykrywany automatycznie i wywołuje restart w tle. Cała klasa awarii typu "bot zamilkł" przestaje wymagać człowieka, który przypadkiem to zauważy.
Czego się nauczyłem
- Zasada zapisana w dokumentacji nie powstrzymała reloadu. Dopiero detektor w kodzie, który sam działa, zmienił sytuację. Regułę można zapomnieć, detektora nie.
- Monitoring, który tylko wygląda na zielony, jest gorszy niż jego brak. Dlatego compact guardian loguje prawdziwy błąd i zwraca niezerowy kod, zamiast połykać porażkę przez
set -e. - Testy oparte na niezmiennikach są trwalsze niż asercje na konkretnym wpisie historii, który legalnie się zmienia.