Worker di visione: /run sincrono dentro l'event loop, senza timeout; unhealthy non viene riavviato #34

Closed
opened 2026-09-21 20:14:53 +00:00 by Adriano · 3 comments
Owner

GRAVITÀ: media
FILE: src/vision_worker/main.py:26-42 ; Dockerfile.vision:40 ; docker-compose.yml:61-67
COSA: async def run esegue PIL e run_graph in modo sincrono. Con --workers 2 due grafi lenti bloccano tutto, /health compreso. Il backend dà 504 a 120 s ma il calcolo continua. restart: unless-stopped non riavvia un container unhealthy.
INPUT: tre tablet acquisiscono insieme con un grafo da ~30 s.
VERIFICATO: lettura di main.py:24-48: nessun run_in_executor/threadpool/timeout.
PRESUNTO: comportamento a container avviati (non avviati).

ORIGINE: revisione fable del 21/09/2026 su ramo V3.0.0, commit 8cc5e82. Documento completo: _output/2026-09-21-TieMeasureFlow-revisione.md su Wasabi.

GRAVITÀ: media FILE: src/vision_worker/main.py:26-42 ; Dockerfile.vision:40 ; docker-compose.yml:61-67 COSA: `async def run` esegue PIL e `run_graph` in modo sincrono. Con `--workers 2` due grafi lenti bloccano tutto, /health compreso. Il backend dà 504 a 120 s ma il calcolo continua. `restart: unless-stopped` non riavvia un container unhealthy. INPUT: tre tablet acquisiscono insieme con un grafo da ~30 s. VERIFICATO: lettura di main.py:24-48: nessun `run_in_executor`/threadpool/timeout. PRESUNTO: comportamento a container avviati (non avviati). ORIGINE: revisione fable del 21/09/2026 su ramo `V3.0.0`, commit 8cc5e82. Documento completo: `_output/2026-09-21-TieMeasureFlow-revisione.md` su Wasabi.
Adriano added the bug label 2026-09-21 20:14:53 +00:00
Adriano added the assegnata:jeeg label 2026-09-21 20:23:25 +00:00
Author
Owner

⚡ jeeg — preso in carico 2026-09-21T20:23:25Z
ramo: lavoro/jeeg · capacità: docker, gpu, systemd

⚡ jeeg — **preso in carico** 2026-09-21T20:23:25Z ramo: `lavoro/jeeg` · capacità: docker, gpu, systemd
Author
Owner

ANALISI (passo 1) — ramo lavoro/jeeg, worktree ~/lavoro/TieMeasureFlow su jeeg, lotto C1

MODIFICHE: src/vision_worker/main.py — /run esegue decodifica + run_graph in await asyncio.wait_for(asyncio.to_thread(...), timeout=VISION_RUN_TIMEOUT_S) (env, default 100, sotto i 120 s del backend) → 504 del worker al timeout (il backend lo traduce in 504). /health resta async leggero, così risponde anche con calcoli in corso. Semaforo asyncio.Semaphore(VISION_MAX_CONCURRENCY default 2): oltre → 503 «worker busy» (backend → 503). Nota nel docstring: il thread scaduto non è interrompibile, continua fino a fine calcolo.
TEST: run_graph finto che dorme 0.5 s con timeout 0.1 → 504 e /health risponde durante l'attesa.
NON TOCCARE: Dockerfile.vision, compose (lotto C2).

ANALISI (passo 1) — ramo `lavoro/jeeg`, worktree `~/lavoro/TieMeasureFlow` su jeeg, lotto C1 MODIFICHE: src/vision_worker/main.py — `/run` esegue decodifica + `run_graph` in `await asyncio.wait_for(asyncio.to_thread(...), timeout=VISION_RUN_TIMEOUT_S)` (env, default 100, sotto i 120 s del backend) → 504 del worker al timeout (il backend lo traduce in 504). `/health` resta async leggero, così risponde anche con calcoli in corso. Semaforo `asyncio.Semaphore(VISION_MAX_CONCURRENCY default 2)`: oltre → 503 «worker busy» (backend → 503). Nota nel docstring: il thread scaduto non è interrompibile, continua fino a fine calcolo. TEST: run_graph finto che dorme 0.5 s con timeout 0.1 → 504 e `/health` risponde durante l'attesa. NON TOCCARE: Dockerfile.vision, compose (lotto C2).
Author
Owner

Soluzione

ESITO: fatto
COSA: /run esegue decodifica e grafo in asyncio.to_thread con timeout VISION_RUN_TIMEOUT_S (100 s) → 504; semaforo VISION_MAX_CONCURRENCY (2) → 503; /health risponde durante i calcoli (test). Il thread scaduto non è interrompibile: documentato.
COMMIT (ramo lavoro/jeeg, unito su V3.0.0 a d483fa1): b150378
PROVA: uv run --extra server --extra client --extra dev pytest -q → 622 passed, 4 skipped (erano 391); visione su Python 3.13 → 16 passed (erano 8).

**Soluzione** ESITO: fatto COSA: `/run` esegue decodifica e grafo in `asyncio.to_thread` con timeout `VISION_RUN_TIMEOUT_S` (100 s) → 504; semaforo `VISION_MAX_CONCURRENCY` (2) → 503; `/health` risponde durante i calcoli (test). Il thread scaduto non è interrompibile: documentato. COMMIT (ramo lavoro/jeeg, unito su V3.0.0 a d483fa1): b150378 PROVA: `uv run --extra server --extra client --extra dev pytest -q` → 622 passed, 4 skipped (erano 391); visione su Python 3.13 → 16 passed (erano 8).
Adriano removed the assegnata:jeeg label 2026-09-21 21:56:41 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/TieMeasureFlow#34