// Package config provides environment-based configuration for handler services. package config import ( "os" "strconv" "time" ) // Settings holds base configuration for all handler services. // Values are loaded from environment variables with sensible defaults. type Settings struct { // Service identification ServiceName string ServiceVersion string ServiceNamespace string DeploymentEnv string // NATS configuration NATSURL string NATSUser string NATSPassword string NATSQueueGroup string // Redis/Valkey configuration RedisURL string RedisPassword string // Milvus configuration MilvusHost string MilvusPort int MilvusCollection string // Service endpoints EmbeddingsURL string RerankerURL string LLMURL string TTSURL string STTURL string // OpenTelemetry configuration OTELEnabled bool OTELEndpoint string OTELUseHTTP bool // HyperDX configuration HyperDXEnabled bool HyperDXAPIKey string HyperDXEndpoint string // MLflow configuration MLflowTrackingURI string MLflowExperimentName string MLflowEnabled bool // Health check configuration HealthPort int HealthPath string ReadyPath string // Timeouts HTTPTimeout time.Duration NATSTimeout time.Duration } // Load creates a Settings populated from environment variables with defaults. func Load() *Settings { return &Settings{ ServiceName: getEnv("SERVICE_NAME", "handler"), ServiceVersion: getEnv("SERVICE_VERSION", "1.0.0"), ServiceNamespace: getEnv("SERVICE_NAMESPACE", "ai-ml"), DeploymentEnv: getEnv("DEPLOYMENT_ENV", "production"), NATSURL: getEnv("NATS_URL", "nats://nats.ai-ml.svc.cluster.local:4222"), NATSUser: getEnv("NATS_USER", ""), NATSPassword: getEnv("NATS_PASSWORD", ""), NATSQueueGroup: getEnv("NATS_QUEUE_GROUP", ""), RedisURL: getEnv("REDIS_URL", "redis://valkey.ai-ml.svc.cluster.local:6379"), RedisPassword: getEnv("REDIS_PASSWORD", ""), MilvusHost: getEnv("MILVUS_HOST", "milvus.ai-ml.svc.cluster.local"), MilvusPort: getEnvInt("MILVUS_PORT", 19530), MilvusCollection: getEnv("MILVUS_COLLECTION", "documents"), EmbeddingsURL: getEnv("EMBEDDINGS_URL", "http://embeddings-predictor.ai-ml.svc.cluster.local"), RerankerURL: getEnv("RERANKER_URL", "http://reranker-predictor.ai-ml.svc.cluster.local"), LLMURL: getEnv("LLM_URL", "http://vllm-predictor.ai-ml.svc.cluster.local"), TTSURL: getEnv("TTS_URL", "http://tts-predictor.ai-ml.svc.cluster.local"), STTURL: getEnv("STT_URL", "http://whisper-predictor.ai-ml.svc.cluster.local"), OTELEnabled: getEnvBool("OTEL_ENABLED", true), OTELEndpoint: getEnv("OTEL_ENDPOINT", "http://opentelemetry-collector.observability.svc.cluster.local:4317"), OTELUseHTTP: getEnvBool("OTEL_USE_HTTP", false), HyperDXEnabled: getEnvBool("HYPERDX_ENABLED", false), HyperDXAPIKey: getEnv("HYPERDX_API_KEY", ""), HyperDXEndpoint: getEnv("HYPERDX_ENDPOINT", "https://in-otel.hyperdx.io"), MLflowTrackingURI: getEnv("MLFLOW_TRACKING_URI", "http://mlflow.mlflow.svc.cluster.local:80"), MLflowExperimentName: getEnv("MLFLOW_EXPERIMENT_NAME", ""), MLflowEnabled: getEnvBool("MLFLOW_ENABLED", true), HealthPort: getEnvInt("HEALTH_PORT", 8080), HealthPath: getEnv("HEALTH_PATH", "/health"), ReadyPath: getEnv("READY_PATH", "/ready"), HTTPTimeout: getEnvDuration("HTTP_TIMEOUT", 60*time.Second), NATSTimeout: getEnvDuration("NATS_TIMEOUT", 30*time.Second), } } func getEnv(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback } func getEnvInt(key string, fallback int) int { if v := os.Getenv(key); v != "" { if i, err := strconv.Atoi(v); err == nil { return i } } return fallback } func getEnvBool(key string, fallback bool) bool { if v := os.Getenv(key); v != "" { if b, err := strconv.ParseBool(v); err == nil { return b } } return fallback } func getEnvDuration(key string, fallback time.Duration) time.Duration { if v := os.Getenv(key); v != "" { if f, err := strconv.ParseFloat(v, 64); err == nil { return time.Duration(f * float64(time.Second)) } } return fallback }