goaidb/config/config.go

185 lines
4.0 KiB
Go
Raw Normal View History

package config
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sync"
2025-06-05 21:05:36 +08:00
"log"
"encoding/json"
"gopkg.in/yaml.v2"
2025-06-05 21:05:36 +08:00
"github.com/fsnotify/fsnotify"
)
// Config 系统配置结构体
type Config struct {
Server ServerConfig `yaml:"server" json:"server"`
Storage StorageConfig `yaml:"storage" json:"storage"`
}
// ServerConfig 服务器配置
type ServerConfig struct {
Host string `yaml:"host" json:"host"`
Port int `yaml:"port" json:"port"`
}
// StorageConfig 存储配置
type StorageConfig struct {
Engine string `yaml:"engine" json:"engine"`
DataPath string `yaml:"dataPath" json:"dataPath"`
}
var (
configInstance *Config
once sync.Once
2025-06-05 21:05:36 +08:00
watcher *fsnotify.Watcher // 配置文件监视器
)
// NewDefaultConfig 创建默认配置
func NewDefaultConfig() *Config {
return &Config{
Server: ServerConfig{
Host: "0.0.0.0",
Port: 27017,
},
Storage: StorageConfig{
Engine: "memory",
DataPath: "/var/lib/goaidb",
},
}
}
// ParseConfig 解析配置文件
// 支持JSON和YAML格式
// 返回解析后的配置对象和错误信息
func ParseConfig(filePath string) (*Config, error) {
// 检查文件是否存在
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return nil, fmt.Errorf("配置文件不存在: %s", filePath)
}
// 读取文件内容
data, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("读取配置文件失败: %v", err)
}
// 根据文件扩展名选择解析方式
var cfg Config
switch filepath.Ext(filePath) {
case ".json":
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("JSON解析失败: %v", err)
}
case ".yaml", ".yml":
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("YAML解析失败: %v", err)
}
default:
return nil, fmt.Errorf("不支持的配置文件格式")
}
return &cfg, nil
}
2025-06-05 21:05:36 +08:00
// ValidateConfig 验证配置有效性
// 返回验证结果和第一个发现的错误(如果有)
func (c *Config) Validate() (bool, error) {
// 验证服务器配置
if c.Server.Port < 1024 || c.Server.Port > 65535 {
return false, fmt.Errorf("端口必须在1024-65535之间: %d", c.Server.Port)
}
// 验证存储配置
if c.Storage.Engine != "memory" && c.Storage.Engine != "rocksdb" {
return false, fmt.Errorf("不支持的存储引擎: %s", c.Storage.Engine)
}
// 验证数据路径是否存在
if _, err := os.Stat(c.Storage.DataPath); os.IsNotExist(err) {
return false, fmt.Errorf("数据目录不存在: %s", c.Storage.DataPath)
}
return true, nil
}
// WatchConfig 监听配置文件变化并自动重载
func WatchConfig(filePath string) error {
// 创建文件监视器
w, err := fsnotify.NewWatcher()
if err != nil {
return fmt.Errorf("创建文件监视器失败: %v", err)
}
// 添加文件监视
dir := filepath.Dir(filePath)
fileName := filepath.Base(filePath)
err = w.Add(dir)
if err != nil {
return fmt.Errorf("添加文件监视失败: %v", err)
}
// 启动监听协程
go func() {
for {
select {
case event, ok := <-w.Events:
if !ok {
return
}
// 当配置文件被修改或创建时重新加载
if (event.Op&fsnotify.Write == fsnotify.Write ||
event.Op&fsnotify.Create == fsnotify.Create) &&
filepath.Base(event.Name) == fileName {
// 重新加载配置
newCfg, err := ParseConfig(filePath)
if err != nil {
log.Printf("配置重载失败: %v", err)
continue
}
// 更新全局配置
SetGlobalConfig(newCfg)
log.Printf("配置已更新")
}
case err, ok := <-w.Errors:
if !ok {
return
}
log.Printf("文件监视错误: %v", err)
}
}
}()
watcher = w
return nil
}
// CloseWatcher 关闭配置文件监视器
func CloseWatcher() {
if watcher != nil {
watcher.Close()
}
}
// GetConfig 获取全局配置实例
func GetConfig() *Config {
once.Do(func() {
configInstance = NewDefaultConfig()
})
return configInstance
}
2025-06-05 21:05:36 +08:00
// SetGlobalConfig 设置全局配置实例
func SetGlobalConfig(cfg *Config) {
once.Do(func() {
configInstance = cfg
})
}