Refactored the application structure to better separate concerns between files and packages
Some checks failed
ci/woodpecker/push/build-image Pipeline failed
Some checks failed
ci/woodpecker/push/build-image Pipeline failed
This commit is contained in:
110
internal/adapters/outbound/postgres/alerts_read.go
Normal file
110
internal/adapters/outbound/postgres/alerts_read.go
Normal file
@@ -0,0 +1,110 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user