diff --git a/src/api/HTTPError.ts b/src/api/HTTPError.ts index 4be34b343..b3e586315 100644 --- a/src/api/HTTPError.ts +++ b/src/api/HTTPError.ts @@ -1,10 +1,12 @@ export class HTTPError extends Error { response: Response; + request: Request; - constructor(response: Response) { + constructor(response: Response, request: Request) { super(response.statusText); this.response = response; + this.request = request; } } \ No newline at end of file diff --git a/src/api/MastodonClient.ts b/src/api/MastodonClient.ts index 22eb35457..0f74abe17 100644 --- a/src/api/MastodonClient.ts +++ b/src/api/MastodonClient.ts @@ -84,7 +84,7 @@ export class MastodonClient { const response = await this.fetch(request); if (!response.ok) { - throw new HTTPError(response); + throw new HTTPError(response, request); } return response; diff --git a/src/api/hooks/instance/useInstanceV1.ts b/src/api/hooks/instance/useInstanceV1.ts index 73fa757d3..2ca494287 100644 --- a/src/api/hooks/instance/useInstanceV1.ts +++ b/src/api/hooks/instance/useInstanceV1.ts @@ -3,7 +3,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query'; import { useApi } from 'soapbox/hooks'; import { InstanceV1, instanceV1Schema } from 'soapbox/schemas/instance'; -interface Opts extends Pick, 'enabled' | 'retry' | 'retryOnMount' | 'staleTime'> { +interface Opts extends Pick, 'enabled' | 'retryOnMount' | 'staleTime'> { /** The base URL of the instance. */ baseUrl?: string; } diff --git a/src/api/hooks/instance/useInstanceV2.ts b/src/api/hooks/instance/useInstanceV2.ts index 8e9b8ab24..d3376063a 100644 --- a/src/api/hooks/instance/useInstanceV2.ts +++ b/src/api/hooks/instance/useInstanceV2.ts @@ -3,7 +3,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query'; import { useApi } from 'soapbox/hooks'; import { InstanceV2, instanceV2Schema } from 'soapbox/schemas/instance'; -interface Opts extends Pick, 'enabled' | 'retry' | 'retryOnMount' | 'staleTime'> { +interface Opts extends Pick, 'enabled' | 'retryOnMount' | 'staleTime'> { /** The base URL of the instance. */ baseUrl?: string; } diff --git a/src/hooks/useInstance.ts b/src/hooks/useInstance.ts index 940fc2b6c..eb7bed170 100644 --- a/src/hooks/useInstance.ts +++ b/src/hooks/useInstance.ts @@ -17,16 +17,8 @@ interface Opts extends Pick, 'enabled' | 'retryOnMount' export function useInstance(opts: Opts = {}) { const { baseUrl, retryOnMount = false, staleTime = Infinity } = opts; - function retry(failureCount: number, error: Error): boolean { - if (error instanceof HTTPError && error.response.status === 404) { - return false; - } else { - return failureCount < 3; - } - } - - const v2 = useInstanceV2({ baseUrl, retry, retryOnMount, staleTime }); - const v1 = useInstanceV1({ baseUrl, retry, retryOnMount, staleTime, enabled: v2.isError }); + const v2 = useInstanceV2({ baseUrl, retryOnMount, staleTime }); + const v1 = useInstanceV1({ baseUrl, retryOnMount, staleTime, enabled: v2.isError }); const instance = useMemo(() => { if (v2.instance) { diff --git a/src/queries/client.ts b/src/queries/client.ts index e11ce296c..0755aca5c 100644 --- a/src/queries/client.ts +++ b/src/queries/client.ts @@ -1,12 +1,30 @@ import { QueryClient } from '@tanstack/react-query'; +import { HTTPError } from 'soapbox/api/HTTPError'; + +/** HTTP response codes to retry. */ +const RETRY_CODES = [502, 503, 504, 521, 522]; + const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false, staleTime: 60000, // 1 minute gcTime: Infinity, - retry: false, + retry(failureCount: number, error: Error): boolean { + if (error instanceof HTTPError) { + const { response } = error; + + // TODO: Implement Retry-After. + // const retryAfter = response.headers.get('Retry-After'); + + if (RETRY_CODES.includes(response.status)) { + return failureCount < 3; + } + } + + return false; + }, }, }, });