first commit
This commit is contained in:
41
internal/db/db.go
Normal file
41
internal/db/db.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
Pool *pgxpool.Pool
|
||||
}
|
||||
|
||||
func Open(ctx context.Context, connString string) (*DB, error) {
|
||||
cfg, err := pgxpool.ParseConfig(connString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.MaxConns = 10
|
||||
cfg.MinConns = 1
|
||||
cfg.MaxConnIdleTime = 5 * time.Minute
|
||||
|
||||
pool, err := pgxpool.NewWithConfig(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := pool.Ping(ctx); err != nil {
|
||||
pool.Close()
|
||||
return nil, fmt.Errorf("db ping failed: %w", err)
|
||||
}
|
||||
|
||||
return &DB{Pool: pool}, nil
|
||||
}
|
||||
|
||||
func (d *DB) Close() {
|
||||
if d.Pool != nil {
|
||||
d.Pool.Close()
|
||||
}
|
||||
}
|
||||
128
internal/db/queries.go
Normal file
128
internal/db/queries.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type InsertWS90Params struct {
|
||||
TS time.Time
|
||||
Site string
|
||||
StationID int64
|
||||
Model string
|
||||
BatteryOK int
|
||||
BatteryMV int
|
||||
TempC float64
|
||||
Humidity float64
|
||||
WindDirDeg float64
|
||||
WindAvgMS float64
|
||||
WindMaxMS float64
|
||||
UVI float64
|
||||
LightLux float64
|
||||
Flags int
|
||||
RainMM float64
|
||||
RainStart int64
|
||||
SupercapV float64
|
||||
Firmware int
|
||||
RawData string
|
||||
MIC string
|
||||
Protocol string
|
||||
RSSI int
|
||||
Duration int64
|
||||
Payload map[string]any
|
||||
}
|
||||
|
||||
func (d *DB) InsertWS90(ctx context.Context, p InsertWS90Params) error {
|
||||
b, _ := json.Marshal(p.Payload)
|
||||
|
||||
var payloadJSON pgtype.JSONB
|
||||
_ = payloadJSON.Set(b)
|
||||
|
||||
_, err := d.Pool.Exec(ctx, `
|
||||
INSERT INTO observations_ws90 (
|
||||
ts, site, station_id, model, battery_ok, battery_mv,
|
||||
temperature_c, humidity,
|
||||
wind_dir_deg, wind_avg_m_s, wind_max_m_s,
|
||||
uvi, light_lux, flags,
|
||||
rain_mm, rain_start,
|
||||
supercap_v, firmware, raw_data, mic, protocol,
|
||||
rssi, duration, payload_json
|
||||
) VALUES (
|
||||
$1,$2,$3,$4,$5,$6,
|
||||
$7,$8,
|
||||
$9,$10,$11,
|
||||
$12,$13,$14,
|
||||
$15,$16,
|
||||
$17,$18,$19,$20,$21,
|
||||
$22,$23,$24
|
||||
)
|
||||
`, p.TS, p.Site, p.StationID, p.Model, p.BatteryOK, p.BatteryMV,
|
||||
p.TempC, p.Humidity,
|
||||
p.WindDirDeg, p.WindAvgMS, p.WindMaxMS,
|
||||
p.UVI, p.LightLux, p.Flags,
|
||||
p.RainMM, p.RainStart,
|
||||
p.SupercapV, p.Firmware, p.RawData, p.MIC, p.Protocol,
|
||||
p.RSSI, p.Duration, payloadJSON)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type InsertOpenMeteoHourlyParams struct {
|
||||
TS time.Time
|
||||
RetrievedAt time.Time
|
||||
Site string
|
||||
Model string
|
||||
TempC *float64
|
||||
RH *float64
|
||||
PressureMSLH *float64
|
||||
WindMS *float64
|
||||
WindGustMS *float64
|
||||
WindDirDeg *float64
|
||||
PrecipMM *float64
|
||||
PrecipProb *float64
|
||||
CloudCover *float64
|
||||
SourcePayload map[string]any
|
||||
}
|
||||
|
||||
func (d *DB) UpsertOpenMeteoHourly(ctx context.Context, p InsertOpenMeteoHourlyParams) error {
|
||||
b, _ := json.Marshal(p.SourcePayload)
|
||||
|
||||
var sourceJSON pgtype.JSONB
|
||||
_ = sourceJSON.Set(b)
|
||||
|
||||
_, err := d.Pool.Exec(ctx, `
|
||||
INSERT INTO forecast_openmeteo_hourly (
|
||||
ts, retrieved_at, site, model,
|
||||
temp_c, rh, pressure_msl_hpa,
|
||||
wind_m_s, wind_gust_m_s, wind_dir_deg,
|
||||
precip_mm, precip_prob, cloud_cover,
|
||||
source_json
|
||||
) VALUES (
|
||||
$1,$2,$3,$4,
|
||||
$5,$6,$7,
|
||||
$8,$9,$10,
|
||||
$11,$12,$13,
|
||||
$14
|
||||
)
|
||||
ON CONFLICT (site, model, retrieved_at, ts) DO UPDATE SET
|
||||
temp_c = EXCLUDED.temp_c,
|
||||
rh = EXCLUDED.rh,
|
||||
pressure_msl_hpa = EXCLUDED.pressure_msl_hpa,
|
||||
wind_m_s = EXCLUDED.wind_m_s,
|
||||
wind_gust_m_s = EXCLUDED.wind_gust_m_s,
|
||||
wind_dir_deg = EXCLUDED.wind_dir_deg,
|
||||
precip_mm = EXCLUDED.precip_mm,
|
||||
precip_prob = EXCLUDED.precip_prob,
|
||||
cloud_cover = EXCLUDED.cloud_cover,
|
||||
source_json = EXCLUDED.source_json
|
||||
`, p.TS, p.RetrievedAt, p.Site, p.Model,
|
||||
p.TempC, p.RH, p.PressureMSLH,
|
||||
p.WindMS, p.WindGustMS, p.WindDirDeg,
|
||||
p.PrecipMM, p.PrecipProb, p.CloudCover,
|
||||
sourceJSON)
|
||||
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user