diff --git a/.zed/debug.json b/.zed/debug.json new file mode 100644 index 0000000..f6c8009 --- /dev/null +++ b/.zed/debug.json @@ -0,0 +1,13 @@ +// Project-local debug tasks +// +// For more documentation on how to configure debug tasks, +// see: https://zed.dev/docs/debugger +[ + { + "label": "dev", + "adapter": "Delve", + "request": "launch", + "program": "./cmd/web/main.go", + "mode": "debug", + }, +] diff --git a/README.md b/README.md index f3a6684..fcca1b0 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ ## TODO 此实现目前并不是完全并发安全的: + - 目前事务等级没有对 cityhash 表的 offset 字段做防丢失,并发操作可能会出问题 +考虑把命令行接口改为 web 接口 + ### 统一节点调度 节点上下线: @@ -24,7 +27,22 @@ util/ 工具类 scripts/ shell 脚本 ``` ---- +## 使用方式 + +此项目在本地运行,其编译产物放在服务器运行 + +1. 在项目根目录下运行 `./deploy.ps1`,或直接复制脚本中的命令,编译出执行程序并上传到服务器 +2. (可选)可以把 `update.sh` 和 `rollback.sh` 也上传到服务器,方便更新和回滚 +3. (可选)可以在服务器将编译出的 cli 可执行文件链接到 /bin 下以实现全局执行 + +cli 有三个命令: +- `cli sync` 是同步城市节点 +- `cli update` 是更新网关配置 +- `cli clear` 是清空网关配置 + +> 三个命令对应于代码中 actions/ 目录下三个同名文件 + +## 逻辑梳理 ``` @@ -33,12 +51,12 @@ scripts/ shell 脚本 遍历配置[网关][配置] 如果无需更新直接放入新配置 如果需要更新,放入城市更新统计 - + 统计[城市][配置] 遍历城市 取到新节点 遍历需要更新的配置: 根据配置放入指定槽位[网关][配置] - + 新配置[网关][配置] -``` \ No newline at end of file +``` diff --git a/deploy.ps1 b/deploy.ps1 index b195802..2e68170 100644 --- a/deploy.ps1 +++ b/deploy.ps1 @@ -1,3 +1,3 @@ -$env:GOOS="linux"; $env:GOARCH="amd64"; $env:CGO_ENABLED=0; go build -o dist/zz main.go +$env:GOOS="linux"; $env:GOARCH="amd64"; $env:CGO_ENABLED=0; go build -o dist/zz ./cmd/clt/main.go -scp ./dist/zz wyk@43.226.58.254:~/zz/cli.new \ No newline at end of file +scp ./dist/zz wyk@43.226.58.254:~/zz/cli.new diff --git a/main.go b/main.go deleted file mode 100644 index 3247744..0000000 --- a/main.go +++ /dev/null @@ -1,107 +0,0 @@ -package main - -import ( - "fmt" - "jhman/actions" - "jhman/clients" - "jhman/model" - "log/slog" - "os" - "path/filepath" - "slices" - "strings" - - "github.com/joho/godotenv" - slogjournal "github.com/systemd/slog-journal" -) - -func main() { - - // 初始化环境 - slog.Debug("初始化环境变量") - ex, err := os.Executable() - if err != nil { - panic(err) - } - exPath := filepath.Dir(ex) - file := filepath.Join(exPath, ".env") - println("加载环境变量文件:", file) - err = godotenv.Load(file) - if err != nil { - slog.Error(fmt.Errorf("初始化变量失败:%w", err).Error()) - } - - // 初始化日志 - handler, err := slogjournal.NewHandler(&slogjournal.Options{ - ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { - a.Key = strings.ToUpper(a.Key) - a.Key = strings.ReplaceAll(a.Key, "-", "_") - return a - }, - }) - slog.SetDefault(slog.New(handler)) - - // 初始化数据库和 Redis - model.Init() - defer model.Close() - - clients.InitRedis() - defer clients.CloseRedis() - - // 执行命令 - if len(os.Args) < 2 { - println("缺少命令参数") - return - } - switch os.Args[1] { - - // 同步城市节点 - case "sync": - err := actions.Sync() - if err != nil { - slog.Error(fmt.Sprintf("同步城市节点数据失败:%s", err.Error())) - } else { - slog.Info("同步城市节点数据成功") - } - return - - // 更新网关 - case "update": - var args actions.UpdateArgs - if len(os.Args) >= 3 { - if slices.Contains(os.Args, "--mock") { - args.Mock = true - } - } - - err := actions.Update(args) - if err != nil { - slog.Error(fmt.Sprintf("更新节点失败:%s", err.Error())) - } else { - slog.Info("更新节点成功") - } - return - - // 清空网关 - case "clear": - err := actions.Clear() - if err != nil { - slog.Error(fmt.Sprintf("清空节点失败:%s", err.Error())) - } else { - slog.Info("清空节点成功") - } - return - - // 新增混拨配置(临时) - case "gen-mix": - err := actions.GenConfig(model.DB) - if err != nil { - slog.Error(fmt.Sprintf("生成混拨配置失败:%s", err.Error())) - } else { - slog.Info("生成混拨配置成功") - } - return - } - - println("请输入正确的命令参数") -} diff --git a/web/web.go b/web/web.go new file mode 100644 index 0000000..8f7e437 --- /dev/null +++ b/web/web.go @@ -0,0 +1,57 @@ +package web + +import ( + "context" + "log/slog" + "net/http" + "os" + "os/signal" +) + +func Start() { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) + defer cancel() + + // 初始化数据库和 Redis + // model.Init() + // defer model.Close() + + // clients.InitRedis() + // defer clients.CloseRedis() + + // 测试 + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Hello, World!")) + }) + + // 同步节点 + http.HandleFunc("/sync", func(w http.ResponseWriter, r *http.Request) { + + }) + + // 更新节点 + http.HandleFunc("/update", func(w http.ResponseWriter, r *http.Request) { + + }) + + // 标记上线 + http.HandleFunc("/up", func(w http.ResponseWriter, r *http.Request) { + + }) + + // 标记下线 + http.HandleFunc("/down", func(w http.ResponseWriter, r *http.Request) { + + }) + + // 启动服务 + server := http.Server{Addr: ":8080"} + go func() { + <-ctx.Done() + server.Shutdown(ctx) + }() + + if err := server.ListenAndServe(); err != nil { + slog.Error("启动服务失败", "error", err) + } +}