Async & Promiseshard

Design async priority queue with concurrency

Implement a priority-based async task queue that executes higher-priority tasks first while respecting a max concurrency limit.

Asked at Google, Uber, Amazon

#promises#queue#priority#concurrency

Answer

class PriorityTaskQueue {
  constructor(concurrency = 2) {
    this.concurrency = concurrency
    this.running = 0
    this.queue = [] // { priority, task, resolve, reject, seq }
    this.seq = 0
  }

  add(task, priority = 0) {
    return new Promise((resolve, reject) => {
      this.queue.push({ task, priority, resolve, reject, seq: this.seq++ })
      // higher priority first, stable order for same priority
      this.queue.sort((a, b) =>
        b.priority - a.priority || a.seq - b.seq
      )
      this._drain()
    })
  }

  _drain() {
    while (this.running < this.concurrency && this.queue.length > 0) {
      const item = this.queue.shift()
      this.running++

      Promise.resolve()
        .then(() => item.task())
        .then(item.resolve, item.reject)
        .finally(() => {
          this.running--
          this._drain()
        })
    }
  }
}

// Usage
const q = new PriorityTaskQueue(2)
q.add(() => Promise.resolve('low-1'), 1).then(console.log)
q.add(() => Promise.resolve('high'), 10).then(console.log)
q.add(() => new Promise((r) => setTimeout(() => r('low-2'), 30)), 1).then(console.log)

Practise more Async & Promises questions →