wood chen 64423b00e2 feat(config): 添加默认配置文件创建功能
- 实现 createDefaultConfig 方法,在配置文件不存在时自动创建默认配置
- 移除 config.json 中的固定路径配置
- 支持自动创建配置文件目录
- 提供默认的压缩和路由配置
2025-03-12 20:50:19 +08:00

160 lines
3.0 KiB
Go

package config
import (
"encoding/json"
"os"
"strings"
"sync"
"sync/atomic"
"time"
)
// Config 配置结构体
type configImpl struct {
sync.RWMutex
Config
// 配置更新回调函数
onConfigUpdate []func(*Config)
}
var (
instance *configImpl
once sync.Once
configCallbacks []func(*Config)
callbackMutex sync.RWMutex
)
type ConfigManager struct {
config atomic.Value
configPath string
}
func NewConfigManager(path string) *ConfigManager {
cm := &ConfigManager{configPath: path}
cm.loadConfig()
go cm.watchConfig()
return cm
}
func (cm *ConfigManager) watchConfig() {
ticker := time.NewTicker(30 * time.Second)
for range ticker.C {
cm.loadConfig()
}
}
// Load 加载配置
func Load(path string) (*Config, error) {
var err error
once.Do(func() {
instance = &configImpl{}
err = instance.reload(path)
// 如果文件不存在,创建默认配置并重新加载
if err != nil && os.IsNotExist(err) {
if createErr := createDefaultConfig(path); createErr == nil {
err = instance.reload(path)
} else {
err = createErr
}
}
})
return &instance.Config, err
}
// createDefaultConfig 创建默认配置文件
func createDefaultConfig(path string) error {
// 创建目录(如果不存在)
dir := path[:strings.LastIndex(path, "/")]
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
// 创建默认配置
defaultConfig := Config{
MAP: map[string]PathConfig{
"/": {
DefaultTarget: "http://localhost:8080",
},
},
Compression: CompressionConfig{
Gzip: CompressorConfig{
Enabled: true,
Level: 6,
},
Brotli: CompressorConfig{
Enabled: true,
Level: 6,
},
},
}
// 序列化为JSON
data, err := json.MarshalIndent(defaultConfig, "", " ")
if err != nil {
return err
}
// 写入文件
return os.WriteFile(path, data, 0644)
}
// RegisterUpdateCallback 注册配置更新回调函数
func RegisterUpdateCallback(callback func(*Config)) {
callbackMutex.Lock()
defer callbackMutex.Unlock()
configCallbacks = append(configCallbacks, callback)
}
// TriggerCallbacks 触发所有回调
func TriggerCallbacks(cfg *Config) {
callbackMutex.RLock()
defer callbackMutex.RUnlock()
for _, callback := range configCallbacks {
callback(cfg)
}
}
// Update 更新配置并触发回调
func (c *configImpl) Update(newConfig *Config) {
c.Lock()
defer c.Unlock()
// 更新配置
c.MAP = newConfig.MAP
c.Compression = newConfig.Compression
// 触发回调
for _, callback := range c.onConfigUpdate {
callback(newConfig)
}
}
// reload 重新加载配置文件
func (c *configImpl) reload(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return err
}
var newConfig Config
if err := json.Unmarshal(data, &newConfig); err != nil {
return err
}
c.Update(&newConfig)
return nil
}
func (cm *ConfigManager) loadConfig() error {
config, err := Load(cm.configPath)
if err != nil {
return err
}
cm.config.Store(config)
return nil
}
func (cm *ConfigManager) GetConfig() *Config {
return cm.config.Load().(*Config)
}