Comparing version 1.0.4 to 1.0.5
@@ -53,3 +53,3 @@ var TokenBucket = require('./tokenBucket'); | ||
var self = this; | ||
var now = +new Date(); | ||
var now = Date.now(); | ||
@@ -91,2 +91,33 @@ // Advance the current interval and reset the current interval token count | ||
/** | ||
* Attempt to remove the requested number of tokens and return immediately. | ||
* If the bucket (and any parent buckets) contains enough tokens and we | ||
* haven't spent too many tokens in this interval already, this will return | ||
* true. Otherwise, false is returned. | ||
* @param {Number} count The number of tokens to remove. | ||
* @param {Boolean} True if the tokens were successfully removed, otherwise | ||
* false. | ||
*/ | ||
tryRemoveTokens: function(count) { | ||
// Make sure the request isn't for more than we can handle | ||
if (count > this.tokenBucket.bucketSize) | ||
return false; | ||
var now = Date.now(); | ||
// Advance the current interval and reset the current interval token count | ||
// if needed | ||
if (now - this.curIntervalStart >= this.tokenBucket.interval) { | ||
this.curIntervalStart = now; | ||
this.tokensThisInterval = 0; | ||
} | ||
// If we don't have enough tokens left in this interval, return false | ||
if (count > this.tokenBucket.tokensPerInterval - this.tokensThisInterval) | ||
return false; | ||
// Try to remove the requested number of tokens from the token bucket | ||
return this.tokenBucket.tryRemoveTokens(count); | ||
}, | ||
/** | ||
* Returns the number of tokens remaining in the TokenBucket. | ||
@@ -93,0 +124,0 @@ * @returns {Number} The number of tokens remaining. |
@@ -60,3 +60,3 @@ | ||
var self = this; | ||
// Is this an infinite size bucket? | ||
@@ -79,9 +79,4 @@ if (!this.bucketSize) { | ||
// If we don't have enough tokens in this bucket, come back later | ||
if (count > this.content) { | ||
// How long do we need to wait to make up the difference in tokens? | ||
var waitInterval = Math.ceil( | ||
(count - this.content) * (this.interval / this.tokensPerInterval)); | ||
setTimeout(function() { self.removeTokens(count, callback); }, waitInterval); | ||
return false; | ||
} | ||
if (count > this.content) | ||
return comeBackLater(); | ||
@@ -91,7 +86,8 @@ if (this.parentBucket) { | ||
return this.parentBucket.removeTokens(count, function(err, remainingTokens) { | ||
if (err) { | ||
callback(err, null); | ||
return; | ||
} | ||
if (err) return callback(err, null); | ||
// Check that we still have enough tokens in this bucket | ||
if (count > self.content) | ||
return comeBackLater(); | ||
// Tokens were removed from the parent bucket, now remove them from | ||
@@ -103,3 +99,3 @@ // this bucket and fire the callback. Note that we look at the current | ||
callback(null, Math.min(remainingTokens, self.content)); | ||
}) | ||
}); | ||
} else { | ||
@@ -111,5 +107,46 @@ // Remove the requested tokens from this bucket and fire the callback | ||
} | ||
function comeBackLater() { | ||
// How long do we need to wait to make up the difference in tokens? | ||
var waitInterval = Math.ceil( | ||
(count - self.content) * (self.interval / self.tokensPerInterval)); | ||
setTimeout(function() { self.removeTokens(count, callback); }, waitInterval); | ||
return false; | ||
} | ||
}, | ||
/** | ||
* Attempt to remove the requested number of tokens and return immediately. | ||
* If the bucket (and any parent buckets) contains enough tokens this will | ||
* return true, otherwise false is returned. | ||
* @param {Number} count The number of tokens to remove. | ||
* @param {Boolean} True if the tokens were successfully removed, otherwise | ||
* false. | ||
*/ | ||
tryRemoveTokens: function(count) { | ||
// Is this an infinite size bucket? | ||
if (!this.bucketSize) | ||
return true; | ||
// Make sure the bucket can hold the requested number of tokens | ||
if (count > this.bucketSize) | ||
return false; | ||
// Drip new tokens into this bucket | ||
this.drip(); | ||
// If we don't have enough tokens in this bucket, return false | ||
if (count > this.content) | ||
return false; | ||
// Try to remove the requested tokens from the parent bucket | ||
if (this.parentBucket && !this.parent.tryRemoveTokens(count)) | ||
return false; | ||
// Remove the requested tokens from this bucket and return | ||
this.content -= count; | ||
return true; | ||
}, | ||
/** | ||
* Add any new tokens to the bucket since the last drip. | ||
@@ -116,0 +153,0 @@ * @returns {Boolean} True if new tokens were added, otherwise false. |
{ | ||
"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.4", | ||
"version": "1.0.5", | ||
"author": "John Hurliman <jhurliman@cull.tv>", | ||
@@ -6,0 +6,0 @@ "dependencies": { }, |
@@ -71,2 +71,13 @@ | ||
A synchronous method, tryRemoveTokens(), is available in both RateLimiter and TokenBucket. This will return immediately with a boolean value indicating if the token removal was successful. | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
var limiter = new RateLimiter(10, 'second'); | ||
if (limiter.tryRemoveTokens(5)) | ||
console.log('Tokens removed'); | ||
else | ||
console.log('No tokens removed'); | ||
``` | ||
To get the number of remaining tokens **outside** the `removeTokens`-callback | ||
@@ -82,3 +93,3 @@ simply use the `getTokensRemaining`-method. | ||
Uses the token bucket directly to throttle at the byte level: | ||
Using the token bucket directly to throttle at the byte level: | ||
@@ -106,6 +117,2 @@ ```javascript | ||
## Sponsors ## | ||
* [cull.tv](http://cull.tv/) - New music television | ||
## License ## | ||
@@ -115,3 +122,3 @@ | ||
Copyright (c) 2011 Cull TV, Inc. <jhurliman@cull.tv> | ||
Copyright (c) 2013 John Hurliman. <jhurliman@jhurliman.org> | ||
@@ -118,0 +125,0 @@ Permission is hereby granted, free of charge, to any person obtaining |
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
19251
321
139