package handlers import ( "errors" "gorm.io/gen/field" "gorm.io/gorm" "log/slog" "platform/pkg/u" "platform/web/auth" edge2 "platform/web/domains/edge" proxy2 "platform/web/domains/proxy" g "platform/web/globals" m "platform/web/models" q "platform/web/queries" s "platform/web/services" "github.com/gofiber/fiber/v2" ) type RegisterEdgeReq struct { Name string `json:"name" validate:"required"` Version int `json:"version" validate:"required"` } type RegisterEdgeResp struct { Id int32 `json:"id"` Host string `json:"host"` } func AssignEdge(c *fiber.Ctx) (err error) { // 验证请求参数 var req = new(RegisterEdgeReq) err = g.Validator.Validate(c, req) if err != nil { return err } // 全局锁,防止并发注册 var mutex = g.Redsync.NewMutex("edge:discovery") if err := mutex.Lock(); err != nil { return errors.New("服务繁忙,请稍后重试") } defer func() { if ok, err := mutex.Unlock(); err != nil { slog.Error("解锁失败", slog.Bool("ok", ok), slog.Any("err", err)) } }() // 检查节点 var fwd *m.Proxy var edge *m.Edge edge, err = q.Edge. Where(q.Edge.Name.Eq(req.Name)). Take() if errors.Is(err, gorm.ErrRecordNotFound) { // 挑选合适的转发服务 fwd, err = q.Proxy. LeftJoin(q.Edge, q.Edge.ProxyID.EqCol(q.Proxy.ID), q.Edge.Status.Eq(1)). Select(q.Proxy.ALL, q.Edge.ALL.Count().As("count")). Where(q.Proxy.Type.Eq(int32(proxy2.TypeSelfHosted))). Group(q.Proxy.ID). Order(field.NewField("", "count").Desc()). First() if err != nil { return err } // 保存节点信息 edge = &m.Edge{ Name: req.Name, Version: int32(req.Version), Type: int32(edge2.TypeSelfHosted), ProxyID: &fwd.ID, } err = q.Edge.Create(edge) if err != nil { return err } } else if err == nil { // 获取已配置的转发服务 fwd, err = q.Proxy. Where(q.Proxy.ID.Eq(*edge.ProxyID)). Take() if err != nil { return err } // 节点已存在,更新版本号 if edge.Version < int32(req.Version) { _, err = q.Edge. Where(q.Edge.ID.Eq(edge.ID)). UpdateSimple(q.Edge.Version.Value(int32(req.Version))) if err != nil { return err } } } else { return err } // 返回服务地址 return c.JSON(RegisterEdgeResp{ Id: edge.ID, Host: fwd.Host, }) } type AllEdgesAvailableReq struct { s.EdgeFilter Count int `json:"count"` } type AllEdgesAvailableRespItem struct { Ip string `json:"ip"` // 节点地址 Port int32 `json:"port"` // 代理服务端口 Isp string `json:"isp"` // 运营商 Prov string `json:"prov"` // 省份 City string `json:"city"` // 城市 Status int32 `json:"status"` // 节点状态:0-离线,1-正常 } func AllEdgesAvailable(c *fiber.Ctx) (err error) { // 检查权限 _, err = auth.NewProtect(c).Payload(auth.PayloadInternalServer).Do() if err != nil { return err } // 验证请求参数 var req = new(AllEdgesAvailableReq) err = g.Validator.Validate(c, req) if err != nil { return err } // 获取可用的转发服务 infos, err := s.Edge.AllEdges(req.Count, req.EdgeFilter) if err != nil { return err } // 返回结果 var edges = make([]AllEdgesAvailableRespItem, len(infos)) for i, info := range infos { edges[i] = AllEdgesAvailableRespItem{ Ip: info.Host, Port: u.Z(info.ProxyPort), Isp: edge2.ISP(info.Isp).String(), Prov: info.Prov, City: info.City, Status: info.Status, } } return c.JSON(edges) }