FrontendPro

102Implement a task scheduler with concurrency limits, priorities, cancellation, and starvation prevention

hardAbout 60 minutesCodingconcurrencyschedulingabortsignalfairness

Problem

Implement class Scheduler:

const scheduler = new Scheduler({ concurrency: 2, agingMs: 1000, now: Date.now });
const result = await scheduler.schedule(({ signal }) => fetch(url, { signal }), { priority: 5, signal });
  • schedule(task, { priority = 0, signal } = {}) returns a promise for the task's result. task receives { signal }.
  • At most concurrency tasks run at once. When a slot frees, the waiting task with the highest effective priority starts.
  • Starvation prevention (aging): effective priority = priority + waitedMs / agingMs. A low-priority task that has waited long enough eventually beats newly scheduled high-priority tasks. Ties go to the task scheduled first.
  • Cancellation: if signal aborts while the task is waiting, remove it and reject with signal.reason without running it. If signal is already aborted, reject immediately. If it aborts while the task is running, the task sees it through its own signal (pass it on to fetch and friends); the scheduler rejects with signal.reason at once and frees the slot.
  • size (waiting) and running counts.

now is injectable so tests can control time.

Try it yourself

Write your solution, run it, then submit to check it against the tests.

solution.jsJavaScript

Press Run or ⌘ Enter to execute your code.

Step-by-step

Each waiting job holds the task, priority, enqueuedAt (from now()), a sequence number for ties, its resolve/reject, and its signal.

Unlock the full solution

What's inside

  • Step-by-step
  • Approach
  • Solution
  • Complexity
  • Edge cases
  • Follow-up questions
  • Tests

Includes 2 code listings, 5 edge cases, 4 follow-up questions.

One-time payment by UPI, card or net banking. Launch price.

All 150 answersOne payment, yours forever