Skip to content

Commit 4e482f9

Browse files
paveltiunovmarianore-muttdata
authored andcommitted
feat(client-core): Add fetch timeout and network retry options (cube-js#9484)
1 parent fad88a8 commit 4e482f9

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

packages/cubejs-client-core/index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ declare module '@cubejs-client/core' {
2323
headers?: Record<string, string>;
2424
credentials?: 'omit' | 'same-origin' | 'include';
2525
method?: 'GET' | 'PUT' | 'POST' | 'PATCH';
26+
/**
27+
* Fetch timeout in milliseconds. Would be passed as AbortSignal.timeout()
28+
*/
29+
fetchTimeout?: number;
2630
};
2731

2832
export interface ITransportResponse<R> {
@@ -81,6 +85,10 @@ declare module '@cubejs-client/core' {
8185
parseDateMeasures?: boolean;
8286
resType?: 'default' | 'compact';
8387
castNumerics?: boolean;
88+
/**
89+
* How many network errors would be retried before returning to users. Default to 0.
90+
*/
91+
networkErrorRetries?: number;
8492
};
8593

8694
export type LoadMethodOptions = {

packages/cubejs-client-core/src/HttpTransport.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import fetch from 'cross-fetch';
22
import 'url-search-params-polyfill';
33

44
class HttpTransport {
5-
constructor({ authorization, apiUrl, method, headers = {}, credentials }) {
5+
constructor({ authorization, apiUrl, method, headers = {}, credentials, fetchTimeout }) {
66
this.authorization = authorization;
77
this.apiUrl = apiUrl;
88
this.method = method;
99
this.headers = headers;
1010
this.credentials = credentials;
11+
this.fetchTimeout = fetchTimeout;
1112
}
1213

1314
request(method, { baseRequestId, ...params }) {
@@ -36,7 +37,8 @@ class HttpTransport {
3637
...this.headers
3738
},
3839
credentials: this.credentials,
39-
body: requestMethod === 'POST' ? JSON.stringify(params) : null
40+
body: requestMethod === 'POST' ? JSON.stringify(params) : null,
41+
signal: this.fetchTimeout ? AbortSignal.timeout(this.fetchTimeout) : undefined,
4042
});
4143

4244
return {

packages/cubejs-client-core/src/index.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class CubeApi {
5757
this.pollInterval = options.pollInterval || 5;
5858
this.parseDateMeasures = options.parseDateMeasures;
5959
this.castNumerics = typeof options.castNumerics === 'boolean' ? options.castNumerics : false;
60+
this.networkErrorRetries = options.networkErrorRetries || 0;
6061

6162
this.updateAuthorizationPromise = null;
6263
}
@@ -104,6 +105,8 @@ class CubeApi {
104105
}
105106
};
106107

108+
let networkRetries = this.networkErrorRetries;
109+
107110
const loadImpl = async (response, next) => {
108111
const requestInstance = await requestPromise;
109112

@@ -135,7 +138,11 @@ class CubeApi {
135138

136139
skipAuthorizationUpdate = false;
137140

138-
if (response.status === 502) {
141+
if (response.status === 502 ||
142+
response.error &&
143+
response.error.toLowerCase() === 'network error' &&
144+
--networkRetries >= 0
145+
) {
139146
await checkMutex();
140147
return continueWait(true);
141148
}

0 commit comments

Comments
 (0)