Skip to content

Commit

Permalink
feat: allow up to 3 retries before throwing
Browse files Browse the repository at this point in the history
  • Loading branch information
angeloashmore committed Oct 30, 2024
1 parent d10ebe6 commit 345ff2b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
15 changes: 13 additions & 2 deletions src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ export const GET_ALL_QUERY_DELAY = 500
*/
const DEFUALT_RETRY_AFTER_MS = 1000

/**
* The maximum number of attemps to retry a query with an invalid ref before
* halting. We allow multiple attemps as each attemp may return a different ref.
* Capping the number of attemps prevents infinite loops.
*/
const MAX_INVALID_REF_RETRY_ATTEMPS = 3

/**
* Extracts one or more Prismic document types that match a given Prismic
* document type. If no matches are found, no extraction is performed and the
Expand Down Expand Up @@ -1696,6 +1703,7 @@ export class Client<
*/
private async _get<TDocument extends TDocuments>(
params?: Partial<BuildQueryURLArgs> & FetchParams,
attemptCount = 0,
): Promise<{ data: Query<TDocument>; url: string }> {
const url = await this.buildQueryURL(params)

Expand All @@ -1705,7 +1713,10 @@ export class Client<
return { data, url }
} catch (error) {
if (
!(error instanceof RefNotFoundError || error instanceof RefExpiredError)
!(
error instanceof RefNotFoundError || error instanceof RefExpiredError
) ||
attemptCount >= MAX_INVALID_REF_RETRY_ATTEMPS - 1
) {
throw error
}
Expand All @@ -1722,7 +1733,7 @@ export class Client<
`The ref (${badRef}) was ${issue}. Now retrying with the latest master ref (${masterRef}). If you were previewing content, the response will not include draft content.`,
)

return await this._get({ ...params, ref: masterRef })
return await this._get({ ...params, ref: masterRef }, attemptCount + 1)
}
}

Expand Down
44 changes: 43 additions & 1 deletion test/__testutils__/testInvalidRefRetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { rest } from "msw"
import { createTestClient } from "./createClient"
import { mockPrismicRestAPIV2 } from "./mockPrismicRestAPIV2"

import type * as prismic from "../../src"
import * as prismic from "../../src"

type TestInvalidRefRetryArgs = {
run: (
Expand Down Expand Up @@ -95,4 +95,46 @@ export const testInvalidRefRetry = (args: TestInvalidRefRetryArgs): void => {
expect(triedRefs).toStrictEqual([badRef, masterRef])
},
)

it.concurrent(
"throws if the maximum number of retries when an invalid ref is used is reached",
async (ctx) => {
const client = createTestClient({ ctx })
const queryResponse = ctx.mock.api.query({
documents: [ctx.mock.value.document()],
})

const triedRefs: (string | null)[] = []

mockPrismicRestAPIV2({ ctx, queryResponse })
const endpoint = new URL(
"documents/search",
`${client.documentAPIEndpoint}/`,
).toString()
ctx.server.use(
rest.get(endpoint, (req) => {
triedRefs.push(req.url.searchParams.get("ref"))
}),
rest.get(endpoint, (_req, res, requestCtx) =>
res(
requestCtx.json({
type: "api_notfound_error",
message: `Master ref is: ${ctx.mock.api.ref().ref}`,
}),
requestCtx.status(404),
),
),
)

const consoleWarnSpy = vi
.spyOn(console, "warn")
.mockImplementation(() => void 0)
await expect(async () => {
await args.run(client)
}).rejects.toThrow(prismic.RefNotFoundError)
consoleWarnSpy.mockRestore()

expect(triedRefs.length).toBe(3)
},
)
}

0 comments on commit 345ff2b

Please sign in to comment.