Skip to content

Commit ac6a830

Browse files
Simon Grondingr2m
authored andcommitted
feat: GraphQL Support
1 parent 7fd7930 commit ac6a830

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

lib/index.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,19 @@ function throttlingPlugin (octokit, octokitOptions = {}) {
8585
events.on('error', e => console.warn('Error in throttling-plugin limit handler', e))
8686

8787
state.retryLimiter.on('failed', async function (error, info) {
88-
if (error.status !== 403) {
88+
const options = info.args[info.args.length - 1]
89+
const isGraphQL = options.url.startsWith('/graphql')
90+
91+
if (!(isGraphQL || error.status === 403)) {
8992
return
9093
}
9194

92-
const options = info.args[info.args.length - 1]
9395
const retryCount = ~~options.request.retryCount
9496
options.request.retryCount = retryCount
9597

9698
const { wantRetry, retryAfter } = await (async function () {
9799
if (/\babuse\b/i.test(error.message)) {
98-
// The user has hit the abuse rate limit.
100+
// The user has hit the abuse rate limit. (REST only)
99101
// https://developer.github.com/v3/#abuse-rate-limits
100102

101103
// The Retry-After header can sometimes be blank when hitting an abuse limit,
@@ -105,7 +107,7 @@ function throttlingPlugin (octokit, octokitOptions = {}) {
105107
return { wantRetry, retryAfter }
106108
}
107109
if (error.headers['x-ratelimit-remaining'] === '0') {
108-
// The user has used all their allowed calls for the current time period
110+
// The user has used all their allowed calls for the current time period (REST and GraphQL)
109111
// https://developer.github.com/v3/#rate-limiting
110112

111113
const rateLimitReset = new Date(~~error.headers['x-ratelimit-reset'] * 1000).getTime()

lib/wrap-request.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ function wrapRequest (state, request, options) {
99
async function doRequest (state, request, options) {
1010
const isWrite = options.method !== 'GET' && options.method !== 'HEAD'
1111
const isSearch = options.method === 'GET' && options.url.startsWith('/search/')
12+
const isGraphQL = options.url.startsWith('/graphql')
1213

1314
const retryCount = ~~options.request.retryCount
1415
const jobOptions = retryCount > 0 ? { priority: 0, weight: 0 } : {}
@@ -19,7 +20,8 @@ async function doRequest (state, request, options) {
1920
}
2021

2122
// Guarantee at least 1000ms between writes
22-
if (isWrite) {
23+
// GraphQL can also trigger writes
24+
if (isWrite || isGraphQL) {
2325
await state.write.key(state.id).schedule(jobOptions, noop)
2426
}
2527

@@ -28,9 +30,20 @@ async function doRequest (state, request, options) {
2830
await state.notifications.key(state.id).schedule(jobOptions, noop)
2931
}
3032

33+
// Guarantee at least 2000ms between search requests
3134
if (isSearch) {
3235
await state.search.key(state.id).schedule(jobOptions, noop)
3336
}
3437

35-
return state.global.key(state.id).schedule(jobOptions, request, options)
38+
const req = state.global.key(state.id).schedule(jobOptions, request, options)
39+
if (isGraphQL) {
40+
const res = await req
41+
if (res.data.errors != null && res.data.errors.some((err) => err.type === 'RATE_LIMITED')) {
42+
const err = new Error('GraphQL Rate Limit Exceeded')
43+
err.headers = res.headers
44+
err.data = res.data
45+
throw err
46+
}
47+
}
48+
return req
3649
}

0 commit comments

Comments
 (0)