Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

05 — Screen Inventory (Scheduler Module)

Every screen of the Scheduled Jobs admin console, its intent, route, composition, states, permissions and events. All console screens are (proposed) — they are specified for the operator UX; only the three endpoints behind them exist (scheduler.controller.ts:23-46). Authoritative components in 00-shared/03; this file enumerates which each screen uses with module specifics. Legend — States: idle / loading / success / empty / error(offline, rate, invalid) / disabled / permission. Analytics: scheduler.{screen}.{action} (proposed) (00-shared/10 §8).


S1 — Scheduled Jobs List (/admin/scheduler) (proposed)

FieldDetail
PurposeInventory of every repeatable job across all queues
Entryadmin settings → Scheduled Jobs; cold app deep link
Exit→ job detail (S2); → create sheet (S3); → DLQ (S6)
SourceGET /scheduler{queue, name, pattern, tz}[] (scheduler.service.ts:152-186) — plus (proposed) lastRun/status enrichment
WidgetsAppListTile rows: job name, queue chip, cron chip, tz chip, status badge; summary header counts
Row actionsTap → S2; AppMenu: "Run now" (S5), "View logs" (S4), "Remove" (confirm)
Statesloading (AppSkeleton), empty ("No scheduled jobs — defaults register at boot" scheduler.service.ts:43-45), error (offline / 403 permission scheduler.read scheduler.controller.ts:24)
Analyticsscheduler.list.open, scheduler.list.refresh, scheduler.job.open
RefreshRefreshIndicator; auto-poll every 60 s (audit-flush cadence scheduler.service.ts:78-83)
a11ybadge colors never sole signal (icon + text), live region on status change

S2 — Job Detail / Run History (/admin/scheduler/jobs/:queue/:name) (proposed)

FieldDetail
PurposeOne job's schedule, definition, and recent runs
Sourceschedule from GET /scheduler; runs (proposed) GET /scheduler/runs?queue=&name=
Compositionheader (name, pattern, tz, queue), run-history list (startedAt, status, duration, error), schedule meta (removeOnComplete/removeOnFail scheduler.service.ts:145-146)
Statesempty ("no runs in retention window — triggers keep 1 h / 100 completed scheduler.service.ts:145")
CTAs"Run now" (S5), "View logs" (S4), "Remove schedule"
Analyticsscheduler.detail.open, scheduler.detail.run

S3 — Create Custom Schedule (sheet) (proposed)

FieldDetail
PurposeOperator-defined cron on a whitelisted queue
SourcePOST /scheduler (scheduler.controller.ts:30-35); DTO contract create-schedule.dto.ts:18-41
Formqueue (enum of 11, dto:4-16), jobName (free text), pattern (5-field cron, regex dto:20-24), tz (default UTC), payload (JSON, optional)
Statesinline cron error ("Invalid cron pattern (5 fields required)" dto:22), success → row appears in S1
Analyticsscheduler.create.submit, scheduler.create.success, scheduler.create.failure(reason)

S4 — Job Logs (/admin/scheduler/jobs/:queue/:name/logs) (proposed)

FieldDetail
PurposePer-run log stream for a job (operator + on-call diagnosis)
Source(proposed) GET /scheduler/jobs/:queue/:name/logs
CompositionAppListTile log lines (timestamp, level, message, jobId), filter by level, tail-live toggle
Statesempty ("no logs kept — job data retention is 1 h completed / 7 d failed scheduler.service.ts:145-146"), error
Analyticsscheduler.logs.open, scheduler.logs.filter

S5 — Manual Trigger (dialog) (proposed)

FieldDetail
PurposeFire a repeatable job's child job now, once
Source(proposed) POST /scheduler/:queue/:name/trigger → re-enqueues child job per jobs/*.job.ts contract
Compositionconfirm dialog: job name, target queue, warning text "deliveries may duplicate — verify idempotency"
Statessuccess → snackbar + row lastRun updates; disabled while a run is in flight
Analyticsscheduler.trigger.submit, scheduler.trigger.success, scheduler.trigger.failure

S6 — Dead Letter Queue (/admin/scheduler/dlq) (proposed)

FieldDetail
PurposeJobs that exhausted retries: attemptsMade >= attempts → DLQ (dlq.setup.ts:8-9)
Source(proposed) GET /scheduler/dlq; record shape dlq.setup.ts:12-21
WidgetsAppCard per DLQ record: originalQueue, originalJobName, failedReason, attemptsMade, failedAt; actions Replay / Delete (confirm)
Empty"No dead letters" — success state
Analyticsscheduler.dlq.open, scheduler.dlq.replay, scheduler.dlq.delete

Shared components used

AppListTile, AppCard, AppChips (queue/cron), AppBadge (status), AppButton, AppMenu, AppDialog, AppBottomSheet, AppSnackbar, AppSkeleton, AppEmptyState, AppOfflineBanner, AppFAB ("New schedule"), AppTextField (cron/jobName), AppDropdown (queue), AppSwitch (tail-live). Module-specific: JobStatusBadge, CronChip, RunHistoryRow, DLQCard — defined in 07_Component_Library.md.

Analytics events (proposed)

scheduler.list.{open,refresh}, scheduler.job.{open,remove}, scheduler.detail.{open,run}, scheduler.create.{submit,success,failure}, scheduler.logs.{open,filter}, scheduler.trigger.{submit,success,failure}, scheduler.dlq.{open,replay,delete}.

Keyboard, landscape, tablet, desktop

  • Console is desktop-first (admin tool); tablet uses two-column list/detail.
  • Forms in AppBottomSheet (max-width 640 dp) on all breakpoints.
  • Cron input: monospace, auto-validate on blur, hint from schedule table (01 §2).
  • All fields keyboard-avoidance + ScrollView resizeToAvoidBottomInset.