TypeDrop

2026-03-26 Challenge

2026-03-26 Medium

Typed Job Queue Retry Scheduler

You're building the background job processing layer for a workflow automation platform. Jobs can succeed, fail with a retryable error, or fail fatally — your scheduler must execute them with typed retry policies, collect per-job outcomes, and surface a structured run report through a `Result<T, E>` type with zero `any`.

Goals

  • Define the `Result<T, E>`, `JobError`, `RetryPolicy`, `Job<P>`, `JobOutcome<P>`, and `RunReport` types with no `any`.
  • Implement `scheduleJob<P>` to run a job with per-attempt timeout racing, retry only on `retryable` errors, and a backoff delay between retries.
  • Implement `runQueue` to fan out all jobs concurrently with `Promise.all` and fold outcomes into a typed `RunReport`.
  • Narrow the `JobError` discriminated union by `kind` to drive control flow — never use type assertions.
challenge.ts

// Core types you must define:

type Result<T, E> =
  | { ok: true;  value: T }
  | { ok: false; error: E };

type JobError =
  | { kind: "retryable"; message: string; retryAfterMs: number }
  | { kind: "fatal";     message: string; code: string }
  | { kind: "timeout";   message: string; elapsedMs: number };

type Job<P> = {
  id:      string;
  name:    string;
  payload: P;
  policy:  RetryPolicy;
  execute: (payload: P) => Promise<Result<unknown, JobError>>;
};

// Function signatures you must implement:

async function scheduleJob<P>(job: Job<P>): Promise<JobOutcome<P>>;

async function runQueue(jobs: Job<unknown>[]): Promise<RunReport>;
Hints (click to reveal)

Hints

  • A `while (attempts < policy.maxAttempts)` loop combined with a `break` on non-retryable errors is the cleanest shape for `scheduleJob`.
  • Use the provided `withTimeout` helper to race each `execute()` call — its return type is already `Promise<Result<T, JobError>>`, so plug it straight into your loop.
  • In `runQueue`, derive `succeeded` and `failed` from `outcomes` with a single `reduce` or `filter` — avoid a separate counter variable.

Or clone locally

git clone -b challenge/2026-03-26 https://github.com/niltonheck/typedrop.git