Initial MVP commit
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful

This commit is contained in:
2026-03-17 08:35:16 -05:00
parent 8c092c2247
commit 27817f9e43
29 changed files with 1890 additions and 1 deletions

View File

@@ -0,0 +1,119 @@
package postgres
import (
"context"
"database/sql"
"fmt"
"time"
"gitea.maximumdirect.net/ejr/weatherapi/internal/core/ports"
"github.com/jackc/pgx/v5/pgxpool"
)
type ForecastRepository struct {
pool *pgxpool.Pool
}
func NewForecastRepository(pool *pgxpool.Pool) *ForecastRepository {
return &ForecastRepository{pool: pool}
}
func (r *ForecastRepository) ListForecastPeriodsAt(ctx context.Context, ts time.Time, limit int) ([]ports.ForecastPeriodMetric, error) {
rows, err := r.pool.Query(ctx, queryForecastPeriodsAt, ts, limit)
if err != nil {
return nil, fmt.Errorf("query forecast periods at timestamp: %w", err)
}
defer rows.Close()
out := make([]ports.ForecastPeriodMetric, 0)
for rows.Next() {
var row ports.ForecastPeriodMetric
var name sql.NullString
var isDay sql.NullBool
var conditionText sql.NullString
var providerRawDescription sql.NullString
var textDescription sql.NullString
var detailedText sql.NullString
var iconURL sql.NullString
var temperature sql.NullFloat64
var temperatureMin sql.NullFloat64
var temperatureMax sql.NullFloat64
var dewpoint sql.NullFloat64
var humidity sql.NullFloat64
var windDirection sql.NullFloat64
var windSpeed sql.NullFloat64
var windGust sql.NullFloat64
var pressure sql.NullFloat64
var visibility sql.NullFloat64
var apparent sql.NullFloat64
var cloudCover sql.NullFloat64
var precipProbability sql.NullFloat64
var precipAmount sql.NullFloat64
var snowfallDepth sql.NullFloat64
var uvIndex sql.NullFloat64
if err := rows.Scan(
&row.PeriodIndex,
&row.StartTime,
&row.EndTime,
&name,
&isDay,
&row.ConditionCode,
&conditionText,
&providerRawDescription,
&textDescription,
&detailedText,
&iconURL,
&temperature,
&temperatureMin,
&temperatureMax,
&dewpoint,
&humidity,
&windDirection,
&windSpeed,
&windGust,
&pressure,
&visibility,
&apparent,
&cloudCover,
&precipProbability,
&precipAmount,
&snowfallDepth,
&uvIndex,
); err != nil {
return nil, fmt.Errorf("scan forecast period row: %w", err)
}
row.Name = ptrString(name)
row.IsDay = ptrBool(isDay)
row.ConditionText = ptrString(conditionText)
row.ProviderRawDescription = ptrString(providerRawDescription)
row.TextDescription = ptrString(textDescription)
row.DetailedText = ptrString(detailedText)
row.IconURL = ptrString(iconURL)
row.TemperatureC = ptrFloat64(temperature)
row.TemperatureCMin = ptrFloat64(temperatureMin)
row.TemperatureCMax = ptrFloat64(temperatureMax)
row.DewpointC = ptrFloat64(dewpoint)
row.RelativeHumidityPercent = ptrFloat64(humidity)
row.WindDirectionDegrees = ptrFloat64(windDirection)
row.WindSpeedKmh = ptrFloat64(windSpeed)
row.WindGustKmh = ptrFloat64(windGust)
row.BarometricPressurePa = ptrFloat64(pressure)
row.VisibilityMeters = ptrFloat64(visibility)
row.ApparentTemperatureC = ptrFloat64(apparent)
row.CloudCoverPercent = ptrFloat64(cloudCover)
row.ProbabilityOfPrecipitationPercent = ptrFloat64(precipProbability)
row.PrecipitationAmountMm = ptrFloat64(precipAmount)
row.SnowfallDepthMm = ptrFloat64(snowfallDepth)
row.UVIndex = ptrFloat64(uvIndex)
out = append(out, row)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate forecast period rows: %w", err)
}
return out, nil
}