Files
silo-server/internal/api/handlers/system.go
T

83 lines
2.3 KiB
Go

package handlers
import (
"context"
"encoding/json"
"fmt"
"log/slog"
"net/http"
"time"
"github.com/Silo-Server/silo-server/internal/buildinfo"
"github.com/Silo-Server/silo-server/internal/nodepool"
"github.com/Silo-Server/silo-server/internal/playback"
)
// SystemHandler serves read-only system inspection endpoints.
type SystemHandler struct {
transcodePool *nodepool.TranscodePool
jwtSecret string
buildInfo buildinfo.Info
}
// NewSystemHandler creates a SystemHandler.
func NewSystemHandler(transcodePool *nodepool.TranscodePool, jwtSecret string) *SystemHandler {
return &SystemHandler{
transcodePool: transcodePool,
jwtSecret: jwtSecret,
buildInfo: buildinfo.Current(),
}
}
// HandleHWAccel handles GET /admin/system/hw-accel.
// When transcode nodes are registered it delegates to the first healthy node.
// Otherwise it probes the local host.
func (h *SystemHandler) HandleHWAccel(w http.ResponseWriter, r *http.Request) {
if h.transcodePool != nil {
if node := h.transcodePool.Acquire(); node != nil {
info, err := h.fetchRemoteHWAccel(r.Context(), node)
if err == nil {
writeJSON(w, http.StatusOK, info)
return
}
slog.Warn("hw-accel: remote node probe failed, falling back to local",
"node", node.URL, "error", err)
}
}
info := playback.DetectHWAccel()
writeJSON(w, http.StatusOK, info)
}
// HandleBuildInfo handles GET /admin/system/build.
func (h *SystemHandler) HandleBuildInfo(w http.ResponseWriter, _ *http.Request) {
writeJSON(w, http.StatusOK, h.buildInfo)
}
func (h *SystemHandler) fetchRemoteHWAccel(ctx context.Context, node *nodepool.Node) (playback.HWAccelInfo, error) {
client := &http.Client{Timeout: 5 * time.Second}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, node.URL+"/hw-capabilities", nil)
if err != nil {
return playback.HWAccelInfo{}, err
}
req.Header.Set("Authorization", "Bearer "+h.jwtSecret)
resp, err := client.Do(req)
if err != nil {
return playback.HWAccelInfo{}, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return playback.HWAccelInfo{}, fmt.Errorf("node returned %d", resp.StatusCode)
}
var info playback.HWAccelInfo
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
return playback.HWAccelInfo{}, err
}
info.Source = "transcode_node"
info.NodeURL = node.URL
return info, nil
}