lock fra cron_book (:47) e cron_cuscino (:53): nessun flock, separazione solo temporale #36
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Revisione 2026-09-27 (goldrake): rilievo Opus 5.5, verifica avversariale fable. Sola lettura, nessun codice toccato.
Rilievo A11 [miglioria]
FILE: PG:scripts/cron_book.sh:37-42
COSA: nessun
timeoutne'flockattorno a book_execute, a differenza di TradingBook/scripts/cron_ombra.sh (timeout -k 10 150). La durata di un giro e' limitata solo dai timeout delle singole chiamate (15s gateway, ccxt, fino a 200 pagine per asset).SCENARIO: giro lento (misurato fino a 659 s il 26/06 19:00) -> sconfina nel :53 di cron_cuscino, che compra/vende USDE sullo stesso conto mentre book_execute sta ancora dimensionando; un giro appeso oltre l'ora si sovrapporrebbe al :47 successivo, con due processi che leggono la stessa posizione e mandano lo stesso delta (ordini doppi).
PROVA: VERIFICATO: parse di logs/cron_book.log (2296 giri): durata max 659 s, 5 giri > 100 s, tutti a fine giugno. Sovrapposizione mai osservata -> rischio PRESUNTO, non misurato.
PROPOSTA:
flock -n /tmp/pg_book.lock timeout -k 10 600 uv run python scripts/live/book_execute.py --execute.TEST:
.venv/bin/python -m pytest -q tests/test_book_live.py tests/test_book_scale.py tests/test_cap_watermark.py tests/test_shadow_usde.py tests/test_live_shadow.py tests/test_book_resilienza_venue.py tests/test_book_staleness_gate.py tests/test_skh_feed_freshness.py tests/test_skh_live_book.py tests/test_book_cadenza.py-> 148 passed. Nessun test esercita rebalance_signed a taglia reale (tutti a $75 @ 60.000) -> A1 non e' coperto.DUPLICAZIONE PG/TB: execution.py, livefeed.py, usde.py, config/live.json, trend_portfolio.py, skyhook.py, sleeves.py identici; book.py/shadow.py differiscono solo per impronta_feed/tp_pieno (TB); deribit.py 55 righe diverse (gateway). A1-A10 valgono identici per TB alla promozione.
COPERTURA: src/live/book.py, src/live/shadow.py, src/live/execution.py, src/live/deribit.py, src/live/livefeed.py, src/live/usde.py (1-150, intero), scripts/live/book_execute.py, scripts/cron_book.sh, config/live.json — per intero. Parziali: src/portfolio/sleeves.py:225-290,397-407; src/strategies/trend_portfolio.py (firme + current_target); src/live/tradesdb.py:1-40,180-224; tests/test_shadow_usde.py, tests/test_book_live.py (elenco test); CLAUDE.md §0-1, §3, §5 (grep).
Verifica fable A11 VERDETTO: CONFERMATO-RIDIMENSIONATO
GRAVITA': basso
PERCHE': scripts/cron_book.sh: nessun timeout/flock (letto). Durate misurate (start->done, 2296 giri): max 659 s (26/06 19:00), 387, 315, 263, 107 — tutte a fine giugno, quando il cron era a :00; con l'attuale :47 un giro da 659 s sconfinerebbe nel :53 di cron_cuscino (stesso conto) ma non nel :47 successivo. Sovrapposizione mai osservata: rischio PRESUNTO.
CORREZIONE:
flock -nsi'; iltimeoutva generoso (>=600 s) e con la consapevolezza che un SIGTERM a meta' ordine perde la riga di log (vedi A4): meglio flock senza kill, o timeout solo attorno alle fasi di lettura.Rilievo B13 [miglioria]
FILE: pg:scripts/cron_cuscino.sh, pg:scripts/cron_book.sh
COSA: nessun flock fra cron_book (:47) e cron_cuscino (:53, puo' mandare ordini spot): la separazione e' solo temporale (6 min).
SCENARIO: book_execute che dura >6 min (misurato: 659s e 387s il 26/06) -> usde_convert modifica il saldo USDC mentre book_execute legge equity/posizioni; lettura non atomica USDC+USDE a meta' di un fill spot = equity sfasata di fino a 100 USDE (~2%) su cui book sizing e watermark ragionano.
PROVA: VERIFICATO: durate cron_book da logs/cron_book.log: 2296 giri, mediana 15s, >300s solo 3 volte (tutte giugno). Rischio basso ma reale; D5 dichiara solo il caso manuale.
PROPOSTA:
flock -w 600 /tmp/pg-conto.lockattorno a book_execute e a cuscino_watch (e a usde_convert --esegui manuale), cosi' anche D5 si chiude.COPERTURA: scripts/live/cuscino_watch.py, scripts/live/usde_watch.py, scripts/live/usde_convert.py, scripts/live/balance_watch.py, src/live/monitor_health.py, scripts/live/monitor_health.py (main), src/live/venue_watch.py (righe 59-393), scripts/live/venue_watch.py, src/live/venue_probe.py, src/live/scale_watch.py, scripts/live/fee_watch.py (40-269), scripts/live/edge_watch.py, src/live/usde.py, tutti scripts/cron_*.sh + crontab; parziali: src/live/book.py (_scala), src/live/deribit.py (DeribitRead, check_specs), CLAUDE.md §1/§5.17. Test: 156 passed (cuscino, usde, venue_watch, monitor_health, fee, edge, venue_probe). Nessun rilievo su balance_watch (formato ts fills compatibile, size gateway in USD verificata sui dati).
Verifica fable B13 VERDETTO: CONFERMATO
GRAVITA': basso
PERCHE':
scripts/cron_book.shescripts/cron_cuscino.sh: nessunflock; separazione solo temporale :47/:53.awksulogs/cron_book.log: 2296 giri, >300s 3, >360s 2 (concorda con il revisore). Oggi cuscino_watch non ha mai lanciato una conversione (tentate 0), quindi il rischio e' teorico ma la barriera non esiste.CORREZIONE: ok (
flock -no-wsu un lock condiviso; con-w 600in cron_cuscino attenzione: il giro :53 slitterebbe fin dentro il :47 successivo — meglio-ne saltare il giro registrandolo).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.
--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).--solo-orarinotifica solo gli alert NUOVI rispetto al marcatore data/live/monitor_health_detto.json: {"detti": [], "ts": ...}.valida(... flag=("--quiet","--solo-orari")).uv run python scripts/live/monitor_health.py --quiet --solo-orari || true. Niente nuova riga di crontab.#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)"
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).--eseguisi lancia conflock 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
bash -n scripts/cron_book.sh scripts/cron_cuscino.sh. Prova il flock a mano con un lock tenuto daflock 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)".
ESITO: fatto sul ramo, non in produzione
RIF: gitea:Adriano/PythagorasGoal#36
FILE: commit
ddcd377su lavoro/goldrake (pushato, HEADd34b0a8)PROVA: /home/adriano/lavoro/PythagorasGoal pytest -q → 1220 passed, 3 skipped
MANCA: merge su main con ok di Adriano; poi issue chiudi --soluzione
Soluzione
cron_book.sh e cron_cuscino.sh: flock -n -E 75 logs/.conto.lock attorno a book_execute e cuscino_watch; rc 75 -> riga SALTATO nel log. Nessun timeout/kill. usde_convert manuale: docstring con flock. Commit
ddcd377.Su main
d34b0a8dal 27/09/2026 17:31Z, produzione aggiornata. Test 1220 passed.