1
- import type { BaseQueryApi , BaseQueryArg , BaseQueryEnhancer , BaseQueryExtraOptions , BaseQueryFn } from './baseQueryTypes'
1
+ import type {
2
+ BaseQueryApi ,
3
+ BaseQueryArg ,
4
+ BaseQueryEnhancer ,
5
+ BaseQueryExtraOptions ,
6
+ BaseQueryFn ,
7
+ } from './baseQueryTypes'
2
8
import { FetchBaseQueryError } from './fetchBaseQuery'
3
9
import { HandledError } from './HandledError'
4
10
@@ -24,42 +30,71 @@ async function defaultBackoff(attempt: number = 0, maxRetries: number = 5) {
24
30
)
25
31
}
26
32
27
- export interface RetryOptions {
28
- /**
29
- * How many times the query will be retried (default: 5)
30
- */
31
- maxRetries ?: number
33
+ type RetryConditionFunction = (
34
+ error : FetchBaseQueryError ,
35
+ args : BaseQueryArg < BaseQueryFn > ,
36
+ extraArgs : {
37
+ attempt : number
38
+ baseQueryApi : BaseQueryApi
39
+ extraOptions : BaseQueryExtraOptions < BaseQueryFn > & RetryOptions
40
+ }
41
+ ) => boolean
42
+
43
+ export type RetryOptions = {
32
44
/**
33
45
* Function used to determine delay between retries
34
46
*/
35
47
backoff ?: ( attempt : number , maxRetries : number ) => Promise < void >
36
- /**
37
- * Callback to determine if a retry should be attempted.
38
- * Return `true` for another retry and `false` to quit trying prematurely.
39
- */
40
- retryCondition ?: ( error : FetchBaseQueryError , args : BaseQueryArg < BaseQueryFn > , extraArgs : {
41
- attempt : number
42
- maxRetries : number
43
- baseQueryApi : BaseQueryApi
44
- extraOptions : BaseQueryExtraOptions < BaseQueryFn > & RetryOptions
45
- } ) => boolean
46
- }
48
+ } & (
49
+ | {
50
+ /**
51
+ * How many times the query will be retried (default: 5)
52
+ */
53
+ maxRetries ?: number
54
+ retryCondition ?: undefined
55
+ }
56
+ | {
57
+ /**
58
+ * Callback to determine if a retry should be attempted.
59
+ * Return `true` for another retry and `false` to quit trying prematurely.
60
+ */
61
+ retryCondition ?: RetryConditionFunction
62
+ maxRetries ?: undefined
63
+ }
64
+ )
47
65
48
66
function fail ( e : any ) : never {
49
67
throw Object . assign ( new HandledError ( { error : e } ) , {
50
68
throwImmediately : true ,
51
69
} )
52
70
}
53
71
72
+ const EMPTY_OPTIONS = { }
73
+
54
74
const retryWithBackoff : BaseQueryEnhancer <
55
75
unknown ,
56
76
RetryOptions ,
57
77
RetryOptions | void
58
78
> = ( baseQuery , defaultOptions ) => async ( args , api , extraOptions ) => {
59
- const defaultRetryCondition : Exclude < RetryOptions [ 'retryCondition' ] , undefined > = ( _ , __ , { attempt, maxRetries} ) => attempt <= maxRetries
79
+ // We need to figure out `maxRetries` before we define `defaultRetryCondition.
80
+ // This is probably goofy, but ought to work.
81
+ // Put our defaults in one array, filter out undefineds, grab the last value.
82
+ const possibleMaxRetries : number [ ] = [
83
+ 5 ,
84
+ ( ( defaultOptions as any ) || EMPTY_OPTIONS ) . maxRetries ,
85
+ ( ( extraOptions as any ) || EMPTY_OPTIONS ) . maxRetries ,
86
+ ] . filter ( Boolean )
87
+ const [ maxRetries ] = possibleMaxRetries . slice ( - 1 )
60
88
61
- const options = {
62
- maxRetries : 5 ,
89
+ const defaultRetryCondition : RetryConditionFunction = ( _ , __ , { attempt } ) =>
90
+ attempt <= maxRetries
91
+
92
+ const options : {
93
+ maxRetries : number
94
+ backoff : typeof defaultBackoff
95
+ retryCondition : typeof defaultRetryCondition
96
+ } = {
97
+ maxRetries,
63
98
backoff : defaultBackoff ,
64
99
retryCondition : defaultRetryCondition ,
65
100
...defaultOptions ,
@@ -87,12 +122,14 @@ const retryWithBackoff: BaseQueryEnhancer<
87
122
throw e
88
123
}
89
124
90
- if ( e instanceof HandledError && ! options . retryCondition ( e . value as FetchBaseQueryError , args , {
91
- attempt : retry ,
92
- maxRetries : options . maxRetries ,
93
- baseQueryApi : api ,
94
- extraOptions
95
- } ) ) {
125
+ if (
126
+ e instanceof HandledError &&
127
+ ! options . retryCondition ( e . value as FetchBaseQueryError , args , {
128
+ attempt : retry ,
129
+ baseQueryApi : api ,
130
+ extraOptions,
131
+ } )
132
+ ) {
96
133
return e . value
97
134
}
98
135
await options . backoff ( retry , options . maxRetries )
0 commit comments