Skip to content

Commit 8f1a2fc

Browse files
authored
Merge pull request #214 from devfeel/develop
Version 1.7.0 - Add DotWeb.ReSetConfig & NotifyPlugin
2 parents 62e39c2 + 5b0169d commit 8f1a2fc

7 files changed

Lines changed: 181 additions & 7 deletions

File tree

config/configs.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ type (
2222
Groups []*GroupNode `xml:"groups>group"`
2323
Middlewares []*MiddlewareNode `xml:"middlewares>middleware"`
2424
ConfigSet core.ReadonlyMap `json:"-" yaml:"-"`
25+
ConfigFilePath string
26+
ConfigType string
2527
}
2628

2729
// AppNode dotweb app global config
@@ -219,6 +221,10 @@ func InitConfig(configFile string, confType ...interface{}) (config *Config, err
219221
// deal config default value
220222
dealConfigDefaultSet(config)
221223

224+
// set config file path
225+
config.ConfigFilePath = realFile
226+
config.ConfigType = cType
227+
222228
return config, nil
223229
}
224230

consts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotweb
33
// Global define
44
const (
55
// Version current version
6-
Version = "1.6.9"
6+
Version = "1.7.0"
77
)
88

99
// Log define

dotweb.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type (
4343
globalUniqueID string
4444
appLog logger.AppLog
4545
serverStateInfo *core.ServerStateInfo
46+
isRun bool
4647
}
4748

4849
// ExceptionHandle supports exception handling
@@ -312,6 +313,27 @@ func (app *DotWeb) SetConfig(config *config.Config) {
312313
app.Config = config
313314
}
314315

316+
// ReSetConfig reset config for app
317+
// only apply when app is running
318+
// Port can not be modify
319+
// if EnabledPProf, EnabledPProf flag and PProfPort can not be modify
320+
func (app *DotWeb) ReSetConfig(config *config.Config) {
321+
if !app.isRun {
322+
app.Logger().Debug("DotWeb is not running, ReSetConfig can not be call", LogTarget_HttpServer)
323+
return
324+
}
325+
326+
config.Server.Port = app.Config.Server.Port
327+
if app.Config.App.EnabledPProf {
328+
config.App.PProfPort = app.Config.App.PProfPort
329+
config.App.EnabledPProf = app.Config.App.EnabledPProf
330+
}
331+
app.Config = config
332+
app.appLog = logger.NewAppLog()
333+
app.initAppConfig()
334+
app.Logger().Debug("DotWeb ReSetConfig is done.", LogTarget_HttpServer)
335+
}
336+
315337
// StartServer start server with http port
316338
// if config the pprof, will be start pprof server
317339
func (app *DotWeb) StartServer(httpPort int) error {
@@ -378,6 +400,7 @@ func (app *DotWeb) ListenAndServe(addr string) error {
378400
err := app.HttpServer.ListenAndServeTLS(addr, app.HttpServer.ServerConfig().TLSCertFile, app.HttpServer.ServerConfig().TLSKeyFile)
379401
return err
380402
}
403+
app.isRun = true
381404
err := app.HttpServer.ListenAndServe(addr)
382405
return err
383406

@@ -480,14 +503,14 @@ func (app *DotWeb) initRegisterConfigGroup() {
480503
func (app *DotWeb) initPlugins() {
481504
for _, p := range app.pluginMap {
482505
if p.IsValidate() {
483-
go func() {
506+
go func(p Plugin) {
484507
defer func() {
485508
if err := recover(); err != nil {
486509
app.Logger().Error(exception.CatchError("DotWeb::initPlugins run error plugin - "+p.Name(), "", err), LogTarget_HttpServer)
487510
}
488511
}()
489512
p.Run()
490-
}()
513+
}(p)
491514
app.Logger().Debug("DotWeb initPlugins start run plugin - "+p.Name(), LogTarget_HttpServer)
492515
} else {
493516
app.Logger().Debug("DotWeb initPlugins not validate plugin - "+p.Name(), LogTarget_HttpServer)

dotweb_test.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package dotweb
22

33
import (
4-
"github.com/devfeel/dotweb/framework/file"
4+
"fmt"
5+
"github.com/devfeel/dotweb/config"
56
"github.com/devfeel/dotweb/test"
67
"testing"
78
)
@@ -44,8 +45,21 @@ func Test_IsDevelopmentMode_2(t *testing.T) {
4445
}
4546

4647
func TestDotWeb_UsePlugin(t *testing.T) {
47-
app := New()
48+
app := newConfigDotWeb()
4849
app.UsePlugin(new(testPlugin))
49-
app.UsePlugin(NewNotifyPlugin("test-notify", file.GetCurrentDirectory(), 500))
50+
app.UsePlugin(NewDefaultNotifyPlugin(app))
51+
fmt.Println(app.pluginMap)
5052
app.StartServer(8081)
5153
}
54+
55+
func newConfigDotWeb() *DotWeb {
56+
app := New()
57+
appConfig, err := config.InitConfig("d:/gotmp/dotweb.conf", "xml")
58+
if err != nil {
59+
fmt.Println("dotweb.InitConfig error => " + fmt.Sprint(err))
60+
return nil
61+
}
62+
app.Logger().SetEnabledConsole(true)
63+
app.SetConfig(appConfig)
64+
return app
65+
}

plugin.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,98 @@
11
package dotweb
22

3+
import (
4+
"fmt"
5+
"github.com/devfeel/dotweb/config"
6+
"os"
7+
"path/filepath"
8+
"time"
9+
)
10+
311
// Plugin a interface for app's global plugin
412
type Plugin interface {
513
Name() string
614
Run() error
715
IsValidate() bool
816
}
17+
18+
// NewDefaultNotifyPlugin return new NotifyPlugin with default config
19+
func NewDefaultNotifyPlugin(app *DotWeb) *NotifyPlugin {
20+
p := new(NotifyPlugin)
21+
p.app = app
22+
p.LoopTime = notifyPlugin_LoopTime
23+
p.Root = app.Config.ConfigFilePath
24+
p.suffix = make(map[string]bool)
25+
p.ModTimes = make(map[string]time.Time)
26+
return p
27+
}
28+
29+
// NewNotifyPlugin return new NotifyPlugin with fileRoot & loopTime & suffix
30+
// if suffix is nil or suffix[0] == "*", will visit all files in fileRoot
31+
/*func NewNotifyPlugin(app *DotWeb, fileRoot string, loopTime int, suffix []string) *NotifyPlugin{
32+
p := new(NotifyPlugin)
33+
p.app = app
34+
p.LoopTime = loopTime
35+
p.Root = fileRoot
36+
Suffix := make(map[string]bool)
37+
if len(suffix) > 0 && suffix[0] != "*" {
38+
for _, v := range suffix {
39+
Suffix[v] = true
40+
}
41+
}
42+
p.suffix = Suffix
43+
p.ModTimes = make(map[string]time.Time)
44+
return p
45+
}*/
46+
47+
const notifyPlugin_LoopTime = 500 //ms
48+
49+
type NotifyPlugin struct {
50+
app *DotWeb
51+
Root string
52+
suffix map[string]bool
53+
LoopTime int
54+
ModTimes map[string]time.Time
55+
}
56+
57+
func (p *NotifyPlugin) Name() string {
58+
return "NotifyPlugin"
59+
}
60+
61+
func (p *NotifyPlugin) IsValidate() bool {
62+
return true
63+
}
64+
65+
func (p *NotifyPlugin) Run() error {
66+
return p.start()
67+
}
68+
69+
func (p *NotifyPlugin) visit(path string, fileinfo os.FileInfo, err error) error {
70+
if err != nil {
71+
return fmt.Errorf("访问文件失败%s", err)
72+
}
73+
ext := filepath.Ext(path)
74+
if !fileinfo.IsDir() && (p.suffix[ext] || len(p.suffix) == 0) {
75+
modTime := fileinfo.ModTime()
76+
if oldModTime, ok := p.ModTimes[path]; !ok {
77+
p.ModTimes[path] = modTime
78+
} else {
79+
if oldModTime.Before(modTime) {
80+
p.app.Logger().Info("NotifyPlugin Reload "+path, LogTarget_HttpServer)
81+
appConfig, err := config.InitConfig(p.app.Config.ConfigFilePath, p.app.Config.ConfigType)
82+
if err != nil {
83+
p.app.Logger().Error("NotifyPlugin Reload "+path+" error => "+fmt.Sprint(err), LogTarget_HttpServer)
84+
}
85+
p.app.ReSetConfig(appConfig)
86+
p.ModTimes[path] = modTime
87+
}
88+
}
89+
}
90+
return nil
91+
}
92+
93+
func (p *NotifyPlugin) start() error {
94+
for {
95+
filepath.Walk(p.Root, p.visit)
96+
time.Sleep(time.Duration(p.LoopTime) * time.Millisecond)
97+
}
98+
}

plugin_test.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package dotweb
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
"github.com/devfeel/dotweb/test"
6+
"testing"
7+
"time"
8+
)
49

510
type testPlugin struct {
611
}
@@ -16,3 +21,30 @@ func (p *testPlugin) Run() error {
1621
func (p *testPlugin) IsValidate() bool {
1722
return true
1823
}
24+
25+
func TestNotifyPlugin_Name(t *testing.T) {
26+
app := newConfigDotWeb()
27+
//fmt.Println(app.Config.ConfigFilePath)
28+
p := NewDefaultNotifyPlugin(app)
29+
needShow := "NotifyPlugin"
30+
test.Equal(t, needShow, p.Name())
31+
}
32+
33+
func TestNotifyPlugin_IsValidate(t *testing.T) {
34+
app := newConfigDotWeb()
35+
p := NewDefaultNotifyPlugin(app)
36+
needShow := true
37+
test.Equal(t, needShow, p.IsValidate())
38+
}
39+
40+
func TestNotifyPlugin_Run(t *testing.T) {
41+
app := newConfigDotWeb()
42+
p := NewDefaultNotifyPlugin(app)
43+
go func() {
44+
for {
45+
fmt.Println(p.ModTimes[app.Config.ConfigFilePath])
46+
time.Sleep(time.Duration(600 * time.Millisecond))
47+
}
48+
}()
49+
p.Run()
50+
}

version.MD

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
## dotweb版本记录:
22

3+
#### Version 1.7.0
4+
* New Feature: 新增NotifyPlugin插件,默认集成监控配置文件变化热重启
5+
* New Feature: 新增DotWeb.ReSetConfig用于运行时重载配置
6+
* About NotifyPlugin:
7+
- 通过NewDefaultNotifyPlugin创建默认集成的NotifyPlugin
8+
- 仅当Dotweb通过配置文件启动方式下有效,监测默认的配置文件
9+
- 当热重启配置文件时,Dotweb本身监听端口以及pprod设置不会重载
10+
- 感谢@地蛋对该插件的支持
11+
* 2019-07-22 14:00 at ShangHai
312

413
#### Version 1.6.9
514
* New Feature: 增加插件机制-Plugin,随App启动一起执行,不会阻塞App启动过程,如需持续运行,在Plugin的Run中自行处理即可。

0 commit comments

Comments
 (0)