package config import ( "fmt" "strings" "testing" "github.com/stretchr/testify/assert" ) // ============================================================================= // Test: config_validate.go — All Validation Functions // 覆盖: Validate, validateJWT, validateLog, validateServerURL, // validateLinuxDo, validateOIDC, validateBilling, validateDatabase, // validateRedis, validateDashboard, validateDashboardAgg, // validateUsageCleanup, validateIdempotency, validateOps, // validateConcurrency // ============================================================================= // --- validateJWT --- func TestValidateJWT(t *testing.T) { tests := []struct { name string cfg JWTConfig wantErr bool errContains string }{ { name: "valid config", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 24, RefreshTokenExpireDays: 30}, wantErr: false, }, { name: "empty secret", cfg: JWTConfig{Secret: "", ExpireHour: 24}, wantErr: true, errContains: "jwt.secret is required", }, { name: "secret too short (<32 bytes)", cfg: JWTConfig{Secret: "short", ExpireHour: 24}, wantErr: true, errContains: "jwt.secret must be at least 32 bytes", }, { name: "secret exactly 32 bytes (valid)", cfg: JWTConfig{Secret: strings.Repeat("a", 32), ExpireHour: 24, RefreshTokenExpireDays: 30}, wantErr: false, }, { name: "expire_hour zero or negative", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 0}, wantErr: true, errContains: "jwt.expire_hour must be positive", }, { name: "expire_hour exceeds max (168)", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 169}, wantErr: true, errContains: "jwt.expire_hour must be <= 168", }, { name: "expire_hour exactly 168 (7 days)", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 168, RefreshTokenExpireDays: 30}, wantErr: false, }, { name: "access_token_expire_minutes negative", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 24, AccessTokenExpireMinutes: -1}, wantErr: true, errContains: "jwt.access_token_expire_minutes must be non-negative", }, { name: "access_token_expire_minutes too high (>720)", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 24, AccessTokenExpireMinutes: 721, RefreshTokenExpireDays: 30}, wantErr: false, // only warns, not errors }, { name: "refresh_token_expire_days zero", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 24, RefreshTokenExpireDays: 0}, wantErr: true, errContains: "jwt.refresh_token_expire_days must be positive", }, { name: "refresh_token_expire_days >90 warns but passes", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 24, RefreshTokenExpireDays: 91}, wantErr: false, // only warns }, { name: "refresh_window_minutes negative", cfg: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 24, RefreshTokenExpireDays: 30, RefreshWindowMinutes: -1}, wantErr: true, errContains: "jwt.refresh_window_minutes must be non-negative", }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { err := validateJWT(&tc.cfg) if tc.wantErr { assert.Error(t, err) assert.Contains(t, err.Error(), tc.errContains) } else { assert.NoError(t, err) } }) } } // --- validateLog --- func TestValidateLog(t *testing.T) { validLog := LogConfig{ Level: "info", Format: "json", StacktraceLevel: "error", Output: LogOutputConfig{ToStdout: true, ToFile: false}, Rotation: LogRotationConfig{MaxSizeMB: 100}, } tests := []struct { name string cfg LogConfig wantErr bool errContains string }{ {"valid", validLog, false, ""}, {"empty level", func() LogConfig { c := validLog; c.Level = ""; return c }(), true, "log.level is required"}, {"invalid level", func() LogConfig { c := validLog; c.Level = "verbose"; return c }(), true, "log.level must be one of"}, {"valid levels", func() LogConfig { c := validLog; c.Level = "debug"; return c }(), false, ""}, // debug is valid {"valid level warn", func() LogConfig { c := validLog; c.Level = "warn"; return c }(), false, ""}, {"empty format", func() LogConfig { c := validLog; c.Format = ""; return c }(), true, "log.format is required"}, {"invalid format", func() LogConfig { c := validLog; c.Format = "xml"; return c }(), true, "log.format must be one of"}, {"both output false", func() LogConfig { c := validLog; c.Output.ToStdout = false; c.Output.ToFile = false; return c }(), true, "cannot both be false"}, {"max_size_mb zero", func() LogConfig { c := validLog; c.Rotation.MaxSizeMB = 0; return c }(), true, "must be positive"}, {"max_backups negative", func() LogConfig { c := validLog; c.Rotation.MaxBackups = -1; return c }(), true, "non-negative"}, {"max_age_days negative", func() LogConfig { c := validLog; c.Rotation.MaxAgeDays = -1; return c }(), true, "non-negative"}, {"sampling enabled with zero initial", func() LogConfig { c := validLog; c.Sampling.Enabled = true; c.Sampling.Initial = 0; return c }(), true, "must be positive when sampling"}, {"sampling disabled negative thereafter", func() LogConfig { c := validLog; c.Sampling.Thereafter = -1; return c }(), true, "non-negative"}, {"stacktrace empty", func() LogConfig { c := validLog; c.StacktraceLevel = ""; return c }(), true, "stacktrace_level is required"}, {"invalid stacktrace", func() LogConfig { c := validLog; c.StacktraceLevel = "warn"; return c }(), true, "stacktrace_level must be one of"}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { err := validateLog(&tc.cfg) if tc.wantErr { assert.Error(t, err) assert.Contains(t, err.Error(), tc.errContains) } else { assert.NoError(t, err) } }) } } // --- validateDatabase --- func TestValidateDatabase(t *testing.T) { tests := []struct { name string cfg DatabaseConfig wantErr bool errContains string }{ {"valid", DatabaseConfig{MaxOpenConns: 10, MaxIdleConns: 5, ConnMaxLifetimeMinutes: 30, ConnMaxIdleTimeMinutes: 5}, false, ""}, {"max_open_conns zero", DatabaseConfig{MaxOpenConns: 0}, true, "must be positive"}, {"max_idle_conns negative", DatabaseConfig{MaxOpenConns: 10, MaxIdleConns: -1}, true, "non-negative"}, {"idle > open", DatabaseConfig{MaxOpenConns: 5, MaxIdleConns: 10}, true, "cannot exceed max_open_conns"}, {"conn_max_lifetime negative", DatabaseConfig{MaxOpenConns: 10, ConnMaxLifetimeMinutes: -1}, true, "non-negative"}, {"conn_max_idle_time negative", DatabaseConfig{MaxOpenConns: 10, ConnMaxIdleTimeMinutes: -1}, true, "non-negative"}, {"all zero is valid for idle conn/time", DatabaseConfig{MaxOpenConns: 10, MaxIdleConns: 0, ConnMaxLifetimeMinutes: 0, ConnMaxIdleTimeMinutes: 0}, false, ""}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { err := validateDatabase(&tc.cfg) if tc.wantErr { assert.Error(t, err) assert.Contains(t, err.Error(), tc.errContains) } else { assert.NoError(t, err) } }) } } // --- validateRedis --- func TestValidateRedis(t *testing.T) { tests := []struct { name string cfg RedisConfig wantErr bool errContains string }{ {"valid", RedisConfig{DialTimeoutSeconds: 5, ReadTimeoutSeconds: 3, WriteTimeoutSeconds: 3, PoolSize: 100, MinIdleConns: 10}, false, ""}, {"dial_timeout zero", RedisConfig{}, true, "dial_timeout_seconds must be positive"}, {"read_timeout zero", RedisConfig{DialTimeoutSeconds: 5}, true, "read_timeout_seconds must be positive"}, {"write_timeout zero", RedisConfig{DialTimeoutSeconds: 5, ReadTimeoutSeconds: 3}, true, "write_timeout_seconds must be positive"}, {"pool_size zero", RedisConfig{DialTimeoutSeconds: 5, ReadTimeoutSeconds: 3, WriteTimeoutSeconds: 3}, true, "pool_size must be positive"}, {"min_idle negative", RedisConfig{DialTimeoutSeconds: 5, ReadTimeoutSeconds: 3, WriteTimeoutSeconds: 3, PoolSize: 100, MinIdleConns: -1}, true, "non-negative"}, {"min_idle > pool_size", RedisConfig{PoolSize: 10, MinIdleConns: 20, DialTimeoutSeconds: 5, ReadTimeoutSeconds: 3, WriteTimeoutSeconds: 3}, true, "cannot exceed pool_size"}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { err := validateRedis(&tc.cfg) if tc.wantErr { assert.Error(t, err) assert.Contains(t, err.Error(), tc.errContains) } else { assert.NoError(t, err) } }) } } // --- validateBilling --- func TestValidateBilling(t *testing.T) { t.Run("disabled passes", func(t *testing.T) { assert.NoError(t, validateBilling(&BillingConfig{})) }) t.Run("enabled with valid values", func(t *testing.T) { bc := BillingConfig{CircuitBreaker: CircuitBreakerConfig{ Enabled: true, FailureThreshold: 5, ResetTimeoutSeconds: 30, HalfOpenRequests: 3, }} assert.NoError(t, validateBilling(&bc)) }) t.Run("enabled failure_threshold zero", func(t *testing.T) { bc := BillingConfig{CircuitBreaker: CircuitBreakerConfig{Enabled: true, FailureThreshold: 0}} err := validateBilling(&bc) assert.Error(t, err) assert.Contains(t, err.Error(), "failure_threshold must be positive") }) t.Run("enabled reset_timeout zero", func(t *testing.T) { bc := BillingConfig{CircuitBreaker: CircuitBreakerConfig{Enabled: true, FailureThreshold: 5, ResetTimeoutSeconds: 0}} err := validateBilling(&bc) assert.Error(t, err) assert.Contains(t, err.Error(), "reset_timeout_seconds must be positive") }) t.Run("enabled half_open_requests zero", func(t *testing.T) { bc := BillingConfig{CircuitBreaker: CircuitBreakerConfig{ Enabled: true, FailureThreshold: 5, ResetTimeoutSeconds: 30, HalfOpenRequests: 0, }} err := validateBilling(&bc) assert.Error(t, err) assert.Contains(t, err.Error(), "half_open_requests must be positive") }) } // --- validateIdempotency --- func TestValidateIdempotency(t *testing.T) { valid := IdempotencyConfig{ DefaultTTLSeconds: 86400, SystemOperationTTLSeconds: 3600, ProcessingTimeoutSeconds: 30, FailedRetryBackoffSeconds: 5, MaxStoredResponseLen: 65536, CleanupIntervalSeconds: 60, CleanupBatchSize: 500, } assert.NoError(t, validateIdempotency(&valid)) fieldsToZero := []string{ "DefaultTTLSeconds", "SystemOperationTTLSeconds", "ProcessingTimeoutSeconds", "FailedRetryBackoffSeconds", "MaxStoredResponseLen", "CleanupIntervalSeconds", "CleanupBatchSize", } for _, f := range fieldsToZero { f := f t.Run(f+"_zero", func(t *testing.T) { c := valid switch f { case "DefaultTTLSeconds": c.DefaultTTLSeconds = 0 case "SystemOperationTTLSeconds": c.SystemOperationTTLSeconds = 0 case "ProcessingTimeoutSeconds": c.ProcessingTimeoutSeconds = 0 case "FailedRetryBackoffSeconds": c.FailedRetryBackoffSeconds = 0 case "MaxStoredResponseLen": c.MaxStoredResponseLen = 0 case "CleanupIntervalSeconds": c.CleanupIntervalSeconds = 0 case "CleanupBatchSize": c.CleanupBatchSize = 0 } err := validateIdempotency(&c) assert.Error(t, err, "%s=0 should error", f) }) } } // --- validateUsageCleanup --- func TestValidateUsageCleanup(t *testing.T) { valid := UsageCleanupConfig{Enabled: true, MaxRangeDays: 31, BatchSize: 5000, WorkerIntervalSeconds: 10, TaskTimeoutSeconds: 1800} assert.NoError(t, validateUsageCleanup(&valid)) t.Run("disabled with non-negative values passes", func(t *testing.T) { uc := UsageCleanupConfig{Enabled: false, MaxRangeDays: 0, BatchSize: 0, WorkerIntervalSeconds: 0, TaskTimeoutSeconds: 0} assert.NoError(t, validateUsageCleanup(&uc)) }) t.Run("disabled with negative value fails", func(t *testing.T) { uc := UsageCleanupConfig{Enabled: false, MaxRangeDays: -1} err := validateUsageCleanup(&uc) assert.Error(t, err) assert.Contains(t, err.Error(), "non-negative") }) t.Run("enabled max_range_days zero", func(t *testing.T) { uc := UsageCleanupConfig{Enabled: true, MaxRangeDays: 0, BatchSize: 1, WorkerIntervalSeconds: 1, TaskTimeoutSeconds: 1} err := validateUsageCleanup(&uc) assert.Error(t, err) assert.Contains(t, err.Error(), "must be positive") }) } // --- validateOps --- func TestValidateOps(t *testing.T) { valid := OpsConfig{Cleanup: OpsCleanupConfig{Enabled: true, Schedule: "0 2 * * *"}} assert.NoError(t, validateOps(&valid)) t.Run("negative metrics cache TTL", func(t *testing.T) { o := OpsConfig{MetricsCollectorCache: OpsMetricsCollectorCacheConfig{TTL: -1}} err := validateOps(&o) assert.Error(t, err) assert.Contains(t, err.Error(), "non-negative") }) t.Run("negative retention days", func(t *testing.T) { o := OpsConfig{Cleanup: OpsCleanupConfig{ErrorLogRetentionDays: -1}} err := validateOps(&o) assert.Error(t, err) assert.Contains(t, err.Error(), "non-negative") }) t.Run("enabled cleanup without schedule", func(t *testing.T) { o := OpsConfig{Cleanup: OpsCleanupConfig{Enabled: true, Schedule: ""}} err := validateOps(&o) assert.Error(t, err) assert.Contains(t, err.Error(), "schedule is required") }) } // --- validateConcurrency --- func TestValidateConcurrency(t *testing.T) { tests := []struct { pingInterval int wantErr bool }{ {5, false}, // min boundary {10, false}, // normal {30, false}, // max boundary {4, true}, // below min {31, true}, // above max {0, true}, {-1, true}, } for _, tc := range tests { tc := tc t.Run(fmt.Sprintf("ping_interval=%d", tc.pingInterval), func(t *testing.T) { c := ConcurrencyConfig{PingInterval: tc.pingInterval} err := validateConcurrency(&c) if tc.wantErr { assert.Error(t, err) } else { assert.NoError(t, err) } }) } } // --- validateServerURL --- func TestValidateServerURL(t *testing.T) { t.Run("empty URL passes", func(t *testing.T) { assert.NoError(t, validateServerURL("")) }) t.Run("valid https URL", func(t *testing.T) { assert.NoError(t, validateServerURL("https://app.example.com")) }) t.Run("valid http URL (with warning)", func(t *testing.T) { assert.NoError(t, validateServerURL("http://localhost:3000")) }) t.Run("URL with query fails", func(t *testing.T) { err := validateServerURL("https://example.com?foo=bar") assert.Error(t, err) assert.Contains(t, err.Error(), "must not include query") }) t.Run("URL with userinfo fails", func(t *testing.T) { err := validateServerURL("https://user:pass@example.com") assert.Error(t, err) assert.Contains(t, err.Error(), "must not include userinfo") }) t.Run("invalid scheme fails", func(t *testing.T) { err := validateServerURL("ftp://example.com") assert.Error(t, err) }) } // --- validateLinuxDo --- func TestValidateLinuxDo(t *testing.T) { validCfg := LinuxDoConnectConfig{ Enabled: true, ClientID: "id", AuthorizeURL: "https://a.com/auth", TokenURL: "https://a.com/token", UserInfoURL: "https://a.com/user", RedirectURL: "https://a.com/cb", FrontendRedirectURL: "/cb", ClientSecret: "secret", } t.Run("disabled passes", func(t *testing.T) { assert.NoError(t, validateLinuxDo(&LinuxDoConnectConfig{})) }) t.Run("enabled valid passes", func(t *testing.T) { assert.NoError(t, validateLinuxDo(&validCfg)) }) t.Run("enabled missing client_id", func(t *testing.T) { c := validCfg; c.ClientID = "" err := validateLinuxDo(&c) assert.Error(t, err) assert.Contains(t, err.Error(), "client_id is required") }) t.Run("enabled invalid authorize_url", func(t *testing.T) { c := validCfg; c.AuthorizeURL = "not-a-url" err := validateLinuxDo(&c) assert.Error(t, err) }) t.Run("token_auth_method none requires PKCE", func(t *testing.T) { c := validCfg; c.TokenAuthMethod = "none"; c.UsePKCE = false; c.ClientSecret = "" err := validateLinuxDo(&c) assert.Error(t, err) assert.Contains(t, err.Error(), "use_pkce must be true") }) t.Run("client_secret_post requires client_secret", func(t *testing.T) { c := validCfg; c.TokenAuthMethod = "client_secret_post"; c.ClientSecret = "" err := validateLinuxDo(&c) assert.Error(t, err) assert.Contains(t, err.Error(), "client_secret is required") }) t.Run("invalid token_auth_method", func(t *testing.T) { c := validCfg; c.TokenAuthMethod = "bearer" err := validateLinuxDo(&c) assert.Error(t, err) assert.Contains(t, err.Error(), "token_auth_method must be") }) } // --- validateOIDC --- func TestValidateOIDC(t *testing.T) { validOIDC := OIDCConnectConfig{ Enabled: true, ClientID: "id", IssuerURL: "https://idp.example.com", RedirectURL: "https://app.com/cb", FrontendRedirectURL: "https://app.com/oidc/cb", ClientSecret: "secret", Scopes: "openid email profile", } t.Run("disabled passes", func(t *testing.T) { assert.NoError(t, validateOIDC(&OIDCConnectConfig{})) }) t.Run("enabled valid passes", func(t *testing.T) { assert.NoError(t, validateOIDC(&validOIDC)) }) t.Run("missing openid scope", func(t *testing.T) { c := validOIDC; c.Scopes = "email profile" err := validateOIDC(&c) assert.Error(t, err) assert.Contains(t, err.Error(), "must contain openid") }) t.Run("clock_skew out of range", func(t *testing.T) { c := validOIDC; c.ClockSkewSeconds = 700 err := validateOIDC(&c) assert.Error(t, err) assert.Contains(t, err.Error(), "between 0-600") }) t.Run("validate_id_token requires allowed_signing_algs", func(t *testing.T) { c := validOIDC; c.ValidateIDToken = true; c.AllowedSigningAlgs = "" err := validateOIDC(&c) assert.Error(t, err) assert.Contains(t, err.Error(), "allowed_signing_algs required") }) t.Run("missing issuer_url", func(t *testing.T) { c := validOIDC; c.IssuerURL = "" err := validateOIDC(&c) assert.Error(t, err) assert.Contains(t, err.Error(), "issuer_url is required") }) } // --- validateDashboard & validateDashboardAgg --- func TestValidateDashboard(t *testing.T) { validDash := DashboardCacheConfig{ Enabled: true, StatsFreshTTLSeconds: 15, StatsTTLSeconds: 30, StatsRefreshTimeoutSeconds: 30, } validAgg := DashboardAggregationConfig{Enabled: true, IntervalSeconds: 60, LookbackSeconds: 120, Retention: DashboardAggregationRetentionConfig{UsageLogsDays: 90, UsageBillingDedupDays: 365, HourlyDays: 180, DailyDays: 730}, } t.Run("enabled dashboard valid", func(t *testing.T) { assert.NoError(t, validateDashboard(&validDash, &validAgg)) }) t.Run("stats_fresh_ttl > stats_ttl fails", func(t *testing.T) { d := validDash; d.StatsFreshTTLSeconds = 100; d.StatsTTLSeconds = 50 err := validateDashboard(&d, &validAgg) assert.Error(t, err) assert.Contains(t, err.Error(), "stats_fresh_ttl_seconds must be <=") }) t.Run("disabled dashboard with negatives fails", func(t *testing.T) { d := DashboardCacheConfig{Enabled: false, StatsFreshTTLSeconds: -1} err := validateDashboard(&d, &DashboardAggregationConfig{}) assert.Error(t, err) assert.Contains(t, err.Error(), "non-negative") }) t.Run("aggregation enabled valid", func(t *testing.T) { assert.NoError(t, validateDashboardAgg(&validAgg)) }) t.Run("aggregation interval zero when enabled", func(t *testing.T) { a := validAgg; a.Enabled = true; a.IntervalSeconds = 0 err := validateDashboardAgg(&a) assert.Error(t, err) assert.Contains(t, err.Error(), "interval_seconds must be positive") }) t.Run("billing_dedup < usage_logs fails", func(t *testing.T) { a := validAgg; a.Retention.UsageLogsDays = 365; a.Retention.UsageBillingDedupDays = 30 err := validateDashboardAgg(&a) assert.Error(t, err) assert.Contains(t, err.Error(), "usage_billing_dedup_days >= usage_logs_days") }) t.Run("backfill_enabled with backfill_max_days=0 fails", func(t *testing.T) { a := validAgg; a.BackfillEnabled = true; a.BackfillMaxDays = 0 err := validateDashboardAgg(&a) assert.Error(t, err) assert.Contains(t, err.Error(), "backfill") // After refactor: partial match }) } // --- Config.Validate() orchestration test --- func TestConfigValidate_Orchestration(t *testing.T) { t.Parallel() t.Run("fully valid config passes all validators", func(t *testing.T) { t.Parallel() cfg := buildValidConfig() assert.NoError(t, cfg.Validate()) }) t.Run("invalid JWT stops validation early", func(t *testing.T) { t.Parallel() cfg := buildValidConfig() cfg.JWT.Secret = "short" err := cfg.Validate() assert.Error(t, err) assert.Contains(t, err.Error(), "jwt.secret") }) t.Run("invalid database stops after earlier checks pass", func(t *testing.T) { t.Parallel() cfg := buildValidConfig() cfg.Database.MaxOpenConns = 0 err := cfg.Validate() assert.Error(t, err) assert.Contains(t, err.Error(), "database.max_open_conns") }) } // Helper to build a fully valid Config for testing. // IMPORTANT: Must include ALL fields that have positive/non-zero validators, // otherwise Validate() will fail before reaching the intended test target. func buildValidConfig() Config { return Config{ Server: ServerConfig{Host: "0.0.0.0", Port: 8080, Mode: "release"}, Log: LogConfig{Level: "info", Format: "json", StacktraceLevel: "error", Output: LogOutputConfig{ToStdout: true}, Rotation: LogRotationConfig{MaxSizeMB: 100}}, Security: SecurityConfig{}, Billing: BillingConfig{}, Turnstile: TurnstileConfig{}, Database: DatabaseConfig{Host: "localhost", Port: 5432, User: "u", DBName: "db", SSLMode: "disable", MaxOpenConns: 256, MaxIdleConns: 128, ConnMaxLifetimeMinutes: 30, ConnMaxIdleTimeMinutes: 5}, Redis: RedisConfig{Host: "localhost", Port: 6379, DialTimeoutSeconds: 5, ReadTimeoutSeconds: 3, WriteTimeoutSeconds: 3, PoolSize: 1024}, JWT: JWTConfig{Secret: strings.Repeat("x", 32), ExpireHour: 24, RefreshTokenExpireDays: 30}, LinuxDo: LinuxDoConnectConfig{}, OIDC: OIDCConnectConfig{}, Default: DefaultConfig{}, RateLimit: RateLimitConfig{}, Pricing: PricingConfig{}, Gateway: GatewayConfig{ MaxBodySize: 1 << 20, // 1MB UpstreamResponseReadMaxBytes: 1 << 24, ProxyProbeResponseReadMaxBytes: 1 << 20, MaxIdleConns: 100, MaxIdleConnsPerHost: 50, MaxConnsPerHost: 200, IdleConnTimeoutSeconds: 90, MaxUpstreamClients: 1000, ClientIdleTTLSeconds: 300, ConcurrencySlotTTLMinutes: 15, UserGroupRateCacheTTLSeconds: 300, ModelsListCacheTTLSeconds: 20, OpenAIWS: GatewayOpenAIWSConfig{ Enabled: true, MaxConnsPerAccount: 10, DialTimeoutSeconds: 10, ReadTimeoutSeconds: 30, WriteTimeoutSeconds: 30, PoolTargetUtilization: 0.8, QueueLimitPerConn: 64, EventFlushBatchSize: 1, LBTopK: 3, StickySessionTTLSeconds: 3600, StickyResponseIDTTLSeconds: 3600, OAuthMaxConnsFactor: 1.0, APIKeyMaxConnsFactor: 1.0, IngressModeDefault: "ctx_pool", StoreDisabledConnMode: "strict", SchedulerScoreWeights: GatewayOpenAIWSSchedulerScoreWeights{Priority: 1, Load: 1, Queue: 1, ErrorRate: 1, TTFT: 1}, }, UsageRecord: GatewayUsageRecordConfig{ WorkerCount: 128, QueueSize: 16384, TaskTimeoutSeconds: 5, OverflowPolicy: UsageRecordOverflowPolicySample, OverflowSamplePercent: 10, AutoScaleEnabled: true, AutoScaleMinWorkers: 128, AutoScaleMaxWorkers: 512, AutoScaleUpQueuePercent: 70, AutoScaleDownQueuePercent: 15, AutoScaleUpStep: 32, AutoScaleDownStep: 16, AutoScaleCheckIntervalSeconds: 3, AutoScaleCooldownSeconds: 10, }, Scheduling: GatewaySchedulingConfig{ StickySessionMaxWaiting: 3, StickySessionWaitTimeout: 120, FallbackWaitTimeout: 30, FallbackMaxWaiting: 100, SnapshotMGetChunkSize: 1000, SnapshotWriteChunkSize: 500, OutboxPollIntervalSeconds: 1, OutboxLagRebuildFailures: 3, OutboxBacklogRebuildRows: 100, }, }, APIKeyAuth: APIKeyAuthCacheConfig{}, SubscriptionCache: SubscriptionCacheConfig{}, Dashboard: DashboardCacheConfig{Enabled: true, StatsFreshTTLSeconds: 15, StatsTTLSeconds: 30, StatsRefreshTimeoutSeconds: 30}, DashboardAgg: DashboardAggregationConfig{Enabled: true, IntervalSeconds: 60, LookbackSeconds: 120, Retention: DashboardAggregationRetentionConfig{UsageLogsDays: 90, UsageBillingDedupDays: 365, HourlyDays: 180, DailyDays: 730}}, UsageCleanup: UsageCleanupConfig{Enabled: true, MaxRangeDays: 31, BatchSize: 5000, WorkerIntervalSeconds: 10, TaskTimeoutSeconds: 1800}, Concurrency: ConcurrencyConfig{PingInterval: 10}, Idempotency: IdempotencyConfig{ DefaultTTLSeconds: 86400, SystemOperationTTLSeconds: 3600, ProcessingTimeoutSeconds: 30, FailedRetryBackoffSeconds: 5, MaxStoredResponseLen: 65536, CleanupIntervalSeconds: 60, CleanupBatchSize: 500, }, } }