package api import ( "net/http" "github.com/pulse-lets-go/internal/models" ) // handleRoute — GET /api/route — главный эндпоинт маршрутизации вызова. func (a *API) handleRoute(w http.ResponseWriter, r *http.Request) { a.engine.IncrementRouteRequests() nodeID, score, fallback := a.engine.GetBestNode() // Нет зарегистрированных нод if nodeID == "" { writeJSON(w, http.StatusServiceUnavailable, models.RouteResponse{ Error: "no_nodes_registered", }) return } // Все ноды unhealthy — fallback if fallback || score < 0 { fallbackGW, _ := a.findFallbackGateway() nodes := a.getRouteNodeInfo() writeJSON(w, http.StatusOK, models.RouteResponse{ Fallback: true, SIPGateway: fallbackGW, Reason: "all_nodes_unhealthy", Nodes: nodes, }) return } // Нормальный маршрут gw, ok := a.findBalanceGateway(nodeID) if !ok { writeError(w, http.StatusInternalServerError, "gateway не найден для ноды") return } writeJSON(w, http.StatusOK, models.RouteResponse{ NodeID: nodeID, Score: score, SIPGateway: gw, }) } // findBalanceGateway ищет gateway для balance-транка, привязанного к nodeID. func (a *API) findBalanceGateway(nodeID string) (string, bool) { trunks, err := a.configManager.ReadTrunks() if err != nil { return "", false } for _, t := range trunks { if t.Type == models.TrunkBalance && t.NodeID == nodeID && t.Enabled { return t.Gateway, true } } return "", false } // findFallbackGateway ищет gateway для fallback-транка. func (a *API) findFallbackGateway() (string, bool) { trunks, err := a.configManager.ReadTrunks() if err != nil { return "", false } for _, t := range trunks { if t.Type == models.TrunkFallback && t.Enabled { return t.Gateway, true } } return "", false } // getRouteNodeInfo возвращает список нод с их скорами для ответа маршрутизации. func (a *API) getRouteNodeInfo() []models.RouteNodeInfo { nodes := a.engine.GetAllNodes() result := make([]models.RouteNodeInfo, 0, len(nodes)) for _, n := range nodes { info := models.RouteNodeInfo{ ID: n.NodeID, Score: n.Score, Reason: n.LethalReason, Status: n.Status, } if n.Disabled { info.Status = "disabled" } else if n.IsStale { info.Status = "stale" } else if n.Score < 0 { info.Status = "unhealthy" } else { info.Status = "healthy" } result = append(result, info) } return result }