增加uinx配置
This commit is contained in:
+76
-5
@@ -4,8 +4,10 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -61,7 +63,8 @@ type SearchConfig struct {
|
||||
ServerPort int `yaml:"server_port"`
|
||||
FlushIntervalSeconds int `yaml:"flush_interval_seconds"`
|
||||
StatsRefreshInterval int `yaml:"stats_refresh_interval"` // 统计缓存刷新间隔(秒),默认 30
|
||||
MissPenalty float64 `yaml:"miss_penalty"` // 缺词惩罚系数(0=不惩罚,1=完全忽略缺词URL),默认 0.15
|
||||
MissPenalty float64 `yaml:"miss_penalty"` // 缺词惩罚系数(0=不惩罚,1=完全忽略缺词URL),默认 0.15
|
||||
UnixSocket string `yaml:"unix_socket"` // Unix socket 路径(仅 Linux/macOS),空字符串表示不启用
|
||||
}
|
||||
|
||||
// BacklinkConfig 反向链接计算相关配置
|
||||
@@ -84,22 +87,87 @@ type PrometheusConfig struct {
|
||||
// Global 全局配置实例,加载后可通过此变量访问
|
||||
var Global Config
|
||||
|
||||
// Load 从指定路径加载配置文件
|
||||
// Load 从指定路径加载配置文件,并自动补全缺失的字段。
|
||||
// 流程:读取 YAML → 与默认值合并 → 写回 config.yml → 赋值 Global
|
||||
func Load(configPath string) error {
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read config file: %v", err)
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||
// 先拿到当前 YAML 内容,用于判断哪些字段实际存在于文件中
|
||||
var yamlOnly Config
|
||||
if err := yaml.Unmarshal(data, &yamlOnly); err != nil {
|
||||
return fmt.Errorf("failed to parse config file: %v", err)
|
||||
}
|
||||
|
||||
Global = cfg
|
||||
// 从默认值开始,YAML 中有值的字段会被覆盖
|
||||
merged := GetDefaultConfig()
|
||||
mergeConfig(&merged, &yamlOnly)
|
||||
|
||||
// 写回 config.yml(自动补全缺失字段)
|
||||
yamlOut, err := yaml.Marshal(&merged)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal config: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(configPath, yamlOut, 0644); err != nil {
|
||||
return fmt.Errorf("failed to write config file: %v", err)
|
||||
}
|
||||
|
||||
Global = merged
|
||||
return nil
|
||||
}
|
||||
|
||||
// mergeConfig 将 src 中的非零字段合并到 dst(原地修改 dst)。
|
||||
// 用于把 YAML 实际配置值覆盖到默认值结构上。
|
||||
func mergeConfig(dst, src interface{}) {
|
||||
if dst == nil || src == nil {
|
||||
return
|
||||
}
|
||||
dstVal := reflect.ValueOf(dst).Elem()
|
||||
srcVal := reflect.ValueOf(src).Elem()
|
||||
|
||||
for i := 0; i < dstVal.NumField(); i++ {
|
||||
dstField := dstVal.Field(i)
|
||||
srcField := srcVal.Field(i)
|
||||
|
||||
switch dstField.Kind() {
|
||||
case reflect.Struct:
|
||||
// 递归合并嵌套 struct
|
||||
mergeConfig(dstField.Addr().Interface(), srcField.Addr().Interface())
|
||||
case reflect.Slice:
|
||||
// slice:仅当 src 非空时才覆盖(避免覆盖用户显式设置的长 0 slice)
|
||||
if srcField.Len() > 0 {
|
||||
dstField.Set(srcField)
|
||||
}
|
||||
default:
|
||||
// 其他类型:src 为零值则保留 dst 原值(默认值)
|
||||
if !isZero(srcField) {
|
||||
dstField.Set(srcField)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isZero 检查 reflect.Value 是否为该类型的零值。
|
||||
func isZero(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return math.Float64bits(v.Float()) == 0
|
||||
case reflect.String:
|
||||
return v.String() == ""
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return v.IsNil()
|
||||
}
|
||||
return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
|
||||
}
|
||||
|
||||
// LoadFromSavedata 从 savedata 目录加载 config.yml
|
||||
func LoadFromSavedata() error {
|
||||
configPath := filepath.Join("savedata", "config.yml")
|
||||
@@ -264,6 +332,9 @@ func StatsRefreshInterval() int {
|
||||
// MissPenalty 返回缺词惩罚系数(0~1),值越大对缺少查询词的 URL 惩罚越重。
|
||||
func MissPenalty() float64 { return Global.Search.MissPenalty }
|
||||
|
||||
// UnixSocket 返回 Unix socket 路径,空字符串表示不启用。
|
||||
func UnixSocket() string { return Global.Search.UnixSocket }
|
||||
|
||||
// BacklinkBaseline 返回配置值
|
||||
func BacklinkBaseline() int { return Global.Backlink.Baseline }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user