// Filename: internal/settings/manager.go package settings import ( "encoding/json" "fmt" "gemini-balancer/internal/models" "gemini-balancer/internal/pkg/reflectutil" "reflect" "time" ) // ========= 便利的读取器 (Convenience Accessors) ========= func (sm *SettingsManager) IsIPBanEnabled() bool { return sm.GetSettings().EnableIPBanning } func (sm *SettingsManager) GetMaxLoginAttempts() int { return sm.GetSettings().MaxLoginAttempts } func (sm *SettingsManager) GetIPBanDuration() time.Duration { minutes := sm.GetSettings().IPBanDurationMinutes return time.Duration(minutes) * time.Minute } // GetSettingsCopy 返回当前系统设置的一个值副本,确保线程安全。 func (sm *SettingsManager) GetSettingsCopy() models.SystemSettings { // 从 syncer 获取当前的设置指针 currentSettingsPtr := sm.GetSettings() if currentSettingsPtr == nil { // 在 syncer 初始化完成前,返回一个安全的默认值 return *defaultSystemSettings() } // 返回指针指向的值,Go会自动创建一个副本 return *currentSettingsPtr } // ========= 辅助与调试函数 (Helpers & Debugging) ========= // [ DisplaySettings 现在接收一个参数,以便在加载后立即打印 func (sm *SettingsManager) DisplaySettings(settings *models.SystemSettings) { if settings == nil { sm.logger.Warn("Cannot display settings, current settings object is nil.") return } sm.logger.Info("") sm.logger.Info("========= Runtime System Settings (from SettingsManager) =========") sm.logger.Infof(" - Request Timeout: %d seconds", settings.RequestTimeoutSeconds) sm.logger.Infof(" - Connect Timeout: %d seconds", settings.ConnectTimeoutSeconds) sm.logger.Infof(" - Max Retries: %d", settings.MaxRetries) sm.logger.Infof(" - Blacklist Threshold: %d", settings.BlacklistThreshold) sm.logger.Info("==================================================================") sm.logger.Info("") } // defaultSystemSettings func defaultSystemSettings() *models.SystemSettings { settings := &models.SystemSettings{} settings.CustomHeaders = make(map[string]string) v := reflect.ValueOf(settings).Elem() t := v.Type() for i := 0; i < t.NumField(); i++ { field := t.Field(i) fieldValue := v.Field(i) // 我们只对“简单组织”动刀 kind := fieldValue.Kind() if kind == reflect.Int || kind == reflect.Int64 || kind == reflect.String || kind == reflect.Bool { defaultValue := field.Tag.Get("default") if defaultValue != "" { if err := reflectutil.SetFieldFromString(fieldValue, defaultValue); err != nil { panic(fmt.Sprintf("FATAL: Invalid default tag for primitive field %s ('%s'): %v", field.Name, defaultValue, err)) } } } } return settings } // parseAndSetField “扫描”数据库字符串,并将其“开箱”到正确的Go类型中 func parseAndSetField(fieldValue reflect.Value, dbValue string) error { if !fieldValue.CanSet() { return fmt.Errorf("field is not settable") } // 如果数据库值为空,我们不进行任何操作,以保留defaultSystemSettings设置的默认值 if dbValue == "" { return nil } kind := fieldValue.Kind() switch kind { case reflect.Slice, reflect.Map: // 如果是 slice 或 map,我们就用“开箱器 (json.Unmarshal)” // fieldValue.Addr().Interface() 获取到的是指向该字段的指针,正是Unmarshal所需要的 return json.Unmarshal([]byte(dbValue), fieldValue.Addr().Interface()) default: // 对于所有原始类型,我们信任并复用现有的 reflectutil 工具 return reflectutil.SetFieldFromString(fieldValue, dbValue) } } // Stop 优雅地停止SettingsManager的后台syncer。 func (sm *SettingsManager) Stop() { if sm.syncer != nil { sm.logger.Info("Stopping SettingsManager's syncer...") sm.syncer.Stop() } }