2025-08-05 10:51:35 +08:00
|
|
|
|
package actions
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
2025-12-26 16:43:08 +08:00
|
|
|
|
"jhman/clients/jd"
|
|
|
|
|
|
"jhman/model"
|
|
|
|
|
|
u "jhman/util"
|
2025-08-05 10:51:35 +08:00
|
|
|
|
"log/slog"
|
2025-12-26 16:43:08 +08:00
|
|
|
|
"os"
|
2025-08-21 15:58:34 +08:00
|
|
|
|
"time"
|
2025-08-19 11:09:58 +08:00
|
|
|
|
|
|
|
|
|
|
"gorm.io/gorm"
|
2025-08-05 10:51:35 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type UpdateArgs struct {
|
|
|
|
|
|
Mock bool
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-11 09:34:13 +08:00
|
|
|
|
func Update(args ...UpdateArgs) error {
|
2025-08-05 10:51:35 +08:00
|
|
|
|
var arg UpdateArgs
|
|
|
|
|
|
if len(args) > 0 {
|
|
|
|
|
|
arg = args[0]
|
|
|
|
|
|
} else {
|
|
|
|
|
|
arg.Mock = false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-19 11:09:58 +08:00
|
|
|
|
return model.DB.Transaction(func(tx *gorm.DB) error {
|
|
|
|
|
|
return update(tx, arg)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func update(tx *gorm.DB, arg UpdateArgs) error {
|
2025-08-21 15:58:34 +08:00
|
|
|
|
var now = time.Now()
|
2025-09-10 18:26:59 +08:00
|
|
|
|
var step = now
|
2025-08-21 15:58:34 +08:00
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
// 获取所有网关
|
2025-08-05 10:51:35 +08:00
|
|
|
|
gateways, err := FindGateways(tx)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("获取所有网关失败:%w", err)
|
|
|
|
|
|
}
|
2025-09-10 18:26:59 +08:00
|
|
|
|
var findGateway = make(map[string]model.Gateway)
|
|
|
|
|
|
for _, gateway := range gateways {
|
|
|
|
|
|
findGateway[gateway.Macaddr] = gateway
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
println(fmt.Sprintf("获取网关:%v", time.Since(step)))
|
|
|
|
|
|
step = time.Now()
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
// 获取所有城市
|
2025-08-05 10:51:35 +08:00
|
|
|
|
cities, err := FindCitiesWithEdgesCount(tx)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("获取所有城市失败:%w", err)
|
|
|
|
|
|
}
|
2025-09-10 18:26:59 +08:00
|
|
|
|
var findCity = make(map[string]model.City)
|
|
|
|
|
|
for _, city := range cities {
|
|
|
|
|
|
findCity[city.Hash] = city
|
2025-08-05 10:51:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
println(fmt.Sprintf("获取城市:%v", time.Since(step)))
|
|
|
|
|
|
step = time.Now()
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
// 获取所有配置
|
|
|
|
|
|
configs, err := FindConfigs(tx)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("获取所有配置失败:%w", err)
|
|
|
|
|
|
}
|
2025-09-11 16:06:14 +08:00
|
|
|
|
|
|
|
|
|
|
println(fmt.Sprintf("获取配置:%v", time.Since(step)))
|
|
|
|
|
|
step = time.Now()
|
|
|
|
|
|
|
|
|
|
|
|
// 查找需要更新的配置
|
|
|
|
|
|
oldConfigs := make(map[model.City][]model.Config)
|
|
|
|
|
|
newConfigs := make(map[model.Gateway][]ConfigInfo)
|
2025-09-23 19:01:49 +08:00
|
|
|
|
for _, gateway := range gateways {
|
|
|
|
|
|
newConfigs[gateway] = make([]ConfigInfo, 250) // 预分配空间,减少扩容
|
|
|
|
|
|
}
|
2025-09-10 18:26:59 +08:00
|
|
|
|
for _, config := range configs {
|
2025-09-11 16:06:14 +08:00
|
|
|
|
city := findCity[config.Cityhash]
|
|
|
|
|
|
gateway := findGateway[config.GatewayMac]
|
|
|
|
|
|
if config.IsChange == 1 {
|
|
|
|
|
|
oldConfigs[city] = append(oldConfigs[city], config)
|
|
|
|
|
|
} else {
|
2025-09-23 19:01:49 +08:00
|
|
|
|
newConfigs[gateway][config.Table-1] = ConfigInfo{
|
2025-09-11 16:06:14 +08:00
|
|
|
|
Change: false,
|
|
|
|
|
|
Remote: jd.EdgeInfo{
|
|
|
|
|
|
Mac: config.EdgeMac,
|
|
|
|
|
|
City: config.Cityhash,
|
|
|
|
|
|
Network: config.Network,
|
|
|
|
|
|
},
|
2025-09-23 19:01:49 +08:00
|
|
|
|
}
|
2025-09-11 16:06:14 +08:00
|
|
|
|
}
|
2025-08-05 10:51:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-11 16:06:14 +08:00
|
|
|
|
println(fmt.Sprintf("查找更新:%v", time.Since(step)))
|
2025-09-10 18:26:59 +08:00
|
|
|
|
step = time.Now()
|
|
|
|
|
|
|
|
|
|
|
|
// 更新网关配置
|
2025-09-11 00:08:11 +08:00
|
|
|
|
var citiesUpdate []model.City
|
|
|
|
|
|
var changesCreate []model.Change
|
2025-09-11 16:06:14 +08:00
|
|
|
|
for city, configs := range oldConfigs {
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
// 如果有需要变更的节点,获取足量新节点
|
2025-09-11 16:06:14 +08:00
|
|
|
|
count := len(configs)
|
2025-08-05 10:51:35 +08:00
|
|
|
|
if count > city.EdgesCount {
|
2025-08-19 11:29:35 +08:00
|
|
|
|
slog.Warn(fmt.Sprintf("城市节点数量不足,跳过本次更新,城市:%s,节点数:%d,网关数:%d", city.Name, city.EdgesCount, count))
|
2025-08-05 10:51:35 +08:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-11 00:08:11 +08:00
|
|
|
|
edges, err := SliceActiveEdges(tx, city.Id, city.Offset, count)
|
2025-08-05 10:51:35 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("查询城市 %s 可用节点失败:%w", city.Name, err)
|
|
|
|
|
|
}
|
2025-08-16 18:38:29 +08:00
|
|
|
|
if len(edges) < count {
|
2025-08-19 11:29:35 +08:00
|
|
|
|
slog.Debug(fmt.Sprintf("城市节点不足,将循环使用节点,城市:%s,节点数:%d,网关数:%d", city.Name, city.EdgesCount, count))
|
2025-08-19 11:09:58 +08:00
|
|
|
|
edges, err = SliceActiveEdges(tx, city.Id, 0, count)
|
2025-08-16 18:38:29 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("查询城市 %s 可用节点失败:%w", city.Name, err)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-11 00:08:11 +08:00
|
|
|
|
citiesUpdate = append(citiesUpdate, model.City{
|
|
|
|
|
|
Id: city.Id,
|
|
|
|
|
|
Offset: edges[len(edges)-1].Id,
|
|
|
|
|
|
})
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
// 分配新节点
|
2025-09-11 16:06:14 +08:00
|
|
|
|
for i, config := range configs {
|
|
|
|
|
|
gateway := findGateway[config.GatewayMac]
|
2025-09-10 18:26:59 +08:00
|
|
|
|
edge := edges[i]
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-11 16:06:14 +08:00
|
|
|
|
slog.Debug(fmt.Sprintf("网关配置变更,网关:%s,旧节点:%s,新节点:%s", gateway.Macaddr, config.EdgeMac, edge.Macaddr))
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-23 19:01:49 +08:00
|
|
|
|
newConfigs[gateway][config.Table-1] = ConfigInfo{
|
2025-09-10 18:26:59 +08:00
|
|
|
|
Change: true,
|
|
|
|
|
|
Remote: jd.EdgeInfo{
|
2025-09-11 16:06:14 +08:00
|
|
|
|
Mac: edge.Macaddr,
|
|
|
|
|
|
City: city.Hash,
|
|
|
|
|
|
Network: config.Network,
|
2025-09-10 18:26:59 +08:00
|
|
|
|
},
|
|
|
|
|
|
Config: model.ConfigUpdate{
|
2025-09-11 16:06:14 +08:00
|
|
|
|
Id: config.Id,
|
2025-09-11 00:08:11 +08:00
|
|
|
|
EdgeMac: u.P(edge.Macaddr),
|
2025-08-05 10:51:35 +08:00
|
|
|
|
IsChange: u.P(0),
|
2025-12-26 16:43:08 +08:00
|
|
|
|
IsOnline: u.P(0),
|
2025-09-10 18:26:59 +08:00
|
|
|
|
},
|
2025-09-23 19:01:49 +08:00
|
|
|
|
}
|
2025-09-11 00:08:11 +08:00
|
|
|
|
changesCreate = append(changesCreate, model.Change{
|
2025-09-10 18:26:59 +08:00
|
|
|
|
Time: now,
|
|
|
|
|
|
CityId: city.Id,
|
|
|
|
|
|
Gateway: gateway.Macaddr,
|
2025-09-11 16:06:14 +08:00
|
|
|
|
OldEdge: config.EdgeMac,
|
2025-09-10 18:26:59 +08:00
|
|
|
|
NewEdge: edge.Macaddr,
|
2026-03-05 15:41:50 +08:00
|
|
|
|
Network: config.Network,
|
|
|
|
|
|
Info: edge.Public,
|
2025-09-10 18:26:59 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-21 15:58:34 +08:00
|
|
|
|
|
2025-09-11 16:06:14 +08:00
|
|
|
|
println(fmt.Sprintf("更新配置:%v", time.Since(step)))
|
2025-09-10 18:26:59 +08:00
|
|
|
|
step = time.Now()
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
// 更新城市偏移量
|
2025-09-11 00:08:11 +08:00
|
|
|
|
err = UpdateCitiesOffset(tx, citiesUpdate)
|
2025-09-10 18:26:59 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("更新城市偏移量失败:%w", err)
|
|
|
|
|
|
}
|
2025-08-21 15:58:34 +08:00
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
println(fmt.Sprintf("更新城市偏移量:%v", time.Since(step)))
|
|
|
|
|
|
step = time.Now()
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
// 记录节点变更
|
2025-12-26 16:43:08 +08:00
|
|
|
|
if os.Getenv("DEBUG") == "true" {
|
|
|
|
|
|
err = RecordChanges(tx, changesCreate)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("记录节点变更失败:%w", err)
|
|
|
|
|
|
}
|
2025-08-05 10:51:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
println(fmt.Sprintf("记录节点变更:%v", time.Since(step)))
|
|
|
|
|
|
step = time.Now()
|
|
|
|
|
|
|
2025-08-05 10:51:35 +08:00
|
|
|
|
// 提交所有网关配置到云端
|
|
|
|
|
|
for gateway, infos := range newConfigs {
|
|
|
|
|
|
edges := make([]jd.EdgeInfo, len(infos))
|
2025-09-10 18:26:59 +08:00
|
|
|
|
configsUpdate := make([]model.ConfigUpdate, 0)
|
|
|
|
|
|
|
|
|
|
|
|
// 统计变更数
|
|
|
|
|
|
change := 0
|
2025-08-05 10:51:35 +08:00
|
|
|
|
for i, info := range infos {
|
2025-09-10 18:26:59 +08:00
|
|
|
|
edges[i] = info.Remote
|
|
|
|
|
|
if info.Change {
|
|
|
|
|
|
configsUpdate = append(configsUpdate, info.Config)
|
2025-08-05 10:51:35 +08:00
|
|
|
|
change++
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-10 18:26:59 +08:00
|
|
|
|
slog.Info(fmt.Sprintf("提交网关配置,网关:%s,变更数:%d", gateway.Macaddr, change))
|
|
|
|
|
|
|
|
|
|
|
|
// 更新配置版本
|
|
|
|
|
|
err = AppendGatewayConfigVersion(tx, gateway.Id)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("更新网关 %s 配置版本失败:%w", gateway.Macaddr, err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新本地配置
|
|
|
|
|
|
err = UpdateConfigs(tx, configsUpdate)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("更新网关 %s 本地配置失败:%w", gateway.Macaddr, err)
|
|
|
|
|
|
}
|
2025-08-05 10:51:35 +08:00
|
|
|
|
|
2025-09-23 19:01:49 +08:00
|
|
|
|
// 记录提交配置
|
2025-12-26 16:43:08 +08:00
|
|
|
|
if os.Getenv("DEBUG") == "true" {
|
|
|
|
|
|
err = RecordSubmit(now, gateway, edges)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("记录网关 %s 提交配置失败:%w", gateway.Macaddr, err)
|
|
|
|
|
|
}
|
2025-09-23 19:01:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-05 10:51:35 +08:00
|
|
|
|
// 提交配置到云端:配置版本 gateway.ConfigVersion
|
2025-08-19 17:25:01 +08:00
|
|
|
|
if !arg.Mock {
|
2025-08-05 10:51:35 +08:00
|
|
|
|
err := jd.GatewayConfigSet(gateway.ConfigVersion, gateway.Macaddr, edges)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return fmt.Errorf("配置网关 %s 失败:%w", gateway.Macaddr, err)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 18:26:59 +08:00
|
|
|
|
println(fmt.Sprintf("提交配置:%v", time.Since(step)))
|
|
|
|
|
|
|
|
|
|
|
|
println(fmt.Sprintf("总耗时:%v", time.Since(now)))
|
2025-09-11 16:06:14 +08:00
|
|
|
|
println(fmt.Sprint("更新总数:", len(changesCreate)))
|
|
|
|
|
|
|
2025-08-05 10:51:35 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2025-09-10 18:26:59 +08:00
|
|
|
|
|
|
|
|
|
|
type ConfigInfo struct {
|
|
|
|
|
|
Change bool
|
|
|
|
|
|
Remote jd.EdgeInfo
|
|
|
|
|
|
Config model.ConfigUpdate
|
|
|
|
|
|
}
|