rate-limiter-flexible
Advanced tools
Comparing version 0.0.4 to 0.1.0
@@ -0,1 +1,3 @@ | ||
const RateLimiterRes = require('./RateLimiterRes'); | ||
class RateLimiter { | ||
@@ -20,2 +22,8 @@ /** | ||
/** | ||
* | ||
* @param key | ||
* @param points | ||
* @returns {Promise<any>} | ||
*/ | ||
consume(key, points = 1) { | ||
@@ -29,3 +37,3 @@ return new Promise((resolve, reject) => { | ||
.exec((err, results) => { | ||
let msBeforeReset = 0; | ||
const res = new RateLimiterRes(); | ||
@@ -36,13 +44,15 @@ if (err) { | ||
const [, consumed, resTtlMs] = results; | ||
res.points = Math.max(this.points - consumed, 0); | ||
if (resTtlMs === -1) { | ||
msBeforeReset = this.duration; | ||
res.msBeforeNext = this.duration; | ||
this.redis.expire(rlKey, this.duration); | ||
} else { | ||
msBeforeReset = resTtlMs; | ||
res.msBeforeNext = resTtlMs; | ||
} | ||
if (consumed > this.points) { | ||
reject(msBeforeReset); // eslint-disable-line prefer-promise-reject-errors | ||
reject(res); | ||
} else { | ||
resolve(this.points - consumed); | ||
resolve(res); | ||
} | ||
@@ -49,0 +59,0 @@ } |
@@ -26,4 +26,4 @@ const expect = require('chai').expect; | ||
.then(() => {}) | ||
.catch((msBeforeReset) => { | ||
expect(msBeforeReset > 0).to.equal(true); | ||
.catch((rejRes) => { | ||
expect(rejRes.msBeforeNext > 0).to.equal(true); | ||
}); | ||
@@ -30,0 +30,0 @@ }); |
{ | ||
"name": "rate-limiter-flexible", | ||
"version": "0.0.4", | ||
"version": "0.1.0", | ||
"description": "Flexible API rate limiter backed by Redis for distributed node.js applications", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -0,1 +1,2 @@ | ||
[![Build Status](https://travis-ci.org/animir/node-rate-limiter-flexible.png)](https://travis-ci.org/animir/node-rate-limiter-flexible) | ||
[![Coverage Status](https://coveralls.io/repos/animir/node-rate-limiter-flexible/badge.svg?branch=master)](https://coveralls.io/r/animir/node-rate-limiter-flexible?branch=master) | ||
@@ -43,11 +44,10 @@ | ||
}) | ||
.catch((err) => { | ||
if (err instanceof Error) { | ||
.catch((rejRes) => { | ||
if (rejRes instanceof Error) { | ||
// Some Redis error | ||
// Decide what to do with it on your own | ||
} else { | ||
const msBeforeReset = err; | ||
// Can't consume | ||
// If there is no error, rateLimiter promise rejected with number of ms before next request allowed | ||
const secs = Math.round(msBeforeReset / 1000) || 1; | ||
const secs = Math.round(rejRes.msBeforeNext / 1000) || 1; | ||
res.set('Retry-After', String(secs)); | ||
@@ -61,2 +61,13 @@ res.status(429).send('Too Many Requests'); | ||
### RateLimiterRes object | ||
Both Promise resolve and reject returns object of `RateLimiterRes` class if there is no any error. | ||
Object attributes: | ||
```javascript | ||
RateLimiterRes = { | ||
msBeforeNext: 250, // Number of milliseconds before next action can be done | ||
points: 0 // Number of left points in current duration | ||
} | ||
```` | ||
### rateLimiter.consume(key, points = 1) | ||
@@ -66,5 +77,4 @@ | ||
* resolved when point(s) is consumed, so action can be done | ||
* rejected when some Redis error happened. Callback is `(err)` | ||
* rejected when there is no points to be consumed. | ||
Callback is `(err, msBeforeReset)`, where `err` is `null` and `msBeforeReset` is number of ms before next allowed action | ||
* rejected when some Redis error happened, where reject reason `rejRes` is Error object | ||
* rejected when there is no points to be consumed, where reject reason `rejRes` is `RateLimiterRes` object | ||
@@ -85,2 +95,2 @@ Arguments: | ||
Doesn't return anything | ||
Doesn't return anything |
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
8567
8
155
93