UNPKG

scalra

Version:

node.js framework to prototype and scale rapidly

133 lines (105 loc) 4.09 kB
// // queue.js // // an advanced queue based on Stephen Morley's queue.js // to automatically handle event re-queueing // // methods: // enqueue(event, event_handler) // store a event onto queue that will be handled by 'event_handler' // activate() // allows the queue to keep execution // // NOTE: 'event_handler' needs to process event and return // 'true' for event completion // 'false' for re-queueing the event to be executed next time // 'undefined' or no return for pausing // //require('./global'); var FIFOqueue = require('./_queue'); exports.icQueue = function () { // internal queue var queue = new FIFOqueue.Queue(); // whether the queue is currently processing var busy = false; // customized handler for the queued event var handler = null; // to show current length of queue this.getLength = function () { return queue.getLength(); }; // to store a event item onto queue this.enqueue = function (item, event_handler) { var caller = arguments.callee.caller + ''; //console.log(SR.Tags.WARN + 'enqueue event, caller: ' + caller.substring(0, 100)); // must provide initial event handler // but can only have one event handler per queue, future queue will be ignored if (handler === null) { if (typeof event_handler !== 'function') { console.log(SR.Tags.ERR + 'cannot enqueue event, no handler provided' + SR.Tags.ERREND); return; } // keep a reference to event handler handler = event_handler; } // store event item in internal FIFO queue queue.enqueue(item); // execute event this.activate(); }; // start processing this.activate = function () { // activate queue processing if currently not busy if (busy === false) { busy = true; UTIL.asyncCall(processEvent); } }; // this is private method to process var processEvent = function () { // get a event from the front of queue var tmdata = queue.dequeue(); // whether to keep processing (default is no) busy = false; // check if data exists if (tmdata === undefined) { return; } // handle the event if handler is available if (handler === null) { console.log(SR.Tags.ERR + 'handler undefined, cannot process event' + ERREND); return; } switch (handler(tmdata)) { // if the event is not handled, re-queue it case false: queue.enqueue(tmdata); break; // return true, keep processing case true: break; /* // NOTE: we do not pause continuing execution, because it's possible for a event // to consider it finished, re-activate the queue (which it think it has paused), // but then the execution runs to the end of handler, and returning a undefine to pause icQueue // this will thus cause a event to indefinitely pause without any on-going progress. // // Currently if the event has returned, we assume it's been processed. // If not yet, then it's up to the handler to re-enqueue the event (by returning 'false') // note that it's possible that the previous event is still being processed // (for example, waiting for DB to return), while the next event starts processing // so the ordering may not be preserved. // The assumption we have is that events are relatively independent from each other // so such out-of-sequence processing may be "okay," as long as handler will properly re-queue the event // in case it needs to be processed again // */ // did not return anything, pause execution default: //console.log(SR.Tags.WARN + 'pause processing event, callee: ' + arguments.callee.name); return; break; } // keep processing busy = true; UTIL.asyncCall(processEvent); }; };