doc(HISTORY): архитекторский разбор телеметрии — 5 проблем и решение
This commit is contained in:
@@ -79,5 +79,39 @@
|
|||||||
(вычистить легаси `internal/api/`, `cmd/sqs-consumer`).
|
(вычистить легаси `internal/api/`, `cmd/sqs-consumer`).
|
||||||
- Платформенные проблемы (wss ~150с, MSS/MTU) — вне кода.
|
- Платформенные проблемы (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/...` — зелёные на каждом шаге.
|
- `go build ./...` и `go vet ./internal/...` — зелёные на каждом шаге.
|
||||||
|
|||||||
Reference in New Issue
Block a user