Skip to content

fix(scheduler): default started_at on cron-fire run insert#55

Merged
finedesignz merged 1 commit into
mainfrom
fix/scheduler-fire-started-at
May 26, 2026
Merged

fix(scheduler): default started_at on cron-fire run insert#55
finedesignz merged 1 commit into
mainfrom
fix/scheduler-fire-started-at

Conversation

@finedesignz
Copy link
Copy Markdown
Owner

Root cause

PR #49 made insertRunV2's started_at param optional and set it to null when status='pending'. The scheduled_task_runs.started_at column is NOT NULL, so every cron fire (incl. midnight 0 */4 * * *) was failing in prod with:

null value in column "started_at" of relation "scheduled_task_runs" violates not-null constraint

Fix (belt-and-suspenders)

  • JS: insertRunV2 always defaults started_at to new Date() when omitted/null.
  • Schema: idempotent ALTER COLUMN started_at SET DEFAULT now() so drifted prod instances are also safe.
  • Regression test: hub/test/insert-run-started-at.test.ts — mocks the postgres tagged-template and asserts the INSERT values include a non-null Date for started_at in pending/success paths.

Verification

  • bun test hub/test/insert-run-started-at.test.ts → 3 pass / 0 fail.
  • After deploy, next 0 */4 * * * fire should insert + dispatch without the NOT NULL violation.

PR #49 made insertRunV2's started_at param optional and set it to null
when status='pending'. The scheduled_task_runs.started_at column is
NOT NULL, so every cron fire was failing with a constraint violation.

- insertRunV2: always default started_at to new Date() when omitted.
- schema.sql: idempotent ALTER to ensure column DEFAULT now() is set in
  prod (belt-and-suspenders against drifted instances).
- regression test asserting started_at is always non-null in the INSERT.
@finedesignz finedesignz merged commit 65aa724 into main May 26, 2026
1 check passed
@finedesignz finedesignz deleted the fix/scheduler-fire-started-at branch May 26, 2026 14:35
finedesignz added a commit that referenced this pull request May 26, 2026
PR #55 fixed insertRunV2's JS-side default, but the registry→dispatcher
cron-fire path was STILL surfacing "null value in column started_at"
in prod logs. Hardens two remaining gaps:

1. hub/src/db/dal.ts insertDeploymentRun — was inserting NULL into
   started_at when status='pending' (coolify-webhook deployment-marker
   rows). Now always now(). started_at is "row created"; that's
   correct for pending too.

2. hub/src/db/scheduled-tasks-dal.ts insertRunV2 — SQL now wraps the
   bound started_at in COALESCE(_, now()), so even an accidentally-null
   bind from a future caller resolves server-side. JS-side default
   (input.started_at ?? new Date()) stays as the primary guard.

Schema.sql already has ALTER COLUMN started_at SET DEFAULT now() from
PR #55 — that runs on every boot via migrate.ts (verified).

Regression tests cover explicit null + the deployment-run path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant