UNPKG

3.82 kBMarkdownView Raw
1# plugin-throttling.js
2
3> Octokit plugin for GitHub’s recommended request throttling
4
5[![npm](https://img.shields.io/npm/v/@octokit/plugin-throttling.svg)](https://www.npmjs.com/package/@octokit/plugin-throttling)
6[![Build Status](https://travis-ci.com/octokit/plugin-throttling.js.svg)](https://travis-ci.com/octokit/plugin-throttling.js)
7[![Coverage Status](https://img.shields.io/coveralls/github/octokit/plugin-throttling.js.svg)](https://coveralls.io/github/octokit/plugin-throttling.js)
8[![Greenkeeper](https://badges.greenkeeper.io/octokit/plugin-throttling.js.svg)](https://greenkeeper.io/)
9
10Implements all [recommended best practises](https://developer.github.com/v3/guides/best-practices-for-integrators/) to prevent hitting abuse rate limits.
11
12## Usage
13
14The 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.
15
16The `throttle.onAbuseLimit` and `throttle.onRateLimit` options are required. Return `true` to automatically retry the request after `retryAfter` seconds.
17
18```js
19const Octokit = require('@octokit/rest')
20 .plugin(require('@octokit/plugin-throttling'))
21
22const octokit = new Octokit({
23 throttle: {
24 onRateLimit: (retryAfter, options) => {
25 console.warn(`Request quota exhausted for request ${options.method} ${options.url}`)
26
27 if (options.request.retryCount === 0) { // only retries once
28 console.log(`Retrying after ${retryAfter} seconds!`)
29 return true
30 }
31 },
32 onAbuseLimit: (retryAfter, options) => {
33 // does not retry, only logs a warning
34 console.warn(`Abuse detected for request ${options.method} ${options.url}`)
35 }
36 }
37})
38
39octokit.authenticate({
40 type: 'token',
41 token: process.env.TOKEN
42})
43
44async function createIssueOnAllRepos (org) {
45 const repos = await octokit.paginate(octokit.repos.listForOrg.endpoint({ org }))
46 return Promise.all(repos.forEach(({ name } => {
47 octokit.issues.create({
48 owner,
49 repo: name,
50 title: 'Hello, world!'
51 })
52 })))
53}
54```
55
56Pass `{ throttle: { enabled: false } }` to disable this plugin.
57
58### Clustering
59
60Enabling Clustering support ensures that your application will not go over rate limits **across Octokit instances and across Nodejs processes**.
61
62First install either `redis` or `ioredis`:
63```
64# NodeRedis (https://github.com/NodeRedis/node_redis)
65npm install --save redis
66
67# or ioredis (https://github.com/luin/ioredis)
68npm install --save ioredis
69```
70
71Then in your application:
72```js
73const Bottleneck = require('bottleneck')
74const Redis = require('redis')
75
76const client = Redis.createClient({ /* options */ })
77const connection = new Bottleneck.RedisConnection({ client })
78connection.on('error', err => console.error(err))
79
80const octokit = new Octokit({
81 throttle: {
82 onAbuseLimit: (retryAfter, options) => { /* ... */ },
83 onRateLimit: (retryAfter, options) => { /* ... */ },
84
85 // The Bottleneck connection object
86 connection,
87
88 // A "throttling ID". All octokit instances with the same ID
89 // using the same Redis server will share the throttling.
90 id: 'my-super-app',
91
92 // Otherwise the plugin uses a lighter version of Bottleneck without Redis support
93 Bottleneck
94 }
95})
96
97// To close the connection and allow your application to exit cleanly:
98await connection.disconnect()
99```
100
101To use the `ioredis` library instead:
102```js
103const Redis = require('ioredis')
104const client = new Redis({ /* options */ })
105const connection = new Bottleneck.IORedisConnection({ client })
106connection.on('error', err => console.error(err))
107```
108
109## LICENSE
110
111[MIT](LICENSE)