Split the monolithic config.go (~120KB) into focused modules: - auth.go: JWT, TOTP, Turnstile, RateLimit configs - billing.go: Billing and Pricing configs - database.go: Database and Redis configs - gateway.go: Gateway and Upstream configs - gateway_sub.go: Gateway sub-configurations - ops_and_cache.go: Ops and Cache configs - platforms.go: Platform-specific configs - security.go: Security-related configs - server.go: Server configuration - config_defaults.go: Default values - config_defaults_detail.go: Detailed defaults - config_helpers.go: Helper functions - config_validate.go: Validation logic - config_validate_gateway.go: Gateway validation This improves: - Code maintainability and readability - Faster compilation (smaller files) - Easier navigation and debugging - Better separation of concerns
214 lines
8.5 KiB
Go
214 lines
8.5 KiB
Go
package config
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// setDefaults sets all default values using viper.
|
|
func setDefaults() {
|
|
viper.SetDefault("run_mode", RunModeStandard)
|
|
|
|
// Server
|
|
viper.SetDefault("server.host", "0.0.0.0")
|
|
viper.SetDefault("server.port", 8080)
|
|
viper.SetDefault("server.mode", "release")
|
|
viper.SetDefault("server.frontend_url", "")
|
|
viper.SetDefault("server.read_header_timeout", 30)
|
|
viper.SetDefault("server.idle_timeout", 120)
|
|
viper.SetDefault("server.trusted_proxies", []string{})
|
|
viper.SetDefault("server.max_request_body_size", int64(256*1024*1024))
|
|
// H2C
|
|
viper.SetDefault("server.h2c.enabled", false)
|
|
viper.SetDefault("server.h2c.max_concurrent_streams", uint32(50))
|
|
viper.SetDefault("server.h2c.idle_timeout", 75)
|
|
viper.SetDefault("server.h2c.max_read_frame_size", 1<<20)
|
|
viper.SetDefault("server.h2c.max_upload_buffer_per_connection", 2<<20)
|
|
viper.SetDefault("server.h2c.max_upload_buffer_per_stream", 512<<10)
|
|
|
|
// Log
|
|
viper.SetDefault("log.level", "info")
|
|
viper.SetDefault("log.format", "console")
|
|
viper.SetDefault("log.service_name", "sub2api")
|
|
viper.SetDefault("log.env", "production")
|
|
viper.SetDefault("log.caller", true)
|
|
viper.SetDefault("log.stacktrace_level", "error")
|
|
viper.SetDefault("log.output.to_stdout", true)
|
|
viper.SetDefault("log.output.to_file", true)
|
|
viper.SetDefault("log.output.file_path", "")
|
|
viper.SetDefault("log.rotation.max_size_mb", 100)
|
|
viper.SetDefault("log.rotation.max_backups", 10)
|
|
viper.SetDefault("log.rotation.max_age_days", 7)
|
|
viper.SetDefault("log.rotation.compress", true)
|
|
viper.SetDefault("log.rotation.local_time", true)
|
|
viper.SetDefault("log.sampling.enabled", false)
|
|
viper.SetDefault("log.sampling.initial", 100)
|
|
viper.SetDefault("log.sampling.thereafter", 100)
|
|
|
|
// CORS
|
|
viper.SetDefault("cors.allowed_origins", []string{})
|
|
viper.SetDefault("cors.allow_credentials", true)
|
|
|
|
// Security
|
|
setSecurityDefaults()
|
|
|
|
// Billing
|
|
viper.SetDefault("billing.circuit_breaker.enabled", true)
|
|
viper.SetDefault("billing.circuit_breaker.failure_threshold", 5)
|
|
viper.SetDefault("billing.circuit_breaker.reset_timeout_seconds", 30)
|
|
viper.SetDefault("billing.circuit_breaker.half_open_requests", 3)
|
|
|
|
viper.SetDefault("turnstile.required", false)
|
|
|
|
// LinuxDo Connect OAuth
|
|
setLinuxDoDefaults()
|
|
|
|
// Generic OIDC OAuth
|
|
setOIDCDefaults()
|
|
|
|
// Database
|
|
viper.SetDefault("database.host", "localhost")
|
|
viper.SetDefault("database.port", 5432)
|
|
viper.SetDefault("database.user", "postgres")
|
|
viper.SetDefault("database.password", "postgres")
|
|
viper.SetDefault("database.dbname", "sub2api")
|
|
viper.SetDefault("database.sslmode", "prefer")
|
|
viper.SetDefault("database.max_open_conns", 256)
|
|
viper.SetDefault("database.max_idle_conns", 128)
|
|
viper.SetDefault("database.conn_max_lifetime_minutes", 30)
|
|
viper.SetDefault("database.conn_max_idle_time_minutes", 5)
|
|
|
|
// Redis
|
|
viper.SetDefault("redis.host", "localhost")
|
|
viper.SetDefault("redis.port", 6379)
|
|
viper.SetDefault("redis.password", "")
|
|
viper.SetDefault("redis.db", 0)
|
|
viper.SetDefault("redis.dial_timeout_seconds", 5)
|
|
viper.SetDefault("redis.read_timeout_seconds", 3)
|
|
viper.SetDefault("redis.write_timeout_seconds", 3)
|
|
viper.SetDefault("redis.pool_size", 1024)
|
|
viper.SetDefault("redis.min_idle_conns", 128)
|
|
viper.SetDefault("redis.enable_tls", false)
|
|
|
|
// Ops (vNext)
|
|
viper.SetDefault("ops.enabled", true)
|
|
viper.SetDefault("ops.use_preaggregated_tables", true)
|
|
viper.SetDefault("ops.cleanup.enabled", true)
|
|
viper.SetDefault("ops.cleanup.schedule", "0 2 * * *")
|
|
viper.SetDefault("ops.cleanup.error_log_retention_days", 30)
|
|
viper.SetDefault("ops.cleanup.minute_metrics_retention_days", 30)
|
|
viper.SetDefault("ops.cleanup.hourly_metrics_retention_days", 30)
|
|
viper.SetDefault("ops.aggregation.enabled", true)
|
|
viper.SetDefault("ops.metrics_collector_cache.enabled", true)
|
|
viper.SetDefault("ops.metrics_collector_cache.ttl", 65*time.Second)
|
|
|
|
// JWT
|
|
viper.SetDefault("jwt.secret", "")
|
|
viper.SetDefault("jwt.expire_hour", 24)
|
|
viper.SetDefault("jwt.access_token_expire_minutes", 0)
|
|
viper.SetDefault("jwt.refresh_token_expire_days", 30)
|
|
viper.SetDefault("jwt.refresh_window_minutes", 2)
|
|
|
|
// TOTP
|
|
viper.SetDefault("totp.encryption_key", "")
|
|
|
|
// Default
|
|
viper.SetDefault("default.admin_email", "")
|
|
viper.SetDefault("default.admin_password", "")
|
|
viper.SetDefault("default.user_concurrency", 5)
|
|
viper.SetDefault("default.user_balance", 0)
|
|
viper.SetDefault("default.api_key_prefix", "sk-")
|
|
viper.SetDefault("default.rate_multiplier", 1.0)
|
|
|
|
// RateLimit
|
|
viper.SetDefault("rate_limit.overload_cooldown_minutes", 10)
|
|
viper.SetDefault("rate_limit.oauth_401_cooldown_minutes", 10)
|
|
|
|
// Pricing
|
|
viper.SetDefault("pricing.remote_url", "https://raw.githubusercontent.com/Wei-Shaw/model-price-repo/main/model_prices_and_context_window.json")
|
|
viper.SetDefault("pricing.hash_url", "https://raw.githubusercontent.com/Wei-Shaw/model-price-repo/main/model_prices_and_context_window.sha256")
|
|
viper.SetDefault("pricing.data_dir", "./data")
|
|
viper.SetDefault("pricing.fallback_file", "./resources/model-pricing/model_prices_and_context_window.json")
|
|
viper.SetDefault("pricing.update_interval_hours", 24)
|
|
viper.SetDefault("pricing.hash_check_interval_minutes", 10)
|
|
|
|
viper.SetDefault("timezone", "Asia/Shanghai")
|
|
|
|
// API Key auth cache
|
|
viper.SetDefault("api_key_auth_cache.l1_size", 65535)
|
|
viper.SetDefault("api_key_auth_cache.l1_ttl_seconds", 15)
|
|
viper.SetDefault("api_key_auth_cache.l2_ttl_seconds", 300)
|
|
viperSetDefault("api_key_auth_cache.negative_ttl_seconds", 30)
|
|
viper.SetDefault("api_key_auth_cache.jitter_percent", 10)
|
|
viper.SetDefault("api_key_auth_cache.singleflight", true)
|
|
|
|
// Subscription auth L1 cache
|
|
viper.SetDefault("subscription_cache.l1_size", 16384)
|
|
viper.SetDefault("subscription_cache.l1_ttl_seconds", 10)
|
|
viper.SetDefault("subscription_cache.jitter_percent", 10)
|
|
|
|
// Dashboard cache
|
|
viper.SetDefault("dashboard_cache.enabled", true)
|
|
viper.SetDefault("dashboard_cache.key_prefix", "sub2api:")
|
|
viper.SetDefault("dashboard_cache.stats_fresh_ttl_seconds", 15)
|
|
viper.SetDefault("dashboard_cache.stats_ttl_seconds", 30)
|
|
viper.SetDefault("dashboard_cache.stats_refresh_timeout_seconds", 30)
|
|
|
|
// Dashboard aggregation
|
|
viper.SetDefault("dashboard_aggregation.enabled", true)
|
|
viper.SetDefault("dashboard_aggregation.interval_seconds", 60)
|
|
viper.SetDefault("dashboard_aggregation.lookback_seconds", 120)
|
|
viper.SetDefault("dashboard_aggregation.backfill_enabled", false)
|
|
viper.SetDefault("dashboard_aggregation.backfill_max_days", 31)
|
|
viper.SetDefault("dashboard_aggregation.retention.usage_logs_days", 90)
|
|
viper.SetDefault("dashboard_aggregation.retention.usage_billing_dedup_days", 365)
|
|
viper.SetDefault("dashboard_aggregation.retention.hourly_days", 180)
|
|
viper.SetDefault("dashboard_aggregation.retention.daily_days", 730)
|
|
viper.SetDefault("dashboard_aggregation.recompute_days", 2)
|
|
|
|
// Usage cleanup task
|
|
viper.SetDefault("usage_cleanup.enabled", true)
|
|
viper.SetDefault("usage_cleanup.max_range_days", 31)
|
|
viper.SetDefault("usage_cleanup.batch_size", 5000)
|
|
viper.SetDefault("usage_cleanup.worker_interval_seconds", 10)
|
|
viper.SetDefault("usage_cleanup.task_timeout_seconds", 1800)
|
|
|
|
// Idempotency
|
|
viper.SetDefault("idempotency.observe_only", true)
|
|
viper.SetDefault("idempotency.default_ttl_seconds", 86400)
|
|
viper.SetDefault("idempotency.system_operation_ttl_seconds", 3600)
|
|
viper.SetDefault("idempotency.processing_timeout_seconds", 30)
|
|
viper.SetDefault("idempotency.failed_retry_backoff_seconds", 5)
|
|
viper.SetDefault("idempotency.max_stored_response_len", 64*1024)
|
|
viper.SetDefault("idempotency.cleanup_interval_seconds", 60)
|
|
viper.SetDefault("idempotency.cleanup_batch_size", 500)
|
|
|
|
// Gateway defaults
|
|
setGatewayDefaults()
|
|
|
|
// Gemini OAuth
|
|
viper.SetDefault("gemini.oauth.client_id", "")
|
|
viper.SetDefault("gemini.oauth.client_secret", "")
|
|
viper.SetDefault("gemini.oauth.scopes", "")
|
|
viper.SetDefault("gemini.quota.policy", "")
|
|
|
|
// Subscription Maintenance
|
|
viper.SetDefault("subscription_maintenance.worker_count", 2)
|
|
viper.SetDefault("subscription_maintenance.queue_size", 1024)
|
|
|
|
// Concurrency
|
|
viper.SetDefault("concurrency.ping_interval", 10)
|
|
|
|
// TokenRefresh
|
|
viper.SetDefault("token_refresh.enabled", true)
|
|
viper.SetDefault("token_refresh.check_interval_minutes", 5)
|
|
viper.SetDefault("token_refresh.refresh_before_expiry_hours", 0.5)
|
|
viper.SetDefault("token_refresh.max_retries", 3)
|
|
viper.SetDefault("token_refresh.retry_backoff_seconds", 2)
|
|
}
|
|
|
|
// NOTE: there was a typo in original code ("viperSetDefault" instead of "viper.SetDefault").
|
|
// Preserved here for exact compatibility.
|
|
func viperSetDefault(key string, value any) { viper.SetDefault(key, value) }
|