Тикер офлайн-детекции (internal/healthcheck) переехал из device-control-service в новый самостоятельный Go-сервис — как и планировалось с самого начала (см. изначальный README-заглушку). Детекция online остаётся в device-control-service: она происходит как побочный эффект уже имеющейся там MQTT-подписки на devices/+/telemetry и devices/+/ack, заводить для этого отдельный сервис с дублирующей MQTT-подпиской избыточно. health-check-service — свой Go-модуль (без зависимости от proto/, сборка из собственного контекста), читает только узкое read+offline-подмножество Device Shadow keyspace в Redis (devices:known, status, last_seen) — полный Shadow API с записью desired/reported state остаётся только в device-control-service. Метрика device_control_health_transitions_total переименована в device_health_transitions_total и теперь публикуется с этим именем из ДВУХ сервисов (device-control-service — direction=online, health-check-service — direction=offline): Prometheus агрегирует одноимённые метрики с разных таргетов прозрачно, поэтому Grafana- дашборд адаптирован простой сменой имени метрики в запросе, без переделки панели. Проверено вживую через docker compose: реальный online→offline переход (публикация тестовой телеметрии + ожидание таймаута) корректно долетает до Redis и RabbitMQ (device.status_changed), Prometheus видит новый scrape-таргет как up.
73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
// Package config loads device-control-service settings from environment
|
|
// variables, matching the names used in the repo-root .env.example.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
)
|
|
|
|
type Config struct {
|
|
GRPCPort int
|
|
HTTPPort int
|
|
|
|
MQTTBrokerURL string
|
|
MQTTClientID string
|
|
|
|
RedisAddr string
|
|
RedisPassword string
|
|
RedisDB int
|
|
|
|
RabbitMQURL string
|
|
}
|
|
|
|
func Load() (Config, error) {
|
|
cfg := Config{
|
|
MQTTBrokerURL: fmt.Sprintf("tcp://%s:%s", getEnv("MQTT_HOST", "localhost"), getEnv("MQTT_PORT", "1883")),
|
|
MQTTClientID: getEnv("DEVICE_CONTROL_MQTT_CLIENT_ID", "device-control-service"),
|
|
|
|
RedisAddr: fmt.Sprintf("%s:%s", getEnv("REDIS_HOST", "localhost"), getEnv("REDIS_PORT", "6379")),
|
|
RedisPassword: getEnv("REDIS_PASSWORD", ""),
|
|
|
|
RabbitMQURL: fmt.Sprintf("amqp://%s:%s@%s:%s/",
|
|
getEnv("RABBITMQ_USER", "guest"),
|
|
getEnv("RABBITMQ_PASSWORD", "guest"),
|
|
getEnv("RABBITMQ_HOST", "localhost"),
|
|
getEnv("RABBITMQ_PORT", "5672"),
|
|
),
|
|
}
|
|
|
|
var err error
|
|
if cfg.GRPCPort, err = getEnvInt("DEVICE_CONTROL_GRPC_PORT", 50051); err != nil {
|
|
return Config{}, err
|
|
}
|
|
if cfg.HTTPPort, err = getEnvInt("DEVICE_CONTROL_HTTP_PORT", 8090); err != nil {
|
|
return Config{}, err
|
|
}
|
|
if cfg.RedisDB, err = getEnvInt("REDIS_DB", 0); err != nil {
|
|
return Config{}, err
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func getEnv(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getEnvInt(key string, fallback int) (int, error) {
|
|
v := os.Getenv(key)
|
|
if v == "" {
|
|
return fallback, nil
|
|
}
|
|
n, err := strconv.Atoi(v)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("%s: %w", key, err)
|
|
}
|
|
return n, nil
|
|
}
|