From 8e2cb7eb4dc871db6a425bfbbc4919d06eed6b3c Mon Sep 17 00:00:00 2001 From: joshua Date: Tue, 27 Oct 2026 11:06:51 +0200 Subject: [PATCH] Background jobs: show last-run times in the right time zone pg-boss timestamps are timestamptz, and Prisma's pg adapter drops the offset in raw queries (10:55+02 came back as 10:55Z, shown as 12:55). Read them AT TIME ZONE 'UTC'. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 9 +++++++++ backend/src/jobs/index.js | 8 +++++++- docs/HANDOVER.md | 3 ++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9247077..54d4f59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project follows [Semantic Versioning](https://semver.org/). ## [Unreleased] +## [1.41.2] - 2026-10-27 + +### Fixed + +- **Background jobs page showed last-run times two hours ahead** (e.g. 12:55 at 10:55). Prisma's + Postgres adapter dropped the time-zone offset of pg-boss's timestamps; the query now reads them + as UTC. Job history itself was never wrong. `APP_TIMEZONE` is now in `backend/.env.example` and + SETTINGS.md. + ## [1.41.1] - 2026-10-27 ### Changed diff --git a/backend/src/jobs/index.js b/backend/src/jobs/index.js index 5087f1d..2d5883b 100644 --- a/backend/src/jobs/index.js +++ b/backend/src/jobs/index.js @@ -247,8 +247,14 @@ async function runNow(name) { async function jobStatus(prisma) { const recent = new Map(); if (mode === 'queue') { + // pg-boss columns are timestamptz, and Prisma's pg adapter drops their offset in raw queries + // (10:55+02 came back as 10:55Z). As plain UTC timestamps they come back right. const rows = await prisma.$queryRawUnsafe(` - SELECT name, state, created_on AS "createdOn", started_on AS "startedOn", completed_on AS "completedOn", output + SELECT name, state, + created_on AT TIME ZONE 'UTC' AS "createdOn", + started_on AT TIME ZONE 'UTC' AS "startedOn", + completed_on AT TIME ZONE 'UTC' AS "completedOn", + output FROM ( SELECT name, state, created_on, started_on, completed_on, output, row_number() OVER (PARTITION BY name ORDER BY created_on DESC) AS rn diff --git a/docs/HANDOVER.md b/docs/HANDOVER.md index 6a44653..e871665 100644 --- a/docs/HANDOVER.md +++ b/docs/HANDOVER.md @@ -1,6 +1,6 @@ # Handover — where things stand and how to carry on -Last updated: 2026-10-27, after **1.41.1** (and Hub 1.0.0). The plan itself is in +Last updated: 2026-10-27, after **1.41.2** (and Hub 1.0.0). The plan itself is in [ROADMAP-v2.md](./ROADMAP-v2.md) (decisions table at the end); the previous round of features is in [FEATURES-ROUND-1.md](./FEATURES-ROUND-1.md). @@ -8,6 +8,7 @@ features is in [FEATURES-ROUND-1.md](./FEATURES-ROUND-1.md). | Version | What | |---------|------| +| 1.41.2 | Background jobs page: last-run times were 2 h ahead (Prisma's pg adapter drops the offset of timestamptz in raw queries — read pg-boss times `AT TIME ZONE 'UTC'`); `APP_TIMEZONE` documented | | 1.41.1 | Licence fixes — no licence (never connected, or the Hub answers `INSTALL_NOT_FOUND`, which now drops the old licence) is read-only like suspended; read-only also blocks editing events/options/variants; heartbeat 30 s after start and after connecting; `LICENCE_CHECK_DISABLED` for e2e | | 1.41.0 | Hope Events Hub connection — licence step in `/setup` and Site settings → Licence, 15-minute heartbeat (health, totals, income bands), licence states checked offline (grace banner for site admins only, read-only when suspended/revoked), `/health`, "update available", `scripts/install.sh`. The Hub itself is `joshua/events-hub` 1.0.0 | | 1.40.0 | POPIA toolkit part 3 — readiness checklist with score, retention policies + nightly `retention` job (inactive accounts anonymised after 5 years with a 30-day warning, on by default), breach register with notification drafts, children's/medical flag in the access log, `{retention}` in the notice |