// alerts_read.go executes alert-run, alerts, and reference queries. // Layer: adapters/outbound/postgres alerts feature. package postgres import ( "context" "database/sql" "errors" "fmt" "gitea.maximumdirect.net/ejr/weatherfeeder/model" ) func (r *Repository) LatestAlertRun(ctx context.Context) (*model.WeatherAlertRun, error) { if r == nil || r.db == nil { return nil, fmt.Errorf("postgres repository is not configured") } var row alertRunParentRow err := r.db.QueryRowContext(ctx, queryLatestAlertRun).Scan( &row.EventID, &row.LocationID, &row.LocationName, &row.AsOf, &row.Latitude, &row.Longitude, ) if errors.Is(err, sql.ErrNoRows) { return nil, nil } if err != nil { return nil, fmt.Errorf("query latest alert run: %w", err) } run := mapAlertRunParentRow(row) alerts, err := r.loadAlerts(ctx, row.EventID) if err != nil { return nil, err } run.Alerts = alerts return &run, nil } func (r *Repository) loadAlerts(ctx context.Context, eventID string) ([]model.WeatherAlert, error) { alertsRows, err := r.db.QueryContext(ctx, queryAlerts, eventID) if err != nil { return nil, fmt.Errorf("query alerts: %w", err) } defer alertsRows.Close() indexedAlerts := make([]indexedAlert, 0) for alertsRows.Next() { var row alertRow if err := alertsRows.Scan( &row.AlertIndex, &row.AlertID, &row.Event, &row.Headline, &row.Severity, &row.Urgency, &row.Certainty, &row.Status, &row.MessageType, &row.Category, &row.Response, &row.Description, &row.Instruction, &row.Sent, &row.Effective, &row.Onset, &row.Expires, &row.AreaDescription, &row.SenderName, ); err != nil { return nil, fmt.Errorf("scan alerts row: %w", err) } indexedAlerts = append(indexedAlerts, mapAlertRow(row)) } if err := alertsRows.Err(); err != nil { return nil, fmt.Errorf("iterate alerts rows: %w", err) } referenceRows, err := r.db.QueryContext(ctx, queryAlertReferences, eventID) if err != nil { return nil, fmt.Errorf("query alert references: %w", err) } defer referenceRows.Close() indexedReferences := make([]indexedAlertReference, 0) for referenceRows.Next() { var row alertReferenceRow if err := referenceRows.Scan( &row.AlertIndex, &row.ID, &row.Identifier, &row.Sender, &row.Sent, ); err != nil { return nil, fmt.Errorf("scan alert reference row: %w", err) } indexedReferences = append(indexedReferences, mapAlertReferenceRow(row)) } if err := referenceRows.Err(); err != nil { return nil, fmt.Errorf("iterate alert reference rows: %w", err) } return attachAlertReferences(indexedAlerts, indexedReferences), nil }