mirror of
https://github.com/kennethreitz/bake.git
synced 2026-06-05 23:00:17 +00:00
cleanup
This commit is contained in:
+104
@@ -0,0 +1,104 @@
|
||||
Grouped Queue [](https://travis-ci.org/SBoudrias/grouped-queue)
|
||||
==============
|
||||
|
||||
In memory queue system prioritizing tasks.
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
Installation
|
||||
-------------
|
||||
|
||||
``` bash
|
||||
$ npm install --save grouped-queue
|
||||
```
|
||||
|
||||
Methods
|
||||
------------
|
||||
|
||||
### Constructor
|
||||
|
||||
The constructor takes an optional array of task groups. The first `String` name will be the first queue to be emptied, the second string will be the second group emptied, etc.
|
||||
|
||||
By default, the constructor will always add a `default` queue in the last position. You can overwrite the position of the `default` group if you specify it explicitly.
|
||||
|
||||
``` javascript
|
||||
var Queue = require('grouped-queue');
|
||||
|
||||
var queue = new Queue([ 'first', 'second', 'third' ]);
|
||||
```
|
||||
|
||||
### Queue#add `add( [group], task, [options] )`
|
||||
|
||||
Add a task into a group queue. If no group name is specified, `default` will be used.
|
||||
|
||||
Implicitly, each time you add a task, the queue will start emptying (if not already running).
|
||||
|
||||
Each task function is passed a callback function. This callback must be called when the task is complete.
|
||||
|
||||
``` javascript
|
||||
queue.add(function( cb ) {
|
||||
DB.fetch().then( cb );
|
||||
});
|
||||
```
|
||||
|
||||
#### Option: `once`
|
||||
|
||||
You can register tasks in queues that will be dropped if they're already planned. This is done with the `once` option. You pass a String (basically a name) to the `once` option.
|
||||
|
||||
``` javascript
|
||||
// This one will eventually run
|
||||
queue.add( method, { once: "readDB" });
|
||||
|
||||
// This one will be dropped as `method` is currently in the queue
|
||||
queue.add( method3, { once: "readDB" });
|
||||
```
|
||||
|
||||
#### Option: `run`
|
||||
|
||||
You can register a task without launching the run loop by passing the argument `run: false`.
|
||||
|
||||
```javascript
|
||||
queue.add( method, { run: false });
|
||||
```
|
||||
|
||||
### Pro tip
|
||||
|
||||
Bind your tasks with context and arguments!
|
||||
|
||||
``` javascript
|
||||
var task = function( models, cb ) {
|
||||
/* you get `models` data here! */
|
||||
};
|
||||
queue.add( task.bind(null, models) );
|
||||
```
|
||||
|
||||
### That's all?
|
||||
|
||||
Yes!
|
||||
|
||||
Events
|
||||
-------------
|
||||
|
||||
### `end`
|
||||
|
||||
This event is called **each time** the queue emptied itself.
|
||||
|
||||
|
||||
Contributing
|
||||
=====================
|
||||
|
||||
**Style Guide**: Please base yourself on [Idiomatic.js](https://github.com/rwldrn/idiomatic.js) style guide with two space indent
|
||||
**Unit test**: Unit tests are written in Mocha. Please add a unit test for every new feature
|
||||
or bug fix. `npm test` to run the test suite.
|
||||
**Documentation**: Add documentation for every API change. Feel free to send corrections
|
||||
or better docs!
|
||||
**Pull Requests**: Send _fixes_ PR on the `master` branch.
|
||||
|
||||
|
||||
License
|
||||
=====================
|
||||
|
||||
Copyright (c) 2013 Simon Boudrias (twitter: @vaxilart)
|
||||
Licensed under the MIT license.
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
'use strict';
|
||||
var util = require('util');
|
||||
var events = require('events');
|
||||
var _ = require('lodash');
|
||||
var SubQueue = require('./subqueue');
|
||||
|
||||
module.exports = Queue;
|
||||
|
||||
/**
|
||||
* Queue constructor
|
||||
* @param {String[]} [subQueue] The order of the sub-queues. First one will be runned first.
|
||||
*/
|
||||
|
||||
function Queue( subQueues ) {
|
||||
subQueues = subQueues || [];
|
||||
subQueues.push('default');
|
||||
subQueues = _.uniq(subQueues);
|
||||
|
||||
this.queueNames = subQueues;
|
||||
this.__queues__ = {};
|
||||
|
||||
subQueues.forEach(function( name ) {
|
||||
this.__queues__[name] = new SubQueue();
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
util.inherits( Queue, events.EventEmitter );
|
||||
|
||||
/**
|
||||
* Add a task to a queue.
|
||||
* @param {String} [name='default'] The sub-queue to append the task
|
||||
* @param {Function} task
|
||||
* @param {Object} [opt] Options hash
|
||||
* @param {String} [opt.once] If a task with the same `once` value is inside the
|
||||
* queue, don't add this task.
|
||||
* @param {Boolean} [opt.run] If `run` is false, don't run the task.
|
||||
*/
|
||||
|
||||
Queue.prototype.add = function( name, task, opt ) {
|
||||
if ( typeof name !== 'string' ) {
|
||||
opt = task;
|
||||
task = name;
|
||||
name = 'default';
|
||||
}
|
||||
|
||||
this.__queues__[name].push( task, opt );
|
||||
|
||||
// don't run the tasks if `opt.run` is false
|
||||
if (opt && opt.run === false) return;
|
||||
setImmediate(this.run.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Start emptying the queues
|
||||
* Tasks are always run from the higher priority queue down to the lowest. After each
|
||||
* task complete, the process is re-runned from the first queue until a task is found.
|
||||
*
|
||||
* Tasks are passed a `callback` method which should be called once the task is over.
|
||||
*/
|
||||
|
||||
Queue.prototype.run = function() {
|
||||
if ( this.running ) return;
|
||||
|
||||
this.running = true;
|
||||
this._exec(function() {
|
||||
this.running = false;
|
||||
if (_(this.__queues__).map('__queue__').flatten().value().length === 0) {
|
||||
this.emit('end');
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
Queue.prototype._exec = function( done ) {
|
||||
var pointer = -1;
|
||||
var names = Object.keys( this.__queues__ );
|
||||
|
||||
var next = function next() {
|
||||
pointer++;
|
||||
if ( pointer >= names.length ) return done();
|
||||
this.__queues__[ names[pointer] ].run( next.bind(this), this._exec.bind(this, done) );
|
||||
}.bind(this);
|
||||
|
||||
next();
|
||||
};
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
var _ = require('lodash');
|
||||
|
||||
module.exports = SubQueue;
|
||||
|
||||
function SubQueue() {
|
||||
this.__queue__ = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a task to this queue
|
||||
* @param {Function} task
|
||||
*/
|
||||
|
||||
SubQueue.prototype.push = function( task, opt ) {
|
||||
opt = opt || {};
|
||||
|
||||
// Don't register named task if they're already planned
|
||||
if ( opt.once && _.find(this.__queue__, { name: opt.once }) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.__queue__.push({ task: task, name: opt.once });
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the first entry of this queue
|
||||
* @return {Function} The first task
|
||||
*/
|
||||
|
||||
SubQueue.prototype.shift = function() {
|
||||
return this.__queue__.shift();
|
||||
};
|
||||
|
||||
/**
|
||||
* Run task
|
||||
* @param {Function} skip Callback if no task is available
|
||||
* @param {Function} done Callback once the task is completed
|
||||
*/
|
||||
|
||||
SubQueue.prototype.run = function( skip, done ) {
|
||||
if ( this.__queue__.length === 0 ) return skip();
|
||||
setImmediate( this.shift().task.bind(null, done) );
|
||||
};
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "grouped-queue",
|
||||
"version": "0.3.3",
|
||||
"description": "In memory queue system prioritizing tasks",
|
||||
"main": "lib/queue.js",
|
||||
"scripts": {
|
||||
"test": "mocha -R spec"
|
||||
},
|
||||
"repository": "SBoudrias/grouped-queue",
|
||||
"keywords": [
|
||||
"queue",
|
||||
"async",
|
||||
"task",
|
||||
"flow",
|
||||
"control"
|
||||
],
|
||||
"author": "Simon Boudrias <admin@simonboudrias.com>",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^3.1.2",
|
||||
"sinon": "^1.12.2"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user