UNPKG

1.7 kBJavaScriptView Raw
1module.exports = wrapRequest
2
3const noop = () => Promise.resolve()
4
5function wrapRequest (state, request, options) {
6 return state.retryLimiter.schedule(doRequest, state, request, options)
7}
8
9async function doRequest (state, request, options) {
10 const isWrite = options.method !== 'GET' && options.method !== 'HEAD'
11 const isSearch = options.method === 'GET' && options.url.startsWith('/search/')
12 const isGraphQL = options.url.startsWith('/graphql')
13
14 const retryCount = ~~options.request.retryCount
15 const jobOptions = retryCount > 0 ? { priority: 0, weight: 0 } : {}
16 if (state.clustering) {
17 // Remove a job from Redis if it has not completed or failed within 60s
18 // Examples: Node process terminated, client disconnected, etc.
19 jobOptions.expiration = 1000 * 60
20 }
21
22 // Guarantee at least 1000ms between writes
23 // GraphQL can also trigger writes
24 if (isWrite || isGraphQL) {
25 await state.write.key(state.id).schedule(jobOptions, noop)
26 }
27
28 // Guarantee at least 3000ms between requests that trigger notifications
29 if (isWrite && state.triggersNotification(options.url)) {
30 await state.notifications.key(state.id).schedule(jobOptions, noop)
31 }
32
33 // Guarantee at least 2000ms between search requests
34 if (isSearch) {
35 await state.search.key(state.id).schedule(jobOptions, noop)
36 }
37
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
49}