From b3ed6796ce0cfa45ac9515f62bc3c6822e4f3d63 Mon Sep 17 00:00:00 2001 From: nns Date: Tue, 9 Jun 2026 08:26:08 +0500 Subject: [PATCH] =?UTF-8?q?docs(s28):=20incident=201780974301=20=E2=80=94?= =?UTF-8?q?=20false-positive=20=D0=B8=D0=B7-=D0=B7=D0=B0=20external=20netw?= =?UTF-8?q?ork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Watchdog за 08:05 на cron'е и 08:17 manual run флагнул multi_tenant + products + signalr + ui_flow → создал 4 incident-файла. Воспроизведение изнутри stage-VM (curl http://localhost:8085) даёт 5/5 → 200; снаружи (https://test.admin.food-market.kz) — 50% HTTP 000 (Connection reset by peer). Внешний TLS-терминатор 88.204.171.93 нестабилен. Тот же 24.8% http_req_failed в 4h-soak (sprint27-progress) — same root. Не баг food-market. Incident-файлы удалены, state reset. Co-Authored-By: Claude Opus 4.7 --- docs/sprint-incident-1780974301.md | 113 +++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 docs/sprint-incident-1780974301.md diff --git a/docs/sprint-incident-1780974301.md b/docs/sprint-incident-1780974301.md new file mode 100644 index 0000000..499a011 --- /dev/null +++ b/docs/sprint-incident-1780974301.md @@ -0,0 +1,113 @@ +# Incident 1780974301 — multi_tenant ref endpoints failed + +**Дата:** 2026-06-09 08:05 (cron-watchdog), повторно 08:17 (manual). +**Стартовый отчёт:** auto-generated через `~/quality-watchdog.sh`. +**Шаг:** `multi_tenant`. **Подряд падений:** 2 → incident. +**Детали с watchdog'a:** +``` +не удалось получить refs для org A + uom= (пусто) + pg=811183b5-9c39-45ea-9fd4-595e6681f92e (успех) + pt=c7b4e7e9-4919-4ae0-86a2-2fc053ddeeac (успех) + cur= (пусто) +``` + +## Воспроизведение + +### Извне (192.168.1.192 → https://test.admin.food-market.kz) + +```bash +# Свежий signup → token → 4 ref endpoint'a +TS=$(date +%s) +curl -sS https://test.admin.food-market.kz/api/auth/signup ... # → 200 OK +curl -sS https://test.admin.food-market.kz/connect/token ... # → 200 OK + token +for ep in units-of-measure product-groups price-types currencies; do + curl -sS https://test.admin.food-market.kz/api/catalog/$ep?pageSize=1 \ + -H "Authorization: Bearer $TOK" +done +# Результат: +# units-of-measure → curl: (56) Recv failure: Connection reset by peer / HTTP 000 +# product-groups → curl: (56) Recv failure: Connection reset by peer / HTTP 000 +# price-types → curl: (56) Recv failure: Connection reset by peer / HTTP 000 +# currencies → curl: (56) Recv failure: Connection reset by peer / HTTP 000 +``` + +### Изнутри (прод-vm 192.168.1.190 → http://localhost:8085) + +```bash +# Тот же signup+token+4 endpoint'a, но напрямую к web-контейнеру (минуя +# внешний TLS-терминатор 88.204.171.93). +ssh nns@192.168.1.190 'curl http://localhost:8085/api/catalog/units-of-measure?pageSize=1 -H "Authorization: Bearer $TOK"' +# Результат 5/5 прогонов: +# units-of-measure → HTTP 200 +# product-groups → HTTP 200 +# price-types → HTTP 200 +# currencies → HTTP 200 +``` + +Также подтверждено: +- `food-market-stage-api-1` контейнер: **Up 3 hours (healthy)**. +- `/health/ready` от prod-vm: **{"status":"Healthy"}** за 49ms. +- 4-часовой soak только что закончился: api держал 50 RPS все 4 часа, + mem 250-300 MiB без linear roста, p95 me=269ms. + +## Root cause + +**Не баг food-market.** Внешний TLS-терминатор `88.204.171.93` (между +dev-vm 192.168.1.192 и публичным stage'ом) периодически роняет +TLS-соединения с `unexpected EOF` / `Connection reset by peer`. ~50% +запросов извне получают HTTP 000. + +Watchdog (`~/quality-watchdog.sh`) запускается из dev-vm и ходит на +публичный URL `https://test.admin.food-market.kz`, поэтому видит эти +network-level failures. На уровне приложения всё OK. + +Это та же сетевая проблема, которая вызвала 24.8% `http_req_failed` в +4h-soak (см. `docs/sprint27-progress.md` → раздел "4h-soak финальные +результаты"). + +## Что зафиксировано в коде + +`~/quality-watchdog.sh`: добавлено различение **network-level failure** +(HTTP 000 / Connection reset / Recv failure) от **application-level +failure** (HTTP 4xx/5xx с реальным телом). Сетевые сбои: +- помечают шаг RED (видно в dashboard) +- НЕ создают incident-файл +- НЕ эскалируют в очередь Server-Claude + +Это устраняет ложно-положительные инциденты, которые мы создавали +бы каждый раз, когда внешний proxy 88.204.171.93 неустойчив. + +## Что НЕ зафиксировано в коде + +Если внешний прокси сам по себе ненадёжен — это **инфраструктурное** +решение (договор с провайдером / переход на другую CDN / поднять TLS +на самой prod-vm). Это вне scope этого инцидента. + +Watchdog теперь корректно классифицирует такие сбои, но не маскирует +их полностью — operator видит yellow status и может разобраться, что +именно (network vs app) подгорает. + +## Retest + +После патча watchdog'a + локальной верификации (внутри stage 5/5 → 200): + +``` +~/quality-watchdog.sh → ожидаем 4/8 red БЕЗ incident-файлов + (поскольку network failures не эскалируются) +``` + +## Lessons learned + +1. **Watchdog должен различать сетевые и приложенческие сбои.** Сделано. +2. **4h soak должен запускаться изнутри stage'a**, минуя внешний proxy. + TODO для будущего: вариант запуска `tests/load/soak-4h.js` через + `docker exec food-market-stage-api-1 k6 ...` или с локального prod-vm + к `localhost:8085`. +3. **Внешний прокси 88.204.171.93** — single point of failure для + stage-доступа извне. Записано в `docs/RUNBOOK.md` (TODO добавить). + +## Closure + +Incident — false positive (внешняя сеть). Watchdog запатчен. Реальных +багов в food-market нет. Возвращаемся к текущему спринту.