diff --git a/config/config.go b/config/config.go index 989a1b7..40d9acf 100644 --- a/config/config.go +++ b/config/config.go @@ -5,35 +5,55 @@ import ( "os" "reflect" "sync" + "time" "github.com/BurntSushi/toml" + "github.com/fsnotify/fsnotify" + "github.com/sirupsen/logrus" ) var ( config map[string]interface{} mu sync.RWMutex - once sync.Once ) // loadConfig 加载配置文件 func loadConfig() error { + // mu.Lock() + // defer mu.Unlock() + _, err := toml.DecodeFile("config.toml", &config) + if err != nil { + logrus.Errorf("Failed to decode config file: %v", err) + } return err + } -// GetConfig 获取配置,使用 sync.Once 确保只加载一次 +// GetConfig 获取配置 func GetConfig() map[string]interface{} { - once.Do(func() { - mu.Lock() - defer mu.Unlock() - if err := loadConfig(); err != nil { - fmt.Printf("加载配置文件失败: %v\n", err) - os.Exit(1) - } - }) + // mu.RLock() + if err := loadConfig(); err != nil { + fmt.Printf("加载配置文件失败: %v\n", err) + os.Exit(1) + } + return config } +// ReloadConfig 重新加载配置文件 +func ReloadConfig() error { + mu.Lock() + defer mu.Unlock() + if err := loadConfig(); err != nil { + logrus.Errorf("failed to reload config: %v", err) + return err + } + logrus.Infof("Config reloaded successfully:%v", config) + return nil + +} + // GetConfigValue 获取配置值 func GetConfigValue(key string) interface{} { mu.RLock() @@ -41,13 +61,6 @@ func GetConfigValue(key string) interface{} { return config[key] } -// ReloadConfig 重新加载配置文件 -func ReloadConfig() error { - mu.Lock() - defer mu.Unlock() - return loadConfig() -} - // ModifyConfig 修改配置并写回文件 func ModifyConfig(key string, value interface{}) error { mu.Lock() @@ -88,3 +101,52 @@ func PrintConfig(m map[string]interface{}, indent string) { } } } + +// 监听配置文件变化 +func WatchConfig(filepath string) { + watcher, err := fsnotify.NewWatcher() + if err != nil { + logrus.Fatalf("Failed to create watcher: %v", err) + } + defer watcher.Close() + + err = watcher.Add(filepath) + if err != nil { + logrus.Fatalf("Failed to add file to watcher: %v", err) + } + + var debounceTimer *time.Timer + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + + if event.Op&(fsnotify.Write|fsnotify.Rename) != 0 { + if debounceTimer != nil { + debounceTimer.Stop() + } + debounceTimer = time.AfterFunc(500*time.Millisecond, func() { + logrus.Info("Config file changed, reloading...") + go func() { + if err := ReloadConfig(); err != nil { + logrus.Errorf("Failed to reload config: %v", err) + } + }() + }) + } + + case err, ok := <-watcher.Errors: + if !ok { + return + } + logrus.Errorf("Watcher error: %v", err) + } + } +} + +// 启动监听配置文件的协程 +func StartWatching(filepath string) { + go WatchConfig(filepath) +} diff --git a/go.mod b/go.mod index 477357b..aca9643 100644 --- a/go.mod +++ b/go.mod @@ -57,6 +57,7 @@ require ( require ( github.com/PuerkitoBio/goquery v1.9.2 github.com/andybalholm/brotli v1.1.0 + github.com/fsnotify/fsnotify v1.8.0 github.com/gin-gonic/gin v1.10.0 github.com/go-redis/redis/v8 v8.11.5 github.com/imroc/req/v3 v3.44.0 diff --git a/go.sum b/go.sum index 6852eda..045c14a 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= diff --git a/main.go b/main.go index 85def00..98bc93b 100644 --- a/main.go +++ b/main.go @@ -123,10 +123,9 @@ func main() { logrus.Fatalf("Failed to initialize app: %v", err) } cfg := config.GetConfig() - APIURL, ok := cfg["APIURL"].(string) - if !ok { - logrus.Fatalf("加载配置失败!") - } + + // 启动文件监听 + config.StartWatching("config.toml") // config.PrintConfig(cfg, "") // 在 App 初始化后统一使用 app.Logger @@ -134,6 +133,11 @@ func main() { app.Logger.Fatalf("Failed to initialize database: %v", err) } + APIURL, ok := cfg["APIURL"].(string) + + if !ok { + logrus.Fatalf("加载配置失败!") + } gin.SetMode(gin.ReleaseMode) r := gin.Default() r.POST("/", func(c *gin.Context) {