This commit is contained in:
XOF
2025-11-20 12:24:05 +08:00
commit f28bdc751f
164 changed files with 64248 additions and 0 deletions

View 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()
}
}