Route report projections through prepared identity

This commit is contained in:
2026-08-13 02:00:18 +00:00
parent e2dd8d0e29
commit 360c665a3e
15 changed files with 163 additions and 253 deletions

View File

@@ -9,7 +9,9 @@ import (
"gitea.maximumdirect.net/eric/weatherreporter/internal/weatherdata"
)
type Metadata struct {
// PreparedIdentity is the single prepared authority for report identity,
// timing, configuration context, and source warnings.
type PreparedIdentity struct {
RunID string `json:"runId"`
ReportID report.ID `json:"reportId"`
Variant string `json:"variant,omitempty"`
@@ -21,24 +23,7 @@ type Metadata struct {
Location *LocationContext `json:"location,omitempty"`
SourceLocationID string `json:"sourceLocationId,omitempty"`
SourceLocation string `json:"sourceLocation,omitempty"`
Sources []SourceMetadata `json:"sources,omitempty"`
SourceWarnings []weatherdata.SourceWarning `json:"sourceWarnings,omitempty"`
Alerts *AlertStatus `json:"alerts,omitempty"`
}
// PreparedIdentity is the single prepared authority for report identity,
// timing, configuration context, and source warnings.
type PreparedIdentity struct {
RunID string `json:"runId"`
ReportID report.ID `json:"reportId"`
Variant string `json:"variant,omitempty"`
PromptID string `json:"promptId"`
GeneratedAt time.Time `json:"generatedAt"`
Units string `json:"units"`
Timezone string `json:"timezone"`
ValidPeriod timeutil.Period `json:"validPeriod"`
Location *LocationContext `json:"location,omitempty"`
SourceWarnings []weatherdata.SourceWarning `json:"sourceWarnings,omitempty"`
}
type LocationContext struct {
@@ -48,24 +33,6 @@ type LocationContext struct {
Timezone string `json:"timezone,omitempty"`
}
type SourceMetadata struct {
Name string `json:"name"`
Endpoint string `json:"endpoint,omitempty"`
FetchedAt time.Time `json:"fetchedAt"`
IssuedAt *time.Time `json:"issuedAt,omitempty"`
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
DataSHA256 string `json:"dataSha256,omitempty"`
Missing bool `json:"missing,omitempty"`
Warnings []weatherdata.SourceWarning `json:"warnings,omitempty"`
}
type AlertStatus struct {
Checked bool `json:"checked"`
ActiveCount int `json:"activeCount"`
RelevantCount int `json:"relevantCount"`
Missing bool `json:"missing,omitempty"`
}
type BuildContext struct {
Resolved report.Resolved
Bundle *weatherdata.Bundle
@@ -76,37 +43,20 @@ type BuildContext struct {
func BuildPreparedIdentity(ctx BuildContext) PreparedIdentity {
metadata := ctx.Resolved.Metadata()
sourceLocationID, sourceLocation := sourceLocation(ctx.Bundle)
return PreparedIdentity{
RunID: metadata.RunID,
ReportID: metadata.ReportID,
Variant: variantForReport(metadata.ReportID),
PromptID: metadata.PromptID,
GeneratedAt: metadata.GeneratedAt,
Units: ctx.Units,
Timezone: ctx.Timezone,
ValidPeriod: metadata.ValidPeriod,
Location: copyLocation(ctx.Location),
SourceWarnings: append([]weatherdata.SourceWarning(nil), sourceWarnings(ctx.Bundle)...),
}
}
func BuildMetadata(identity PreparedIdentity, bundle *weatherdata.Bundle) Metadata {
sourceLocationID, sourceLocation := sourceLocation(bundle)
return Metadata{
RunID: identity.RunID,
ReportID: identity.ReportID,
Variant: identity.Variant,
PromptID: identity.PromptID,
GeneratedAt: identity.GeneratedAt,
Units: identity.Units,
Timezone: identity.Timezone,
ValidPeriod: identity.ValidPeriod,
Location: copyLocation(identity.Location),
RunID: metadata.RunID,
ReportID: metadata.ReportID,
Variant: variantForReport(metadata.ReportID),
PromptID: metadata.PromptID,
GeneratedAt: metadata.GeneratedAt,
Units: ctx.Units,
Timezone: ctx.Timezone,
ValidPeriod: metadata.ValidPeriod,
Location: copyLocation(ctx.Location),
SourceLocationID: sourceLocationID,
SourceLocation: sourceLocation,
Sources: sourceMetadata(bundle),
SourceWarnings: append([]weatherdata.SourceWarning(nil), identity.SourceWarnings...),
Alerts: alertStatus(bundle),
SourceWarnings: append([]weatherdata.SourceWarning(nil), sourceWarnings(ctx.Bundle)...),
}
}
@@ -165,26 +115,6 @@ func sourceLocation(bundle *weatherdata.Bundle) (string, string) {
return "", ""
}
func sourceMetadata(bundle *weatherdata.Bundle) []SourceMetadata {
if bundle == nil {
return nil
}
out := make([]SourceMetadata, 0, len(bundle.Sources))
for _, source := range bundle.Sources {
out = append(out, SourceMetadata{
Name: source.Name,
Endpoint: source.Endpoint,
FetchedAt: source.FetchedAt,
IssuedAt: source.IssuedAt,
UpdatedAt: source.UpdatedAt,
DataSHA256: source.DataSHA256,
Missing: source.Missing,
Warnings: source.Warnings,
})
}
return out
}
func sourceWarnings(bundle *weatherdata.Bundle) []weatherdata.SourceWarning {
if bundle == nil {
return nil
@@ -192,27 +122,6 @@ func sourceWarnings(bundle *weatherdata.Bundle) []weatherdata.SourceWarning {
return bundle.Warnings
}
func alertStatus(bundle *weatherdata.Bundle) *AlertStatus {
if bundle == nil {
return nil
}
status := &AlertStatus{}
if bundle.Alerts != nil {
status.Checked = true
status.ActiveCount = len(bundle.Alerts.Alerts)
}
for _, source := range bundle.Sources {
if source.Name == "alerts" && source.Missing {
status.Missing = true
break
}
}
if !status.Checked && !status.Missing {
return nil
}
return status
}
func variantForReport(id report.ID) string {
switch id {
case report.Daily, report.Today: