update for 4 hour rain forecast

This commit is contained in:
2026-04-06 18:32:33 +10:00
parent fb50c8ed71
commit 3a7309b2cf
20 changed files with 716 additions and 132 deletions
+34 -6
View File
@@ -9,6 +9,24 @@ from typing import Any
import psycopg2
DEFAULT_HORIZON_HOURS = 4
def normalize_horizon_hours(horizon_hours: int) -> int:
out = int(horizon_hours)
if out <= 0:
raise ValueError("horizon_hours must be > 0")
return out
def prediction_table_for_horizon(horizon_hours: int) -> str:
horizon = normalize_horizon_hours(horizon_hours)
if horizon == 1:
return "predictions_rain_1h"
if horizon == 4:
return "predictions_rain_4h"
raise ValueError(f"unsupported prediction-table horizon: {horizon_hours}")
def parse_duration(value: str) -> timedelta:
raw = value.strip().lower()
@@ -27,14 +45,20 @@ def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Check freshness/health of rain-model data and predictions.")
parser.add_argument("--db-url", default=os.getenv("DATABASE_URL"), help="Postgres connection string.")
parser.add_argument("--site", required=True, help="Site name.")
parser.add_argument("--model-name", default="rain_next_1h", help="Prediction model_name to check.")
parser.add_argument("--model-name", default="rain_next_4h", help="Prediction model_name to check.")
parser.add_argument(
"--horizon-hours",
type=int,
default=DEFAULT_HORIZON_HOURS,
help="Prediction horizon in hours used to select prediction storage table.",
)
parser.add_argument("--max-ws90-age", default="20m", help="Max allowed age for ws90 latest row.")
parser.add_argument("--max-baro-age", default="30m", help="Max allowed age for barometer latest row.")
parser.add_argument("--max-forecast-age", default="3h", help="Max allowed age for forecast latest row.")
parser.add_argument("--max-prediction-age", default="30m", help="Max allowed age for latest prediction write.")
parser.add_argument(
"--max-pending-eval-age",
default="3h",
default="6h",
help="Pending evaluations older than this count toward alert.",
)
parser.add_argument(
@@ -91,6 +115,8 @@ def main() -> int:
max_forecast_age = parse_duration(args.max_forecast_age)
max_prediction_age = parse_duration(args.max_prediction_age)
max_pending_eval_age = parse_duration(args.max_pending_eval_age)
horizon_hours = normalize_horizon_hours(args.horizon_hours)
prediction_table = prediction_table_for_horizon(horizon_hours)
with psycopg2.connect(args.db_url) as conn:
ws90_latest = fetch_latest_ts(
@@ -110,9 +136,9 @@ def main() -> int:
)
prediction_latest = fetch_latest_ts(
conn,
"""
f"""
SELECT max(generated_at)
FROM predictions_rain_1h
FROM {prediction_table}
WHERE site = %s
AND model_name = %s
""",
@@ -120,9 +146,9 @@ def main() -> int:
)
pending_eval_rows = fetch_count(
conn,
"""
f"""
SELECT count(*)
FROM predictions_rain_1h
FROM {prediction_table}
WHERE site = %s
AND model_name = %s
AND evaluated_at IS NULL
@@ -188,6 +214,8 @@ def main() -> int:
"generated_at": now.isoformat(),
"site": args.site,
"model_name": args.model_name,
"horizon_hours": horizon_hours,
"prediction_table": prediction_table,
"status": overall_status,
"failing_checks": failing,
"checks": checks,