From 5f86ca1b86ca5e2ba9385a13dc78dd2740780ecc Mon Sep 17 00:00:00 2001 From: Claudio Ortolina Date: Mon, 11 May 2026 14:18:29 +0100 Subject: [PATCH] ML-171: track upstream fix --- ...n-sparkline-from-SQLite-datetime-string.md | 34 ++----------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/backlog/tasks/ml-171 - Fix-Oban-Web-crons-page-crash-MatchError-in-sparkline-from-SQLite-datetime-string.md b/backlog/tasks/ml-171 - Fix-Oban-Web-crons-page-crash-MatchError-in-sparkline-from-SQLite-datetime-string.md index 3f4c1cd4..d8ef51b3 100644 --- a/backlog/tasks/ml-171 - Fix-Oban-Web-crons-page-crash-MatchError-in-sparkline-from-SQLite-datetime-string.md +++ b/backlog/tasks/ml-171 - Fix-Oban-Web-crons-page-crash-MatchError-in-sparkline-from-SQLite-datetime-string.md @@ -6,7 +6,7 @@ title: >- status: To Do assignee: [] created_date: "2026-05-09 05:28" -updated_date: "2026-05-11 06:46" +updated_date: "2026-05-11 13:17" labels: - bug - oban-web @@ -30,35 +30,7 @@ priority: medium The `/dev/oban/crons` dashboard page crashes with `Elixir.MatchError` when rendering cron job history sparklines. This happens because Oban Web's `TableComponent.sparkline/1` calls `DateTime.from_naive!/2` which expects a `NaiveDateTime` struct, but receives a raw ISO 8601 string from SQLite. -## Root Cause - -In `Oban.Web.CronQuery.cron_history/2` (deps/oban_web/lib/oban/web/queries/cron_query.ex:164-177), the query selects: - -```elixir -finished_at: fragment("COALESCE(?, ?, ?)", j.completed_at, j.cancelled_at, j.discarded_at) -``` - -SQLite stores `utc_datetime_usec` fields as ISO 8601 text. While regular field references like `j.scheduled_at` are properly decoded to `DateTime` structs by Ecto, the `fragment()` call bypasses type decoding and returns a raw string like `"2026-05-08T11:00:00.708342Z"`. - -The sparkline function at `Oban.Web.Crons.TableComponent` line 81 then fails: - -```elixir -(job.finished_at || job.attempted_at || job.scheduled_at) -|> DateTime.from_naive!("Etc/UTC") # 💥 expects NaiveDateTime, gets string -``` - -## Error Details - -- **ErrorTracker ID**: 4039 -- **Occurrences**: 2 (both on 2026-05-08) -- **View**: Oban.Web.DashboardLive (crons page) -- **Fingerprint**: `2C5253F1AB9B5D61231B7579E912FD2F7C155738DBB4325275F14E844C5D7B0C` - -## Approach - -The `sparkline/1` function is marked as `@doc overridable: 1` in Oban Web, so we can override it in the app. The fix should handle both `DateTime` structs (PostgreSQL) and ISO 8601 strings (SQLite) by parsing strings through `DateTime.from_iso8601!/1` first. - -Alternatively, the fix could be applied upstream in Oban Web's `CronQuery` to use a typed fragment or cast the `COALESCE` result. +This will be resolved when oban_web ships https://github.com/oban-bg/oban_web/commit/9e9b7ad470ac87cfcad67bec9140dc318549dc09 @@ -68,6 +40,4 @@ Alternatively, the fix could be applied upstream in Oban Web's `CronQuery` to us - [ ] #1 Visiting /dev/oban/crons no longer crashes with MatchError - [ ] #2 Cron history sparklines render correctly showing job state colors -- [ ] #3 The fix handles both DateTime structs (PostgreSQL) and ISO 8601 strings (SQLite) -- [ ] #4 The overridden sparkline/1 function preserves the same visual output as upstream