🔧 chore: 初始化番茄小说 API 项目结构
新增项目基础框架,包含核心 API 实现、算法模块、HTTP 处理器等完整功能模块
This commit is contained in:
commit
6981148727
107 files changed
+12463
No files matched your search
@@ -0,0 +1,120 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
// ConfigWatcher 配置文件监控器
|
||||
type ConfigWatcher struct {
|
||||
watcher *fsnotify.Watcher
|
||||
configPath string
|
||||
stopCh chan struct{}
|
||||
}
|
||||
|
||||
// NewConfigWatcher 创建配置文件监控器
|
||||
func NewConfigWatcher(configPath string) (*ConfigWatcher, error) {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为绝对路径
|
||||
absPath, err := filepath.Abs(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ConfigWatcher{
|
||||
watcher: watcher,
|
||||
configPath: absPath,
|
||||
stopCh: make(chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start 启动配置文件监控
|
||||
func (w *ConfigWatcher) Start() error {
|
||||
// 监控配置文件所在目录
|
||||
configDir := filepath.Dir(w.configPath)
|
||||
if err := w.watcher.Add(configDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go w.watchLoop()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop 停止配置文件监控
|
||||
func (w *ConfigWatcher) Stop() {
|
||||
close(w.stopCh)
|
||||
if w.watcher != nil {
|
||||
w.watcher.Close()
|
||||
}
|
||||
log.Println("配置文件监控已停止")
|
||||
}
|
||||
|
||||
// watchLoop 监控循环
|
||||
func (w *ConfigWatcher) watchLoop() {
|
||||
// 防抖动:在短时间内多次文件变化只处理一次
|
||||
var debounceTimer *time.Timer
|
||||
const debounceDelay = 500 * time.Millisecond
|
||||
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-w.watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// 只处理配置文件的写入或创建事件
|
||||
if filepath.Base(event.Name) == filepath.Base(w.configPath) {
|
||||
if event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create {
|
||||
// log.Printf("检测到配置文件变化: %s", event.Name)
|
||||
|
||||
// 重置防抖动定时器
|
||||
if debounceTimer != nil {
|
||||
debounceTimer.Stop()
|
||||
}
|
||||
|
||||
debounceTimer = time.AfterFunc(debounceDelay, func() {
|
||||
if err := ReloadConfig(); err != nil {
|
||||
log.Printf("重新加载配置失败: %v", err)
|
||||
} else {
|
||||
log.Println("✅ 配置热更新成功!")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
case err, ok := <-w.watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Printf("配置文件监控错误: %v", err)
|
||||
|
||||
case <-w.stopCh:
|
||||
if debounceTimer != nil {
|
||||
debounceTimer.Stop()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StartConfigWatcher 启动配置文件监控(全局函数)
|
||||
func StartConfigWatcher(configPath string) (*ConfigWatcher, error) {
|
||||
watcher, err := NewConfigWatcher(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := watcher.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user