356 lines
9.2 KiB
Go
356 lines
9.2 KiB
Go
package global
|
|
|
|
import (
|
|
"log"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/yaoapp/gou"
|
|
"github.com/yaoapp/xiang/table"
|
|
)
|
|
|
|
var shutdown = make(chan bool)
|
|
var shutdownComplete = make(chan bool)
|
|
|
|
// ServiceStart 启动服务
|
|
func ServiceStart() {
|
|
gou.SetHTTPGuards(Guards)
|
|
gou.ServeHTTP(
|
|
gou.Server{
|
|
Host: Conf.Service.Host,
|
|
Port: Conf.Service.Port,
|
|
Allows: Conf.Service.Allow,
|
|
Root: "/api",
|
|
},
|
|
&shutdown, func(s gou.Server) {
|
|
shutdownComplete <- true
|
|
},
|
|
Middlewares...)
|
|
}
|
|
|
|
// ServiceStop 关闭服务
|
|
func ServiceStop(onComplete func()) {
|
|
shutdown <- true
|
|
<-shutdownComplete
|
|
onComplete()
|
|
}
|
|
|
|
// WatchChanges 监听配置文件变更
|
|
func WatchChanges() {
|
|
watchEngine(Conf.Path)
|
|
watchApp(AppRoot{
|
|
APIs: Conf.RootAPI,
|
|
Flows: Conf.RootFLow,
|
|
Models: Conf.RootModel,
|
|
Plugins: Conf.RootPlugin,
|
|
Tables: Conf.RootTable,
|
|
Charts: Conf.RootChart,
|
|
Screens: 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 Watch(filepath.Join(rootAbs, "flows"), func(op string, file string) {
|
|
|
|
if !strings.HasSuffix(file, ".json") {
|
|
return
|
|
}
|
|
|
|
if strings.HasSuffix(file, ".js") {
|
|
basName := getFileBaseName(root, file)
|
|
file = basName + ".flow.json"
|
|
}
|
|
|
|
if op == "write" || op == "create" {
|
|
script := 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." + getFileName(root, file)
|
|
if _, has := gou.Flows[name]; has {
|
|
delete(gou.Flows, name)
|
|
log.Printf("Flow %s 已经移除", name)
|
|
}
|
|
}
|
|
})
|
|
|
|
// 监听 models
|
|
go Watch(filepath.Join(rootAbs, "models"), func(op string, file string) {
|
|
|
|
if !strings.HasSuffix(file, ".json") {
|
|
return
|
|
}
|
|
if op == "write" || op == "create" {
|
|
script := 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." + getFileName(root, file)
|
|
if _, has := gou.Models[name]; has {
|
|
delete(gou.Models, name)
|
|
log.Printf("Model %s 已经移除", name)
|
|
}
|
|
}
|
|
})
|
|
|
|
// 监听 apis
|
|
go Watch(filepath.Join(rootAbs, "apis"), func(op string, file string) {
|
|
|
|
if !strings.HasSuffix(file, ".json") {
|
|
return
|
|
}
|
|
if op == "write" || op == "create" {
|
|
script := 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." + 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" {
|
|
ServiceStop(func() {
|
|
log.Printf("服务器重启完毕")
|
|
go ServiceStart()
|
|
})
|
|
}
|
|
})
|
|
|
|
// 监听 tables
|
|
go Watch(filepath.Join(rootAbs, "tables"), func(op string, file string) {
|
|
|
|
if !strings.HasSuffix(file, ".json") {
|
|
return
|
|
}
|
|
if op == "write" || op == "create" {
|
|
script := getFile(root, file)
|
|
table.Load(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." + 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" {
|
|
ServiceStop(func() {
|
|
log.Printf("服务器重启完毕")
|
|
go ServiceStart()
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
// watchApp 监听应用目录文件变更
|
|
func watchApp(app 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 Watch(rootAbs, func(op string, file string) {
|
|
if !strings.HasSuffix(file, ".json") {
|
|
return
|
|
}
|
|
|
|
if op == "write" || op == "create" {
|
|
script := getAppFile(root, file)
|
|
table.Load(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 := 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" {
|
|
ServiceStop(func() {
|
|
log.Printf("服务器重启完毕")
|
|
go ServiceStart()
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
// 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 Watch(rootAbs, func(op string, file string) {
|
|
if !strings.HasSuffix(file, ".json") {
|
|
return
|
|
}
|
|
|
|
if op == "write" || op == "create" {
|
|
script := getAppFile(root, file)
|
|
gou.LoadAPI(string(script.Content), script.Name) // Reload
|
|
log.Printf("API %s 已重新加载完毕", script.Name)
|
|
|
|
} else if op == "remove" || op == "rename" {
|
|
name := 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" {
|
|
ServiceStop(func() {
|
|
log.Printf("服务器重启完毕")
|
|
go ServiceStart()
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
// 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 Watch(rootAbs, func(op string, file string) {
|
|
if !strings.HasSuffix(file, ".json") && !strings.HasSuffix(file, ".js") {
|
|
return
|
|
}
|
|
if strings.HasSuffix(file, ".js") {
|
|
basName := getAppFileBaseName(root, file)
|
|
file = basName + ".flow.json"
|
|
}
|
|
if op == "write" || op == "create" {
|
|
script := getAppFile(root, file)
|
|
gou.LoadFlow(string(script.Content), script.Name) // Reload
|
|
log.Printf("Flow %s 已重新加载完毕", script.Name)
|
|
} else if op == "remove" || op == "rename" {
|
|
name := 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 Watch(rootAbs, func(op string, file string) {
|
|
if !strings.HasSuffix(file, ".json") {
|
|
return
|
|
}
|
|
if op == "write" || op == "create" {
|
|
script := getAppFile(root, file)
|
|
gou.LoadModel(string(script.Content), script.Name) // Reload
|
|
log.Printf("Model %s 已重新加载完毕", script.Name)
|
|
} else if op == "remove" || op == "rename" {
|
|
name := 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 Watch(rootAbs, func(op string, file string) {
|
|
if !strings.HasSuffix(file, ".so") {
|
|
return
|
|
}
|
|
|
|
if op == "write" || op == "create" {
|
|
script := getAppPluginFile(root, file)
|
|
gou.LoadPlugin(script.File, script.Name) // Reload
|
|
log.Printf("Plugin %s 已重新加载完毕", script.Name)
|
|
} else if op == "remove" || op == "rename" {
|
|
name := getAppPluginFileName(root, file)
|
|
if _, has := gou.Plugins[name]; has {
|
|
delete(gou.Plugins, name)
|
|
log.Printf("Plugin %s 已经移除", name)
|
|
}
|
|
}
|
|
})
|
|
}
|