diff --git a/services/servicebase.go b/services/servicebase.go index ce2327298..9ce29e7d0 100644 --- a/services/servicebase.go +++ b/services/servicebase.go @@ -20,6 +20,7 @@ func (this *ServiceBase) InitSys() { if err := configure.OnInit(this.GetSettings().Sys["configure"]); err != nil { panic(fmt.Sprintf("init sys.configure err: %s", err.Error())) } else { + configure.Start() log.Infof("init sys.configure success!") } } diff --git a/sys/configure/configure.go b/sys/configure/configure.go index 6a7342c02..7ee69a2a1 100644 --- a/sys/configure/configure.go +++ b/sys/configure/configure.go @@ -2,11 +2,14 @@ package configure import ( "fmt" + "go_dreamfactory/lego/sys/log" + "io/fs" "io/ioutil" "os" "path" "reflect" "sync" + "time" jsoniter "github.com/json-iterator/go" ) @@ -22,8 +25,10 @@ type configurehandle struct { func newSys(options Options) (sys *Configure, err error) { sys = &Configure{ options: options, - configurehandles: map[string]*configurehandle{}, - configure: map[string]interface{}{}, + closeSignal: make(chan struct{}), + configurehandles: make(map[string]*configurehandle), + configure: make(map[string]interface{}), + fileinfos: make(map[string]*FileInfo), } err = sys.init() return @@ -31,10 +36,12 @@ func newSys(options Options) (sys *Configure, err error) { type Configure struct { options Options + closeSignal chan struct{} hlock sync.RWMutex configurehandles map[string]*configurehandle clock sync.RWMutex configure map[string]interface{} + fileinfos map[string]*FileInfo } func (this *Configure) init() (err error) { @@ -42,6 +49,26 @@ func (this *Configure) init() (err error) { return } +func (this *Configure) Start() (err error) { + tc := time.NewTicker(time.Second * time.Duration(this.options.CheckInterval)) + go func() { + locp: + for { + select { + case <-this.closeSignal: + break locp + case <-tc.C: + this.checkConfigure() + } + } + }() + return +} +func (this *Configure) Stop() (err error) { + this.closeSignal <- struct{}{} + return +} + //加载配置文件 func (this *Configure) RegisterConfigure(name string, fn interface{}) (err error) { this.hlock.RLock() @@ -94,8 +121,7 @@ func (this *Configure) UpdateConfigure(names ...string) (err error) { handle, ok := this.configurehandles[v] this.hlock.RUnlock() if !ok { - err = fmt.Errorf("no RegisterConfigure:%s", v) - return + continue } if err = this.loaderConfigure(v, handle); err != nil { err = fmt.Errorf("loaderConfigure:%s err:%v", v, err) @@ -120,12 +146,19 @@ func (this *Configure) GetConfigure(name string) (v interface{}, err error) { func (this *Configure) loaderConfigure(name string, handle *configurehandle) (err error) { var ( fliepath string + fileInfo fs.FileInfo file *os.File bytes []byte data []map[string]interface{} returnValues []reflect.Value ) + fliepath = path.Join(this.options.ConfigurePath, name) + if fileInfo, err = os.Stat(fliepath); err != nil { + err = fmt.Errorf("no fond file:%s", fliepath) + return + } + if file, err = os.Open(fliepath); err != nil { err = fmt.Errorf("no fond file:%s", fliepath) return @@ -147,6 +180,30 @@ func (this *Configure) loaderConfigure(name string, handle *configurehandle) (er } this.clock.Lock() this.configure[name] = returnValues[0].Interface() + this.fileinfos[fileInfo.Name()] = &FileInfo{Name: name, Size: fileInfo.Size(), ModTime: fileInfo.ModTime()} this.clock.Unlock() return } + +//检查配置文件是否有更新 +func (this *Configure) checkConfigure() { + if dir, err := ioutil.ReadDir(this.options.ConfigurePath); err != nil { + log.Errorf("[Configure Sys] checkConfigure err:%v", err) + } else { + for _, fi := range dir { + if !fi.IsDir() { //不处理目录代码 + this.clock.RLock() + v, ok := this.fileinfos[fi.Name()] + this.clock.RUnlock() + if ok && fi.ModTime().After(v.ModTime) { + this.hlock.RLock() + handle := this.configurehandles[v.Name] + this.hlock.RUnlock() + if err = this.loaderConfigure(v.Name, handle); err != nil { + return + } + } + } + } + } +} diff --git a/sys/configure/core.go b/sys/configure/core.go index 77de5b75b..652270749 100644 --- a/sys/configure/core.go +++ b/sys/configure/core.go @@ -1,12 +1,22 @@ package configure +import "time" + /* 系统 服务配置中心 */ type ( + //配置文件信息 + FileInfo struct { + Name string // 文件名 + Size int64 // 文件大小 + ModTime time.Time // 文件修改时间 + } ISys interface { + Start() (err error) + Stop() (err error) RegisterConfigure(name string, fn interface{}) (err error) //注册配置 UpdateConfigure(names ...string) (err error) //更新配置 GetConfigure(name string) (v interface{}, err error) //获取配置 @@ -32,7 +42,12 @@ func NewSys(option ...Option) (sys ISys, err error) { defsys, err = newSys(options) return } - +func Start() (err error) { + return defsys.Start() +} +func Stop() (err error) { + return defsys.Stop() +} func RegisterConfigure(name string, fn interface{}) (err error) { return defsys.RegisterConfigure(name, fn) } diff --git a/sys/configure/options.go b/sys/configure/options.go index 5917e51f4..1ac470dfc 100644 --- a/sys/configure/options.go +++ b/sys/configure/options.go @@ -6,11 +6,14 @@ import ( type Option func(*Options) type Options struct { - ConfigurePath string + ConfigurePath string //配置中心路径 + CheckInterval int //配置文件更新检查间隔时间 单位秒 } func newOptions(config map[string]interface{}, opts ...Option) (Options, error) { - options := Options{} + options := Options{ + CheckInterval: 60, + } if config != nil { mapstructure.Decode(config, &options) } @@ -21,7 +24,9 @@ func newOptions(config map[string]interface{}, opts ...Option) (Options, error) } func newOptionsByOption(opts ...Option) (Options, error) { - options := Options{} + options := Options{ + CheckInterval: 60, + } for _, o := range opts { o(&options) }