diff --git a/HISTORY/2026-10-07-session-log.md b/HISTORY/2026-10-07-session-log.md index 8b5fb81..6bc10ee 100644 --- a/HISTORY/2026-10-07-session-log.md +++ b/HISTORY/2026-10-07-session-log.md @@ -79,5 +79,39 @@ (вычистить легаси `internal/api/`, `cmd/sqs-consumer`). - Платформенные проблемы (wss ~150с, MSS/MTU) — вне кода. +--- + +## Архитекторский разбор (Дипсик Про, по итогам перепроверки) + +Перечитана цепочка `bridge → SQS → consumer → iotpg` целиком. Найдены 5 проблем +(часть — мой же недочёт при кодинге P0-7/P0-8): + +1. 🔴 **Залипание на «ядовитом» батче.** После моего фикса «возвращаем строки в + буфер при ошибке» один payload, падающий не по `ON CONFLICT`, зацикливает + flush этого namespace навсегда (flusher каждые 200мс). Так «тихая потеря» + превратилась в «вечное залипание». ← моя ошибка: фикс без различения типов ошибок. +2. 🔴 **Битый envelope теряется безвозвратно.** `processTelemetry` на битый JSON + возвращает `nil` → consumer подтверждает (DeleteMessage) → мусор исчезает без + следа. Если мусор шлёт bridge по багу — данные теряются навсегда, без DLQ. +3. 🟠 **Нарушение порядка телеметрии.** `ts` ставится `now()` в БД при INSERT, а + не в момент приёма (`ReceivedAt` из envelope не идёт в батч). При батчинге и + нескольких потоках порядок для device_id не гарантирован. +4. 🟠 **Дублирование / нет дедупа для `message_id=""`.** `ON CONFLICT` по + `(device_id, message_id)` не ловит NULL: legacy `cmd/sqs-consumer` передаёт + `""` → дубли вставляются. Плюс гонка InsertTelemetry(full) ↔ flusher на одном + namespace = два параллельных INSERT. +5. 🟡 **Close() может потерять последний батч** при ошибке shutdown-flush + (`_ = flushAll(...)` — ошибка игнорируется). + +### Решение (как принято) +- п.1 + п.3 (битые/ядовитые → DLQ) — делаю я (Дипсик Про), это дизайн-развилки. +- п.2 + п.4 (ReceivedAt; message_id NOT NULL) — передаются Флашу, с критериями. +- Битое сообщение — **в DLQ** (стандартный паттерн: valid→process, invalid→DLQ). +- Ядовитый SQL-батч — различать retryable (сеть/PG лежит → ретрай в буфер) от + permanent (нарушение constraint → не вешать namespace, выброс в лог/DLQ). + +### Статус +Реализация п.1 (разделение ошибок flush) и п.3 (ббитые → DLQ) — см. ниже. + ## Проверки - `go build ./...` и `go vet ./internal/...` — зелёные на каждом шаге.