import debugLib from 'debug';
const debug = debugLib('SlimmingWorld:KeyedTaskQueue');
/**
* Util class that maintains queues for asynchronous tasks for each key assigned to a task.
*/
class KeyedTaskQueue {
/**
* Map of promises of running tasks for each key.
*/
queues = {};
/**
* Contains a symbol identifying the task that was last added to the queue.
* Used to determine if we should clear the queue after the task completes.
*/
lastInQueue = {};
/**
* Queues a new task
* @param generator {function} A function that returns a Promise (the task to be executed)
* @param key {string} The key that this task should queue under. If more tasks with the same
* key are already running (or queued), this task will execute after they resolve
* @returns {Promise} A promise that resolves with the result of the generator function
*/
queue(generator, key) {
const taskId = Symbol(`Task ${key}`);
const shortKey = key.substring(0, 70);
const promise = (async () => {
const currentItem = this.queues[key];
if (currentItem) {
try {
debug(`Waiting for running tasks with key "${shortKey}..."`);
await currentItem;
} catch (e) {
// ignore errors in the queue, make sure they still continue.
}
}
debug(`Executing task with key "${shortKey}..."`);
const result = await generator();
if (this.lastInQueue[key] === taskId) {
debug(`Clearing queue for key "${shortKey}..."`);
delete this.queues[key];
delete this.lastInQueue[key];
}
return result;
})();
this.queues[key] = promise;
this.lastInQueue[key] = taskId;
return promise;
}
}
export default KeyedTaskQueue;