Files
pangolin/server
wangjia a7ae7156f4 fix(scheduler): 修复 #15H 两个 flaky leader-election 测试的根因
TestGracefulShutdown(真 bug):runLoop 在 SetNX 获取 leader 锁后、进入
runLeaderLoop(其 defer 负责释放)之前,若 ctx 恰好在此刻 cancel,
`if ctx.Err() != nil { return }` 会丢弃已获取的 key 而不释放 →
关停后 leader 键残留(DEL 从未执行)。早 cancel 时三个 loop 各自命中此竞态,
故残留的键不固定。修复:将 ctx.Err() 早退限定在 SetNX 出错(未获取)的分支;
一旦获取成功就必定进入 runLeaderLoop,由其 defer 保证释放。

TestFollowerTakeover(测试设计竞态):测试同时启动 leader/follower 两实例却
假定名为 "leader" 的实例赢得选举——而选举是先到先得,"follower" 可能先抢到
detect 锁,导致 engLeader 永不 tick("leader never ticked")。修复:先单独
启动 leader 并等其 tick(确认占锁),再启动 follower,消除选举非确定性。

两修复均移除原 t.Skip,恢复测试。验证:各自隔离 12/12 通过、scheduler 全包
10/10、全量 go test ./... 3 连跑 0 失败、scheduler -race 无数据竞争。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 07:06:48 +08:00
..

Pangolin Server

Go 后端控制面,负责账户、套餐、激活码、设备与节点目录管理。架构详见 ../design/server/ARCHITECTURE.md

目录结构

server/
├── cmd/
│   ├── server/          # HTTP 服务入口(chi router/healthz/v1 挂载归 1d
│   └── migrate/         # 数据库迁移 CLI 入口(实现归 1e)
├── internal/
│   ├── config/          # 配置加载(env + 文件,归 1e)
│   ├── store/           # 数据库访问层 Postgres(归 1e
│   ├── apierr/          # 统一错误体 {code, message_zh, message_en}(归 1f
│   ├── idgen/           # UUID + Crockford Base32 激活码(归 1f
│   ├── auth/            # 验证码、argon2id、JWT RS256(归 1c/1d
│   ├── codes/           # 激活码批次、兑换、审计(归 1d)
│   ├── devices/         # 设备管理(归 1d)
│   ├── nodes/           # 节点目录、connect/disconnect(归 1d
│   ├── usage/           # 用量统计(归 1d)
│   └── admin/           # 内部管理端(归 1d)
├── Makefile
├── go.mod
├── go.sum
├── tools.go             # //go:build tools — 锁定 oapi-codegen / migrate 版本
└── .golangci.yml

常用命令

make build        # go build ./...
make test         # go test ./...
make vet          # go vet ./...
make lint         # golangci-lint run ./...
make generate     # oapi-codegen 代码生成(1d 填充)
make migrate-up   # 执行迁移(1e 填充)
make migrate-down # 回滚迁移(1e 填充)

# 快速启动(默认监听 :8080
go run ./cmd/server
# 指定地址
go run ./cmd/server -addr :9090
# 或通过环境变量
ADDR=:9090 go run ./cmd/server