83 lines
2.3 KiB
Go
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
|
|
}
|