08 — Form Specifications (Scheduler Module)
- F1 — Create Custom Schedule (S3)
- F2 — Manual Trigger Confirm (S5,
(proposed)) - F3 — Remove Schedule Confirm (S1/S2)
- F4 — DLQ Replay / Delete Confirms (S6,
(proposed)) - Form inventory
Forms of the Scheduled Jobs console. Only S3 maps to a real endpoint (
POST /scheduler); all other forms belong to(proposed)screens. Validation rules quoted fromdto/create-schedule.dto.ts. Baseline form behavior per 00-shared/03 (AppTextField/AppDropdown/AppBottomSheet).
F1 — Create Custom Schedule (S3)
| Field | Widget | Validation (server) | Notes |
|---|---|---|---|
| Queue | AppDropdown | @IsIn(QUEUE_NAMES) (dto:26-28) | 11 whitelisted queues: emails, push, in-app, attendance-process, biometric-sync, invoice-generate, payment-reminder, report-generate, audit-write, tenant-purge, cache-rebuild (dto:4-16) |
| Job name | AppTextField | @IsString(), required (dto:30-32) | free text; visible in S1 rows |
| Cron pattern | AppTextField (monospace) | @Matches(/^(\S+\s+){4}\S+$/) — error "Invalid cron pattern (5 fields required)" (dto:20-24) | client mirrors regex on blur; preset chips C8 fill from defaults (scheduler.service.ts:48-119) |
| Timezone | AppDropdown | @IsString(), optional, default UTC (dto:38-41) | only UTC used by defaults (scheduler.service.ts:54,62,70,…); tz aware display in S1 |
| Payload | JSON textarea | optional Record<string, unknown> (dto:34-36) | passed to queue.add(dto.jobName, dto.payload ?? {}, {repeat}) (scheduler.service.ts:200-204) |
Behavior
- Submit →
POST /scheduler(scheduler.controller.ts:30-35) →createJob(scheduler.service.ts:198-208); sheet closes on 201/200; row appears in S1 (optimistic, rollback on failure). - Duplicate warn:
registerRepeatableskips an existingname+pattern(scheduler.service.ts:128-133) — UI shows a confirm before submitting a row that already exists in the S1 list. - Validation errors inline per field; server errors surface in the sheet (envelope per 00-shared/07).
- a11y: each field labelled, error messages in live regions, first invalid field focused on submit.
F2 — Manual Trigger Confirm (S5, (proposed))
Not a form — a confirmation dialog:
- Content: "Trigger
<jobName>→<child job>on queue<queue>now? Deliveries may duplicate — worker idempotency must hold." (child-job map fromjobs/*.job.ts:check-overdue,send-daily-digest,send-payment-reminder,generate-attendance-report). - Confirm disabled while a run is in flight; success → snackbar + S2 run-history refresh.
- No input fields; risk is disclosed, not edited (idempotency is the guard,
bullmq.module.ts:76).
F3 — Remove Schedule Confirm (S1/S2)
- Dialog: "Remove repeatable
<name>(<pattern>,<queue>)?" — matchesremoveRepeatable(jobName, {pattern, tz: 'UTC'})(scheduler.service.ts:194). - Shows pattern+queue read-only so the operator confirms the exact triple (BullMQ dedupes by name+pattern+queue).
- Success → row removed from list (optimistic).
F4 — DLQ Replay / Delete Confirms (S6, (proposed))
- Replay: "Re-queue
<originalJobName>from<originalQueue>? It failed<attemptsMade>× — verify idempotency before retry." (dlq.setup.ts:8-9,12-21). - Delete: standard destructive confirm; note "record will be lost".
Form inventory
| Form | Screen | Endpoint | Status |
|---|---|---|---|
| F1 Create schedule | S3 | POST /scheduler | implemented |
| F2 Trigger confirm | S5 | (proposed) | proposed |
| F3 Remove confirm | S1/S2 | DELETE /scheduler | implemented |
| F4 DLQ replay/delete | S6 | (proposed) | proposed |