JSPM

  • Created
  • Published
  • Downloads 2655426
  • Score
    100M100P100Q218532F
  • License MIT

Automatic rate limiting plugin for octokit

Package Exports

  • @octokit/plugin-throttling

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@octokit/plugin-throttling) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

plugin-throttling.js

Octokit plugin for GitHub’s recommended request throttling

npm Build Status Coverage Status Greenkeeper

Implements all recommended best practises to prevent hitting abuse rate limits.

Usage

The code below creates a "Hello, world!" issue on every repository in a given organization. Without the throttling plugin it would send many requests in parallel and would hit rate limits very quickly. But the @octokit/plugin-throttling slows down your requests according to the official guidelines, so you don't get blocked before your quota is exhausted.

The throttle.onAbuseLimit and throttle.onRateLimit options are required. Return true to automatically retry the request after retryAfter seconds.

const Octokit = require('@octokit/rest')
  .plugin(require('@octokit/plugin-throttling'))

const octokit = new Octokit({
  auth: `token ${process.env.TOKEN}`,
  throttle: {
    onRateLimit: (retryAfter, options) => {
      console.warn(`Request quota exhausted for request ${options.method} ${options.url}`)

      if (options.request.retryCount === 0) { // only retries once
        console.log(`Retrying after ${retryAfter} seconds!`)
        return true
      }
    },
    onAbuseLimit: (retryAfter, options) => {
      // does not retry, only logs a warning
      console.warn(`Abuse detected for request ${options.method} ${options.url}`)
    }
  }
})

async function createIssueOnAllRepos (org) {
  const repos = await octokit.paginate(octokit.repos.listForOrg.endpoint({ org }))
  return Promise.all(repos.forEach(({ name } => {
    octokit.issues.create({
      owner,
      repo: name,
      title: 'Hello, world!'
    })
  })))
}

Pass { throttle: { enabled: false } } to disable this plugin.

Clustering

Enabling Clustering support ensures that your application will not go over rate limits across Octokit instances and across Nodejs processes.

First install either redis or ioredis:

# NodeRedis (https://github.com/NodeRedis/node_redis)
npm install --save redis

# or ioredis (https://github.com/luin/ioredis)
npm install --save ioredis

Then in your application:

const Bottleneck = require('bottleneck')
const Redis = require('redis')

const client = Redis.createClient({ /* options */ })
const connection = new Bottleneck.RedisConnection({ client })
connection.on('error', err => console.error(err))

const octokit = new Octokit({
  throttle: {
    onAbuseLimit: (retryAfter, options) => { /* ... */ },
    onRateLimit: (retryAfter, options) => { /* ... */ },

    // The Bottleneck connection object
    connection,

    // A "throttling ID". All octokit instances with the same ID
    // using the same Redis server will share the throttling.
    id: 'my-super-app',

    // Otherwise the plugin uses a lighter version of Bottleneck without Redis support
    Bottleneck
  }
})

// To close the connection and allow your application to exit cleanly:
await connection.disconnect()

To use the ioredis library instead:

const Redis = require('ioredis')
const client = new Redis({ /* options */ })
const connection = new Bottleneck.IORedisConnection({ client })
connection.on('error', err => console.error(err))

LICENSE

MIT