yao/service/watch.go
2022-02-14 23:40:21 +08:00

459 lines
12 KiB
Go

package service
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/fatih/color"
"github.com/yaoapp/gou"
"github.com/yaoapp/yao/chart"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/engine"
"github.com/yaoapp/yao/page"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/table"
"github.com/yaoapp/yao/workflow"
)
// Watch 监听应用目录文件变更
func Watch(cfg config.Config) {
if os.Getenv("YAO_DEV") != "" {
WatchEngine(filepath.Join(os.Getenv("YAO_DEV"), "/yao"))
}
WatchModel(filepath.Join(cfg.Root, "models"), "")
WatchAPI(filepath.Join(cfg.Root, "apis"), "")
WatchFlow(filepath.Join(cfg.Root, "flows"), "")
WatchPlugin(filepath.Join(cfg.Root, "plugins"))
WatchTable(filepath.Join(cfg.Root, "tables"), "")
WatchChart(filepath.Join(cfg.Root, "charts"), "")
WatchPage(filepath.Join(cfg.Root, "pages"), "")
WatchWorkFlow(filepath.Join(cfg.Root, "workflows"), "")
// 看板大屏
WatchPage(filepath.Join(cfg.Root, "kanban"), "")
WatchPage(filepath.Join(cfg.Root, "screen"), "")
// 监听脚本 & libs更新
WatchGlobal(filepath.Join(cfg.Root, "libs"))
WatchGlobal(filepath.Join(cfg.Root, "scripts"))
}
// WatchEngine 监听监听引擎内建数据变更
func WatchEngine(root string) {
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.")
}
// WatchGlobal 监听通用程序更新
func WatchGlobal(root 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 op == "write" || op == "create" || op == "remove" || op == "rename" {
err := engine.Load(config.Conf)
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
StopWithouttSession(func() {
fmt.Println(color.GreenString("Service Restarted"))
go StartWithouttSession()
})
}
})
}
// 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)
_, err := gou.LoadModelReturn(string(content), name) // Reload
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
fmt.Println(color.GreenString("Model %s Reloaded", name))
} else if op == "remove" || op == "rename" {
name := prefix + share.SpecName(root, filename)
if _, has := gou.Models[name]; has {
delete(gou.Models, name)
fmt.Println(color.RedString("Model %s Removed", 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)
_, err := gou.LoadAPIReturn(string(content), name) // Reload
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
fmt.Println(color.GreenString("API %s Reloaded", name))
} else if op == "remove" || op == "rename" {
name := prefix + share.SpecName(root, filename)
if _, has := gou.APIs[name]; has {
delete(gou.APIs, name)
fmt.Println(color.RedString("API %s Removed", name))
}
}
// 重启服务器
if op == "write" || op == "create" || op == "remove" || op == "rename" {
StopWithouttSession(func() {
fmt.Println(color.GreenString("Service Restarted"))
go StartWithouttSession()
})
}
})
}
// 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)
name = strings.ReplaceAll(name, ".", "/")
filename = filepath.Join(root, name+".flow.json")
}
if op == "write" || op == "create" {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
flow, err := gou.LoadFlowReturn(string(content), name) // Reload
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
if flow != nil { // Reload Script
dir := filepath.Dir(filename)
share.Walk(dir, ".js", func(root, filename string) {
script := share.ScriptName(filename)
content := share.ReadFile(filename)
_, err := flow.LoadScriptReturn(string(content), script)
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
})
}
fmt.Println(color.GreenString("Flow %s Reloaded", name))
} else if op == "remove" || op == "rename" {
name := prefix + share.SpecName(root, filename)
if _, has := gou.Flows[name]; has {
delete(gou.Flows, name)
fmt.Println(color.RedString("Flow %s Removed", 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)
_, err := gou.LoadPluginReturn(filename, name) // Reload
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
fmt.Println(color.GreenString("Plugin %s Reloaded", name))
} else if op == "remove" || op == "rename" {
name := share.SpecName(root, filename)
if _, has := gou.Plugins[name]; has {
delete(gou.Plugins, name)
fmt.Println(color.RedString("Plugin %s Removed", 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)
_, err := table.LoadTable(string(content), name) // Reload Table
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
api, has := gou.APIs["xiang.table"]
if has {
_, err := gou.LoadAPIReturn(api.Source, api.Name)
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
}
fmt.Println(color.GreenString("Table %s Reloaded", name))
} else if op == "remove" || op == "rename" {
name := prefix + share.SpecName(root, filename)
if _, has := table.Tables[name]; has {
delete(table.Tables, name)
fmt.Println(color.RedString("Table %s Removed", name))
}
}
// 重启服务器
if op == "write" || op == "create" || op == "remove" || op == "rename" {
StopWithouttSession(func() {
fmt.Println(color.GreenString("Service Restarted"))
go StartWithouttSession()
})
}
})
}
// 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)
name = strings.ReplaceAll(name, ".", "/")
filename = filepath.Join(root, name+".chart.json")
}
if op == "write" || op == "create" {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
chart, err := chart.LoadChart(content, name) // Relaod
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
if chart != nil { // Reload Script
dir := filepath.Dir(filename)
share.Walk(dir, ".js", func(root, filename string) {
script := share.ScriptName(filename)
content := share.ReadFile(filename)
_, err := chart.LoadScriptReturn(string(content), script)
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
})
}
api, has := gou.APIs["xiang.chart"]
if has {
_, err := gou.LoadAPIReturn(api.Source, api.Name)
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
}
fmt.Println(color.GreenString("Chart %s Reloaded", name))
} else if op == "remove" || op == "rename" {
name := prefix + share.SpecName(root, filename)
if _, has := chart.Charts[name]; has {
delete(chart.Charts, name)
fmt.Println(color.RedString("Chart %s Removed", name))
}
}
// 重启服务器
if op == "write" || op == "create" || op == "remove" || op == "rename" {
StopWithouttSession(func() {
fmt.Println(color.GreenString("Service Restarted"))
go StartWithouttSession()
})
}
})
}
// WatchPage 监听页面更新
func WatchPage(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)
name = strings.ReplaceAll(name, ".", "/")
filename = filepath.Join(root, name+".page.json")
}
if op == "write" || op == "create" {
name := prefix + share.SpecName(root, filename)
content := share.ReadFile(filename)
page, err := page.LoadPage(content, name) // Relaod
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
if page != nil { // Reload Script
dir := filepath.Dir(filename)
share.Walk(dir, ".js", func(root, filename string) {
script := share.ScriptName(filename)
content := share.ReadFile(filename)
_, err := page.LoadScriptReturn(string(content), script)
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
})
}
api, has := gou.APIs["xiang.page"]
if has {
_, err := gou.LoadAPIReturn(api.Source, api.Name)
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
}
fmt.Println(color.GreenString("Page %s Reloaded", name))
} else if op == "remove" || op == "rename" {
name := prefix + share.SpecName(root, filename)
if _, has := page.Pages[name]; has {
delete(page.Pages, name)
fmt.Println(color.RedString("Page %s Removed", name))
}
}
// 重启服务器
if op == "write" || op == "create" || op == "remove" || op == "rename" {
StopWithouttSession(func() {
fmt.Println(color.GreenString("Service Restarted"))
go StartWithouttSession()
})
}
})
}
// WatchWorkFlow 监听工作流更新
func WatchWorkFlow(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)
_, err := workflow.LoadWorkFlow(content, name) // Relaod
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
api, has := gou.APIs["xiang.workflow."+name]
if has {
_, err := gou.LoadAPIReturn(api.Source, api.Name)
if err != nil {
fmt.Println(color.RedString("Fatal: %s", err.Error()))
return
}
}
fmt.Println(color.GreenString("Workflow %s Reloaded", name))
} else if op == "remove" || op == "rename" {
name := prefix + share.SpecName(root, filename)
if _, has := workflow.WorkFlows[name]; has {
delete(workflow.WorkFlows, name)
fmt.Println(color.RedString("Workflow %s Removed", name))
}
}
// 重启服务器
if op == "write" || op == "create" || op == "remove" || op == "rename" {
StopWithouttSession(func() {
fmt.Println(color.GreenString("Service Restarted"))
go StartWithouttSession()
})
}
})
}