2.6 KiB
scheduler
Purpose
scheduler.ts exposes pickSlot, the pure function WorkerPool calls to
decide which slot receives the next submit. The function takes a
projection of the pool's slots (only the data the scheduler needs:
name + pendingCount) and the strategy name, and returns the chosen
slot plus the next round-robin index.
Isolating the scheduling decision in a pure function makes it independently testable, swappable (a future scheduler can be added without touching the pool), and free of side effects.
Features
- Two scheduling strategies:
round-robinandleast-busy. SchedulerSlotprojection — lightweight view of the pool's slots so the scheduler doesn't depend onWorkerPool's internals.- Returns
undefinedwhen the slot list is empty, letting the caller decide what to do (typically reject withRESTART_EXHAUSTED). - Round-robin returns the next index so the caller can persist it.
Usage: Basic Example
import { pickSlot } from "@suaveplan/web-workers";
const slots = [
{ name: "w0", pendingCount: 0 },
{ name: "w1", pendingCount: 0 },
];
const pick = pickSlot("round-robin", slots, 0);
// pick.slot.name === "w0", pick.nextIndex === 1
Usage: Advanced Example
import {
pickSlot,
type SchedulerSlot,
type SchedulerStrategy,
} from "@suaveplan/web-workers";
class CustomPool {
private slots: Array<{ name: string; pendingCount: number }> = [];
private nextRR = 0;
pick(strategy: SchedulerStrategy): SchedulerSlot | undefined {
const projection = this.slots.map((s) => ({
name: s.name,
pendingCount: s.pendingCount,
}));
const result = pickSlot(strategy, projection, this.nextRR);
if (result === undefined) return undefined;
this.nextRR = result.nextIndex;
return result.slot;
}
}
API Reference
type SchedulerStrategy = "round-robin" | "least-busy".interface SchedulerSlot { name: string; pendingCount: number }.pickSlot(strategy, slots, nextRoundRobinIndex): { slot, nextIndex } | undefined.
Implementation Notes
round-robin uses nextRoundRobinIndex % slots.length so the caller can
keep a monotonically-increasing counter without worrying about wraparound.
least-busy linear-scans the slot list; ties go to the lowest-index slot
(deterministic). The pure-function shape means the same slot projection
always returns the same result — no hidden state, no randomness. For
large pools (> 100 slots) a heap-based least-busy could be faster, but
the typical pool size (4–16 slots) makes the linear scan negligible.