package config import ( "strconv" "time" sharedpostgres "knowfoolery/backend/shared/infra/database/postgres" sharedredis "knowfoolery/backend/shared/infra/database/redis" "knowfoolery/backend/shared/infra/observability/logging" "knowfoolery/backend/shared/infra/observability/metrics" "knowfoolery/backend/shared/infra/observability/tracing" "knowfoolery/backend/shared/infra/utils/envutil" ) // Config holds runtime configuration for leaderboard-service. type Config struct { AppName string Port int TopLimit int PlayerHistoryDefault int PlayerHistoryMax int CacheTTL time.Duration UpdateRequireAuth bool UpstreamHTTPTimeout time.Duration Postgres sharedpostgres.Config Redis sharedredis.Config Tracing tracing.Config Metrics metrics.Config Logging logging.Config ZitadelBaseURL string ZitadelIssuer string ZitadelAudience string ZitadelClientID string ZitadelSecret string } // FromEnv builds config from env vars. func FromEnv() Config { env := envutil.String("ENVIRONMENT", "development") serviceName := "leaderboard-service" logCfg := logging.DefaultConfig() logCfg.ServiceName = serviceName logCfg.Environment = env logCfg.Level = envutil.String("LOG_LEVEL", logCfg.Level) traceCfg := tracing.ConfigFromEnv() if traceCfg.ServiceName == "knowfoolery" { traceCfg.ServiceName = serviceName } traceCfg.Environment = env metricsCfg := metrics.ConfigFromEnv() if metricsCfg.ServiceName == "knowfoolery" { metricsCfg.ServiceName = serviceName } return Config{ AppName: "Know Foolery - Leaderboard Service", Port: envutil.Int("LEADERBOARD_PORT", 8083), TopLimit: envutil.Int("LEADERBOARD_TOP_LIMIT", 10), PlayerHistoryDefault: envutil.Int("LEADERBOARD_PLAYER_HISTORY_DEFAULT_LIMIT", 20), PlayerHistoryMax: envutil.Int("LEADERBOARD_PLAYER_HISTORY_MAX_LIMIT", 100), CacheTTL: envutil.Duration("LEADERBOARD_CACHE_TTL", 60*time.Second), UpdateRequireAuth: parseBool("LEADERBOARD_UPDATE_REQUIRE_AUTH", true), UpstreamHTTPTimeout: envutil.Duration("UPSTREAM_HTTP_TIMEOUT", 3*time.Second), Postgres: sharedpostgres.ConfigFromEnv(), Redis: sharedredis.ConfigFromEnv(), Tracing: traceCfg, Metrics: metricsCfg, Logging: logCfg, ZitadelBaseURL: envutil.String("ZITADEL_URL", ""), ZitadelIssuer: envutil.String("ZITADEL_ISSUER", ""), ZitadelAudience: envutil.String("ZITADEL_AUDIENCE", ""), ZitadelClientID: envutil.String("ZITADEL_CLIENT_ID", ""), ZitadelSecret: envutil.String("ZITADEL_CLIENT_SECRET", ""), } } func parseBool(key string, fallback bool) bool { v := envutil.String(key, "") if v == "" { return fallback } parsed, err := strconv.ParseBool(v) if err != nil { return fallback } return parsed }