52 lines
4.2 KiB
Markdown
52 lines
4.2 KiB
Markdown
# Журнал сессии — 2026-10-11 (IoT: внешнее код-ревью и фиксы)
|
||
|
||
> Запись по требованию «документировать всё, включая собственные ошибки» (приказ 2026-09-24).
|
||
> Предыдущие: `HISTORY/2026-10-07-session-log.md`, `HISTORY/2026-10-10-session-log.md`.
|
||
> Основание: внешнее ревью Claude Sonnet по промпту `../CLAUDE-REVIEW-PROMPT.md`
|
||
> (40 пунктов на два сервиса; SQS-часть — в `SQS-service/HISTORY/2026-10-11-session-log.md`).
|
||
|
||
## 1. Задача
|
||
|
||
Разобрать находки ревью по монолиту `iot-service` и исправить их.
|
||
|
||
## 2. Что исправлено
|
||
|
||
### 🔴 Критичные
|
||
|
||
- **🔴8/🔴9 — poison-строка в `flushAll`** (`internal/storage/iotpg/iot_telemetry_store.go:166,177`).
|
||
При постоянной (не retryable) ошибке `flushAll` возвращал ошибку → consumer
|
||
(`consumer.go:159`) не удалял батч из SQS → бесконечный redelivery всего батча.
|
||
Теперь ошибку ставит только retryable-ветка; постоянная ошибка означает «валидные
|
||
строки уже вставлены построчно, битые отброшены» → `Flush` возвращает nil, батч
|
||
подтверждается. Коммит `1fe543f`.
|
||
|
||
### 🟡 Важные
|
||
|
||
| Пункт | Файл | Суть | Коммит |
|
||
|-------|------|------|--------|
|
||
| 🟡13 | `bridge/sender.go` | Ретраил бесконечно любые ошибки SQS; permanent (4xx/размер/нет очереди) занимали воркеры → классификация `isPermanentSQSErr` (smithy APIError) | `657850d` |
|
||
| 🟡14 | `bridge/handler.go` | `MessageID = uuid` на каждый колбэк → повторная QoS1-доставка не дедуплицировалась. Теперь `SHA256(ns\|device\|topic\|payload)` | `657850d` |
|
||
| 🟡15 | `bridge/bridge.go` | После 3 неудач подписки ждали следующего реконнекта (которого не будет при живом соединении) → бесконечный ретрай подписки | `657850d` |
|
||
| (new) | `bridge/handler.go` | Defense-in-depth: валидация формата `ns`/`deviceID` из топика (барьер — EMQX authz) | `657850d` |
|
||
| 🟡17 | `consumer/consumer.go` | `receiveCount` проверялся только для битого envelope → применяем `maxReceiveCount` ко всем ошибкам | `5114320` |
|
||
| 🟡18 | `cmd/iot-service/main.go` | `run()` выходил до завершения `server.Shutdown` → deferred Close срабатывали до дренажа in-flight. Добавлен `shutdownDone` | `5114320` |
|
||
| 🟡19 | `api/handler/devices.go` | Ошибка `GetByName` после успешного INSERT давала 500 (пароль терялся, повтор → 409) → отдаём 201 с in-memory объектом | `5114320` |
|
||
| 🟡11 | `iotpg/iot_telemetry_store.go` | `getTenantDB`/`QueryTelemetry` не проверяли `safeNamespaceRe` (`a_b` ↔ `a-b` → одна БД) → валидация на всех путях | `f41a9fe` |
|
||
|
||
### Осознанно НЕ менялось (решения)
|
||
|
||
- 🟡16 (QoS1 ack): оставлен async-ack + метрика дропов (throughput важнее; синхронный
|
||
ack блокировал бы MQTT-колбэк — это уже чинили ранее).
|
||
- 🟡12 (`AUTH_TEST_MODE`): уже fail-closed — при отсутствии `JWT_HMAC_SECRET` и
|
||
`AUTH_TEST_MODE=false` middleware отказывает в обслуживании.
|
||
|
||
## 3. Прочее (перед ревью, в этой же сессии)
|
||
|
||
- `193509c` — консоль: namespace = `sub` (убрали `sless-{SHA256}`, расходившийся с
|
||
middleware) и удалили несуществующий `POST /v1/namespaces/{ns}/ensure`.
|
||
|
||
## 4. Верификация
|
||
|
||
- `go build ./...`, `go vet ./...`, `go test -race ./...` — зелёные.
|
||
- Push: `54fe1f5..f41a9fe` в `origin/master`.
|