feat: publish standalone worker
Separate worker packaging and service lifecycle from the control plane.
Этот коммит содержится в:
84
internal/webapp/handlers_overview.go
Обычный файл
84
internal/webapp/handlers_overview.go
Обычный файл
@@ -0,0 +1,84 @@
|
||||
package webapp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// handleOverview is the landing page after login. Phase 1 shows the
|
||||
// worker status, recent results counts, and a tail of the worker
|
||||
// log buffer. The data shape will grow in later phases as the
|
||||
// heartbeat inventory and 24h result counts come online.
|
||||
func (s *Server) handleOverview(w http.ResponseWriter, r *http.Request) {
|
||||
writeNoStore(w)
|
||||
sess, _ := sessionFromContext(r.Context())
|
||||
snap, snapAt := s.metrics.Last()
|
||||
data := overviewPageData{
|
||||
basePageData: s.newBasePage(r, "Overview", sess),
|
||||
WorkerID: workerIDOrDash(s.deps.Runner),
|
||||
RegionCode: regionOrDash(s.deps.Runner),
|
||||
WorkerState: workerState(s.deps.Runner, s.deps.StartedAt),
|
||||
LastAckAt: lastAckOrZero(s.deps.Runner),
|
||||
StartedAt: s.deps.StartedAt,
|
||||
Snapshot: snap,
|
||||
SnapshotAt: snapAt,
|
||||
DiscoveredCount: len(s.inventory.Snapshot()),
|
||||
ResultCount: len(s.deps.Runner.RecentResults(1000)),
|
||||
NotifCount: len(s.deps.Runner.RecentNotifications(1000)),
|
||||
LogTail: s.logBuffer.Tail(20),
|
||||
}
|
||||
if err := s.templates.Execute(w, "overview.html", data); err != nil {
|
||||
s.deps.Logger.Printf("render overview: %v", err)
|
||||
http.Error(w, "template error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func workerIDOrDash(v WorkerView) string {
|
||||
if v == nil {
|
||||
return "—"
|
||||
}
|
||||
return v.WorkerID()
|
||||
}
|
||||
|
||||
func regionOrDash(v WorkerView) string {
|
||||
if v == nil {
|
||||
return "—"
|
||||
}
|
||||
return v.RegionCode()
|
||||
}
|
||||
|
||||
func workerState(v WorkerView, startedAt time.Time) string {
|
||||
if v == nil {
|
||||
return "—"
|
||||
}
|
||||
if last := v.LastHeartbeatAck(); !last.IsZero() && last.After(startedAt) {
|
||||
return "connected"
|
||||
}
|
||||
return "starting"
|
||||
}
|
||||
|
||||
func lastAckOrZero(v WorkerView) time.Time {
|
||||
if v == nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return v.LastHeartbeatAck()
|
||||
}
|
||||
|
||||
// overviewPageData is the data backing overview.html.
|
||||
type overviewPageData struct {
|
||||
basePageData
|
||||
WorkerID string
|
||||
RegionCode string
|
||||
WorkerState string
|
||||
LastAckAt time.Time
|
||||
StartedAt time.Time
|
||||
Snapshot Snapshot
|
||||
SnapshotAt time.Time
|
||||
DiscoveredCount int
|
||||
ResultCount int
|
||||
NotifCount int
|
||||
LogTail []string
|
||||
}
|
||||
|
||||
var _ = strings.TrimSpace
|
||||
Ссылка в новой задаче
Block a user