New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

bottleneck

Package Overview
Dependencies
Maintainers
1
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bottleneck - npm Package Compare versions

Comparing version 1.7.2 to 1.8.0

27

bottleneck.js

@@ -5,2 +5,3 @@ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

var Bottleneck,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
slice = [].slice;

@@ -22,2 +23,3 @@

this.strategy = strategy != null ? strategy : Bottleneck.prototype.strategy.LEAK;
this.submit = bind(this.submit, this);
this._nextRequest = Date.now();

@@ -111,2 +113,27 @@ this._nbRunning = 0;

Bottleneck.prototype.schedule = function() {
var args, task, wrapped;
task = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
wrapped = function(cb) {
return (task.apply({}, args)).then(function() {
var args;
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
return cb.apply({}, Array.prototype.concat.call([], null, args));
})["catch"](function() {
var args;
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
return cb.apply({}, Array.prototype.concat.call({}, args));
});
};
return new Promise((function(_this) {
return function(resolve, reject) {
return _this.submit.apply({}, Array.prototype.concat.call(wrapped, function() {
var args, error;
error = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
return (error != null ? reject : resolve).apply({}, args);
}));
};
})(this));
};
Bottleneck.prototype.changeSettings = function(maxNb, minTime, highWater, strategy) {

@@ -113,0 +140,0 @@ this.maxNb = maxNb != null ? maxNb : this.maxNb;

2

bottleneck.min.js

@@ -1,1 +0,1 @@

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){(function(){var Bottleneck,slice=[].slice;Bottleneck=function(){Bottleneck.strategy=Bottleneck.prototype.strategy={LEAK:1,OVERFLOW:2,BLOCK:3};Bottleneck.Cluster=Bottleneck.prototype.Cluster=require("./Cluster");function Bottleneck(maxNb,minTime,highWater,strategy){this.maxNb=maxNb!=null?maxNb:0;this.minTime=minTime!=null?minTime:0;this.highWater=highWater!=null?highWater:0;this.strategy=strategy!=null?strategy:Bottleneck.prototype.strategy.LEAK;this._nextRequest=Date.now();this._nbRunning=0;this._queue=[];this._timeouts=[];this._unblockTime=0;this.penalty=15*this.minTime||5e3;this.interrupt=false;this.reservoir=null;this.limiter=null}Bottleneck.prototype.chain=function(limiter){this.limiter=limiter;return this};Bottleneck.prototype.isBlocked=function(){return this._unblockTime>=Date.now()};Bottleneck.prototype.check=function(){return(this._nbRunning<this.maxNb||this.maxNb<=0)&&this._nextRequest-Date.now()<=0&&(this.reservoir==null||this.reservoir>0)};Bottleneck.prototype._tryToRun=function(){var done,index,next,wait;if((this._nbRunning<this.maxNb||this.maxNb<=0)&&this._queue.length>0&&(this.reservoir==null||this.reservoir>0)){this._nbRunning++;if(this.reservoir!=null){this.reservoir--}wait=Math.max(this._nextRequest-Date.now(),0);this._nextRequest=Date.now()+wait+this.minTime;next=this._queue.shift();done=false;index=-1+this._timeouts.push(setTimeout(function(_this){return function(){var completed;completed=function(){var ref;if(!done){done=true;delete _this._timeouts[index];_this._nbRunning--;_this._tryToRun();if(!_this.interrupt){return(ref=next.cb)!=null?ref.apply({},Array.prototype.slice.call(arguments,0)):void 0}}};if(_this.limiter!=null){return _this.limiter.submit.apply(_this.limiter,Array.prototype.concat.call(next.task,next.args,completed))}else{return next.task.apply({},next.args.concat(completed))}}}(this),wait));return true}else{return false}};Bottleneck.prototype.submit=function(){var args,cb,i,reachedHighWaterMark,task;task=arguments[0],args=3<=arguments.length?slice.call(arguments,1,i=arguments.length-1):(i=1,[]),cb=arguments[i++];reachedHighWaterMark=this.highWater>0&&this._queue.length===this.highWater;if(this.strategy===Bottleneck.prototype.strategy.BLOCK&&(reachedHighWaterMark||this.isBlocked())){this._unblockTime=Date.now()+this.penalty;this._nextRequest=this._unblockTime+this.minTime;this._queue=[];return true}else if(reachedHighWaterMark){if(this.strategy===Bottleneck.prototype.strategy.LEAK){this._queue.shift()}else if(this.strategy===Bottleneck.prototype.strategy.OVERFLOW){return reachedHighWaterMark}}this._queue.push({task:task,args:args,cb:cb});this._tryToRun();return reachedHighWaterMark};Bottleneck.prototype.changeSettings=function(maxNb,minTime,highWater,strategy){this.maxNb=maxNb!=null?maxNb:this.maxNb;this.minTime=minTime!=null?minTime:this.minTime;this.highWater=highWater!=null?highWater:this.highWater;this.strategy=strategy!=null?strategy:this.strategy;while(this._tryToRun()){}return this};Bottleneck.prototype.changePenalty=function(penalty){this.penalty=penalty!=null?penalty:this.penalty;return this};Bottleneck.prototype.changeReservoir=function(reservoir){this.reservoir=reservoir;while(this._tryToRun()){}return this};Bottleneck.prototype.incrementReservoir=function(incr){if(incr==null){incr=0}this.changeReservoir(this.reservoir+incr);return this};Bottleneck.prototype.stopAll=function(interrupt){var a,i,len,ref;this.interrupt=interrupt!=null?interrupt:this.interrupt;ref=this._timeouts;for(i=0,len=ref.length;i<len;i++){a=ref[i];clearTimeout(a)}this._tryToRun=function(){};this.submit=function(){return false};return this.check=function(){return false}};return Bottleneck}();module.exports=Bottleneck}).call(this)},{"./Cluster":2}],2:[function(require,module,exports){(function(){var Cluster,hasProp={}.hasOwnProperty;Cluster=function(){function Cluster(maxNb,minTime,highWater,strategy){var base;this.maxNb=maxNb;this.minTime=minTime;this.highWater=highWater;this.strategy=strategy;this.limiters={};this.Bottleneck=require("./Bottleneck");if(typeof(base=setInterval(function(_this){return function(){var k,ref,results,time,v;time=Date.now();ref=_this.limiters;results=[];for(k in ref){v=ref[k];if(v._nextRequest+60*1e3*5<time){results.push(delete _this.limiters[k])}else{results.push(void 0)}}return results}}(this),60*1e3)).unref==="function"){base.unref()}}Cluster.prototype.key=function(key){var ref;if(key==null){key=""}return(ref=this.limiters[key])!=null?ref:this.limiters[key]=new this.Bottleneck(this.maxNb,this.minTime,this.highWater,this.strategy)};Cluster.prototype.all=function(cb){var k,ref,results,v;ref=this.limiters;results=[];for(k in ref){if(!hasProp.call(ref,k))continue;v=ref[k];results.push(cb(v))}return results};Cluster.prototype.keys=function(){return Object.keys(this.limiters)};return Cluster}();module.exports=Cluster}).call(this)},{"./Bottleneck":1}],3:[function(require,module,exports){(function(global){(function(){module.exports=require("./Bottleneck");if(global.window!=null){global.window.Bottleneck=module.exports}}).call(this)}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./Bottleneck":1}]},{},[3]);
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){(function(){var Bottleneck,bind=function(fn,me){return function(){return fn.apply(me,arguments)}},slice=[].slice;Bottleneck=function(){Bottleneck.strategy=Bottleneck.prototype.strategy={LEAK:1,OVERFLOW:2,BLOCK:3};Bottleneck.Cluster=Bottleneck.prototype.Cluster=require("./Cluster");function Bottleneck(maxNb,minTime,highWater,strategy){this.maxNb=maxNb!=null?maxNb:0;this.minTime=minTime!=null?minTime:0;this.highWater=highWater!=null?highWater:0;this.strategy=strategy!=null?strategy:Bottleneck.prototype.strategy.LEAK;this.submit=bind(this.submit,this);this._nextRequest=Date.now();this._nbRunning=0;this._queue=[];this._timeouts=[];this._unblockTime=0;this.penalty=15*this.minTime||5e3;this.interrupt=false;this.reservoir=null;this.limiter=null}Bottleneck.prototype.chain=function(limiter){this.limiter=limiter;return this};Bottleneck.prototype.isBlocked=function(){return this._unblockTime>=Date.now()};Bottleneck.prototype.check=function(){return(this._nbRunning<this.maxNb||this.maxNb<=0)&&this._nextRequest-Date.now()<=0&&(this.reservoir==null||this.reservoir>0)};Bottleneck.prototype._tryToRun=function(){var done,index,next,wait;if((this._nbRunning<this.maxNb||this.maxNb<=0)&&this._queue.length>0&&(this.reservoir==null||this.reservoir>0)){this._nbRunning++;if(this.reservoir!=null){this.reservoir--}wait=Math.max(this._nextRequest-Date.now(),0);this._nextRequest=Date.now()+wait+this.minTime;next=this._queue.shift();done=false;index=-1+this._timeouts.push(setTimeout(function(_this){return function(){var completed;completed=function(){var ref;if(!done){done=true;delete _this._timeouts[index];_this._nbRunning--;_this._tryToRun();if(!_this.interrupt){return(ref=next.cb)!=null?ref.apply({},Array.prototype.slice.call(arguments,0)):void 0}}};if(_this.limiter!=null){return _this.limiter.submit.apply(_this.limiter,Array.prototype.concat.call(next.task,next.args,completed))}else{return next.task.apply({},next.args.concat(completed))}}}(this),wait));return true}else{return false}};Bottleneck.prototype.submit=function(){var args,cb,i,reachedHighWaterMark,task;task=arguments[0],args=3<=arguments.length?slice.call(arguments,1,i=arguments.length-1):(i=1,[]),cb=arguments[i++];reachedHighWaterMark=this.highWater>0&&this._queue.length===this.highWater;if(this.strategy===Bottleneck.prototype.strategy.BLOCK&&(reachedHighWaterMark||this.isBlocked())){this._unblockTime=Date.now()+this.penalty;this._nextRequest=this._unblockTime+this.minTime;this._queue=[];return true}else if(reachedHighWaterMark){if(this.strategy===Bottleneck.prototype.strategy.LEAK){this._queue.shift()}else if(this.strategy===Bottleneck.prototype.strategy.OVERFLOW){return reachedHighWaterMark}}this._queue.push({task:task,args:args,cb:cb});this._tryToRun();return reachedHighWaterMark};Bottleneck.prototype.schedule=function(){var args,task,wrapped;task=arguments[0],args=2<=arguments.length?slice.call(arguments,1):[];wrapped=function(cb){return task.apply({},args).then(function(){var args;args=1<=arguments.length?slice.call(arguments,0):[];return cb.apply({},Array.prototype.concat.call([],null,args))})["catch"](function(){var args;args=1<=arguments.length?slice.call(arguments,0):[];return cb.apply({},Array.prototype.concat.call({},args))})};return new Promise(function(_this){return function(resolve,reject){return _this.submit.apply({},Array.prototype.concat.call(wrapped,function(){var args,error;error=arguments[0],args=2<=arguments.length?slice.call(arguments,1):[];return(error!=null?reject:resolve).apply({},args)}))}}(this))};Bottleneck.prototype.changeSettings=function(maxNb,minTime,highWater,strategy){this.maxNb=maxNb!=null?maxNb:this.maxNb;this.minTime=minTime!=null?minTime:this.minTime;this.highWater=highWater!=null?highWater:this.highWater;this.strategy=strategy!=null?strategy:this.strategy;while(this._tryToRun()){}return this};Bottleneck.prototype.changePenalty=function(penalty){this.penalty=penalty!=null?penalty:this.penalty;return this};Bottleneck.prototype.changeReservoir=function(reservoir){this.reservoir=reservoir;while(this._tryToRun()){}return this};Bottleneck.prototype.incrementReservoir=function(incr){if(incr==null){incr=0}this.changeReservoir(this.reservoir+incr);return this};Bottleneck.prototype.stopAll=function(interrupt){var a,i,len,ref;this.interrupt=interrupt!=null?interrupt:this.interrupt;ref=this._timeouts;for(i=0,len=ref.length;i<len;i++){a=ref[i];clearTimeout(a)}this._tryToRun=function(){};this.submit=function(){return false};return this.check=function(){return false}};return Bottleneck}();module.exports=Bottleneck}).call(this)},{"./Cluster":2}],2:[function(require,module,exports){(function(){var Cluster,hasProp={}.hasOwnProperty;Cluster=function(){function Cluster(maxNb,minTime,highWater,strategy){var base;this.maxNb=maxNb;this.minTime=minTime;this.highWater=highWater;this.strategy=strategy;this.limiters={};this.Bottleneck=require("./Bottleneck");if(typeof(base=setInterval(function(_this){return function(){var k,ref,results,time,v;time=Date.now();ref=_this.limiters;results=[];for(k in ref){v=ref[k];if(v._nextRequest+60*1e3*5<time){results.push(delete _this.limiters[k])}else{results.push(void 0)}}return results}}(this),60*1e3)).unref==="function"){base.unref()}}Cluster.prototype.key=function(key){var ref;if(key==null){key=""}return(ref=this.limiters[key])!=null?ref:this.limiters[key]=new this.Bottleneck(this.maxNb,this.minTime,this.highWater,this.strategy)};Cluster.prototype.all=function(cb){var k,ref,results,v;ref=this.limiters;results=[];for(k in ref){if(!hasProp.call(ref,k))continue;v=ref[k];results.push(cb(v))}return results};Cluster.prototype.keys=function(){return Object.keys(this.limiters)};return Cluster}();module.exports=Cluster}).call(this)},{"./Bottleneck":1}],3:[function(require,module,exports){(function(global){(function(){module.exports=require("./Bottleneck");if(global.window!=null){global.window.Bottleneck=module.exports}}).call(this)}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./Bottleneck":1}]},{},[3]);
// Generated by CoffeeScript 1.9.2
(function() {
var Bottleneck,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
slice = [].slice;

@@ -20,2 +21,3 @@

this.strategy = strategy != null ? strategy : Bottleneck.prototype.strategy.LEAK;
this.submit = bind(this.submit, this);
this._nextRequest = Date.now();

@@ -109,2 +111,27 @@ this._nbRunning = 0;

Bottleneck.prototype.schedule = function() {
var args, task, wrapped;
task = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
wrapped = function(cb) {
return (task.apply({}, args)).then(function() {
var args;
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
return cb.apply({}, Array.prototype.concat.call([], null, args));
})["catch"](function() {
var args;
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
return cb.apply({}, Array.prototype.concat.call({}, args));
});
};
return new Promise((function(_this) {
return function(resolve, reject) {
return _this.submit.apply({}, Array.prototype.concat.call(wrapped, function() {
var args, error;
error = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
return (error != null ? reject : resolve).apply({}, args);
}));
};
})(this));
};
Bottleneck.prototype.changeSettings = function(maxNb, minTime, highWater, strategy) {

@@ -111,0 +138,0 @@ this.maxNb = maxNb != null ? maxNb : this.maxNb;

{
"name": "bottleneck",
"version": "1.7.2",
"version": "1.8.0",
"description": "Async rate limiter",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -12,3 +12,3 @@ # bottleneck

It's battle-hardened, reliable and production-ready. [Unblock.us.org](http://unblock.us.org) uses it to serve millions of queries per day.
It's battle-hardened, reliable and production-ready. [DNSChain](https://github.com/okTurtles/dnschain) uses it to serve millions of queries per day.

@@ -53,2 +53,4 @@

Promise users can use [`schedule()`](https://github.com/SGrondin/bottleneck#schedule).
Bottleneck builds a queue of requests and executes them as soon as possible. All the requests will be executed *in order*.

@@ -83,7 +85,21 @@

### schedule()
Adds a request to the queue. This is the Promise version of `submit`. It uses the built-in [Promise](http://caniuse.com/#feat=promises) object.
```js
var fn = function(arg1, arg2, argN) {
return httpGet(arg1, arg2, argN); # Here httpGet() returns a promise
};
limiter.schedule(fn, arg1, arg2, argN);
```
In plain language, `schedule` takes a function fn and a list of arguments. Fn must return a promise. `schedule` returns a promise that will be executed according to the rate limits. It's safe to mix `submit` and `schedule` in the same limiter.
#### Gotchas
* If a callback isn't necessary, you must pass `null` or an empty function instead. It will not work if you forget to do this.
* When using `submit`, if a callback isn't necessary, you must pass `null` or an empty function instead. It will not work if you forget to do this.
* Make sure that all the requests will eventually complete by calling their callback! Again, even if you submitted your request with a `null` callback , it still needs to call its callback. This is very important if you are using a `maxConcurrent` value that isn't `0` (unlimited), otherwise those uncompleted requests will be clogging up the limiter and no new requests will be getting through. It's safe to call the callback more than once, subsequent calls are ignored.
* Make sure that all the requests will eventually complete by calling their callback or resolving/rejecting (in the case of promises). Again, even if you `submit`ted your request with a `null` callback , it still needs to call its callback. This is very important if you are using a `maxConcurrent` value that isn't `0` (unlimited), otherwise those uncompleted requests will be clogging up the limiter and no new requests will be getting through. It's safe to call the callback more than once, subsequent calls are ignored.

@@ -94,3 +110,3 @@ * If you want to rate limit a synchronous function (console.log(), for example), you must wrap it in a closure to make it asynchronous. See [this](https://github.com/SGrondin/bottleneck#rate-limiting-synchronous-functions) example.

A strategy is a simple algorithm that is executed every time `submit` would cause the queue to exceed `highWater`.
A strategy is a simple algorithm that is executed every time adding a request would cause the queue to exceed `highWater`.

@@ -112,3 +128,3 @@ #### Bottleneck.strategy.LEAK

```
If a request was submitted right now, would it be run immediately? Returns a boolean.
If a request was added right now, would it be run immediately? Returns a boolean.

@@ -128,3 +144,3 @@ ### isBlocked()

```
Cancels all *queued up* requests and prevents additonal requests from being submitted.
Cancels all *queued up* requests and prevents additonal requests from being added.

@@ -143,3 +159,3 @@ * `interrupt` : If true, prevent the requests currently running from calling their callback when they're done. *Default: `false`*

For example, imagine that 3 60-second requests are submitted at time T+0 with `maxConcurrent = 0` and `minTime = 2000`. The requests will be launched at T+0 seconds, T+2 seconds and T+4 seconds respectively. If right after adding the requests to Bottleneck, you were to call `limiter.changeSettings(1);`, it won't change the fact that there will be 3 requests running at the same time for roughly 60 seconds. Once again, `changeSettings` only affects requests that have not yet been *submitted*.
For example, imagine that 3 60-second requests are submitted at time T+0 with `maxConcurrent = 0` and `minTime = 2000`. The requests will be launched at T+0 seconds, T+2 seconds and T+4 seconds respectively. If right after adding the requests to Bottleneck, you were to call `limiter.changeSettings(1);`, it won't change the fact that there will be 3 requests running at the same time for roughly 60 seconds. Once again, `changeSettings` only affects requests that have not yet been added.

@@ -170,3 +186,3 @@ This is by design, as Bottleneck made a promise to execute those requests according to the settings valid at the time. Changing settings afterwards should not break previous assumptions, as that would make code very error-prone and Bottleneck a tool that cannot be relied upon.

* `limiter` : If another limiter is passed, tasks that are ready to be executed will be submitted to that other limiter. *Default: `null` (none)*
* `limiter` : If another limiter is passed, tasks that are ready to be executed will be added to that other limiter. *Default: `null` (none)*

@@ -180,5 +196,5 @@ Suppose you have 2 types of tasks, A and B. They both have their own limiter with their own settings, but both must also follow a global limiter C:

limiterB.chain(limiterC);
// Requests submitted to limiterA must follow the A and C rate limits.
// Requests submitted to limiterB must follow the B and C rate limits.
// Requests submitted to limiterC must follow the C rate limits.
// Requests added to limiterA must follow the A and C rate limits.
// Requests added to limiterB must follow the B and C rate limits.
// Requests added to limiterC must follow the C rate limits.
```

@@ -188,6 +204,6 @@

Bottleneck will execute every submitted request in order. They will **all** *eventually* be executed as long as:
Bottleneck will execute every request in order. They will **all** *eventually* be executed as long as:
* `highWater` is set to `0` (default), which prevents the strategy from ever being run.
* `maxConcurrent` is set to `0` (default) **OR** all requests call the callback *eventually*.
* `maxConcurrent` is set to `0` (default) **OR** all requests call the callback *eventually* (in the case of promises, they must be resolved or rejected eventually).
* `reservoir` is `null` (default).

@@ -200,3 +216,3 @@

The `Cluster` feature of Bottleneck manages limiters automatically for you. It is created exactly like a limiter:
The `Cluster` feature of Bottleneck manages limiters automatically for you. It creates limiters dynamically and transparently. A cluster is created exactly like a limiter:

@@ -207,3 +223,3 @@ ```js

Those arguments are the same as for a basic limiter. The cluster is then used with the `.key(str)` method:
The cluster is then used with the `.key(str)` method:

@@ -210,0 +226,0 @@ ```js

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc