100 lines
4.7 KiB
Markdown
100 lines
4.7 KiB
Markdown
# 10 — Code Review (Sonnet) + Fix
|
||
|
||
**Дата:** 2026-07-22
|
||
**Источник:** Анализ Sonnet (Claude) через VS Code Copilot Chat
|
||
|
||
---
|
||
|
||
## Структура проекта
|
||
|
||
### apps — исходный код приложений
|
||
|
||
| Папка | Роль | Зависимости |
|
||
|---|---|---|
|
||
| `iot-producer` | Генерирует события → RabbitMQ | `amqplib`, `express` |
|
||
| `iot-consumer` | RabbitMQ → Redis + MongoDB | `amqplib`, `redis`, `mongodb`, `express` |
|
||
| `iot-dashboard` | Redis → UI (Chart.js) | `express`, `redis` |
|
||
| `iot-demo` | Только HISTORY — не приложение | — |
|
||
|
||
### IOT_RMQ_DEMO — Terraform-конфиг стенда
|
||
|
||
6 ресурсов в 5 файлах: infra.tf (RabbitMQ + Redis + MongoDB), producer.tf, consumer.tf, dashboard.tf, locals.tf (все параметры вынесены сюда).
|
||
|
||
---
|
||
|
||
## Что хорошо
|
||
|
||
**Архитектура:**
|
||
- Чёткое разделение ответственности: каждое приложение делает одно дело
|
||
- Dashboard читает **только Redis** — правильно, никакой нагрузки на MongoDB
|
||
- `ch.prefetch(10)` у consumer — нормальное управление backpressure
|
||
- TTL-индекс в MongoDB (`expireAfterSeconds: 604800`, 7 дней) — события автоматически удалятся
|
||
- `zRemRangeByRank("iot:recent", 0, -1001)` — лента событий ограничена 1000 записями
|
||
|
||
**Terraform:**
|
||
- `adopt_existing_on_create = true` — удобно при повторных `apply` без пересоздания
|
||
- `depends_on` расставлены корректно: consumer ждёт все три сервиса, dashboard — только Redis
|
||
- Весь хардкод вынесен в locals.tf, в ресурсах чисто
|
||
- `sensitive = true` на `api_token`
|
||
|
||
---
|
||
|
||
## Проблемы (на момент анализа)
|
||
|
||
### 🔴 Баг: `MONGO_URI` без схемы `mongodb://` — **ИСПРАВЛЕНО 2026-07-22**
|
||
|
||
В consumer.tf строка формировалась так:
|
||
```hcl
|
||
MONGO_URI = "${local.cons_mgo_user}:${local.cons_mgo_pass}@${local.cons_mgo_host}:27017/iot?authSource=admin"
|
||
```
|
||
Результат: `admin:@hostname:27017/iot?authSource=admin`
|
||
|
||
В consumer.js `MongoClient` получал этот URI и падал — схема `mongodb://` отсутствовала. Дефолтный fallback `mongodb://localhost:27017/iot` не срабатывал, потому что переменная окружения была задана (просто невалидна).
|
||
|
||
**Фикс (2026-07-22):**
|
||
```hcl
|
||
MONGO_URI = "mongodb://${local.cons_mgo_user}:${local.cons_mgo_pass}@${local.cons_mgo_host}:27017/iot?authSource=admin"
|
||
```
|
||
Результат: `mongodb://admin:@hostname:27017/iot?authSource=admin`
|
||
|
||
**Верификация:** consumer `errors=0` после фикса.
|
||
|
||
### 🟡 nack с requeue=true — потенциальный infinite loop
|
||
|
||
В consumer.js:
|
||
```js
|
||
ch.nack(msg, false, true); // requeue = true
|
||
```
|
||
При систематической ошибке (например MongoDB недоступна) сообщение будет бесконечно возвращаться в очередь и перечитываться.
|
||
|
||
**Рекомендация:** `requeue=false` + логировать потерянное сообщение.
|
||
|
||
### 🟡 `s3_name` — объявлена, но не используется
|
||
|
||
В main.tf есть переменная `s3_name`, которая нигде в TF-файлах стенда не применяется. Legacy от шаблона.
|
||
|
||
### 🟡 `.trigger` — пустой файл в `iot-producer`
|
||
|
||
Файл .trigger пустой. Если нужен для force-redeploy — добавить комментарий.
|
||
|
||
### 🟡 `requirements.txt` в Node.js-папках
|
||
|
||
Файлы `requirements.txt` остались от Flask-экспериментов в iot-producer и iot-consumer. Мусор.
|
||
|
||
### 🟡 MongoDB без пароля
|
||
|
||
`cons_mgo_pass = ""` в locals.tf. Для демо-стенда приемлемо, но зафиксировано как известное ограничение.
|
||
|
||
---
|
||
|
||
## Статус на 2026-07-22
|
||
|
||
| Проблема | Статус |
|
||
|---|---|
|
||
| MONGO_URI без mongodb:// | ✅ Исправлено |
|
||
| nack + requeue=true | 🟡 Не исправлено (низкий приоритет) |
|
||
| s3_name не используется | 🟡 Не исправлено |
|
||
| .trigger пустой | 🟡 Не исправлено |
|
||
| requirements.txt мусор | 🟡 Не исправлено |
|
||
| MongoDB без пароля | ℹ️ Приемлемо для демо |
|