diff --git a/rust/prop_grid_rs/src/db.rs b/rust/prop_grid_rs/src/db.rs index 633441fd..c55bc8fc 100644 --- a/rust/prop_grid_rs/src/db.rs +++ b/rust/prop_grid_rs/src/db.rs @@ -7,7 +7,7 @@ //! * On success: status=done, NOTIFY propagation_ready ''. //! * On failure: status=failed, error=. An hourly cron reseeds. -use chrono::{DateTime, Utc}; +use chrono::{DateTime, NaiveDateTime, Utc}; use sqlx::postgres::{PgNotification, PgPool, PgPoolOptions}; use sqlx::Row; use std::time::Duration; @@ -63,10 +63,16 @@ pub async fn claim_next(pool: &PgPool) -> Result, DbError> { }; let id: Uuid = row.try_get("id")?; - let run_time: DateTime = row.try_get("run_time")?; + // Elixir writes run_time/valid_time via Ecto `:utc_datetime`, which + // lands in Postgres as TIMESTAMP WITHOUT TIME ZONE (values are UTC + // by Ecto contract). Read as NaiveDateTime and reattach UTC so the + // rest of the worker can keep its DateTime signature. + let run_time_naive: NaiveDateTime = row.try_get("run_time")?; + let run_time = DateTime::::from_naive_utc_and_offset(run_time_naive, Utc); let forecast_hour: i32 = row.try_get("forecast_hour")?; let forecast_hour = forecast_hour as i16; - let valid_time: DateTime = row.try_get("valid_time")?; + let valid_time_naive: NaiveDateTime = row.try_get("valid_time")?; + let valid_time = DateTime::::from_naive_utc_and_offset(valid_time_naive, Utc); let attempt: i32 = row.try_get("attempt")?; sqlx::query( @@ -177,7 +183,8 @@ mod tests { }; let pool = connect(&url, 4).await.unwrap(); - // Seed a unique fh>0 row. + // Seed a unique fh>0 row. run_time/valid_time bind as + // NaiveDateTime to match Ecto's :utc_datetime column type. let run_time = Utc::now(); let fh: i16 = 7; let valid_time = run_time + chrono::Duration::hours(fh as i64); @@ -187,9 +194,9 @@ mod tests { VALUES ($1, $2, $3, $4, 'queued', 0, NOW(), NOW())"#, ) .bind(id) - .bind(run_time) + .bind(run_time.naive_utc()) .bind(fh as i32) - .bind(valid_time) + .bind(valid_time.naive_utc()) .execute(&pool) .await .unwrap();