mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-07 11:54:59 -04:00
Backend-only re-cut of the #76 availability work onto main, stacked on the canonical Weekend Context API. Adds request-scoped freshness reporting so aggregate responses cannot report fresh when a component is stale, plus local-first driver summary resolution and cache/pacing truth. The frontend half of #76 is deliberately excluded: it is built on the Weekend shell that failed owner review, including the full-width Partial banner treatment. Availability presentation is re-cut with the shell in #89. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
78 lines
2.4 KiB
Go
78 lines
2.4 KiB
Go
package web
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/AmanTahiliani/box-box/internal/live"
|
|
"github.com/AmanTahiliani/box-box/internal/query"
|
|
)
|
|
|
|
func (s *Server) handleWeekendContext(w http.ResponseWriter, _ *http.Request) {
|
|
if !s.hasLocalQuery() {
|
|
markDataResponse(w, "none", "limited")
|
|
writeJSON(w, query.WeekendContext{TemporalState: query.TemporalNoSeason})
|
|
return
|
|
}
|
|
|
|
state := s.hub.State()
|
|
evidence := query.LiveEvidence{}
|
|
if state.IsLive && state.Data != nil {
|
|
evidence = liveEvidence(state.Data, true, false)
|
|
} else if state.LastSnapshot != nil && terminalSessionStatus(state.LastSnapshot.SessionStatus) {
|
|
evidence = liveEvidence(state.LastSnapshot, false, true)
|
|
if state.LastSnapshotAt != nil {
|
|
evidence.ObservedAt = *state.LastSnapshotAt
|
|
}
|
|
}
|
|
context, err := s.query.ResolveWeekendContext(evidence)
|
|
if err != nil {
|
|
writeError(w, err, http.StatusInternalServerError, false)
|
|
return
|
|
}
|
|
if focus := focusedContextSession(context); focus != nil {
|
|
markDataResponse(w, focus.Availability.Source, focus.Availability.Freshness)
|
|
} else {
|
|
markDataResponse(w, "none", "limited")
|
|
}
|
|
writeJSON(w, context)
|
|
}
|
|
|
|
// focusedContextSession selects the session whose state the Weekend shell is
|
|
// presenting. An older terminal/default session must never override an
|
|
// upcoming focus session's metadata.
|
|
func focusedContextSession(context query.WeekendContext) *query.ContextSession {
|
|
if context.ActiveSession != nil {
|
|
return context.ActiveSession
|
|
}
|
|
if context.FocusMeeting == nil {
|
|
return nil
|
|
}
|
|
focusKey := context.FocusMeeting.MeetingKey
|
|
for _, ref := range []*query.ContextSession{context.NextSession, context.PreviousCompletedSession, context.DefaultAnalysisSession} {
|
|
if ref != nil && ref.Meeting != nil && ref.Meeting.MeetingKey == focusKey {
|
|
return ref
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func liveEvidence(data *live.LiveStreamData, active, final bool) query.LiveEvidence {
|
|
return query.LiveEvidence{Active: active, Final: final, MeetingName: data.Session.MeetingName, CircuitName: data.Session.CircuitName, SessionName: data.Session.SessionName, SessionType: data.Session.SessionType}
|
|
}
|
|
|
|
func terminalSessionStatus(status string) bool {
|
|
normalized := strings.ToLower(strings.Map(func(r rune) rune {
|
|
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
|
|
return r
|
|
}
|
|
return -1
|
|
}, status))
|
|
switch normalized {
|
|
case "finished", "finalised", "finalized", "ended", "aborted":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|