Skip to content

fix(scheduler): manual Run-now returns run_ids + fail-fast on offline targets#51

Merged
finedesignz merged 1 commit into
mainfrom
fix/manual-run-now
May 26, 2026
Merged

fix(scheduler): manual Run-now returns run_ids + fail-fast on offline targets#51
finedesignz merged 1 commit into
mainfrom
fix/manual-run-now

Conversation

@finedesignz
Copy link
Copy Markdown
Owner

Summary

The Run now button on the Schedules page silently did nothing when:

  • the bound session/supervisor was offline (run was grace-queued for up to 10 minutes with no UI signal),
  • and even on success, the API returned { ok, status } with no run_ids, while the web layer was typed against { run_ids: string[] }, so it had no run id to track progress with.

Root cause

POST /api/scheduled-tasks/:id/run-now was fire-and-forget. It returned 202 immediately and called dispatcher.runNow(...) in the background. runNow returned void, and offline targets were registered for grace replay (which is correct for cron fires but wrong for manual clicks — the user expects immediate feedback).

Fix

  • dispatcher.runNow now returns { runIds: string[] }. All early-return paths push their run id before returning. Backward-compatible — existing call sites (catchup, grace, chain) ignore the return value and still work.
  • New isManual opt:
    • resolveTargets empty → error='target_offline' (was 'no_targets') and a scheduled_run_finished WS event fires so the Runs drawer shows the failure immediately.
    • resolved-but-offline target → fail-fast with 'target_offline' instead of grace-queuing.
  • /api/scheduled-tasks/:id/run-now now awaits the dispatcher and returns { ok, status, run_ids }.
  • SchedulesPage.handleRunNow logs when zero rows are returned (defensive).

hub/src/scheduler/catchup.ts is intentionally untouched (separate owner per branch coordination).

Verification

  • bun test hub/test/scheduler.test.ts — 52 pass, 0 fail.
  • bun build of both edited hub modules succeeds.
  • bunx tsc --noEmit on web/ clean.

Test plan

  • Click Run now on a task whose session is online → 202 + run_ids: [<id>]; new row appears in the Runs drawer with status transitioning pending → running → succeeded.
  • Click Run now on a task whose target is offline → 202 + run_ids: [<id>]; row appears with status failed, error target_offline (no 10-minute grace silence).
  • Click Run now when daily cost cap reached → row appears with status skipped, error daily_cost_cap (existing behavior, now also returns the run id).

🤖 Generated with Claude Code

… targets

Root cause: the POST /api/scheduled-tasks/:id/run-now route was
fire-and-forget — it returned 202 immediately with no run_ids, while
the web UI was typed against `{ run_ids: string[] }` and had no way to
know whether a row was actually created. Worse, when the task's target
was offline, the dispatcher silently grace-queued the run (intended for
cron fires, not manual clicks), leaving the user with a button that
appeared to do nothing.

Fix:
- dispatcher.runNow now returns `{ runIds: string[] }` (was void). All
  internal early-return paths push their run id before returning.
  Backward-compatible: existing callers (catchup, grace, chain) that
  ignore the return value still work.
- New `isManual` flag on runNow. When set:
  - resolveTargets empty → error='target_offline' (was 'no_targets')
    and a `scheduled_run_finished` WS event is broadcast so the
    Schedules drawer shows the failure immediately.
  - resolved-but-offline target → fail-fast with 'target_offline'
    instead of grace-queuing. Manual clicks expect immediate feedback.
- /api/scheduled-tasks/:id/run-now now awaits the dispatcher and
  returns `{ ok, status, run_ids }` so the UI can track progress via WS
  using the returned ids.
- SchedulesPage logs when dispatch returns zero rows (defensive — the
  server now always returns ≥1 row for a found task).

Catchup is untouched (separate owner). Cost-cap behavior preserved
(skipped runs still emit a run row and broadcast the skipped event).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@finedesignz finedesignz merged commit d16c3db into main May 26, 2026
1 check passed
@finedesignz finedesignz deleted the fix/manual-run-now branch May 26, 2026 14:35
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