From d3073bee8251e937341b09c1752d842e09bc46d6 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 28 Sep 2021 16:43:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=A1=A8=E6=A0=BC=E7=83=AD?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- global/config.go | 9 ++++ global/load.go | 55 ++++++++++++++++++----- global/load_test.go | 10 ++++- global/service.go | 99 +++++++++++++++++++++++++++++++++++++++--- xiang/tables/user.json | 14 +----- 5 files changed, 155 insertions(+), 32 deletions(-) diff --git a/global/config.go b/global/config.go index 4205b67a..b00a9616 100644 --- a/global/config.go +++ b/global/config.go @@ -122,4 +122,13 @@ func (cfg *Config) SetDefaults() { if cfg.RootPlugin == "" { cfg.RootPlugin = cfg.Root + "/plugins" } + if cfg.RootTable == "" { + cfg.RootTable = cfg.Root + "/tables" + } + if cfg.RootChart == "" { + cfg.RootChart = cfg.Root + "/charts" + } + if cfg.RootScreen == "" { + cfg.RootScreen = cfg.Root + "/screens" + } } diff --git a/global/load.go b/global/load.go index 9b927f07..aa9979cb 100644 --- a/global/load.go +++ b/global/load.go @@ -21,10 +21,29 @@ type Script struct { File string } +// AppRoot 应用目录 +type AppRoot struct { + APIs string + Flows string + Models string + Plugins string + Tables string + Charts string + Screens string +} + // Load 根据配置加载 API, FLow, Model, Plugin func Load(cfg Config) { LoadEngine(cfg.Path) - LoadApp(cfg.RootAPI, cfg.RootFLow, cfg.RootModel, cfg.RootPlugin) + LoadApp(AppRoot{ + APIs: cfg.RootAPI, + Flows: cfg.RootFLow, + Models: cfg.RootModel, + Plugins: cfg.RootPlugin, + Tables: cfg.RootTable, + Charts: cfg.RootChart, + Screens: cfg.RootScreen, + }) } // Reload 根据配置重新加载 API, FLow, Model, Plugin @@ -56,7 +75,7 @@ func LoadEngine(from string) { exception.New("读取文件失败, 未找到任何可执行脚本", 500, from).Throw() } - // 加载 API, Flow, Models, Table + // 加载 API, Flow, Models, Table, Chart, Screens for _, script := range scripts { switch script.Type { case "models": @@ -76,10 +95,11 @@ func LoadEngine(from string) { } // LoadApp 加载应用的 API, Flow, Model 和 Plugin -func LoadApp(api string, flow string, model string, plugin string) { +func LoadApp(app AppRoot) { + // api string, flow string, model string, plugin string // 创建应用目录 - paths := []string{api, flow, model, plugin} + paths := []string{app.APIs, app.Flows, app.Models, app.Plugins, app.Charts, app.Screens} for _, p := range paths { if !strings.HasPrefix(p, "fs://") && strings.Contains(p, "://") { continue @@ -98,8 +118,8 @@ func LoadApp(api string, flow string, model string, plugin string) { } // 加载API - if strings.HasPrefix(api, "fs://") || !strings.Contains(api, "://") { - root := strings.TrimPrefix(api, "fs://") + if strings.HasPrefix(app.APIs, "fs://") || !strings.Contains(app.APIs, "://") { + root := strings.TrimPrefix(app.APIs, "fs://") scripts := getAppFilesFS(root, ".json") for _, script := range scripts { // 验证API 加载逻辑 @@ -108,8 +128,8 @@ func LoadApp(api string, flow string, model string, plugin string) { } // 加载Flow - if strings.HasPrefix(flow, "fs://") || !strings.Contains(flow, "://") { - root := strings.TrimPrefix(flow, "fs://") + if strings.HasPrefix(app.Flows, "fs://") || !strings.Contains(app.Flows, "://") { + root := strings.TrimPrefix(app.Flows, "fs://") scripts := getAppFilesFS(root, ".json") for _, script := range scripts { gou.LoadFlow(string(script.Content), script.Name) @@ -117,8 +137,8 @@ func LoadApp(api string, flow string, model string, plugin string) { } // 加载Model - if strings.HasPrefix(model, "fs://") || !strings.Contains(model, "://") { - root := strings.TrimPrefix(model, "fs://") + if strings.HasPrefix(app.Models, "fs://") || !strings.Contains(app.Models, "://") { + root := strings.TrimPrefix(app.Models, "fs://") scripts := getAppFilesFS(root, ".json") for _, script := range scripts { gou.LoadModel(string(script.Content), script.Name) @@ -126,13 +146,24 @@ func LoadApp(api string, flow string, model string, plugin string) { } // 加载Plugin - if strings.HasPrefix(plugin, "fs://") || !strings.Contains(plugin, "://") { - root := strings.TrimPrefix(plugin, "fs://") + if strings.HasPrefix(app.Plugins, "fs://") || !strings.Contains(app.Plugins, "://") { + root := strings.TrimPrefix(app.Plugins, "fs://") scripts := getAppPlugins(root, ".so") for _, script := range scripts { gou.LoadPlugin(script.File, script.Name) } } + + // 加载Table + if strings.HasPrefix(app.Tables, "fs://") || !strings.Contains(app.Tables, "://") { + root := strings.TrimPrefix(app.Tables, "fs://") + scripts := getAppFilesFS(root, ".json") + for _, script := range scripts { + // 验证API 加载逻辑 + table.Load(string(script.Content), script.Name) + } + } + } // / getAppPluins 遍历应用目录,读取文件列表 diff --git a/global/load_test.go b/global/load_test.go index 9907e239..d49e5f60 100644 --- a/global/load_test.go +++ b/global/load_test.go @@ -33,6 +33,14 @@ func TestLoadEngineBin(t *testing.T) { // 从文件系统载入应用脚本 func TestLoadAppFS(t *testing.T) { assert.NotPanics(t, func() { - LoadApp(Conf.RootAPI, Conf.RootFLow, Conf.RootModel, Conf.RootPlugin) + LoadApp(AppRoot{ + APIs: Conf.RootAPI, + Flows: Conf.RootFLow, + Models: Conf.RootModel, + Plugins: Conf.RootPlugin, + Tables: Conf.RootTable, + Charts: Conf.RootChart, + Screens: Conf.RootScreen, + }) }) } diff --git a/global/service.go b/global/service.go index a795e5d7..eb92046f 100644 --- a/global/service.go +++ b/global/service.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/yaoapp/gou" + "github.com/yaoapp/xiang/table" ) var shutdown = make(chan bool) @@ -37,7 +38,15 @@ func ServiceStop(onComplete func()) { // WatchChanges 监听配置文件变更 func WatchChanges() { watchEngine(Conf.Path) - watchApp(Conf.RootAPI, Conf.RootFLow, Conf.RootModel, Conf.RootPlugin) + watchApp(AppRoot{ + APIs: Conf.RootAPI, + Flows: Conf.RootFLow, + Models: Conf.RootModel, + Plugins: Conf.RootPlugin, + Tables: Conf.RootTable, + Charts: Conf.RootChart, + Screens: Conf.RootScreen, + }) } // watchEngine 监听引擎目录文件变更 @@ -129,14 +138,92 @@ func watchEngine(from string) { }) } }) + + // 监听 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(api string, flow string, model string, plugin string) { - watchAppAPI(api) - watchAppFlow(flow) - watchAppModel(model) - watchAppPlugin(plugin) +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变更 diff --git a/xiang/tables/user.json b/xiang/tables/user.json index 5b7ef06b..5015cfbe 100644 --- a/xiang/tables/user.json +++ b/xiang/tables/user.json @@ -3,19 +3,7 @@ "version": "1.0.0", "decription": "象传用户", "bind": { - "model": "xiang.user", - "withs": { - "manu": { - "query": { - "select": ["id", "name", "short_name", "status"] - } - }, - "kind": { - "query": { - "select": ["id", "name"] - } - } - } + "model": "xiang.user" }, "apis": {}, "columns": {},