diff --git a/HISTORY/10-code-review-sonnet.md b/HISTORY/10-code-review-sonnet.md new file mode 100644 index 0000000..f368286 --- /dev/null +++ b/HISTORY/10-code-review-sonnet.md @@ -0,0 +1,99 @@ +# 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 без пароля | ℹ️ Приемлемо для демо | diff --git a/HISTORY/prompt_for_gemini_iot_diagram.md b/HISTORY/prompt_for_gemini_iot_diagram.md new file mode 100644 index 0000000..bf56d5e --- /dev/null +++ b/HISTORY/prompt_for_gemini_iot_diagram.md @@ -0,0 +1,108 @@ +# Prompt для Gemini: диаграмма пайплайна IoT Demo + +## Задача + +Создай красивую диаграмму (flowchart/архитектурную схему) пайплайна данных для IoT-демонстрации «Умный дом». Нужна **одна картинка** с 6 блоками сервисов и стрелками между ними. + +--- + +## Сервисы (блоки) + +### 1. Producer (верхний левый угол) +- **Название:** Producer +- **Подпись:** Node.js · Генератор IoT-событий +- **Форма:** прямоугольник, синий/голубой (#3B82F6 или похожий) +- **Иконка:** ⚙️ или 📡 +- **Что делает:** Эмулирует 8 IoT-датчиков (температура °C, влажность %, энергопотребление kW), каждые 3 секунды генерирует случайное JSON-событие + +### 2. RabbitMQ (центр-верх) +- **Название:** RabbitMQ +- **Подпись:** Очередь сообщений · iot-events +- **Форма:** прямоугольник, оранжевый (#FF6600 — брендовый цвет RabbitMQ) +- **Иконка:** 🐰 или 📬 +- **Что делает:** Буфер сообщений AMQP. Принимает от Producer, отдаёт Consumer. Durable — не теряет при рестарте. + +### 3. Consumer (правый верхний) +- **Название:** Consumer +- **Подпись:** Node.js · Обработчик +- **Форма:** прямоугольник, зелёный (#10B981) +- **Иконка:** 📥 или 🔄 +- **Что делает:** Читает очередь RabbitMQ, параллельно пишет в Redis и MongoDB + +### 4. Redis (левый-центр, под Producer) +- **Название:** Redis +- **Подпись:** Кэш · latest + counters + recent +- **Форма:** прямоугольник, красный (#DC2626 — брендовый цвет Redis) +- **Иконка:** ⚡ или 🗄️ +- **Что делает:** Оперативный кэш для Dashboard. Хранит: последние значения датчиков (hash), счётчики по типам (hash), ленту 1000 событий (zset). + +### 5. MongoDB (центр-низ) +- **Название:** MongoDB +- **Подпись:** Архив · TTL 7 дней +- **Форма:** прямоугольник, тёмно-зелёный (#00684A — брендовый цвет MongoDB) +- **Иконка:** 🍃 или 💾 +- **Что делает:** Постоянный архив всех событий в коллекции iot_events. Автоудаление через 7 дней (TTL-индекс). + +### 6. Dashboard (правый-низ) +- **Название:** Dashboard +- **Подпись:** Node.js + Chart.js · Веб-интерфейс +- **Форма:** прямоугольник, фиолетовый (#8B5CF6) +- **Иконка:** 📊 или 🖥️ +- **Что делает:** Читает Redis, отдаёт JSON API и HTML с графиками. Bar chart (значения), Doughnut (счётчики), таблица событий. Автообновление каждые 3 сек. + +--- + +## Стрелки (потоки данных) + +| От | К | Протокол | Подпись на стрелке | +|---|---|---|---| +| Producer | RabbitMQ | AMQP (порт 5672) | JSON-события → очередь iot-events | +| RabbitMQ | Consumer | AMQP (порт 5672) | JSON-события ← очередь iot-events | +| Consumer | Redis (latest) | TCP (порт 6379) | HSET sensor_id → значение | +| Consumer | Redis (counters) | TCP (порт 6379) | HINCRBY device_type | +| Consumer | Redis (recent) | TCP (порт 6379) | ZADD лента событий | +| Consumer | MongoDB | TCP (порт 27017) | insertOne → коллекция iot_events | +| Redis | Dashboard | TCP (порт 6379) | HGETALL + ZRANGE (только чтение) | + +--- + +## Расположение на схеме + +``` + Producer ──→ RabbitMQ ──→ Consumer + │ + ┌──────────────┼──────────────┐ + ↓ ↓ ↓ + Redis MongoDB Redis + (latest, (архив) (counters, + recent) ...) + │ │ │ + └──────────────┼──────────────┘ + ↓ + Dashboard +``` + +--- + +## Стиль + +- **Тёмный фон** (#0F172A или похожий) — как у самого дашборда +- **Блоки** с закруглёнными углами (border-radius 8–12px) +- **Цвета блоков** — брендовые цвета каждого сервиса (см. выше) +- **Текст в блоках** — белый или светлый +- **Стрелки** — с подписями протоколов (AMQP, TCP) и названиями данных +- **Иконки** в блоках приветствуются +- **Легенда** внизу: протоколы (AMQP — оранжевая стрелка, TCP — серая стрелка) +- Заголовок схемы: «IoT Demo — Умный дом» и подзаголовок «6 сервисов Nubes Cloud» + +--- + +## Дополнительно + +Можно добавить разделительную линию (или фон) показывающую, что все сервисы внутри Kubernetes-кластера, а наружу торчит только Dashboard (HTTP/HTTPS) и Producer/Consumer (для health-check). + +--- + +## Формат + +Сгенерируй **SVG** или **PNG**, который можно вставить в README.md. diff --git a/HISTORY/prompt_for_gemini_iot_diagram_FINAL.md b/HISTORY/prompt_for_gemini_iot_diagram_FINAL.md new file mode 100644 index 0000000..3810f72 --- /dev/null +++ b/HISTORY/prompt_for_gemini_iot_diagram_FINAL.md @@ -0,0 +1,41 @@ +# Промпт для Gemini — ФИНАЛЬНАЯ ПРАВКА + +У тебя уже есть схема. В ней **две ошибки**, исправь только их: + +## Ошибка 1: Dashboard соединён с MongoDB — УБРАТЬ + +Никакой связи между Dashboard и MongoDB нет. Dashboard читает ТОЛЬКО Redis. Убери эту стрелку. + +## Ошибка 2: Нет связи Consumer → MongoDB + +Consumer пишет в MongoDB (insertOne). Добавь стрелку Consumer → MongoDB с подписью "TCP · insertOne · архив 7 дн". + +--- + +## Правильные связи (ВСЕ, ничего лишнего): + +``` +Producer ──AMQP──→ RabbitMQ ──AMQP──→ Consumer + │ + ┌───────────┼───────────┐ + │ TCP │ TCP │ TCP + ▼ ▼ ▼ + Redis MongoDB Redis + (HSET/ZADD) (insertOne) (HINCRBY) + │ + │ TCP (только чтение) + ▼ + Dashboard ──HTTP──→ Браузер +``` + +--- + +## Что МЕНЯТЬ в имеющейся схеме: + +1. **Удали** стрелку между Dashboard и MongoDB (в любую сторону) +2. **Добавь** стрелку Consumer → MongoDB (TCP, insertOne) +3. **Проверь** что Consumer → Redis (TCP, три команды: HSET, HINCRBY, ZADD) +4. **Проверь** что Redis → Dashboard (TCP, только чтение) +5. Всё. Больше ничего не трогай. + +Никаких других изменений. Только эти две правки. diff --git a/TEST_STAND/IOT_RMQ_DEMO/consumer.tf b/TEST_STAND/IOT_RMQ_DEMO/consumer.tf index 1697f00..63c3250 100644 --- a/TEST_STAND/IOT_RMQ_DEMO/consumer.tf +++ b/TEST_STAND/IOT_RMQ_DEMO/consumer.tf @@ -56,7 +56,7 @@ resource "nubes_nodejs" "consumer" { REDIS_HOST = local.cons_rds_host # хост Redis REDIS_PORT = "6379" # порт Redis REDIS_PASS = local.cons_rds_pass # пароль Redis - MONGO_URI = "${local.cons_mgo_user}:${local.cons_mgo_pass}@${local.cons_mgo_host}:27017/iot?authSource=admin" + MONGO_URI = "mongodb://${local.cons_mgo_user}:${local.cons_mgo_pass}@${local.cons_mgo_host}:27017/iot?authSource=admin" MONGO_DB = "iot" # имя базы MongoDB }) diff --git a/TEST_STAND/IOT_RMQ_DEMO/locals.tf b/TEST_STAND/IOT_RMQ_DEMO/locals.tf index c378fe5..fc8f488 100644 --- a/TEST_STAND/IOT_RMQ_DEMO/locals.tf +++ b/TEST_STAND/IOT_RMQ_DEMO/locals.tf @@ -40,8 +40,8 @@ locals { prod_timeout = "11m" # таймаут операций # --- Consumer (Node.js): RabbitMQ -> Redis + MongoDB --- - cons_resource_name = "iot-cons3" # имя инстанса (cons = CONSumer, версия 3) - cons_domain = "iotcons22n" # поддомен -> iotcons22n.nodejsk8s.dev.nubes.ru + cons_resource_name = "iot-cons4" # имя инстанса (cons = CONSumer, версия 4) + cons_domain = "iotcons23n" # поддомен -> iotcons23n.nodejsk8s.dev.nubes.ru cons_git_path = "https://gitea.services.ngcloud.ru/Nail/tf-iot-consumer.git" # Git-репо с кодом consumer cons_git_revision = "03fefc0" # хеш коммита (менять для редеплоя) cons_cpu = 300 # CPU millicores @@ -50,8 +50,8 @@ locals { cons_timeout = "11m" # таймаут операций # --- Dashboard (Node.js + Chart.js): Redis -> графики --- - dash_resource_name = "iot-dash" # имя инстанса (dash = DASHboard) - dash_domain = "iotdash22" # поддомен -> iotdash22.nodejsk8s.dev.nubes.ru + dash_resource_name = "iot-dash2" # имя инстанса (dash = DASHboard, версия 2) + dash_domain = "iotdash23" # поддомен -> iotdash23.nodejsk8s.dev.nubes.ru dash_git_path = "https://gitea.services.ngcloud.ru/Nail/tf-iot-dashboard.git" # Git-репо с кодом dashboard dash_git_revision = "bc6f43d" # хеш коммита (менять для редеплоя) dash_cpu = 300 # CPU millicores diff --git a/demo.jpg b/demo.jpg new file mode 100755 index 0000000..8178bde Binary files /dev/null and b/demo.jpg differ