Files
home_automatization/services/rule-engine-service/README.md
cacto 81040eec62 Добавлены метрики Prometheus и дашборды Grafana (этап 2.5)
Все три Go-сервиса (ingest, device-control, rule-engine) отдают
/metrics в формате Prometheus: счётчики MQTT/RabbitMQ/ClickHouse
операций, гистограммы длительности батч-флашей и диспатча правил,
переходы устройств online/offline. Добавлены сервисы prometheus и
grafana в docker-compose с провижининг конфигом (datasource +
два готовых дашборда: "Ingest & Telemetry" и "Automation & Devices").
2026-08-11 21:58:59 +05:00

4.1 KiB
Raw Permalink Blame History

rule-engine-service (Go)

Статус: реализован (MVP).

Зона ответственности:

  • Потребляет события «новое показание» из RabbitMQ (очередь telemetry.new_reading, публикуемая ingest-service) — асинхронно, с ручным ack/nack: надёжность доставки здесь важнее задержки.
  • Загружает активные automation_rules из PostgreSQL в кэш в памяти (обновляется по тикеру), чтобы не ходить в БД на каждое событие.
  • Оценивает условия правил обобщённо: sensor_type X operator value против показания — никаких зашитых названий датчиков/устройств, всё берётся из строки automation_rules.
  • При срабатывании: вызывает device-control-service по gRPC (нужен быстрый результат успех/неудача) и публикует событие automation.rule_triggered в RabbitMQ для будущего notification-service (не критично к задержке).

Не входит в зону ответственности: прямое взаимодействие с MQTT или Redis — изменения состояния устройства всегда идут через gRPC API device-control-service.

Архитектурные решения

  • automation_rules хранит внутренние ID Postgres, а не внешние device_id. condition_source_device_id/target_device_id — это FK на devices.id (bigserial), а MQTT/Redis/gRPC везде оперируют devices.external_id (строка). Поэтому кэш правил грузится JOIN'ом automation_rules с devices (дважды — для source и target), резолвя оба ID в external_id один раз при загрузке, а не на каждое событие.
  • Retry — только на транспортных ошибках. Если gRPC-вызов device-control-service не удался физически (сеть, сервис недоступен) — событие из RabbitMQ nack'ается с requeue=true, всё правило переигрывается позже. Если устройство само отклонило команду (CommandResult.success=false, например неизвестный device_id) — это финальный исход, ack, повторов не будет. Осознанное упрощение: если из нескольких правил на одно показание одно не удалось из-за сети, при повторной доставке переиграются ВСЕ правила читающие это показание, включая уже успешно сработавшие — дедупликация не реализована, для MVP это приемлемо (команды идемпотентны: turn_on дважды — не проблема).
  • Кэш правил — только для чтения активных правил, никакой записи назад в Postgres. CRUD правил — это зона ответственности Laravel (этап 2).

Метрики

GET /metrics (порт RULE_ENGINE_METRICS_PORT, по умолчанию 9102) — счётчики обработанных показаний, сработавших правил (по action_type и исходу), latency вызова device-control-service, обновлений кэша правил.

Запуск

cd services/rule-engine-service
go test ./...
go build ./cmd/rule-engine-service

Конфигурация — через переменные окружения (секция rule-engine-service в корневом .env.example). Как и device-control-service, использует proto/device_control через replace на ../../proto в go.mod.