@@ -2,7 +2,7 @@ const url = require('url');
22const { memoize} = require ( 'lodash' ) ;
33const Octokit = require ( '@octokit/rest' ) ;
44const pRetry = require ( 'p-retry' ) ;
5- const pThrottle = require ( 'p-throttle ' ) ;
5+ const Bottleneck = require ( 'bottleneck ' ) ;
66
77/**
88 * Default exponential backoff configuration for retries.
@@ -16,44 +16,33 @@ const DEFAULT_RETRY = {retries: 3, factor: 2, minTimeout: 1000};
1616 * See {@link https://developer.github.com/v3/#rate-limiting|Rate limiting}.
1717 */
1818const RATE_LIMITS = {
19- search : [ 30 , 60 * 1000 ] ,
20- core : [ 5000 , 60 * 60 * 1000 ] ,
19+ search : 60 * 1000 / 30 , // 30 calls per minutes => 1 call per 2s
20+ core : 60 * 60 * 1000 / 5000 , // 5000 calls per hour => 1 call per 720ms
2121} ;
2222
2323/**
2424 * Global rate limit to prevent abuse.
2525 *
2626 * See {@link https://developer.github.com/v3/guides/best-practices-for-integrators/#dealing-with-abuse-rate-limits|Dealing with abuse rate limits}
2727 */
28- const GLOBAL_RATE_LIMIT = [ 1 , 1000 ] ;
28+ const GLOBAL_RATE_LIMIT = 1000 ;
2929
3030/**
3131 * Http error codes for which to not retry.
3232 */
3333const SKIP_RETRY_CODES = [ 400 , 401 , 403 ] ;
3434
35- /**
36- * @typedef {Function } Throttler
37- * @param {Function } func The function to throttle.
38- * @param {Arguments } args The arguments to pass to the function to throttle.
39- */
40-
4135/**
4236 * Create or retrieve the throttler function for a given rate limit group.
4337 *
4438 * @param {Array } rate The rate limit group.
4539 * @param {String } limit The rate limits per API endpoints.
46- * @return {Throttler } The throller function for the given rate limit group.
47- */
48- const getThrottler = memoize ( ( rate , limit ) => pThrottle ( ( func , ...args ) => func ( ...args ) , ...limit [ rate ] ) ) ;
49-
50- /**
51- * Create the global throttler function to comply with GitHub abuse prevention recommandations.
52- *
53- * @param {Array } globalLimit The global rate limit.
54- * @return {Throttler } The throller function for the global rate limit.
40+ * @param {Bottleneck } globalThrottler The global throttler.
41+ * @return {Bottleneck } The throller function for the given rate limit group.
5542 */
56- const getGlobalThrottler = globalLimit => pThrottle ( ( func , ...args ) => func ( ...args ) , ...globalLimit ) ;
43+ const getThrottler = memoize ( ( rate , limit , globalThrottler ) =>
44+ new Bottleneck ( { minTime : limit [ rate ] } ) . chain ( globalThrottler )
45+ ) ;
5746
5847/**
5948 * Create a`handler` for a `Proxy` wrapping an Octokit instance to:
@@ -89,11 +78,11 @@ const handler = (retry, limit, globalThrottler, endpoint) => ({
8978 * @return {Promise<Any> } The result of the function called.
9079 */
9180 apply : ( func , that , args ) => {
92- const throttler = getThrottler ( limit [ endpoint ] ? endpoint : 'core' , limit ) ;
81+ const throttler = getThrottler ( limit [ endpoint ] ? endpoint : 'core' , limit , globalThrottler ) ;
9382
9483 return pRetry ( async ( ) => {
9584 try {
96- return await globalThrottler ( ( func , ... args ) => throttler ( func , ... args ) , func , ...args ) ;
85+ return await throttler . wrap ( func ) ( ...args ) ;
9786 } catch ( err ) {
9887 if ( SKIP_RETRY_CODES . includes ( err . code ) ) {
9988 throw new pRetry . AbortError ( err ) ;
@@ -120,5 +109,5 @@ module.exports = ({
120109 pathPrefix : githubApiPathPrefix ,
121110 } ) ;
122111 github . authenticate ( { type : 'token' , token : githubToken } ) ;
123- return new Proxy ( github , handler ( retry , limit , getGlobalThrottler ( globalLimit ) ) ) ;
112+ return new Proxy ( github , handler ( retry , limit , new Bottleneck ( { minTime : globalLimit } ) ) ) ;
124113} ;
0 commit comments