monitor_health gira solo alle 00:30: i sorveglianti orari (limite 3h) si scoprono fermi fino a 24h dopo #30

Closed
opened 2026-09-27 13:12:13 +00:00 by Adriano · 3 comments
Owner

Revisione 2026-09-27 (goldrake): rilievo Opus 5.5, verifica avversariale fable. Sola lettura, nessun codice toccato.

Rilievo B6 [bug]

FILE: pg:src/live/monitor_health.py:86-130 + scripts/cron_daily.sh:53
COSA: i sorveglianti ORARI (cuscino_watch, venue_watch, collect_chain) hanno max_age 3h "= due giri persi", ma monitor_health gira UNA volta al giorno (cron_daily 00:30): la latenza reale di scoperta e' fino a ~24h.
SCENARIO: cuscino_watch smette di scrivere alle 01:00 (es. eccezione non gestita a cuscino_watch.py:216 se config/live.json e' illeggibile, o import rotto dopo un commit) -> nessun allarme cuscino e nessuna riconversione automatica fino alle 00:30 del giorno dopo; monitor_health lo dichiara FERMO dopo 23h, non dopo 3h.
PROVA: VERIFICATO: grep -rn monitor_health scripts/*.sh -> solo cron_daily.sh:53; crontab 30 0 * * * per cron_daily.
PROPOSTA: lanciare monitor_health.py --quiet anche orario (es. in coda a cron_cuscino.sh o a un minuto libero), con marcatore "gia' detto" per non ripetere ogni ora; oppure dividere i monitor orari in un secondo giro orario.

Verifica fable B6 VERDETTO: CONFERMATO

GRAVITA': medio
PERCHE': src/live/monitor_health.py:105-107,128-130 max_age 3h per cuscino_watch/venue_watch/collect_chain; grep -rn monitor_health scripts/*.sh -> solo scripts/cron_daily.sh:53; crontab 30 0 * * *. Latenza reale di scoperta fino a ~24h. scripts/live/monitor_health.py:50 notifica senza marcatore «gia' detto».
CORREZIONE: ok, con un vincolo: se si lancia orario (in coda a cron_book.sh o cron_cuscino.sh) SERVE il marcatore per monitor (oggi assente), altrimenti un monitor fermo produce 24 Telegram al giorno e si impara a ignorarlo (P14). In alternativa, un secondo giro --solo-orari che guarda i tre monitor da 3h.

Revisione 2026-09-27 (goldrake): rilievo Opus 5.5, verifica avversariale fable. Sola lettura, nessun codice toccato. ### Rilievo B6 [bug] FILE: pg:src/live/monitor_health.py:86-130 + scripts/cron_daily.sh:53 COSA: i sorveglianti ORARI (cuscino_watch, venue_watch, collect_chain) hanno max_age 3h "= due giri persi", ma monitor_health gira UNA volta al giorno (cron_daily 00:30): la latenza reale di scoperta e' fino a ~24h. SCENARIO: cuscino_watch smette di scrivere alle 01:00 (es. eccezione non gestita a cuscino_watch.py:216 se config/live.json e' illeggibile, o import rotto dopo un commit) -> nessun allarme cuscino e nessuna riconversione automatica fino alle 00:30 del giorno dopo; monitor_health lo dichiara FERMO dopo 23h, non dopo 3h. PROVA: VERIFICATO: `grep -rn monitor_health scripts/*.sh` -> solo cron_daily.sh:53; crontab `30 0 * * *` per cron_daily. PROPOSTA: lanciare `monitor_health.py --quiet` anche orario (es. in coda a cron_cuscino.sh o a un minuto libero), con marcatore "gia' detto" per non ripetere ogni ora; oppure dividere i monitor orari in un secondo giro orario. ### Verifica fable B6 VERDETTO: CONFERMATO GRAVITA': medio PERCHE': `src/live/monitor_health.py:105-107,128-130` max_age 3h per cuscino_watch/venue_watch/collect_chain; `grep -rn monitor_health scripts/*.sh` -> solo `scripts/cron_daily.sh:53`; crontab `30 0 * * *`. Latenza reale di scoperta fino a ~24h. `scripts/live/monitor_health.py:50` notifica senza marcatore «gia' detto». CORREZIONE: ok, con un vincolo: se si lancia orario (in coda a `cron_book.sh` o `cron_cuscino.sh`) SERVE il marcatore per monitor (oggi assente), altrimenti un monitor fermo produce 24 Telegram al giorno e si impara a ignorarlo (P14). In alternativa, un secondo giro `--solo-orari` che guarda i tre monitor da 3h.
Adriano added the bug label 2026-09-27 13:12:13 +00:00
Author
Owner

ANALISI (passo 1, Opus, 27/09/2026)

ANALISI U8 — gitea:Adriano/PythagorasGoal#30 (B6) + #36 (A11, B13)
CARTELLA: /home/adriano/lavoro/PG-u8 RAMO: lavoro/goldrake-u8 (da main 841d4c7)

#30
PERCHE': monitor_health gira solo alle 00:30 (cron_daily.sh). I sorveglianti orari hanno max_age 3h (cuscino_watch, venue_watch, collect_chain), quindi un sorvegliante fermo si scopre fino a 24h dopo.

  1. scripts/live/monitor_health.py — nuovo flag --solo-orari: controlla solo i monitor con max_age <= 6h (derivato dalla tabella in src/live/monitor_health.py, non da una lista di nomi cablata).
    • Con --solo-orari notifica solo gli alert NUOVI rispetto al marcatore data/live/monitor_health_detto.json: {"detti": [], "ts": ...}.
    • Chiave = nome monitor + stato, non il testo (il testo contiene l'eta', che cambia ogni ora).
    • Quando un monitor torna OK la sua chiave si toglie dal marcatore, cosi' un nuovo guasto riparte con un nuovo avviso.
    • Il marcatore si scrive SOLO se notify ha restituito True (stessa regola di fee_watch #29: niente "gia' detto" su un invio fallito).
    • Exit: 2 se ci sono alert (anche gia' detti), 0 altrimenti.
    • Il giro giornaliero senza flag resta identico: ogni giorno report completo e avviso.
    • Aggiornare USO e valida(... flag=("--quiet","--solo-orari")).
  2. scripts/cron_cuscino.sh — dopo cuscino_watch: uv run python scripts/live/monitor_health.py --quiet --solo-orari || true. Niente nuova riga di crontab.
  3. src/live/monitor_health.py — solo se serve esporre una funzione pura che filtra i monitor per max_age e calcola chiavi e nuovi. Una funzione pura e' preferibile: si testa.

#36
PERCHE': book_execute (:47) e cuscino_watch (:53, puo' mandare ordini spot USDE) sono separati solo dal tempo; giri fino a 659 s sono stati misurati.
4. scripts/cron_book.sh — solo la riga di book_execute diventa:
flock -n -E 75 logs/.conto.lock uv run python scripts/live/book_execute.py --execute; rc=$?
[ $rc -eq 75 ] && echo " book: SALTATO — conto occupato da un altro giro (logs/.conto.lock)"

  • L'exit code del wrapper oggi non conta (lo script e' dentro {} >> log); guarda se il resto dello script usa $? dopo book_execute e preservalo.
  • NIENTE timeout/kill: un SIGTERM a meta' ordine perde la riga di log (verifica fable A11).
  • venue_watch e trades_db restano fuori dal lock.
  1. scripts/cron_cuscino.sh — cuscino_watch dentro flock -n -E 75 logs/.conto.lock .... Se 75, riga " cuscino: SALTATO — conto occupato (logs/.conto.lock)". Mai -w: il giro scivolerebbe (verifica fable B13).
  2. scripts/live/usde_convert.py — solo documentazione: nel docstring d'uso, la conversione manuale --esegui si lancia con flock logs/.conto.lock uv run python scripts/live/usde_convert.py --esegui .... Controlla se CLAUDE.md del repo ha una riga d'uso di usde_convert --esegui: se si', aggiorna anche quella (una riga).
    Controlla se cuscino_watch lancia usde_convert come subprocess: se si', il lock e' gia' tenuto dal padre, quindi usde_convert NON deve prenderlo di nuovo (deadlock con -n: il figlio lo troverebbe occupato). Documentalo in un commento.

TEST

  • tests/test_monitor_health_orari.py: funzione pura su righe finte. Filtro per max_age; alert nuovo -> notifica; lo stesso alert al secondo giro -> nessuna notifica; ritorno OK -> chiave tolta; notify False -> marcatore non scritto. Monkeypatch di notify e del percorso del marcatore; niente Telegram.
  • Script shell: bash -n scripts/cron_book.sh scripts/cron_cuscino.sh. Prova il flock a mano con un lock tenuto da flock logs/.conto.lock sleep 5 & e un comando finto (NON book_execute), per vedere il rc 75. Riportalo in PROVA.
    Suite: cd /home/adriano/lavoro/PG-u8 && /opt/docker/PythagorasGoal/.venv/bin/python -m pytest -q -p no:cacheprovider. Baseline 1166 passed, 3 skipped.

NON TOCCARE: la crontab, cron_daily.sh (il giro giornaliero resta), book_execute.py, cuscino_watch.py (salvo lettura).
COMMIT: "monitor_health: giro orario dei sorveglianti da 3h con marcatore gia' detto (#30)" e "cron_book/cron_cuscino: flock -n sul conto, un giro occupato si salta e si scrive (#36)".

ANALISI (passo 1, Opus, 27/09/2026) ANALISI U8 — gitea:Adriano/PythagorasGoal#30 (B6) + #36 (A11, B13) CARTELLA: /home/adriano/lavoro/PG-u8 RAMO: lavoro/goldrake-u8 (da main 841d4c7) #30 PERCHE': monitor_health gira solo alle 00:30 (cron_daily.sh). I sorveglianti orari hanno max_age 3h (cuscino_watch, venue_watch, collect_chain), quindi un sorvegliante fermo si scopre fino a 24h dopo. 1. scripts/live/monitor_health.py — nuovo flag `--solo-orari`: controlla solo i monitor con max_age <= 6h (derivato dalla tabella in src/live/monitor_health.py, non da una lista di nomi cablata). - Con `--solo-orari` notifica solo gli alert NUOVI rispetto al marcatore data/live/monitor_health_detto.json: {"detti": [<chiave alert>], "ts": ...}. - Chiave = nome monitor + stato, non il testo (il testo contiene l'eta', che cambia ogni ora). - Quando un monitor torna OK la sua chiave si toglie dal marcatore, cosi' un nuovo guasto riparte con un nuovo avviso. - Il marcatore si scrive SOLO se notify ha restituito True (stessa regola di fee_watch #29: niente "gia' detto" su un invio fallito). - Exit: 2 se ci sono alert (anche gia' detti), 0 altrimenti. - Il giro giornaliero senza flag resta identico: ogni giorno report completo e avviso. - Aggiornare USO e `valida(... flag=("--quiet","--solo-orari"))`. 2. scripts/cron_cuscino.sh — dopo cuscino_watch: `uv run python scripts/live/monitor_health.py --quiet --solo-orari || true`. Niente nuova riga di crontab. 3. src/live/monitor_health.py — solo se serve esporre una funzione pura che filtra i monitor per max_age e calcola chiavi e nuovi. Una funzione pura e' preferibile: si testa. #36 PERCHE': book_execute (:47) e cuscino_watch (:53, puo' mandare ordini spot USDE) sono separati solo dal tempo; giri fino a 659 s sono stati misurati. 4. scripts/cron_book.sh — solo la riga di book_execute diventa: flock -n -E 75 logs/.conto.lock uv run python scripts/live/book_execute.py --execute; rc=$? [ $rc -eq 75 ] && echo " book: SALTATO — conto occupato da un altro giro (logs/.conto.lock)" - L'exit code del wrapper oggi non conta (lo script e' dentro {} >> log); guarda se il resto dello script usa $? dopo book_execute e preservalo. - NIENTE timeout/kill: un SIGTERM a meta' ordine perde la riga di log (verifica fable A11). - venue_watch e trades_db restano fuori dal lock. 5. scripts/cron_cuscino.sh — cuscino_watch dentro `flock -n -E 75 logs/.conto.lock ...`. Se 75, riga " cuscino: SALTATO — conto occupato (logs/.conto.lock)". Mai `-w`: il giro scivolerebbe (verifica fable B13). 6. scripts/live/usde_convert.py — solo documentazione: nel docstring d'uso, la conversione manuale `--esegui` si lancia con `flock logs/.conto.lock uv run python scripts/live/usde_convert.py --esegui ...`. Controlla se CLAUDE.md del repo ha una riga d'uso di usde_convert --esegui: se si', aggiorna anche quella (una riga). Controlla se cuscino_watch lancia usde_convert come subprocess: se si', il lock e' gia' tenuto dal padre, quindi usde_convert NON deve prenderlo di nuovo (deadlock con -n: il figlio lo troverebbe occupato). Documentalo in un commento. TEST - tests/test_monitor_health_orari.py: funzione pura su righe finte. Filtro per max_age; alert nuovo -> notifica; lo stesso alert al secondo giro -> nessuna notifica; ritorno OK -> chiave tolta; notify False -> marcatore non scritto. Monkeypatch di notify e del percorso del marcatore; niente Telegram. - Script shell: `bash -n scripts/cron_book.sh scripts/cron_cuscino.sh`. Prova il flock a mano con un lock tenuto da `flock logs/.conto.lock sleep 5 &` e un comando finto (NON book_execute), per vedere il rc 75. Riportalo in PROVA. Suite: `cd /home/adriano/lavoro/PG-u8 && /opt/docker/PythagorasGoal/.venv/bin/python -m pytest -q -p no:cacheprovider`. Baseline 1166 passed, 3 skipped. NON TOCCARE: la crontab, cron_daily.sh (il giro giornaliero resta), book_execute.py, cuscino_watch.py (salvo lettura). COMMIT: "monitor_health: giro orario dei sorveglianti da 3h con marcatore gia' detto (#30)" e "cron_book/cron_cuscino: flock -n sul conto, un giro occupato si salta e si scrive (#36)".
Author
Owner

ESITO: fatto sul ramo, non in produzione
RIF: gitea:Adriano/PythagorasGoal#30
FILE: commit d59aea7 su lavoro/goldrake (pushato, HEAD d34b0a8)
PROVA: /home/adriano/lavoro/PythagorasGoal pytest -q → 1220 passed, 3 skipped
MANCA: merge su main con ok di Adriano; poi issue chiudi --soluzione

ESITO: fatto sul ramo, non in produzione RIF: gitea:Adriano/PythagorasGoal#30 FILE: commit d59aea7 su lavoro/goldrake (pushato, HEAD d34b0a8) PROVA: /home/adriano/lavoro/PythagorasGoal pytest -q → 1220 passed, 3 skipped MANCA: merge su main con ok di Adriano; poi issue chiudi --soluzione
Author
Owner

Soluzione

monitor_health.py --solo-orari in coda a cron_cuscino.sh (ogni ora): monitor con max_age<=6h, avviso solo sul nuovo, marcatore data/live/monitor_health_detto.json scritto solo su invio riuscito. Giro giornaliero invariato. Commit d59aea7.
Su main d34b0a8 dal 27/09/2026 17:31Z, produzione aggiornata. Test 1220 passed.

**Soluzione** monitor_health.py --solo-orari in coda a cron_cuscino.sh (ogni ora): monitor con max_age<=6h, avviso solo sul nuovo, marcatore data/live/monitor_health_detto.json scritto solo su invio riuscito. Giro giornaliero invariato. Commit d59aea7. Su main d34b0a8 dal 27/09/2026 17:31Z, produzione aggiornata. Test 1220 passed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/PythagorasGoal#30