Skip to content

Commit

Permalink
feat(gatsby-source-wordpress): Add retries to graphql requests (#35949)
Browse files Browse the repository at this point in the history
* add retries to graphql requests

* fix test

* small test refactor

* Update yarn.lock
  • Loading branch information
TylerBarnes committed Jun 30, 2022
1 parent b535098 commit 48a64f6
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 25 deletions.
44 changes: 28 additions & 16 deletions packages/gatsby-source-wordpress/__tests__/fetch-graphql.test.js
Expand Up @@ -2,6 +2,19 @@ import chalk from "chalk"
import fetchGraphQL, { moduleHelpers } from "../dist/utils/fetch-graphql"
import store from "../dist/store"

jest.mock(`async-retry`, () => {
return {
__esModule: true,
default: jest.fn((tryFunction) => {
const bail = (e) => {
throw e
}

return tryFunction(bail)
})
}
})

describe(`fetchGraphQL helper`, () => {
let mock
const panicMessages = []
Expand All @@ -17,12 +30,12 @@ describe(`fetchGraphQL helper`, () => {
}

if (query === `wpgraphql-deactivated`) {
return {
return Promise.resolve({
request: {},
headers: {
[`content-type`]: `text/html`,
},
}
})
}

return null
Expand Down Expand Up @@ -55,33 +68,32 @@ describe(`fetchGraphQL helper`, () => {
})

expect(
panicMessages[0].includes(
`Your WordPress server is either overloaded or encountered a PHP error.`
)
).toBeTruthy()
panicMessages[0]
).toInclude(`Your WordPress server is either overloaded or encountered a PHP error.`)
})

test(`handles 502, 503, and 504 errors`, async () => {
const errorMessage = `Your WordPress server at ${chalk.bold(
`fake url`
)} appears to be overloaded.`

await fetchGraphQL({
query: 502,
url: `fake url`,
})
expect(panicMessages[1]).toInclude(errorMessage)

await fetchGraphQL({
query: 503,
url: `fake url`,
})
expect(panicMessages[2]).toInclude(errorMessage)

await fetchGraphQL({
query: 504,
url: `fake url`,
})

const errorMessage = `Your WordPress server at ${chalk.bold(
`fake url`
)} appears to be overloaded.`

expect(panicMessages[1].includes(errorMessage)).toBeTruthy()
expect(panicMessages[2].includes(errorMessage)).toBeTruthy()
expect(panicMessages[3].includes(errorMessage)).toBeTruthy()
expect(panicMessages[3]).toInclude(errorMessage)
})

test(`errors when WPGraphQL is not active`, async () => {
Expand All @@ -91,8 +103,8 @@ describe(`fetchGraphQL helper`, () => {
})

expect(
panicMessages[4].includes(`Unable to connect to WPGraphQL.`)
).toBeTruthy()
panicMessages[4]
).toInclude(`Unable to connect to WPGraphQL.`)
})

afterAll(() => {
Expand Down
36 changes: 27 additions & 9 deletions packages/gatsby-source-wordpress/src/utils/fetch-graphql.ts
Expand Up @@ -7,6 +7,7 @@ import clipboardy from "clipboardy"
import axios, { AxiosRequestConfig, AxiosResponse } from "axios"
import rateLimit, { RateLimitedAxiosInstance } from "axios-rate-limit"
import { bold } from "chalk"
import retry from "async-retry"
import { formatLogMessage } from "./format-log-message"
import store from "~/store"
import { getPluginOptions } from "./get-gatsby-api"
Expand All @@ -27,6 +28,13 @@ export const moduleHelpers = {
},
}

const errorIs500ish = (e: Error): boolean =>
e.message.includes(`Request failed with status code 50`) &&
(e.message.includes(`502`) ||
e.message.includes(`503`) ||
e.message.includes(`500`) ||
e.message.includes(`504`))

interface IHandleErrorOptionsInput {
variables: IJSON
query: string
Expand Down Expand Up @@ -331,12 +339,7 @@ const handleFetchErrors = async ({
return
}

if (
e.message.includes(`Request failed with status code 50`) &&
(e.message.includes(`502`) ||
e.message.includes(`503`) ||
e.message.includes(`504`))
) {
if (errorIs500ish(e) && !e.message.includes(`500`)) {
if (`message` in e) {
console.error(formatLogMessage(new Error(e.message).stack))
}
Expand Down Expand Up @@ -729,9 +732,24 @@ const fetchGraphql = async ({
requestOptions.auth = htaccessCredentials
}

response = await moduleHelpers
.getHttp(limit)
.post(url, { query, variables }, requestOptions)
response = await retry(
(bail: (e: Error) => void) =>
moduleHelpers
.getHttp(limit)
.post(url, { query, variables }, requestOptions)
.catch(e => {
if (!errorIs500ish(e)) {
// for any error that is not a 50x error, we bail, meaning we stop retrying. error will be thrown one level higher
bail(e)

return null
} else {
// otherwise throwing the error will cause the retry to happen again
throw e
}
}),
{ retries: 5 }
)

if (response.data === ``) {
throw new Error(`GraphQL request returned an empty string.`)
Expand Down

0 comments on commit 48a64f6

Please sign in to comment.