test(loadtests): 10 load scenarios + verifier; docs: Sonnet review findings

This commit is contained in:
“Naeel”
2026-08-16 16:59:29 +04:00
parent a4a11bae54
commit 090cedca67
14 changed files with 1024 additions and 0 deletions
+49
View File
@@ -1068,3 +1068,52 @@ EMQX 4 CPU/2Gi, iot-service 1 CPU/1Gi.
### 30.3 Запрос Sonnet (код-ревью + план тестов)
Статус: ЗАПРОШЕН — результат в секции 31.
---
## 31. Sonnet-ревью + набор нагрузочных тестов (16:10 GMT+03)
### 31.1 Ревью Sonnet — ключевые находки (полный отчёт сохранён в чате)
20 находок. ВАЖНЕЙШИЕ (проверено по коду):
1. **CRITICAL** `internal/service/bridge/handler.go:50` — `SendMessage` в SQS
синхронный внутри MQTT-колбэка paho (сериализованный диспатч). При
недоступности SQS (таймаут ~30с) блокируется приём ВСЕХ MQTT-сообщений
→ потери. ФИКС: канал + worker-пул, дроп при переполнении. ПОДТВЕРЖДЕНО.
2. **HIGH** consumer: VisibilityTimeout=30с vs EnsureTenantDB (CREATE DATABASE
5-10с + user + grant + table) → дубли при медленной обработке. ФИКС:
VisibilityTimeout 120-180с или раздельная обработка.
3. **HIGH** consumer: нет backoff при падении PG → лавина ретраев после
восстановления. ФИКС: exponential backoff + jitter, DLQ.
4. **MEDIUM** main.go: shutdown — HTTP гаснет раньше bridge/consumer →
liveness-килл. ФИКС: сначала bridge/consumer, потом HTTP.
5. **MEDIUM** iotpg.InsertTelemetry без батчинга (1000 msg/s = 1000 INSERT).
ФИКС: буфер + batch INSERT.
Прочие: гонка getTenantDB (singleflight), лимит tenant-БД (whitelist),
defer в цикле AdminStats, MaxOpenConns=5 (devices/admin), List без пагинации,
JWT без подписи (архитектурно), валидация MQTT_BROKER_URL, топик в bridge
(пустой ns), CREATE USER через Sprintf (%I/%L), логирование пустых SQS-body,
молчаливый дроп битого JSON, subscribe-таймаут не фатален.
СТАТУС: НИЧЕГО НЕ ИСПРАВЛЕНО — ждём команду «делай» по фиксам.
### 31.2 Набор нагрузочных тестов — создан `loadtests/`
Python-пакет (paho-mqtt + stdlib), запуск: `python3 -m loadtests.run <сценарий>`.
10 сценариев: baseline, burst, large-payload, reconnect-storm, multitenant,
acl-violation, auth-neg, api-crud, telemetry-query, soak.
Механика: тест сам создаёт устройства (namespace lt_*) через API, публикует
payload {run_id, seq, sent_at, pad}, верификатор сверяет доставку через API:
delivered/lost/duplicates/latency (p50/p95/p99, ts(PG)-sent_at, NTP).
Документация и критерии успеха — loadtests/README.md; ручные SQS/PG-outage
тесты (через kubectl) описаны там же.
Грабли: POST /devices НЕ возвращает пароль (только GET по имени — учтено);
paho connect() rc=0 даже при CONNACK≠0 (on_connect обязателен); ts парсится
через datetime.fromisoformat (таймзона!); API отдаёт ≤1000 строк.
### 31.3 Смоук-прогон (прод, минимальная нагрузка)
- auth-neg: wrong_password rc=4, unknown_user rc=5 — PASS.
- baseline (2 устройства, 0.5 msg/s, 10с): sent 10, delivered 10/10,
lost 0, duplicates 0, latency p50≈208мс, первое сообщение ≈1.25с
(consumer long-poll). PASS.
### 31.4 Дальше
- Ждём «делай» по фиксам из 31.1 (минимум №1 и №2 перед большими нагрузками).
- Прогон полных сценариев — по команде.