# 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`.