The problem
Need to manage async tasks with priorities and concurrency limits
The solution
class PriorityQueue {
constructor(maxConcurrent = 3) {
this.queue = [];
this.running = 0;
this.maxConcurrent = maxConcurrent;
this.nextId = 1;
}
add(task, priority = 0) {
const taskId = this.nextId++;
const queueItem = {
id: taskId,
task,
priority,
addedAt: Date.now(),
status: 'pending'
};
this.queue.push(queueItem);
this.queue.sort((a, b) => {
if (a.priority !== b.priority) {
return b.priority - a.priority; // Higher priority first
}
return a.addedAt - b.addedAt; // Older first if same priority
});
this.process();
return taskId;
}
async process() {
if (this.running >= this.maxConcurrent || this.queue.length === 0) {
return;
}
const nextItem = this.queue.shift();
this.running++;
nextItem.status = 'running';
try {
const result = await nextItem.task();
nextItem.status = 'completed';
nextItem.result = result;
nextItem.completedAt = Date.now();
} catch (error) {
nextItem.status = 'failed';
nextItem.error = error;
nextItem.failedAt = Date.now();
} finally {
this.running--;
this.process(); // Try to process next item
}
}
getStatus(id) {
const item = this.queue.find(item => item.id === id) ||
this.completed.find(item => item.id === id);
return item ? item.status : 'not_found';
}
setMaxConcurrent(max) {
this.maxConcurrent = max;
this.process();
}
clearPending() {
this.queue = this.queue.filter(item => item.status === 'running');
}
getStats() {
return {
pending: this.queue.length,
running: this.running,
maxConcurrent: this.maxConcurrent,
totalInQueue: this.queue.length + this.running
};
}
}
// Task Factory
function createTask(name, duration, shouldFail = false) {
return async () => {
console.log(`Starting task: ${name}`);
await new Promise(resolve => setTimeout(resolve, duration));
if (shouldFail) {
throw new Error(`Task ${name} failed!`);
}
console.log(`Completed task: ${name}`);
return `Result of ${name}`;
};
}Put it to work
const taskQueue = new PriorityQueue(2); // Max 2 concurrent tasks
// Add tasks with different priorities
taskQueue.add(createTask('Task 1', 1000), 1);
taskQueue.add(createTask('Task 2', 2000), 3); // High priority
taskQueue.add(createTask('Task 3', 1500), 2);
taskQueue.add(createTask('Task 4', 500), 1);
// Get queue stats
console.log(taskQueue.getStats());
// { pending: 2, running: 2, maxConcurrent: 2, totalInQueue: 4 }
// Update concurrency
taskQueue.setMaxConcurrent(3);
// Add task that might fail
taskQueue.add(createTask('Failing Task', 1000, true), 1);
// Clear pending tasks
// taskQueue.clearPending();