Skip to content

Commit 82e0514

Browse files
FEATURE (requests): Add requests retries
1 parent eea3f72 commit 82e0514

File tree

7 files changed

+137
-24
lines changed

7 files changed

+137
-24
lines changed

frontend/src/entity/backups/api/backupsApi.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export const backupsApi = {
77
async getBackups(databaseId: string) {
88
return apiHelper.fetchGetJson<Backup[]>(
99
`${getApplicationServer()}/api/v1/backups?database_id=${databaseId}`,
10+
undefined,
11+
true,
1012
);
1113
},
1214

frontend/src/entity/databases/api/databaseApi.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const databaseApi = {
2727
return apiHelper.fetchGetJson<Database>(
2828
`${getApplicationServer()}/api/v1/databases/${id}`,
2929
requestOptions,
30+
true,
3031
);
3132
},
3233

@@ -35,6 +36,7 @@ export const databaseApi = {
3536
return apiHelper.fetchGetJson<Database[]>(
3637
`${getApplicationServer()}/api/v1/databases`,
3738
requestOptions,
39+
true,
3840
);
3941
},
4042

@@ -71,6 +73,7 @@ export const databaseApi = {
7173
}>(
7274
`${getApplicationServer()}/api/v1/databases/notifier/${notifierId}/is-using`,
7375
requestOptions,
76+
true,
7477
)
7578
.then((res) => res.isUsing);
7679
},
@@ -80,7 +83,11 @@ export const databaseApi = {
8083
return apiHelper
8184
.fetchGetJson<{
8285
isUsing: boolean;
83-
}>(`${getApplicationServer()}/api/v1/databases/storage/${storageId}/is-using`, requestOptions)
86+
}>(
87+
`${getApplicationServer()}/api/v1/databases/storage/${storageId}/is-using`,
88+
requestOptions,
89+
true,
90+
)
8491
.then((res) => res.isUsing);
8592
},
8693
};

frontend/src/entity/notifiers/api/notifierApi.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const notifierApi = {
1818
return apiHelper.fetchGetJson<Notifier>(
1919
`${getApplicationServer()}/api/v1/notifiers/${id}`,
2020
requestOptions,
21+
true,
2122
);
2223
},
2324

@@ -26,6 +27,7 @@ export const notifierApi = {
2627
return apiHelper.fetchGetJson<Notifier[]>(
2728
`${getApplicationServer()}/api/v1/notifiers`,
2829
requestOptions,
30+
true,
2931
);
3032
},
3133

frontend/src/entity/restores/api/restoreApi.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export const restoreApi = {
88
async getRestores(backupId: string) {
99
return apiHelper.fetchGetJson<Restore[]>(
1010
`${getApplicationServer()}/api/v1/restores/${backupId}`,
11+
undefined,
12+
true,
1113
);
1214
},
1315

frontend/src/entity/storages/api/storageApi.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const storageApi = {
1818
return apiHelper.fetchGetJson<Storage>(
1919
`${getApplicationServer()}/api/v1/storages/${id}`,
2020
requestOptions,
21+
true,
2122
);
2223
},
2324

@@ -26,6 +27,7 @@ export const storageApi = {
2627
return apiHelper.fetchGetJson<Storage[]>(
2728
`${getApplicationServer()}/api/v1/storages`,
2829
requestOptions,
30+
true,
2931
);
3032
},
3133

frontend/src/entity/users/api/userApi.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ export const userApi = {
4343
async isAnyUserExists(): Promise<boolean> {
4444
const requestOptions: RequestOptions = new RequestOptions();
4545
return apiHelper
46-
.fetchGetJson(`${getApplicationServer()}/api/v1/users/is-any-user-exist`, requestOptions)
46+
.fetchGetJson(
47+
`${getApplicationServer()}/api/v1/users/is-any-user-exist`,
48+
requestOptions,
49+
true,
50+
)
4751
.then((response: unknown) => {
4852
const typedResponse = response as { isExist: boolean };
4953
return typedResponse.isExist;

frontend/src/shared/api/apiHelper.ts

Lines changed: 116 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { accessTokenHelper } from '.';
22
import RequestOptions from './RequestOptions';
33

4+
const REPEAT_TRIES_COUNT = 10;
5+
const REPEAT_INTERVAL_MS = 3_000;
6+
47
const handleOrThrowMessageIfResponseError = async (
58
url: string,
69
response: Response,
@@ -33,114 +36,205 @@ const handleOrThrowMessageIfResponseError = async (
3336
}
3437
};
3538

36-
const makeRequest = async (url: string, optionsWrapper: RequestOptions): Promise<Response> => {
37-
const response = await fetch(url, optionsWrapper.toRequestInit());
38-
await handleOrThrowMessageIfResponseError(url, response);
39-
return response;
39+
const makeRequest = async (
40+
url: string,
41+
optionsWrapper: RequestOptions,
42+
currentTry = 0,
43+
): Promise<Response> => {
44+
try {
45+
const response = await fetch(url, optionsWrapper.toRequestInit());
46+
await handleOrThrowMessageIfResponseError(url, response);
47+
return response;
48+
} catch (e) {
49+
if (currentTry < REPEAT_TRIES_COUNT) {
50+
await new Promise((resolve) => setTimeout(resolve, REPEAT_INTERVAL_MS));
51+
return makeRequest(url, optionsWrapper, currentTry + 1);
52+
}
53+
54+
throw e;
55+
}
4056
};
4157

4258
export const apiHelper = {
43-
fetchPostJson: async <T>(url: string, requestOptions?: RequestOptions): Promise<T> => {
59+
fetchPostJson: async <T>(
60+
url: string,
61+
requestOptions?: RequestOptions,
62+
isRetryOnError = false,
63+
): Promise<T> => {
4464
const optionsWrapper = (requestOptions ?? new RequestOptions())
4565
.setMethod('POST')
4666
.addHeader('Content-Type', 'application/json')
4767
.addHeader('Access-Control-Allow-Methods', 'POST')
4868
.addHeader('Accept', 'application/json')
4969
.addHeader('Authorization', accessTokenHelper.getAccessToken());
5070

51-
const response = await makeRequest(url, optionsWrapper);
71+
const response = await makeRequest(
72+
url,
73+
optionsWrapper,
74+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
75+
);
5276

5377
return response.json();
5478
},
5579

56-
fetchPostRaw: async (url: string, requestOptions?: RequestOptions): Promise<string> => {
80+
fetchPostRaw: async (
81+
url: string,
82+
requestOptions?: RequestOptions,
83+
isRetryOnError = false,
84+
): Promise<string> => {
5785
const optionsWrapper = (requestOptions ?? new RequestOptions())
5886
.setMethod('POST')
5987
.addHeader('Content-Type', 'application/json')
6088
.addHeader('Access-Control-Allow-Methods', 'POST')
6189
.addHeader('Accept', 'application/json')
6290
.addHeader('Authorization', accessTokenHelper.getAccessToken());
6391

64-
const response = await makeRequest(url, optionsWrapper);
92+
const response = await makeRequest(
93+
url,
94+
optionsWrapper,
95+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
96+
);
6597

6698
return response.text();
6799
},
68100

69-
fetchPostBlob: async (url: string, requestOptions?: RequestOptions): Promise<Blob> => {
101+
fetchPostBlob: async (
102+
url: string,
103+
requestOptions?: RequestOptions,
104+
isRetryOnError = false,
105+
): Promise<Blob> => {
70106
const optionsWrapper = (requestOptions ?? new RequestOptions())
71107
.setMethod('POST')
72108
.addHeader('Content-Type', 'application/json')
73109
.addHeader('Access-Control-Allow-Methods', 'POST')
74110
.addHeader('Authorization', accessTokenHelper.getAccessToken());
75111

76-
const response = await makeRequest(url, optionsWrapper);
112+
const response = await makeRequest(
113+
url,
114+
optionsWrapper,
115+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
116+
);
77117

78118
return response.blob();
79119
},
80120

81-
fetchGetJson: async <T>(url: string, requestOptions?: RequestOptions): Promise<T> => {
121+
fetchGetJson: async <T>(
122+
url: string,
123+
requestOptions?: RequestOptions,
124+
isRetryOnError = false,
125+
): Promise<T> => {
82126
const optionsWrapper = (requestOptions ?? new RequestOptions())
83127
.addHeader('Content-Type', 'application/json')
84128
.addHeader('Access-Control-Allow-Methods', 'GET')
85129
.addHeader('Accept', 'application/json')
86130
.addHeader('Authorization', accessTokenHelper.getAccessToken());
87131

88-
const response = await makeRequest(url, optionsWrapper);
132+
const response = await makeRequest(
133+
url,
134+
optionsWrapper,
135+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
136+
);
137+
89138
return response.json();
90139
},
91140

92-
fetchGetRaw: async (url: string, requestOptions?: RequestOptions): Promise<string> => {
141+
fetchGetRaw: async (
142+
url: string,
143+
requestOptions?: RequestOptions,
144+
isRetryOnError = false,
145+
): Promise<string> => {
93146
const optionsWrapper = (requestOptions ?? new RequestOptions())
94147
.addHeader('Content-Type', 'application/json')
95148
.addHeader('Access-Control-Allow-Methods', 'GET')
96149
.addHeader('Accept', 'application/json')
97150
.addHeader('Authorization', accessTokenHelper.getAccessToken());
98151

99-
const response = await makeRequest(url, optionsWrapper);
152+
const response = await makeRequest(
153+
url,
154+
optionsWrapper,
155+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
156+
);
157+
100158
return response.text();
101159
},
102160

103-
fetchGetBlob: async (url: string, requestOptions?: RequestOptions): Promise<Blob> => {
161+
fetchGetBlob: async (
162+
url: string,
163+
requestOptions?: RequestOptions,
164+
isRetryOnError = false,
165+
): Promise<Blob> => {
104166
const optionsWrapper = (requestOptions ?? new RequestOptions())
105167
.addHeader('Content-Type', 'application/json')
106168
.addHeader('Access-Control-Allow-Methods', 'GET')
107169
.addHeader('Authorization', accessTokenHelper.getAccessToken());
108170

109-
const response = await makeRequest(url, optionsWrapper);
171+
const response = await makeRequest(
172+
url,
173+
optionsWrapper,
174+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
175+
);
176+
110177
return response.blob();
111178
},
112179

113-
fetchPutJson: async <T>(url: string, requestOptions?: RequestOptions): Promise<T> => {
180+
fetchPutJson: async <T>(
181+
url: string,
182+
requestOptions?: RequestOptions,
183+
isRetryOnError = false,
184+
): Promise<T> => {
114185
const optionsWrapper = (requestOptions ?? new RequestOptions())
115186
.setMethod('PUT')
116187
.addHeader('Content-Type', 'application/json')
117188
.addHeader('Access-Control-Allow-Methods', 'PUT')
118189
.addHeader('Accept', 'application/json')
119190
.addHeader('Authorization', accessTokenHelper.getAccessToken());
120191

121-
const response = await makeRequest(url, optionsWrapper);
192+
const response = await makeRequest(
193+
url,
194+
optionsWrapper,
195+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
196+
);
197+
122198
return response.json();
123199
},
124200

125-
fetchDeleteJson: async <T>(url: string, requestOptions?: RequestOptions): Promise<T> => {
201+
fetchDeleteJson: async <T>(
202+
url: string,
203+
requestOptions?: RequestOptions,
204+
isRetryOnError = false,
205+
): Promise<T> => {
126206
const optionsWrapper = (requestOptions ?? new RequestOptions())
127207
.setMethod('DELETE')
128208
.addHeader('Access-Control-Allow-Methods', 'DELETE')
129209
.addHeader('Accept', 'application/json')
130210
.addHeader('Authorization', accessTokenHelper.getAccessToken());
131211

132-
const response = await makeRequest(url, optionsWrapper);
212+
const response = await makeRequest(
213+
url,
214+
optionsWrapper,
215+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
216+
);
217+
133218
return response.json();
134219
},
135220

136-
fetchDeleteRaw: async (url: string, requestOptions?: RequestOptions): Promise<string> => {
221+
fetchDeleteRaw: async (
222+
url: string,
223+
requestOptions?: RequestOptions,
224+
isRetryOnError = false,
225+
): Promise<string> => {
137226
const optionsWrapper = (requestOptions ?? new RequestOptions())
138227
.setMethod('DELETE')
139228
.addHeader('Access-Control-Allow-Methods', 'DELETE')
140229
.addHeader('Accept', 'application/json')
141230
.addHeader('Authorization', accessTokenHelper.getAccessToken());
142231

143-
const response = await makeRequest(url, optionsWrapper);
232+
const response = await makeRequest(
233+
url,
234+
optionsWrapper,
235+
isRetryOnError ? 0 : REPEAT_TRIES_COUNT,
236+
);
237+
144238
return response.text();
145239
},
146240
};

0 commit comments

Comments
 (0)