Skip to content

Instantly share code, notes, and snippets.

@miketromba
Created February 7, 2022 17:10
Show Gist options
  • Save miketromba/458c2e1895eea9f411d69b0d8d16b603 to your computer and use it in GitHub Desktop.
Save miketromba/458c2e1895eea9f411d69b0d8d16b603 to your computer and use it in GitHub Desktop.
FifoOperationQueueCache.js
// @ts-nocheck
function createDeferredPromise(){
let res, rej
const promise = new Promise((resolve, reject) => { [res, rej] = [resolve, reject] })
promise.resolve = res
promise.reject = rej
return promise
}
class FifoOperationQueue {
constructor({ onEmpty }){
this.onEmpty = onEmpty || function(){}
this.idGen = 0
this.queue = []
this.promises = {}
this.state = 'idle'
}
generateId(){
return this.idGen++
}
push(operation, input){
// Init queue array
const itemId = this.generateId()
this.queue.push({
operation,
input,
id: itemId
})
// Create promise
const dPromise = this.promises[itemId] = createDeferredPromise()
// Run the queue (don't await)
this.runQueue()
// Return dPromise so client can await on it's completion if it needs
return dPromise
}
async runQueue(){
// Already running, skip.
if(this.state == 'running'){ return }
// Set status to running
this.state = 'running'
// Execute operations (FIFO) until queue is empty
while(this.queue.length){
// Pull the first item from the queue
const item = this.queue.shift()
const promise = this.promises[item.id]
delete this.promises[item.id]
try {
promise.resolve(
await item.operation(item.input)
)
}
catch(e){ promise.reject(e) }
}
// Emit on empty
this.onEmpty()
// Set status for this queue to idle
this.state = 'idle'
}
}
export default class FifoOperationQueueCache {
constructor(){
this.queues = {}
}
push(queueId, operation, input){
// Init queue array
if(!this.queues[queueId]){
const self = this
this.queues[queueId] = new FifoOperationQueue({
onEmpty(){ delete self.queues[queueId] }
})
}
// Returns a promise
return this.queues[queueId].push(operation, input)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment