This commit is contained in:
2019-09-17 13:20:42 -04:00
parent d211d1dc34
commit bef10ce4c9
8352 changed files with 568242 additions and 51 deletions
+104
View File
@@ -0,0 +1,104 @@
Grouped Queue [![Build Status](https://travis-ci.org/SBoudrias/grouped-queue.svg?branch=master)](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
View File
@@ -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
View File
@@ -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
View File
@@ -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"
}
}