fix(fallback): connectTimeoutMs 2500→15000 e breakerTripAfter 2→3

Il default di 2,5 s per connect+headers è troppo stretto su percorsi VPN/AP:
misurati GET /v1/status 1,23 s e POST /v1/memories:search 1,98 s, talvolta
oltre 2,5 s. In quelle condizioni il breaker si apriva pur con gateway
raggiungibile e tutte le chiamate successive andavano in fast-fail per 2–10
minuti, spingendo di fatto ogni operazione sul solo fallback locale e
lasciando l'outbox non sincronizzata.

- extensions/shared.ts: connectTimeoutMs 2500 → 15_000 (default, fallback nel
  path di richiesta e commento), breakerTripAfter 2 → 3
- README.md: default aggiornati + motivazione nella tabella dei timeout
- skills/qmem/SKILL.md: default aggiornato e sintassi CLI del reset breaker
  (`qmem-sqlite.mjs breaker --reset`)

Verifica sul campo: con connectTimeoutMs=60000 l'outbox (18 record) è stata
sincronizzata completamente e il breaker è rimasto chiuso.
This commit is contained in:
Matteo Benedetto
2026-09-16 10:26:52 +02:00
parent 76eedcd526
commit 12e63d09fa
3 changed files with 12 additions and 12 deletions
+3 -3
View File
@@ -41,11 +41,11 @@ In quel caso:
dalle sessioni pi + ultimo enrich): verifica prima dell'uso;
- comandi: `/qmem:local status | import | find <query> | queue | flush | breaker [reset] | enrich | pull`
(`import` dalle sessioni, `enrich`/`pull` dal gateway quando torna online);
- **circuit breaker**: quando il gateway non risponde entro `connectTimeoutMs` (default 2,5 s) le
- **circuit breaker**: quando il gateway non risponde entro `connectTimeoutMs` (default 15 s) le
chiamate successive falliscono in ~0 ms **senza toccare la rete** per ~2 minuti (stato in
`~/.local/share/pi-qmem/breaker.json`): il fallback locale è immediato. Un 5xx o un body lento
sono invece "ambigui" (retry con `Retry-After`, apertura dopo 2 fallimenti). Reset:
`/qmem:local breaker reset`.
sono invece "ambigui" (retry con `Retry-After`, apertura dopo 3 fallimenti). Reset:
`/qmem:local breaker reset` (CLI: `node scripts/qmem-sqlite.mjs breaker --reset`).
`qmem_store` accoda in locale: con il gateway giù il record entra nell'**outbox**
locale (SQLite), è subito ricercabile (marcato ⏳) e viene inviato al gateway al