FredKSchott / wyt

A time-based rate limiter that uses promises.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

wyt - wait your turn

Build Status Codebeat badge Codacy Badge Maintainability Coverage Status

wyt is a time-based rate limiter that uses promises.

Use Cases

  • Limiting calls to APIs that only allow a limited number of calls within a certain period.

Features

  • Promise-based API
  • Full test coverage
  • Flow typed
  • Easy to use

Installation

npm install --save wyt

Usage

Just put it in front of your HTTP requests.

import wyt from 'wyt';

// 5 api calls per second
const rateLimit = wyt(5, 1000);

async function getStuff() {
  await rateLimit();
  const response = await fetch('/stuff');
  return response.json();
}

API

const waitTurn = wyt(turnsPerInterval: number, interval: number)

  • turnsPerInterval (number): The number of turns that can be taken within a certain interval.
  • interval (number): The interval within which turnsPerInterval can be executed.

Returns a function that can be called to "take a turn".

await waitTurn(turns?: number)

  • turns (number, optional, default: 1): The number of turnsthat will be taken at the same time. You can not await more turns at the same time as turnsPerInterval.

Returns a promise that will resolve as soon as another turn can be taken. If more than turnsPerInterval are requested at the same time the promise will reject.

Example

Alice, Bob, Cindy, Derek, Elizabeth, Fred, Gwendolyn, Herbert and Iris want to buy tickets for a theater. They coincidentally queue up at the ticket desk in alphabetical order.
Derek and Elizabeth are friends and buy their tickets together.
Gwendolyn, Herbert and Iris are a group and want to buy their tickets together too.

Barbara, who works at the ticket desk, can handle 2 customers at the same time in only 1 second, and she can handle a single customer in only 0.5 seconds. But if she has to handle 3 customers at the same time it's too stressful for her and she rejects them.

import wyt from 'wyt';

/**
 * A helper function that returns the seconds that have passed.
 */
function timePassed() {
  this.start = this.start || Date.now();
  return Math.round(((Date.now() - this.start) / 1000) * 10) / 10;
}

/**
 * The ticket desk can handle 2 customers per 1000 milliseconds.
 */
const waitTurn = wyt(2, 1000);

await waitTurn();
console.log(`Alice waited ${timePassed()} seconds`);
// > Alice waited 0 seconds

await waitTurn();
console.log(`Bob waited ${timePassed()} seconds`);
// > Bob waited 0 seconds

/**
 * Alice and Bob got their tickets immediately because Barbara was prepared and
 * nobody was waiting at the ticket desk before.
 */

await waitTurn();
console.log(`Cindy waited ${timePassed()} seconds`);
// Cindy waited 0.5 seconds

/**
 * Cindy got her ticket afer half a second because Barbara can handle a single
 * customer in 1000 / 2 milliseconds.
 */

/**
 * Derek and Elizabeth go together and take 2 turns at the same time.
 */
await waitTurn(2);
console.log(`Derek and Elizabeth waited ${timePassed()} seconds`);
// Derek and Elisabeth waited 1.5 seconds

/**
 * Derek and Elizabeth had to wait a full second after Cindy because it takes
 * Barbara a whole second to process two customers.
 */

await waitTurn();
console.log(`Fred waited ${timePassed()} seconds`);
// Fred waited 2 seconds

/**
 * Fred waited a total of two seconds, but only 0.5 seconds after Derek and
 * Elizabeth.
 */

/**
 * Gwendolyn, Herbert and Iris want to buy tickets at the same time.
 */
await waitTurn(3);
console.log(`Gwendolyn waited ${timePassed()} seconds`);
// UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id:2):
//   Error: Turns can not be greater than the number of turns per interval

/**
 * Barbara can only handle 2 customers per 1000ms so she rejected the whole
 * group by throwing an exception.
 * In order to handle the group of three she would have to be able to handle 3
 * customers per 1500ms instead.
 */
 

License

Copyright (c) 2017 Max Kueng

MIT License

About

A time-based rate limiter that uses promises.

License:MIT License


Languages

Language:JavaScript 100.0%