food-market/docs/sprint-incident-1780974301.md
nns b3ed6796ce
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
docs(s28): incident 1780974301 — false-positive из-за external network
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 <noreply@anthropic.com>
2026-06-09 08:26:08 +05:00

5.5 KiB
Raw Blame History

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)

# Свежий 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)

# Тот же 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 нет. Возвращаемся к текущему спринту.