Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

rolling-window-throttler

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rolling-window-throttler - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

50

index.js
'use strict';
module.exports = require('./lib/rolling-window-throttler');
const parseDuration = require('parse-duration');
module.exports = options => {
const throttler = new RollingWindowThrottler(options);
return {
tryAcquire: key => throttler.tryAcquire(key)
};
};
class RollingWindowThrottler {
constructor(options) {
this.max = options.max;
this.durationWindow = RollingWindowThrottler.calculateDuration(options.durationWindow);
this.invocations = {};
}
tryAcquire(key) {
const invocation = this.getOrElseCreate(key);
RollingWindowThrottler.incrementInvocationCount(invocation);
if (this.isExpires(invocation)) {
delete this.invocations[key];
return this.tryAcquire(key);
}
return invocation.count <= this.max;
}
isExpires(invocation) {
return ((Date.now() - invocation.timestamp) > this.durationWindow)
}
getOrElseCreate(key) {
return this.invocations[key] || (this.invocations[key] = RollingWindowThrottler.newInvocation());
}
static newInvocation() {
return {
count: 0,
timestamp: Date.now()
};
}
static incrementInvocationCount(invocation) {
invocation.count++;
}
static calculateDuration(durationWindow) {
return isNaN(durationWindow) ? parseDuration(durationWindow) : durationWindow;
}
}

5

package.json
{
"name": "rolling-window-throttler",
"version": "1.0.0",
"version": "1.0.1",
"description": "rolling window throttler for node server",

@@ -27,4 +27,5 @@ "main": "index.js",

"chai": "~3.5.0",
"mocha": "~3.1.0"
"mocha": "~3.1.0",
"sinon": "~1.17.6"
}
}

@@ -14,3 +14,3 @@ # Rolling Window Throttler [![Build Status](https://img.shields.io/travis/wix/rolling-window-throttler-js/master.svg?label=build%20status)](https://travis-ci.org/wix/rolling-window-throttler-js) [![npm version](https://badge.fury.io/js/rolling-window-throttler-js.svg)](https://badge.fury.io/js/rolling-window-throttler-js)

const rollingWindowThrottler = require('rolling-window-throttler')
const throttler = rollingWindowThrottler.get({max: 1, durationWindow: '1s'})
const throttler = rollingWindowThrottler({max: 1, durationWindow: '1s'})

@@ -24,3 +24,3 @@ if (throttler.tryAcquire('some-key')) {

### get({max, durationWindow}): RollingWindowThrottler
### ({max, durationWindow}): RollingWindowThrottler
Create new instance of `RollingWindowThrottler`.

@@ -27,0 +27,0 @@

'use strict';
const expect = require('chai').expect,
factory = require('..');
rollingWindowThrottler = require('..'),
sinon = require('sinon');
describe('rolling window throttler', () => {
const key = '192.168.2.1';
const aThrottler = (clock, durationWindow) => factory.get({
max: 1,
durationWindow: durationWindow,
clock: clock
});
let throttler;
beforeEach(function () {
this.clock = new FakeClock();
this.throttler = aThrottler(this.clock, 1000);
});
beforeEach(() => throttler = aThrottler(1000));
it('Should allow single request', function () {
expect(this.throttler.tryAcquire(key)).to.be.true;
it('Should allow single request', () => {
expect(throttler.tryAcquire(key)).to.equal(true);
});
it('Should throttle second request', function () {
this.throttler.tryAcquire(key);
expect(this.throttler.tryAcquire(key)).to.be.false;
it('Should throttle second request', () => {
throttler.tryAcquire(key);
expect(throttler.tryAcquire(key)).to.equal(false);
});
it('should allow second request but from different key', function () {
it('should allow second request but from different key', () => {
const anotherKey = '200.200.200.1';
expect(this.throttler.tryAcquire(key)).to.be.true;
expect(this.throttler.tryAcquire(anotherKey)).to.be.true;
expect(throttler.tryAcquire(key)).to.equal(true);
expect(throttler.tryAcquire(anotherKey)).to.equal(true);
});
it('should re-allow request after the rolling window', function () {
this.throttler.tryAcquire(key);
this.clock.age(2000);
expect(this.throttler.tryAcquire(key)).to.be.true;
});
it('should work with verbal durationWindow and not milliseconds', function () {
const throttler = aThrottler(this.clock, '1s');
it('should re-allow request after the rolling window', sinon.test(function() {
throttler.tryAcquire(key);
this.clock.age(2000);
expect(throttler.tryAcquire(key)).to.be.true;
});
this.clock.tick(2000);
expect(throttler.tryAcquire(key)).to.equal(true);
}));
it('should work with verbal durationWindow and not milliseconds', sinon.test(function() {
throttler = aThrottler('1s');
throttler.tryAcquire(key);
this.clock.tick(2000);
expect(throttler.tryAcquire(key)).to.equal(true);
}));
it('Not providing clock should work, has default clock', function () {
const throttler = aThrottler(null, 1000);
expect(throttler.tryAcquire(key)).to.be.true;
});
});
class FakeClock {
constructor() {
this.currentTime = new Date().getTime();
function aThrottler(durationWindow) {
return rollingWindowThrottler({max: 1, durationWindow: durationWindow || 1000});
}
age(ms) {
this.currentTime = this.currentTime + ms;
}
currentMillis() {
return this.currentTime;
}
}
});

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