I'm just trying my luck here because I didn't get an answer in about every other JS thread I could think of.
I am trying to make a queue system where my app can handle 1 job at a time. The jobs can come from different queues where users have to wait for the previous user before their job can be picked up. The previous user can either send a signal they are "done" in 30 seconds after their job finished, or the signal will be sent automatically after 30 seconds so that the next user in that queue has a chance for their job to be picked up. I am trying to achieve the functionality I added in comments:
enum Title {
A,
B,
}
const createQueue = () => {
let tailPromise = Promise.resolve();
return {
add: (job: (...args: unknown[]) => Promise<void>) => {
const promise = tailPromise.then(job);
tailPromise = promise;
return promise;
},
};
};
export const createTitleQueueManager = () => {
const queue = createQueue();
const queues = {
[Title.A]: createQueue(),
[Title.B]: createQueue(),
};
return {
requestTitle: async (title: Title, signal: AbortSignal) => {
let success = false;
const cancelled = new Promise((resolve) => {
signal.addEventListener("abort", resolve, { once: true });
});
await queues[title].add(async () => {
await queue.add(async () => {
await setTimeout(5_000);
success = true;
});
// Want to return the success status to the caller here...
// Then wait for the caller to send an abort signal before 30 seconds
// Or resolve after 30 seconds if no signal was sent
await Promise.race([cancelled, setTimeout(30_000)]);
});
// Don't want to return success here because Promise.race already happened
return { success };
},
};
}
The reason I'd like to achieve this is so that I can have this usage at the caller side: https://sourceb.in/lEhsIvnhAb