Comparing version 1.0.1 to 1.0.2
@@ -6,4 +6,4 @@ var TokenBucket = require('./tokenBucket'); | ||
* an additional check to limit how many tokens we can remove each interval. | ||
* @author John Hurliman <jhurliman@cull.tv> | ||
* | ||
* @author John Hurliman <jhurliman@jhurliman.org> | ||
* | ||
* @param {Number} tokensPerInterval Maximum number of tokens that can be | ||
@@ -13,4 +13,6 @@ * removed at any given moment and over the course of one interval. | ||
* one of the following strings: 'second', 'minute', 'hour', day'. | ||
* @param {Boolean} fireImmediately Optional. Whether or not the callback | ||
* will fire immediately when rate limiting is in effect (default is false). | ||
*/ | ||
var RateLimiter = function(tokensPerInterval, interval) { | ||
var RateLimiter = function(tokensPerInterval, interval, fireImmediately) { | ||
this.tokenBucket = new TokenBucket(tokensPerInterval, tokensPerInterval, | ||
@@ -24,2 +26,3 @@ interval, null); | ||
this.tokensThisInterval = 0; | ||
this.fireImmediately = fireImmediately; | ||
}; | ||
@@ -31,2 +34,3 @@ | ||
tokensThisInterval: 0, | ||
fireImmediately: false, | ||
@@ -65,9 +69,12 @@ /** | ||
if (count > this.tokenBucket.tokensPerInterval - this.tokensThisInterval) { | ||
var waitInterval = Math.ceil( | ||
this.curIntervalStart + this.tokenBucket.interval - now); | ||
setTimeout(function() { | ||
self.tokenBucket.removeTokens(count, afterTokensRemoved); | ||
}, waitInterval); | ||
if (this.fireImmediately) { | ||
callback(null, -1); | ||
} else { | ||
var waitInterval = Math.ceil( | ||
this.curIntervalStart + this.tokenBucket.interval - now); | ||
setTimeout(function() { | ||
self.tokenBucket.removeTokens(count, afterTokensRemoved); | ||
}, waitInterval); | ||
} | ||
return false; | ||
@@ -74,0 +81,0 @@ } |
{ | ||
"name": "limiter", | ||
"description": "A generic rate limiter for node.js. Useful for API clients, web crawling, or other tasks that need to be throttled", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"author": "John Hurliman <jhurliman@cull.tv>", | ||
@@ -6,0 +6,0 @@ "dependencies": { }, |
@@ -22,40 +22,66 @@ | ||
var RateLimiter = require('limiter').RateLimiter; | ||
// Allow 150 requests per hour (the Twitter search limit). Also understands | ||
// 'second', 'minute', 'day', or a number of milliseconds | ||
var limiter = new RateLimiter(150, 'hour'); | ||
// Throttle requests | ||
limiter.removeTokens(1, function(err, remainingRequests) { | ||
// err will only be set if we request more than the maximum number of | ||
// requests we set in the constructor | ||
// remainingRequests tells us how many additional requests could be sent | ||
// right this moment | ||
callMyRequestSendingFunction(...); | ||
}); | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
// Allow 150 requests per hour (the Twitter search limit). Also understands | ||
// 'second', 'minute', 'day', or a number of milliseconds | ||
var limiter = new RateLimiter(150, 'hour'); | ||
// Throttle requests | ||
limiter.removeTokens(1, function(err, remainingRequests) { | ||
// err will only be set if we request more than the maximum number of | ||
// requests we set in the constructor | ||
// remainingRequests tells us how many additional requests could be sent | ||
// right this moment | ||
callMyRequestSendingFunction(...); | ||
}); | ||
``` | ||
Another example allowing one message to be sent every 250ms: | ||
var RateLimiter = require('limiter').RateLimiter; | ||
var limiter = new RateLimiter(1, 250); | ||
limiter.removeTokens(1, function() { | ||
callMyMessageSendingFunction(...); | ||
}); | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
var limiter = new RateLimiter(1, 250); | ||
limiter.removeTokens(1, function() { | ||
callMyMessageSendingFunction(...); | ||
}); | ||
``` | ||
The default behaviour is to wait for the duration of the rate limiting | ||
that’s currently in effect before the callback is fired, but if you | ||
pass in ```true``` as the third parameter, the callback will be fired | ||
immediately with remainingRequests set to -1: | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
var limiter = new RateLimiter(150, 'hour', true); // fire CB immediately | ||
// Immediately send 429 header to client when rate limiting is in effect | ||
limiter.removeTokens(1, function(err, remainingRequests) { | ||
if (remainingRequests < 0) { | ||
response.writeHead(429, {'Content-Type': 'text/plain;charset=UTF-8'}); | ||
response.end('429 Too Many Requests - your IP is being rate limited'); | ||
} else { | ||
callMyMessageSendingFunction(...); | ||
} | ||
}); | ||
``` | ||
Uses the token bucket directly to throttle at the byte level: | ||
var BURST_RATE = 1024 * 1024 * 150; // 150KB/sec burst rate | ||
var FILL_RATE = 1024 * 1024 * 50; // 50KB/sec sustained rate | ||
var TokenBucket = require('limiter').TokenBucket; | ||
// We could also pass a parent token bucket in as the last parameter to | ||
// create a hierarchical token bucket | ||
var bucket = new TokenBucket(BURST_RATE, FILL_RATE, 'second', null); | ||
bucket.removeTokens(myData.byteLength, function() { | ||
sendMyData(myData); | ||
}); | ||
```javascript | ||
var BURST_RATE = 1024 * 1024 * 150; // 150KB/sec burst rate | ||
var FILL_RATE = 1024 * 1024 * 50; // 50KB/sec sustained rate | ||
var TokenBucket = require('limiter').TokenBucket; | ||
// We could also pass a parent token bucket in as the last parameter to | ||
// create a hierarchical token bucket | ||
var bucket = new TokenBucket(BURST_RATE, FILL_RATE, 'second', null); | ||
bucket.removeTokens(myData.byteLength, function() { | ||
sendMyData(myData); | ||
}); | ||
``` | ||
## Additional Notes ## | ||
@@ -62,0 +88,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15909
258
122