优化热加载逻辑
This commit is contained in:
parent
2779e792f9
commit
490a1c999f
8 changed files with 272 additions and 340 deletions
|
|
@ -29,22 +29,21 @@ func LoadFrom(dir string, prefix string) {
|
||||||
share.Walk(dir, ".json", func(root, filename string) {
|
share.Walk(dir, ".json", func(root, filename string) {
|
||||||
name := share.SpecName(root, filename)
|
name := share.SpecName(root, filename)
|
||||||
content := share.ReadFile(filename)
|
content := share.ReadFile(filename)
|
||||||
chart, err := LoadChart(content, name)
|
_, err := LoadChart(content, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception.New("%s 图表格式错误", 400, name).Ctx(filename).Throw()
|
exception.New("%s 图表格式错误", 400, name).Ctx(filename).Throw()
|
||||||
}
|
}
|
||||||
Charts[name] = chart
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadChart 载入数据表格
|
// LoadChart 载入数据表格
|
||||||
func LoadChart(source []byte, name string) (*Chart, error) {
|
func LoadChart(source []byte, name string) (*Chart, error) {
|
||||||
chart := Chart{
|
chart := &Chart{
|
||||||
Flow: gou.Flow{
|
Flow: gou.Flow{
|
||||||
Name: name,
|
Name: name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := jsoniter.Unmarshal(source, &chart)
|
err := jsoniter.Unmarshal(source, chart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xlog.Println(name)
|
xlog.Println(name)
|
||||||
xlog.Println(err.Error())
|
xlog.Println(err.Error())
|
||||||
|
|
@ -53,8 +52,8 @@ func LoadChart(source []byte, name string) (*Chart, error) {
|
||||||
}
|
}
|
||||||
chart.Prepare()
|
chart.Prepare()
|
||||||
chart.SetupAPIs()
|
chart.SetupAPIs()
|
||||||
|
Charts[name] = chart
|
||||||
return &chart, nil
|
return chart, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select 读取已加载图表
|
// Select 读取已加载图表
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ var startCmd = &cobra.Command{
|
||||||
|
|
||||||
// 调试模式
|
// 调试模式
|
||||||
if config.Conf.Mode == "debug" {
|
if config.Conf.Mode == "debug" {
|
||||||
service.WatchChanges()
|
service.Watch(config.Conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
service.Start()
|
service.Start()
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ import (
|
||||||
|
|
||||||
// Load 加载业务插件
|
// Load 加载业务插件
|
||||||
func Load(cfg config.Config) {
|
func Load(cfg config.Config) {
|
||||||
LoadFrom(cfg.RootPlugin, "")
|
LoadFrom(cfg.RootPlugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadFrom 从特定目录加载
|
// LoadFrom 从特定目录加载
|
||||||
func LoadFrom(dir string, prefix string) {
|
func LoadFrom(dir string) {
|
||||||
|
|
||||||
if share.DirNotExists(dir) {
|
if share.DirNotExists(dir) {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import (
|
||||||
func TestLoad(t *testing.T) {
|
func TestLoad(t *testing.T) {
|
||||||
gou.Plugins = make(map[string]*gou.Plugin)
|
gou.Plugins = make(map[string]*gou.Plugin)
|
||||||
Load(config.Conf)
|
Load(config.Conf)
|
||||||
LoadFrom("not a path", "404.")
|
LoadFrom("404")
|
||||||
check(t)
|
check(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/yaoapp/gou"
|
"github.com/yaoapp/gou"
|
||||||
"github.com/yaoapp/xiang/config"
|
"github.com/yaoapp/xiang/config"
|
||||||
"github.com/yaoapp/xiang/share"
|
|
||||||
"github.com/yaoapp/xiang/table"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var shutdown = make(chan bool)
|
var shutdown = make(chan bool)
|
||||||
|
|
@ -36,323 +30,3 @@ func Stop(onComplete func()) {
|
||||||
<-shutdownComplete
|
<-shutdownComplete
|
||||||
onComplete()
|
onComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
// WatchChanges 监听配置文件变更
|
|
||||||
func WatchChanges() {
|
|
||||||
watchEngine(config.Conf.Path)
|
|
||||||
watchApp(share.AppRoot{
|
|
||||||
APIs: config.Conf.RootAPI,
|
|
||||||
Flows: config.Conf.RootFLow,
|
|
||||||
Models: config.Conf.RootModel,
|
|
||||||
Plugins: config.Conf.RootPlugin,
|
|
||||||
Tables: config.Conf.RootTable,
|
|
||||||
Charts: config.Conf.RootChart,
|
|
||||||
Screens: config.Conf.RootScreen,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchEngine 监听引擎目录文件变更
|
|
||||||
func watchEngine(from string) {
|
|
||||||
if !strings.HasPrefix(from, "fs://") && strings.Contains(from, "://") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
root := strings.TrimPrefix(from, "fs://")
|
|
||||||
rootAbs, err := filepath.Abs(root)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("路径错误 %s %s", root, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听 flows (这里应该重构)
|
|
||||||
go share.Watch(filepath.Join(rootAbs, "flows"), func(op string, file string) {
|
|
||||||
|
|
||||||
if !strings.HasSuffix(file, ".json") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasSuffix(file, ".js") {
|
|
||||||
basName := share.GetFileBaseName(root, file)
|
|
||||||
file = basName + ".flow.json"
|
|
||||||
}
|
|
||||||
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetFile(root, file)
|
|
||||||
gou.LoadFlow(string(script.Content), "xiang."+script.Name) // Reload
|
|
||||||
log.Printf("Flow %s 已重新加载完毕", "xiang."+script.Name)
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := "xiang." + share.GetFileName(root, file)
|
|
||||||
if _, has := gou.Flows[name]; has {
|
|
||||||
delete(gou.Flows, name)
|
|
||||||
log.Printf("Flow %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 监听 models
|
|
||||||
go share.Watch(filepath.Join(rootAbs, "models"), func(op string, file string) {
|
|
||||||
|
|
||||||
if !strings.HasSuffix(file, ".json") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetFile(root, file)
|
|
||||||
gou.LoadModel(string(script.Content), "xiang."+script.Name) // Reload
|
|
||||||
log.Printf("Model %s 已重新加载完毕", "xiang."+script.Name)
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := "xiang." + share.GetFileName(root, file)
|
|
||||||
if _, has := gou.Models[name]; has {
|
|
||||||
delete(gou.Models, name)
|
|
||||||
log.Printf("Model %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 监听 apis
|
|
||||||
go share.Watch(filepath.Join(rootAbs, "apis"), func(op string, file string) {
|
|
||||||
|
|
||||||
if !strings.HasSuffix(file, ".json") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetFile(root, file)
|
|
||||||
gou.LoadAPI(string(script.Content), "xiang."+script.Name) // Reload
|
|
||||||
log.Printf("API %s 已重新加载完毕", "xiang."+script.Name)
|
|
||||||
|
|
||||||
// 打印最新API信息
|
|
||||||
api := gou.APIs["xiang."+script.Name]
|
|
||||||
log.Printf("%s(%d)", api.Name, len(api.HTTP.Paths))
|
|
||||||
for _, p := range api.HTTP.Paths {
|
|
||||||
log.Println(p.Method, filepath.Join("/api", api.HTTP.Group, p.Path), "\tprocess:", p.Process)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := "xiang." + share.GetFileName(root, file)
|
|
||||||
if _, has := gou.APIs[name]; has {
|
|
||||||
delete(gou.APIs, name)
|
|
||||||
log.Printf("API %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重启服务器
|
|
||||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
|
||||||
Stop(func() {
|
|
||||||
log.Printf("服务器重启完毕")
|
|
||||||
go Start()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 监听 tables
|
|
||||||
go share.Watch(filepath.Join(rootAbs, "tables"), func(op string, file string) {
|
|
||||||
|
|
||||||
if !strings.HasSuffix(file, ".json") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetFile(root, file)
|
|
||||||
table.LoadTable(string(script.Content), "xiang."+script.Name) // Reload
|
|
||||||
api, has := gou.APIs["xiang.table"]
|
|
||||||
if has {
|
|
||||||
api.Reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("数据表格 %s 已重新加载完毕", "xiang."+script.Name)
|
|
||||||
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := "xiang." + share.GetFileName(root, file)
|
|
||||||
if _, has := table.Tables[name]; has {
|
|
||||||
delete(table.Tables, name)
|
|
||||||
log.Printf("数据表格 %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重启服务器
|
|
||||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
|
||||||
Stop(func() {
|
|
||||||
log.Printf("服务器重启完毕")
|
|
||||||
go Start()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchApp 监听应用目录文件变更
|
|
||||||
func watchApp(app share.AppRoot) {
|
|
||||||
watchAppAPI(app.APIs)
|
|
||||||
watchAppFlow(app.Flows)
|
|
||||||
watchAppModel(app.Models)
|
|
||||||
watchAppPlugin(app.Plugins)
|
|
||||||
watchAppTable(app.Tables)
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchAppTable 监听数据表格变更
|
|
||||||
func watchAppTable(rootTable string) {
|
|
||||||
if !strings.HasPrefix(rootTable, "fs://") && strings.Contains(rootTable, "://") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
root := strings.TrimPrefix(rootTable, "fs://")
|
|
||||||
rootAbs, err := filepath.Abs(root)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("路径错误 %s %s", root, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go share.Watch(rootAbs, func(op string, file string) {
|
|
||||||
if !strings.HasSuffix(file, ".json") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetAppFile(root, file)
|
|
||||||
table.LoadTable(string(script.Content), script.Name) // Reload
|
|
||||||
api, has := gou.APIs["xiang.table"]
|
|
||||||
if has {
|
|
||||||
api.Reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("数据表格 %s 已重新加载完毕", script.Name)
|
|
||||||
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := share.GetAppFileName(root, file)
|
|
||||||
if _, has := gou.APIs[name]; has {
|
|
||||||
delete(table.Tables, name)
|
|
||||||
log.Printf("数据表格 %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重启服务器
|
|
||||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
|
||||||
Stop(func() {
|
|
||||||
log.Printf("服务器重启完毕")
|
|
||||||
go Start()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchAppAPI 监听API变更
|
|
||||||
func watchAppAPI(api string) {
|
|
||||||
if !strings.HasPrefix(api, "fs://") && strings.Contains(api, "://") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
root := strings.TrimPrefix(api, "fs://")
|
|
||||||
rootAbs, err := filepath.Abs(root)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("路径错误 %s %s", root, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go share.Watch(rootAbs, func(op string, file string) {
|
|
||||||
if !strings.HasSuffix(file, ".json") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetAppFile(root, file)
|
|
||||||
gou.LoadAPI(string(script.Content), script.Name) // Reload
|
|
||||||
log.Printf("API %s 已重新加载完毕", script.Name)
|
|
||||||
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := share.GetAppFileName(root, file)
|
|
||||||
if _, has := gou.APIs[name]; has {
|
|
||||||
delete(gou.APIs, name)
|
|
||||||
log.Printf("API %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重启服务器
|
|
||||||
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
|
||||||
Stop(func() {
|
|
||||||
log.Printf("服务器重启完毕")
|
|
||||||
go Start()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchAppFlow 监听Flow变更
|
|
||||||
func watchAppFlow(flow string) {
|
|
||||||
if !strings.HasPrefix(flow, "fs://") && strings.Contains(flow, "://") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
root := strings.TrimPrefix(flow, "fs://")
|
|
||||||
rootAbs, err := filepath.Abs(root)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("路径错误 %s %s", root, err)
|
|
||||||
}
|
|
||||||
go share.Watch(rootAbs, func(op string, file string) {
|
|
||||||
if !strings.HasSuffix(file, ".json") && !strings.HasSuffix(file, ".js") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(file, ".js") {
|
|
||||||
basName := share.GetAppFileBaseName(root, file)
|
|
||||||
file = basName + ".flow.json"
|
|
||||||
}
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetAppFile(root, file)
|
|
||||||
gou.LoadFlow(string(script.Content), script.Name) // Reload
|
|
||||||
log.Printf("Flow %s 已重新加载完毕", script.Name)
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := share.GetAppFileName(root, file)
|
|
||||||
if _, has := gou.Flows[name]; has {
|
|
||||||
delete(gou.Flows, name)
|
|
||||||
log.Printf("Flow %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchAppModel 监听Model变更
|
|
||||||
func watchAppModel(model string) {
|
|
||||||
if !strings.HasPrefix(model, "fs://") && strings.Contains(model, "://") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
root := strings.TrimPrefix(model, "fs://")
|
|
||||||
rootAbs, err := filepath.Abs(root)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("路径错误 %s %s", root, err)
|
|
||||||
}
|
|
||||||
go share.Watch(rootAbs, func(op string, file string) {
|
|
||||||
if !strings.HasSuffix(file, ".json") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetAppFile(root, file)
|
|
||||||
gou.LoadModel(string(script.Content), script.Name) // Reload
|
|
||||||
log.Printf("Model %s 已重新加载完毕", script.Name)
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := share.GetAppFileName(root, file)
|
|
||||||
if _, has := gou.Models[name]; has {
|
|
||||||
delete(gou.Models, name)
|
|
||||||
log.Printf("Model %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchAppPlugin 监听Plugin变更
|
|
||||||
func watchAppPlugin(plugin string) {
|
|
||||||
if !strings.HasPrefix(plugin, "fs://") && strings.Contains(plugin, "://") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
root := strings.TrimPrefix(plugin, "fs://")
|
|
||||||
rootAbs, err := filepath.Abs(root)
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("路径错误 %s %s", root, err)
|
|
||||||
}
|
|
||||||
go share.Watch(rootAbs, func(op string, file string) {
|
|
||||||
if !strings.HasSuffix(file, ".so") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if op == "write" || op == "create" {
|
|
||||||
script := share.GetAppPluginFile(root, file)
|
|
||||||
gou.LoadPlugin(script.File, script.Name) // Reload
|
|
||||||
log.Printf("Plugin %s 已重新加载完毕", script.Name)
|
|
||||||
} else if op == "remove" || op == "rename" {
|
|
||||||
name := share.GetAppPluginFileName(root, file)
|
|
||||||
if _, has := gou.Plugins[name]; has {
|
|
||||||
delete(gou.Plugins, name)
|
|
||||||
log.Printf("Plugin %s 已经移除", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
248
service/watch.go
Normal file
248
service/watch.go
Normal file
|
|
@ -0,0 +1,248 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou"
|
||||||
|
"github.com/yaoapp/xiang/chart"
|
||||||
|
"github.com/yaoapp/xiang/config"
|
||||||
|
"github.com/yaoapp/xiang/share"
|
||||||
|
"github.com/yaoapp/xiang/table"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Watch 监听应用目录文件变更
|
||||||
|
func Watch(cfg config.Config) {
|
||||||
|
WatchEngine(cfg.Path)
|
||||||
|
WatchModel(cfg.RootModel, "")
|
||||||
|
WatchAPI(cfg.RootAPI, "")
|
||||||
|
WatchFlow(cfg.RootFLow, "")
|
||||||
|
WatchPlugin(cfg.RootPlugin)
|
||||||
|
WatchTable(cfg.RootTable, "")
|
||||||
|
WatchChart(cfg.RootChart, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchEngine 监听监听引擎内建数据变更
|
||||||
|
func WatchEngine(root string) {
|
||||||
|
if !strings.HasPrefix(root, "fs://") && strings.Contains(root, "://") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root = strings.TrimPrefix(root, "fs://")
|
||||||
|
root = share.DirAbs(root)
|
||||||
|
|
||||||
|
WatchModel(filepath.Join(root, "models"), "xiang.")
|
||||||
|
WatchAPI(filepath.Join(root, "apis"), "xiang.")
|
||||||
|
WatchFlow(filepath.Join(root, "flows"), "xiang.")
|
||||||
|
WatchTable(filepath.Join(root, "tables"), "xiang.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchModel 监听业务接口更新
|
||||||
|
func WatchModel(root string, prefix string) {
|
||||||
|
if share.DirNotExists(root) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root = share.DirAbs(root)
|
||||||
|
go share.Watch(root, func(op string, filename string) {
|
||||||
|
|
||||||
|
if !strings.HasSuffix(filename, ".json") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if op == "write" || op == "create" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
content := share.ReadFile(filename)
|
||||||
|
gou.LoadModel(string(content), name) // Reload
|
||||||
|
log.Printf("Model %s 已重新加载完毕", name)
|
||||||
|
|
||||||
|
} else if op == "remove" || op == "rename" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
if _, has := gou.Models[name]; has {
|
||||||
|
delete(gou.Models, name)
|
||||||
|
log.Printf("Model %s 已经移除", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchAPI 监听业务接口更新
|
||||||
|
func WatchAPI(root string, prefix string) {
|
||||||
|
if share.DirNotExists(root) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root = share.DirAbs(root)
|
||||||
|
go share.Watch(root, func(op string, filename string) {
|
||||||
|
|
||||||
|
if !strings.HasSuffix(filename, ".json") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if op == "write" || op == "create" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
content := share.ReadFile(filename)
|
||||||
|
gou.LoadAPI(string(content), name) // Reload
|
||||||
|
log.Printf("API %s 已重新加载完毕", name)
|
||||||
|
|
||||||
|
} else if op == "remove" || op == "rename" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
if _, has := gou.APIs[name]; has {
|
||||||
|
delete(gou.APIs, name)
|
||||||
|
log.Printf("API %s 已经移除", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重启服务器
|
||||||
|
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||||
|
Stop(func() {
|
||||||
|
log.Printf("服务器重启完毕")
|
||||||
|
go Start()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchFlow 监听业务逻辑变更
|
||||||
|
func WatchFlow(root string, prefix string) {
|
||||||
|
if share.DirNotExists(root) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root = share.DirAbs(root)
|
||||||
|
go share.Watch(root, func(op string, filename string) {
|
||||||
|
if !strings.HasSuffix(filename, ".json") && !strings.HasSuffix(filename, ".js") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(filename, ".js") {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
filename = name + ".flow.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
if op == "write" || op == "create" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
content := share.ReadFile(filename)
|
||||||
|
gou.LoadFlow(string(content), name) // Reload
|
||||||
|
log.Printf("Flow %s 已重新加载完毕", name)
|
||||||
|
|
||||||
|
} else if op == "remove" || op == "rename" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
if _, has := gou.Flows[name]; has {
|
||||||
|
delete(gou.Flows, name)
|
||||||
|
log.Printf("Flow %s 已经移除", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchPlugin 监听业务插件变更
|
||||||
|
func WatchPlugin(root string) {
|
||||||
|
if share.DirNotExists(root) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root = share.DirAbs(root)
|
||||||
|
go share.Watch(root, func(op string, filename string) {
|
||||||
|
|
||||||
|
if !strings.HasSuffix(filename, ".so") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if op == "write" || op == "create" {
|
||||||
|
name := share.SpecName(root, filename)
|
||||||
|
gou.LoadPlugin(filename, name) // Reload
|
||||||
|
log.Printf("Plugin %s 已重新加载完毕", name)
|
||||||
|
|
||||||
|
} else if op == "remove" || op == "rename" {
|
||||||
|
name := share.SpecName(root, filename)
|
||||||
|
if _, has := gou.Plugins[name]; has {
|
||||||
|
delete(gou.Plugins, name)
|
||||||
|
log.Printf("Plugin %s 已经移除", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchTable 监听数据表格更新
|
||||||
|
func WatchTable(root string, prefix string) {
|
||||||
|
if share.DirNotExists(root) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root = share.DirAbs(root)
|
||||||
|
go share.Watch(root, func(op string, filename string) {
|
||||||
|
|
||||||
|
if !strings.HasSuffix(filename, ".json") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if op == "write" || op == "create" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
content := share.ReadFile(filename)
|
||||||
|
table.LoadTable(string(content), name) // Reload Table
|
||||||
|
|
||||||
|
api, has := gou.APIs["xiang.table"]
|
||||||
|
if has {
|
||||||
|
api.Reload() // 重载API
|
||||||
|
}
|
||||||
|
log.Printf("数据表格 %s 已重新加载完毕", name)
|
||||||
|
|
||||||
|
} else if op == "remove" || op == "rename" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
if _, has := table.Tables[name]; has {
|
||||||
|
delete(table.Tables, name)
|
||||||
|
log.Printf("数据表格 %s 已经移除", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重启服务器
|
||||||
|
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||||
|
Stop(func() {
|
||||||
|
log.Printf("服务器重启完毕")
|
||||||
|
go Start()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchChart 监听分析图表更新
|
||||||
|
func WatchChart(root string, prefix string) {
|
||||||
|
if share.DirNotExists(root) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root = share.DirAbs(root)
|
||||||
|
go share.Watch(root, func(op string, filename string) {
|
||||||
|
if !strings.HasSuffix(filename, ".json") && !strings.HasSuffix(filename, ".js") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(filename, ".js") {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
filename = name + ".chart.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
if op == "write" || op == "create" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
content := share.ReadFile(filename)
|
||||||
|
chart.LoadChart(content, name) // Relaod
|
||||||
|
|
||||||
|
api, has := gou.APIs["xiang.chart"]
|
||||||
|
if has {
|
||||||
|
fmt.Println("Reload API:", "--")
|
||||||
|
api.Reload() // 重载API
|
||||||
|
}
|
||||||
|
log.Printf("Chart %s 已重新加载完毕", name)
|
||||||
|
|
||||||
|
} else if op == "remove" || op == "rename" {
|
||||||
|
name := prefix + share.SpecName(root, filename)
|
||||||
|
if _, has := chart.Charts[name]; has {
|
||||||
|
delete(chart.Charts, name)
|
||||||
|
log.Printf("Chart %s 已经移除", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重启服务器
|
||||||
|
if op == "write" || op == "create" || op == "remove" || op == "rename" {
|
||||||
|
Stop(func() {
|
||||||
|
log.Printf("服务器重启完毕")
|
||||||
|
go Start()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package share
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -61,6 +62,17 @@ func DirNotExists(dir string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DirAbs 文件绝对路径
|
||||||
|
func DirAbs(dir string) string {
|
||||||
|
dir = strings.TrimPrefix(dir, "fs://")
|
||||||
|
dir = strings.TrimPrefix(dir, "file://")
|
||||||
|
dirAbs, err := filepath.Abs(dir)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("获取绝对路径错误 %s %s", dir, err)
|
||||||
|
}
|
||||||
|
return dirAbs
|
||||||
|
}
|
||||||
|
|
||||||
// ************************************************
|
// ************************************************
|
||||||
// 警告: 以下函数将被弃用
|
// 警告: 以下函数将被弃用
|
||||||
// ************************************************
|
// ************************************************
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package engine
|
package share
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
@ -8,16 +8,15 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/yaoapp/xiang/config"
|
"github.com/yaoapp/xiang/config"
|
||||||
"github.com/yaoapp/xiang/share"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWatch(t *testing.T) {
|
func TestWatch(t *testing.T) {
|
||||||
root := path.Join(config.Conf.Source, "/tests/flows")
|
root := path.Join(config.Conf.Source, "/tests/flows")
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
go share.Watch(root, func(op string, file string) {
|
go Watch(root, func(op string, file string) {
|
||||||
log.Println(op, file)
|
log.Println(op, file)
|
||||||
})
|
})
|
||||||
time.Sleep(time.Second * 2)
|
time.Sleep(time.Second * 2)
|
||||||
defer share.StopWatch()
|
defer StopWatch()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue