This commit is contained in:
15
node_modules/semaphore/.npmignore
generated
vendored
Normal file
15
node_modules/semaphore/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
lib-cov
|
||||
*.seed
|
||||
*.log
|
||||
*.csv
|
||||
*.dat
|
||||
*.out
|
||||
*.pid
|
||||
*.gz
|
||||
|
||||
pids
|
||||
logs
|
||||
results
|
||||
|
||||
node_modules
|
||||
npm-debug.log
|
||||
9
node_modules/semaphore/.travis.yml
generated
vendored
Normal file
9
node_modules/semaphore/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.12"
|
||||
- "0.10"
|
||||
- "0.8"
|
||||
- "4"
|
||||
- "6"
|
||||
- "8"
|
||||
sudo: false
|
||||
71
node_modules/semaphore/README.md
generated
vendored
Normal file
71
node_modules/semaphore/README.md
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
semaphore.js
|
||||
============
|
||||
|
||||
[](https://travis-ci.org/abrkn/semaphore.js)
|
||||
|
||||
Install:
|
||||
npm install semaphore
|
||||
|
||||
Limit simultaneous access to a resource.
|
||||
|
||||
```javascript
|
||||
// Create
|
||||
var sem = require('semaphore')(capacity);
|
||||
|
||||
// Take
|
||||
sem.take(fn[, n=1])
|
||||
sem.take(n, fn)
|
||||
|
||||
// Leave
|
||||
sem.leave([n])
|
||||
|
||||
// Available
|
||||
sem.available([n])
|
||||
```
|
||||
|
||||
|
||||
```javascript
|
||||
// Limit concurrent db access
|
||||
var sem = require('semaphore')(1);
|
||||
var server = require('http').createServer(req, res) {
|
||||
sem.take(function() {
|
||||
expensive_database_operation(function(err, res) {
|
||||
sem.leave();
|
||||
|
||||
if (err) return res.end("Error");
|
||||
|
||||
return res.end(res);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// 2 clients at a time
|
||||
var sem = require('semaphore')(2);
|
||||
var server = require('http').createServer(req, res) {
|
||||
res.write("Then good day, madam!");
|
||||
|
||||
sem.take(function() {
|
||||
res.end("We hope to see you soon for tea.");
|
||||
sem.leave();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Rate limit
|
||||
var sem = require('semaphore')(10);
|
||||
var server = require('http').createServer(req, res) {
|
||||
sem.take(function() {
|
||||
res.end(".");
|
||||
|
||||
setTimeout(sem.leave, 500)
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
License
|
||||
===
|
||||
|
||||
MIT
|
||||
26
node_modules/semaphore/bower.json
generated
vendored
Normal file
26
node_modules/semaphore/bower.json
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "semaphore.js",
|
||||
"version": "1.0.3",
|
||||
"homepage": "https://github.com/abrkn/semaphore.js",
|
||||
"authors": [
|
||||
"Andreas Brekken <andreas@opuno.com>"
|
||||
],
|
||||
"description": "Limit simultaneous access to a resource.",
|
||||
"main": "lib/semaphore.js",
|
||||
"moduleType": [
|
||||
"globals",
|
||||
"node"
|
||||
],
|
||||
"keywords": [
|
||||
"semaphore",
|
||||
"concurrency"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
]
|
||||
}
|
||||
101
node_modules/semaphore/lib/semaphore.js
generated
vendored
Normal file
101
node_modules/semaphore/lib/semaphore.js
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
;(function(global) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var nextTick = function (fn) { setTimeout(fn, 0); }
|
||||
if (typeof process != 'undefined' && process && typeof process.nextTick == 'function') {
|
||||
// node.js and the like
|
||||
nextTick = process.nextTick;
|
||||
}
|
||||
|
||||
function semaphore(capacity) {
|
||||
var semaphore = {
|
||||
capacity: capacity || 1,
|
||||
current: 0,
|
||||
queue: [],
|
||||
firstHere: false,
|
||||
|
||||
take: function() {
|
||||
if (semaphore.firstHere === false) {
|
||||
semaphore.current++;
|
||||
semaphore.firstHere = true;
|
||||
var isFirst = 1;
|
||||
} else {
|
||||
var isFirst = 0;
|
||||
}
|
||||
var item = { n: 1 };
|
||||
|
||||
if (typeof arguments[0] == 'function') {
|
||||
item.task = arguments[0];
|
||||
} else {
|
||||
item.n = arguments[0];
|
||||
}
|
||||
|
||||
if (arguments.length >= 2) {
|
||||
if (typeof arguments[1] == 'function') item.task = arguments[1];
|
||||
else item.n = arguments[1];
|
||||
}
|
||||
|
||||
var task = item.task;
|
||||
item.task = function() { task(semaphore.leave); };
|
||||
|
||||
if (semaphore.current + item.n - isFirst > semaphore.capacity) {
|
||||
if (isFirst === 1) {
|
||||
semaphore.current--;
|
||||
semaphore.firstHere = false;
|
||||
}
|
||||
return semaphore.queue.push(item);
|
||||
}
|
||||
|
||||
semaphore.current += item.n - isFirst;
|
||||
item.task(semaphore.leave);
|
||||
if (isFirst === 1) semaphore.firstHere = false;
|
||||
},
|
||||
|
||||
leave: function(n) {
|
||||
n = n || 1;
|
||||
|
||||
semaphore.current -= n;
|
||||
|
||||
if (!semaphore.queue.length) {
|
||||
if (semaphore.current < 0) {
|
||||
throw new Error('leave called too many times.');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var item = semaphore.queue[0];
|
||||
|
||||
if (item.n + semaphore.current > semaphore.capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
semaphore.queue.shift();
|
||||
semaphore.current += item.n;
|
||||
|
||||
nextTick(item.task);
|
||||
},
|
||||
|
||||
available: function(n) {
|
||||
n = n || 1;
|
||||
return(semaphore.current + n <= semaphore.capacity);
|
||||
}
|
||||
};
|
||||
|
||||
return semaphore;
|
||||
};
|
||||
|
||||
if (typeof exports === 'object') {
|
||||
// node export
|
||||
module.exports = semaphore;
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
// amd export
|
||||
define(function () {
|
||||
return semaphore;
|
||||
});
|
||||
} else {
|
||||
// browser global
|
||||
global.semaphore = semaphore;
|
||||
}
|
||||
}(this));
|
||||
22
node_modules/semaphore/package.json
generated
vendored
Normal file
22
node_modules/semaphore/package.json
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "semaphore",
|
||||
"version": "1.1.0",
|
||||
"description": "semaphore for node",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"main": "./lib/semaphore.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"mocha": "2.x.x",
|
||||
"should": "8.x.x"
|
||||
},
|
||||
"homepage": "https://github.com/abrkn/semaphore.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:abrkn/semaphore.js.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha"
|
||||
}
|
||||
}
|
||||
167
node_modules/semaphore/test/semaphore.js
generated
vendored
Normal file
167
node_modules/semaphore/test/semaphore.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
var should = require('should');
|
||||
var assert = require('assert');
|
||||
var semaphore = require("../lib/semaphore.js");
|
||||
require('mocha');
|
||||
|
||||
var Phone = function() {
|
||||
return {
|
||||
state: "free",
|
||||
|
||||
dial: function(callback) {
|
||||
if (this.state != "free") {
|
||||
return callback(new Error("The phone is busy"));
|
||||
}
|
||||
|
||||
this.state = "busy";
|
||||
|
||||
setTimeout(function() {
|
||||
callback();
|
||||
}, 100);
|
||||
},
|
||||
|
||||
hangup: function() {
|
||||
if (this.state == "free") {
|
||||
return callback(new Error("The phone is not in use"));
|
||||
}
|
||||
|
||||
this.state = "free";
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
it("should not be using a bad example", function(done) {
|
||||
var phone = new Phone();
|
||||
|
||||
// Call Bob
|
||||
phone.dial(function(err) {
|
||||
if (err) return done(err);
|
||||
|
||||
phone.hangup();
|
||||
});
|
||||
|
||||
// Cannot call Bret, because the phone is already busy with Bob.
|
||||
phone.dial(function(err) {
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should not break the phone", function(done) {
|
||||
var phone = new Phone();
|
||||
var sem = require('../lib/semaphore.js')(1);
|
||||
|
||||
// Call Jane
|
||||
sem.take(function() {
|
||||
phone.dial(function(err) {
|
||||
if (err) return done(err);
|
||||
|
||||
phone.hangup();
|
||||
|
||||
sem.leave();
|
||||
});
|
||||
});
|
||||
|
||||
// Call Jon (will need to wait for call with Jane to complete)
|
||||
sem.take(function() {
|
||||
phone.dial(function(err) {
|
||||
if (err) return done(err);
|
||||
|
||||
phone.hangup();
|
||||
|
||||
sem.leave();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be slow', function(done) {
|
||||
var s = require('../lib/semaphore.js')(3);
|
||||
var values = [];
|
||||
|
||||
s.take(function() { values.push(1); s.leave(); });
|
||||
s.take(function() { values.push(2); s.leave(); });
|
||||
s.take(function() { values.push(3); s.leave(); });
|
||||
s.take(function() { values.push(4); s.leave(); });
|
||||
s.take(function() { values.push(5); s.leave(); });
|
||||
|
||||
process.nextTick(function() {
|
||||
values.length.should.equal(5);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not let past more than capacity', function(done) {
|
||||
this.timeout(6000);
|
||||
|
||||
var s = require('../lib/semaphore.js')(3);
|
||||
var values = [];
|
||||
var speed = 250;
|
||||
|
||||
s.take(function() { values.push(1); setTimeout(function() { s.leave(); }, speed * 1); });
|
||||
s.take(function() { values.push(2); setTimeout(function() { s.leave(); }, speed * 2); });
|
||||
s.take(function(leave) { values.push(3); setTimeout(function() { leave(); }, speed * 3); });
|
||||
s.take(function() { values.push(4); });
|
||||
s.take(function() { values.push(5); });
|
||||
|
||||
var tickN = 0;
|
||||
|
||||
var check = function() {
|
||||
switch (tickN++) {
|
||||
case 0: // After 0 sec
|
||||
console.log("0 seconds passed.")
|
||||
s.current.should.equal(s.capacity);
|
||||
s.queue.length.should.equal(2);
|
||||
values.should.eql([1, 2, 3]);
|
||||
break;
|
||||
case 1: // After 1 sec
|
||||
console.log("1 seconds passed.");
|
||||
s.current.should.equal(s.capacity);
|
||||
s.queue.length.should.equal(1);
|
||||
values.should.eql([1, 2, 3, 4]);
|
||||
break;
|
||||
case 2: // After 2 sec
|
||||
console.log("2 seconds passed.");
|
||||
s.current.should.equal(3);
|
||||
s.queue.length.should.equal(0);
|
||||
values.should.eql([1, 2, 3, 4, 5]);
|
||||
break;
|
||||
case 3: // After 3 sec
|
||||
console.log("3 seconds passed.");
|
||||
s.current.should.equal(2);
|
||||
s.queue.length.should.equal(0);
|
||||
values.should.eql([1, 2, 3, 4, 5]);
|
||||
return done();
|
||||
}
|
||||
|
||||
setTimeout(check, speed * 1.1);
|
||||
};
|
||||
|
||||
check();
|
||||
});
|
||||
|
||||
describe("should respect number", function() {
|
||||
it("should fail when taking more than the capacity allows", function(done) {
|
||||
var s = semaphore(1);
|
||||
|
||||
s.take(2, function() {
|
||||
assert.fail();
|
||||
});
|
||||
|
||||
process.nextTick(done);
|
||||
});
|
||||
|
||||
it("should work fine with correct input values", function(done) {
|
||||
var s = semaphore(10); // 10
|
||||
|
||||
s.take(5, function(leave) { // 5
|
||||
s.take(4, function() { // 1
|
||||
leave(4); // 5
|
||||
|
||||
s.take(5, function() {
|
||||
return done()
|
||||
}); // 0
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user