Three-tier routing cache (ESL global -> file -> HTTP) eliminates HTTP
from call path for 2500-5000 concurrent calls. Lua reads cached route
in ~0.1us instead of blocking on api:execute('curl', ...).
Engine fixes:
- recalcBestLocked now skips stale nodes (was 5 min bug -> now ~10-15s)
- PickNodeForCall action_type='node' checks staleness for consistency
- onMetric callback pushes cache on every metric (no ticker delay)
Config:
- stale_threshold_sec default 20 -> 10 (industry standard)
- contrib/ included in Makefile deploy target
- route.lua paths updated for /opt/pulse-lets-go
55 lines
1.5 KiB
Go
55 lines
1.5 KiB
Go
package api
|
||
|
||
import (
|
||
"net/http"
|
||
|
||
"github.com/pulse-lets-go/internal/models"
|
||
)
|
||
|
||
// handleGetNodes — GET /api/nodes — список всех нод с текущими score.
|
||
func (a *API) handleGetNodes(w http.ResponseWriter, r *http.Request) {
|
||
nodes := a.engine.GetAllNodes()
|
||
writeJSON(w, http.StatusOK, nodes)
|
||
}
|
||
|
||
// handleGetNodeMetrics — GET /api/nodes/{id}/metrics — история метрик ноды из ring buffer.
|
||
func (a *API) handleGetNodeMetrics(w http.ResponseWriter, r *http.Request) {
|
||
nodeID := r.PathValue("id")
|
||
if nodeID == "" {
|
||
writeError(w, http.StatusBadRequest, "не указан id ноды")
|
||
return
|
||
}
|
||
|
||
snapshots := a.engine.GetNodeHistory(nodeID)
|
||
writeJSON(w, http.StatusOK, map[string]interface{}{
|
||
"node_id": nodeID,
|
||
"snapshots": snapshots,
|
||
"count": len(snapshots),
|
||
})
|
||
}
|
||
|
||
// handleToggleNode — PUT /api/nodes/{id}/toggle — включение/выключение ноды.
|
||
func (a *API) handleToggleNode(w http.ResponseWriter, r *http.Request) {
|
||
nodeID := r.PathValue("id")
|
||
if nodeID == "" {
|
||
writeError(w, http.StatusBadRequest, "не указан id ноды")
|
||
return
|
||
}
|
||
|
||
var req models.ToggleNodeRequest
|
||
if err := decodeJSON(r, &req); err != nil {
|
||
writeError(w, http.StatusBadRequest, "некорректный JSON")
|
||
return
|
||
}
|
||
|
||
if err := a.engine.ToggleNode(nodeID, req.Disabled, req.Reason); err != nil {
|
||
writeError(w, http.StatusNotFound, err.Error())
|
||
return
|
||
}
|
||
|
||
a.PushRouteCache()
|
||
|
||
info, _ := a.engine.GetNodeInfo(nodeID)
|
||
writeJSON(w, http.StatusOK, info)
|
||
}
|