New
This commit is contained in:
107
internal/settings/manager.go
Normal file
107
internal/settings/manager.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user