Files
home_automatization/services/rule-engine-service/README.md
T
cacto abc83faf05 Реализация rule-engine-service: RabbitMQ → правила из PostgreSQL → gRPC
Слушает telemetry.new_reading (ручной ack/nack, реквизишн только при
транспортных ошибках gRPC), кэширует активные automation_rules в памяти
с периодическим обновлением из PostgreSQL (JOIN с devices — резолвит
внутренние ID в external_id, которым оперируют MQTT/Redis/gRPC). Условия
правил (>,<,>=,<=,=,!=) оцениваются обобщённо, без привязки к конкретным
типам устройств. При срабатывании вызывает device-control-service по gRPC
и публикует automation.rule_triggered в RabbitMQ.

Проверено сквозным тестом через docker compose на полном пайплайне:
mosquitto_pub → ingest-service (ClickHouse + telemetry.new_reading) →
rule-engine-service (совпадение правила) → device-control-service (gRPC →
Redis desired_state + MQTT-команда) → automation.rule_triggered. Показание
ниже порога проверено отдельно — правило корректно не срабатывает.
2026-07-26 21:18:59 +05:00

53 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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).
## Запуск
```bash
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`.