Maksim Totmin 78785e54e1 feat: production-grade routing cache + stale detection fixes
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
2026-06-25 22:23:16 +07:00

55 lines
1.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}