Реализация 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. Показание ниже порога проверено отдельно — правило корректно не срабатывает.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
// Package config loads rule-engine-service settings from environment
|
||||
// variables, matching the names used in the repo-root .env.example.
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
PostgresDSN string
|
||||
|
||||
DeviceControlGRPCTarget string
|
||||
|
||||
RabbitMQURL string
|
||||
|
||||
RuleCacheRefreshInterval time.Duration
|
||||
}
|
||||
|
||||
func Load() (Config, error) {
|
||||
cfg := Config{
|
||||
PostgresDSN: fmt.Sprintf("postgres://%s:%s@%s:%s/%s",
|
||||
getEnv("POSTGRES_USER", "home_automation"),
|
||||
getEnv("POSTGRES_PASSWORD", ""),
|
||||
getEnv("POSTGRES_HOST", "localhost"),
|
||||
getEnv("POSTGRES_PORT", "5432"),
|
||||
getEnv("POSTGRES_DB", "home_automation"),
|
||||
),
|
||||
|
||||
DeviceControlGRPCTarget: fmt.Sprintf("%s:%s",
|
||||
getEnv("DEVICE_CONTROL_HOST", "localhost"),
|
||||
getEnv("DEVICE_CONTROL_GRPC_PORT", "50051"),
|
||||
),
|
||||
|
||||
RabbitMQURL: fmt.Sprintf("amqp://%s:%s@%s:%s/",
|
||||
getEnv("RABBITMQ_USER", "guest"),
|
||||
getEnv("RABBITMQ_PASSWORD", "guest"),
|
||||
getEnv("RABBITMQ_HOST", "localhost"),
|
||||
getEnv("RABBITMQ_PORT", "5672"),
|
||||
),
|
||||
}
|
||||
|
||||
interval, err := getEnvDuration("RULE_ENGINE_CACHE_REFRESH_INTERVAL", 15*time.Second)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.RuleCacheRefreshInterval = interval
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func getEnv(key, fallback string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func getEnvDuration(key string, fallback time.Duration) (time.Duration, error) {
|
||||
v := os.Getenv(key)
|
||||
if v == "" {
|
||||
return fallback, nil
|
||||
}
|
||||
d, err := time.ParseDuration(v)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("%s: %w", key, err)
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
Reference in New Issue
Block a user