Skip to content

Latest commit

 

History

History
82 lines (60 loc) · 2.99 KB

README.md

File metadata and controls

82 lines (60 loc) · 2.99 KB

🚓 SpeedTrap

Tired of blowing 3rd party API rate limits? Does your 3rd party API keep counting requests even when it returns a 429? Does your app run in a distributed environment? Does your app have a "heavy foot"?? Then this library is for you! SpeedTrap is a tool that uses redis to keep track of your speed. Just run() the SpeedTrap with your function and parameters, and get a Promise back with your result. But watch your speed! If you go too fast, the SpeedTrap Will catch you and ticket you with a rejected Promise. You wont be running anywhere.

Config options

Name Type Description Default
duration Integer the duration of the sliding window for speed calculation
letOffWithAWarning Boolean when true will allow your function to still run when the speed limit is exceeded false
name String the unique name of your SpeedTrap used to create redis keys
onExceeded Function an optional function that will be called when the speed limit is exceeded noop
max Integer the number off allowed calls per sliding duration window
redis redis client the redis client to be used for tracking the rate

Usage

Create the SpeedTrap with your options object. Then when you are ready, call speedTrap.run() with your function and parameters

const { SpeedTrap } = require('@articulate/speedtrap')
const RedisClient = require('ioredis')

const redisClient = new RedisClient('my-redis-url')

function onRateLimitExceeded(info) {
  const {
    waitTime // The time (ms) until a run can be made again
  } = info

  console.info(`Speed limit exceeded, must wait at least ${waitTime}ms`)
}

const config = {
  name: 'my-speed-trap',
  duration: 2000,
  max: 200,
  onExceeded: onRateLimitExceeded,
  redis: redisClient,
}

const speedTrap = new SpeedTrap(config)

function makeApiCall(param1, param2) {
  return /* a call to a crummy rate limited 3rd party marketing api */
}

speedTrap.run(myApiCall, param1, param2)
  .then(doOtherThings)
  .catch((error) => {
    if (error.isSpeedTrap) {
      // We were going too fast!! API call was not made. Maybe we sleep and retry?
      console.log(`got ticketed, gonna have to wait ${error.waitTime}ms`)
    } else {
      throw error // not from speeding...
    }
  })

Let off with a warning

Want to be let off with a warning? Better hope you get a nice officer. The letOffWithAWarning configuration option will allow your function to continue running, but rest assured a warning will still be issued to the handler you provided for the onExceeded option.

Contributing

If you have Docker Compose installed, you can run lint and tests with:

docker compose run --rm test

Run tests in watch mode with:

docker compose run --rm test yarn test --watchAll

You can also run without Docker Compose by setting a REDIS_URL environment variable.

REDIS_URL=redis://localhost:6379 yarn test