TypeDrop

2026-03-13 Challenge

2026-03-13 Hard

Typed Concurrent Task Scheduler with Priority Queues

You're building the background job engine for a data-pipeline platform. Tasks arrive with a priority level and resource tags, must be executed with a concurrency cap per resource group, and every outcome — success, failure, or cancellation — must be surfaced through a fully typed Result hierarchy with zero `any`.

Goals

  • Define branded TaskId, Priority, TaskError, and TaskResult<T> types with zero `any` and no type casts.
  • Implement createScheduler() so tasks are dispatched in priority order while respecting both per-group and global concurrency caps.
  • Handle timeout races, runtime rejections, and queue-overflow cancellations — each surfaced as the correct TaskResult variant.
  • Derive SchedulerStats.totals via a mapped type over GroupCounts keys so the shape stays in sync automatically.
challenge.ts
// Key types and main entry-point — enough to understand the challenge

declare const __taskIdBrand: unique symbol;
export type TaskId = string & { readonly [__taskIdBrand]: true };

export type Priority = "low" | "normal" | "high" | "critical";

export type TaskError =
  | { kind: "timeout";  durationMs: number }
  | { kind: "runtime";  message: string; cause?: unknown }
  | { kind: "overflow"; queueSize: number };

export type TaskResult<T> =
  | { status: "fulfilled"; id: TaskId; value: T }
  | { status: "rejected";  id: TaskId; error: TaskError }
  | { status: "cancelled"; id: TaskId; reason: string };

export interface TaskDefinition<T> {
  id: TaskId;
  priority: Priority;
  resourceGroup: string;
  run: () => Promise<T>;
  timeoutMs?: number;
}

export interface Scheduler {
  submit<T>(task: TaskDefinition<T>): Promise<TaskResult<T>>;
  cancel(id: TaskId): boolean;
  stats(): SchedulerStats;
}

export function createScheduler(config: SchedulerConfig): Scheduler { /* TODO */ }
Hints (click to reveal)

Hints

  • A priority queue can be a plain array you re-sort on insert — use the PRIORITY_ORDER weight map to compare entries.
  • To race a task against its timeout, wrap both in Promise.race: one resolves with the value, the other rejects after timeoutMs ms.
  • Store each queued task alongside its resolve function so that cancel() and overflow can settle the promise from outside the run loop.

Or clone locally

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