Last active
August 29, 2015 14:24
-
-
Save sndrs/a769577d27944fa8ff63 to your computer and use it in GitHub Desktop.
PoC of a JS module loading + monitoring queue – trying to avoid the '9am' rush
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Modules extend a generic queueable module, and add themselves to a global | |
// queue, which manages running them synchronously, as soon as it can (on the next tick). | |
// Running order is based on 'high', 'medium' and 'low' priorities, which modules | |
// can assign themselves. | |
// The queue also measures how long modules take to run, and if a module exceeds 10ms | |
// the queue sends a warning (probably to sentry IRL). | |
// The log() calls work best with chrome devtools, rather than the repl one | |
// QUEUE TO HANDLE REGISTRATION AND RUNNING OF MODULES | |
class ModuleQueue { | |
constructor () { | |
this.priorities = ['high', 'medium', 'low']; | |
this.maxRunTime = 10; // no module should take longer than this to run | |
// this.queue = {high: [],...} | |
this.queue = this.priorities.reduce((queue, priority) => { | |
queue[priority] = []; | |
return queue; | |
}, {}); | |
// we won't try and run anything if we already are | |
this.isRunning = false; | |
} | |
// add a module to the queue, and start the queue off if it's not already | |
registerModule (module, {run = true} = {}) { | |
console.log('registering module', module) | |
this.queue[module.priority].push(module); | |
if (run) this.runModules(); | |
} | |
// look through the queue and run any modules we find, in order | |
runModules () { | |
if (!this.isRunning) { | |
this.isRunning = true; | |
// make sure we always pull from the top of the queue, | |
// incase new modules have been registered while running the last | |
for (let i = 0, len = this.priorities.length ; i < len; i++) { | |
const module = this.queue[this.priorities[i]].shift(); | |
if (module) { | |
console.log('found module to run', module) | |
this.runModule(module); | |
return; | |
} | |
} | |
// looks like nothing was left | |
this.isRunning = false; | |
} | |
} | |
// run a given module's init() on the next tick | |
runModule (module) { | |
setTimeout(() => { | |
console.log('running module', module) | |
const then = Date.now(); | |
module.init(); // init() is the way in for each QueueableModule module | |
const now = Date.now(), duration = now - then; | |
console.log('finished running module', module, `in ${duration}ms`); | |
// handle modules taking too long (probably ping sentry) | |
if (this.maxRunTime < duration) { | |
console.log('CAREFULL!!!', module, `TOOK ${duration - this.maxRunTime}ms TOO LONG TO RUN`) | |
} | |
this.isRunning = false; | |
this.runModules(); | |
}, 0); | |
} | |
} | |
// global to house the queue | |
const moduleQueue = new ModuleQueue(); | |
// QueueableModule = the ur-module. | |
class QueueableModule { | |
// if you don't supply an init() method, your class will never be run by the queue | |
init () { | |
console.log(`${this.constructor.name}: init() MISSING`); | |
} | |
// method that subclasses can call to run themselves | |
run ({priority = 'medium'} = {}) { | |
this.priority = priority; | |
moduleQueue.registerModule(this); | |
} | |
} | |
// ****************** THESE JUST FOR DEMO PURPOSES ****************** | |
// CLASSES THAT EXTEND THE QueueableModule | |
class MyModule1 extends QueueableModule {}; | |
class MyModule2 extends QueueableModule { | |
init () { | |
console.log('hello from an instance of MyModule2'); | |
workHard(); | |
setTimeout(() => { | |
console.log('hello from an instance of MyModule2 after 2s'); | |
}, 2000) | |
} | |
}; | |
class MyModule3 extends QueueableModule { | |
init () { | |
console.log('hello from an instance of MyModule3'); | |
workHard(); | |
} | |
}; | |
// INSTANCES THAT USE THE QUEUE | |
var myModule1 = new MyModule1(); | |
myModule1.run(); | |
var myModule2 = new MyModule2(); | |
myModule2.run({priority: 'low'}); | |
var myModule3 = new MyModule3(); | |
myModule3.run({priority: 'high'}); | |
// fake a random amount of hard work | |
function workHard () { | |
for (var i=0; i<Math.floor(Math.random() * (999999999 - 999999) + 999999);i++){ | |
var y = Math.pow(i,i); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment