更新文档

This commit is contained in:
2026-02-26 16:10:17 +08:00
parent 54c2903c75
commit 539477de4b
5 changed files with 94 additions and 113 deletions

13
.zed/debug.json Normal file
View File

@@ -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",
},
]

View File

@@ -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 脚本
遍历配置[网关][配置]
如果无需更新直接放入新配置
如果需要更新,放入城市更新统计
统计[城市][配置]
遍历城市
取到新节点
遍历需要更新的配置:
根据配置放入指定槽位[网关][配置]
新配置[网关][配置]
```
```

View File

@@ -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
scp ./dist/zz wyk@43.226.58.254:~/zz/cli.new

107
main.go
View File

@@ -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("请输入正确的命令参数")
}

57
web/web.go Normal file
View File

@@ -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)
}
}