88 lines
2.2 KiB
Go
88 lines
2.2 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"ai-service/internal/model"
|
|
)
|
|
|
|
type dashboardResponse struct {
|
|
At time.Time `json:"at"`
|
|
Summary dashboardSummary `json:"summary"`
|
|
Stats *model.Stats `json:"stats"`
|
|
Providers providersStatusResponse `json:"providers"`
|
|
Infra infraStatusResponse `json:"infra"`
|
|
Jobs []*model.JobSummary `json:"jobs"`
|
|
}
|
|
|
|
type dashboardSummary struct {
|
|
Pending int64 `json:"pending"`
|
|
Running int64 `json:"running"`
|
|
Done int64 `json:"done"`
|
|
Failed int64 `json:"failed"`
|
|
Cancelled int64 `json:"cancelled"`
|
|
Total int64 `json:"total"`
|
|
}
|
|
|
|
func (s *Server) handleDashboard(w http.ResponseWriter, r *http.Request) {
|
|
now := time.Now().UTC()
|
|
ctx, cancel := contextWithTimeout(r, 12*time.Second)
|
|
defer cancel()
|
|
|
|
stats, err := s.store.Stats(ctx)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
jobs, err := s.store.ListJobSummaries(ctx, model.JobFilter{
|
|
Statuses: []string{model.StatusFailed, model.StatusRunning},
|
|
Limit: 40,
|
|
})
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
resp := dashboardResponse{
|
|
At: now,
|
|
Summary: summarizeQueues(stats),
|
|
Stats: stats,
|
|
Providers: providersStatusResponse{
|
|
At: now,
|
|
Providers: []providerStatus{
|
|
s.checkLLM(ctx),
|
|
s.checkWhisperX(ctx),
|
|
s.checkAudioLLM(ctx, "qwen2-audio", s.cfg.QwenAudioBaseURL, s.cfg.QwenAudioAPIKey, s.cfg.QwenAudioModel, s.cfg.QwenAudioTimeout),
|
|
s.checkAudioLLM(ctx, "voxtral-small", s.cfg.VoxtralBaseURL, s.cfg.VoxtralAPIKey, s.cfg.VoxtralModel, s.cfg.VoxtralTimeout),
|
|
},
|
|
},
|
|
Infra: loadInfraSnapshot(r, s.cfg),
|
|
Jobs: jobs,
|
|
}
|
|
writeJSON(w, http.StatusOK, resp)
|
|
}
|
|
|
|
func summarizeQueues(stats *model.Stats) dashboardSummary {
|
|
var out dashboardSummary
|
|
if stats == nil {
|
|
return out
|
|
}
|
|
for _, row := range stats.Queues {
|
|
switch row.Status {
|
|
case model.StatusPending:
|
|
out.Pending += row.Total
|
|
case model.StatusRunning:
|
|
out.Running += row.Total
|
|
case model.StatusDone:
|
|
out.Done += row.Total
|
|
case model.StatusFailed:
|
|
out.Failed += row.Total
|
|
case model.StatusCancelled:
|
|
out.Cancelled += row.Total
|
|
}
|
|
out.Total += row.Total
|
|
}
|
|
return out
|
|
}
|