@ampsec/platform-client 70.7.0 → 71.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/src/services/rest/RestClient.js +47 -28
- package/build/src/services/rest/RestClient.js.map +1 -1
- package/build/src/services/rest/retry.rest.d.ts +17 -3
- package/build/src/services/rest/retry.rest.js +24 -12
- package/build/src/services/rest/retry.rest.js.map +1 -1
- package/package.json +1 -1
- package/src/services/rest/RestClient.ts +46 -27
- package/src/services/rest/retry.rest.ts +33 -13
|
@@ -47,39 +47,55 @@ class DefaultRestClient {
|
|
|
47
47
|
this.call = async (request) => {
|
|
48
48
|
var _a, _b;
|
|
49
49
|
const req = lodash_1.default.merge(request);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (err instanceof axios_1.AxiosError) {
|
|
66
|
-
const axiosError = err;
|
|
67
|
-
const status = (_b = (_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : 500;
|
|
68
|
-
// ! DO NOT print the entire error here because axiosError.request likely contains sensitive data
|
|
69
|
-
this.logger.error(`[${status}] ${axiosError.message}`);
|
|
70
|
-
// ! DO NOT print the entire error here because axiosError.request likely contains sensitive data
|
|
71
|
-
if (this.strict && status >= 400) {
|
|
72
|
-
throw new Error(`[${status}] ${axiosError.message} (apc-hGRxLB-2)`);
|
|
50
|
+
let attempt = 0;
|
|
51
|
+
const processing = true;
|
|
52
|
+
retryLoop: while (processing) {
|
|
53
|
+
attempt++;
|
|
54
|
+
try {
|
|
55
|
+
await this.rateLimitStrategy.reserve(req);
|
|
56
|
+
this.logger.debug({ req }); // noop logger by default
|
|
57
|
+
const res = await this.ampAxios.request(req);
|
|
58
|
+
if (this.strict && res.status >= 400) {
|
|
59
|
+
const delay = this.retryStrategy.onError({ response: res }, attempt);
|
|
60
|
+
if (delay > 0) {
|
|
61
|
+
await sleep(delay);
|
|
62
|
+
continue retryLoop;
|
|
63
|
+
}
|
|
64
|
+
throw new Error(`[${res.status}] ${req.url} ${res.statusText} (apc-P8ZZJp-1)`);
|
|
73
65
|
}
|
|
74
66
|
return {
|
|
75
|
-
status: status,
|
|
76
|
-
headers:
|
|
77
|
-
data:
|
|
78
|
-
error:
|
|
67
|
+
status: res.status,
|
|
68
|
+
headers: (0, utils_1.convertHeaders)(res),
|
|
69
|
+
data: res.data,
|
|
70
|
+
error: null,
|
|
79
71
|
};
|
|
80
72
|
}
|
|
81
|
-
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (err instanceof axios_1.AxiosError) {
|
|
75
|
+
const axiosError = err;
|
|
76
|
+
const delay = this.retryStrategy.onError(axiosError, attempt);
|
|
77
|
+
if (delay > 0) {
|
|
78
|
+
await sleep(delay);
|
|
79
|
+
continue retryLoop;
|
|
80
|
+
}
|
|
81
|
+
const status = (_b = (_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : 500;
|
|
82
|
+
// ! DO NOT print the entire error here because axiosError.request likely contains sensitive data
|
|
83
|
+
this.logger.error(`[${status}] ${req.url} ${axiosError.message}`);
|
|
84
|
+
// ! DO NOT print the entire error here because axiosError.request likely contains sensitive data
|
|
85
|
+
if (this.strict && status >= 400) {
|
|
86
|
+
throw new Error(`[${status}] ${req.url} ${axiosError.message} (apc-hGRxLB-2)`);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
status: status,
|
|
90
|
+
headers: axiosError.response ? (0, utils_1.convertHeaders)(axiosError.response) : {},
|
|
91
|
+
data: null,
|
|
92
|
+
error: err,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
82
97
|
}
|
|
98
|
+
throw new Error('Unknown Error');
|
|
83
99
|
};
|
|
84
100
|
const client = (_a = options.client) !== null && _a !== void 0 ? _a : axios_1.default;
|
|
85
101
|
this.ampAxios = client.create({
|
|
@@ -129,4 +145,7 @@ const getAmpRestClient = (options) => {
|
|
|
129
145
|
return ampClient;
|
|
130
146
|
};
|
|
131
147
|
exports.getAmpRestClient = getAmpRestClient;
|
|
148
|
+
function sleep(delay) {
|
|
149
|
+
return new Promise(resolve => setTimeout(resolve, delay));
|
|
150
|
+
}
|
|
132
151
|
//# sourceMappingURL=RestClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RestClient.js","sourceRoot":"","sources":["../../../../src/services/rest/RestClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAAuB;AACvB,4CAAoB;AACpB,+CAA4D;AAG5D,6CAA4E;AAC5E,mCAAmD;AACnD,qDAAiI;AACjI,2CAAoD;AAqCpD;;;;;;GAMG;AACH,MAAa,iBAAiB;IAQ5B,YAAY,UAA6B,EAAE;;QA+B3C,SAAI,GAAG,KAAK,EAAE,OAAoB,EAAyB,EAAE;;YAC3D,MAAM,GAAG,GAAG,gBAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"RestClient.js","sourceRoot":"","sources":["../../../../src/services/rest/RestClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import { AxiosError } from 'axios';
|
|
2
|
-
import { RestRequest } from './RestRequest';
|
|
3
|
-
import { RestResponse } from './RestResponse';
|
|
4
2
|
export interface RestClientRetryStrategy {
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @param _err The error that caused the retry
|
|
5
|
+
* @param attempt The number of attempts that have been made
|
|
6
|
+
* @returns The delay in milliseconds before the next retry. Return 0 to stop retrying.
|
|
7
|
+
*/
|
|
8
|
+
onError(_err: AxiosError, attempt: number): number;
|
|
6
9
|
}
|
|
7
10
|
export declare const noopRestRetryStrategy: RestClientRetryStrategy;
|
|
11
|
+
export type RetryStrategyOptions = {
|
|
12
|
+
delay: number;
|
|
13
|
+
maxRetries: number;
|
|
14
|
+
};
|
|
15
|
+
export declare const getConstantRetryStrategy: (options: RetryStrategyOptions) => RestClientRetryStrategy;
|
|
16
|
+
export declare const getLinearRetryStrategy: (options: RetryStrategyOptions) => RestClientRetryStrategy;
|
|
17
|
+
export declare const REST_RETRY_STRATEGIES: {
|
|
18
|
+
noopRestRetryStrategy: RestClientRetryStrategy;
|
|
19
|
+
getConstantRetryStrategy: (options: RetryStrategyOptions) => RestClientRetryStrategy;
|
|
20
|
+
getLinearRetryStrategy: (options: RetryStrategyOptions) => RestClientRetryStrategy;
|
|
21
|
+
};
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.noopRestRetryStrategy = void 0;
|
|
4
|
-
const utils_1 = require("./utils");
|
|
3
|
+
exports.REST_RETRY_STRATEGIES = exports.getLinearRetryStrategy = exports.getConstantRetryStrategy = exports.noopRestRetryStrategy = void 0;
|
|
5
4
|
exports.noopRestRetryStrategy = {
|
|
6
|
-
onError: (
|
|
7
|
-
|
|
8
|
-
const axiosError = err;
|
|
9
|
-
const res = {
|
|
10
|
-
status: (_b = (_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : 500,
|
|
11
|
-
headers: axiosError.response ? (0, utils_1.convertHeaders)(axiosError.response) : {},
|
|
12
|
-
data: null,
|
|
13
|
-
error: err,
|
|
14
|
-
};
|
|
15
|
-
return Promise.resolve(res);
|
|
5
|
+
onError: (_err, _attempt) => {
|
|
6
|
+
return 0;
|
|
16
7
|
},
|
|
17
8
|
};
|
|
9
|
+
const getConstantRetryStrategy = (options) => ({
|
|
10
|
+
onError: (_err, attempt) => {
|
|
11
|
+
if (attempt >= options.maxRetries)
|
|
12
|
+
return 0;
|
|
13
|
+
return options.delay;
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
exports.getConstantRetryStrategy = getConstantRetryStrategy;
|
|
17
|
+
const getLinearRetryStrategy = (options) => ({
|
|
18
|
+
onError: (_err, attempt) => {
|
|
19
|
+
if (attempt >= options.maxRetries)
|
|
20
|
+
return 0;
|
|
21
|
+
return attempt * options.delay;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
exports.getLinearRetryStrategy = getLinearRetryStrategy;
|
|
25
|
+
exports.REST_RETRY_STRATEGIES = {
|
|
26
|
+
noopRestRetryStrategy: exports.noopRestRetryStrategy,
|
|
27
|
+
getConstantRetryStrategy: exports.getConstantRetryStrategy,
|
|
28
|
+
getLinearRetryStrategy: exports.getLinearRetryStrategy,
|
|
29
|
+
};
|
|
18
30
|
//# sourceMappingURL=retry.rest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.rest.js","sourceRoot":"","sources":["../../../../src/services/rest/retry.rest.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"retry.rest.js","sourceRoot":"","sources":["../../../../src/services/rest/retry.rest.ts"],"names":[],"mappings":";;;AAWa,QAAA,qBAAqB,GAA4B;IAC5D,OAAO,EAAE,CAAC,IAAgB,EAAE,QAAgB,EAAU,EAAE;QACtD,OAAO,CAAC,CAAC;IACX,CAAC;CACF,CAAC;AAOK,MAAM,wBAAwB,GAAG,CAAC,OAA6B,EAA2B,EAAE,CAAC,CAAC;IACnG,OAAO,EAAE,CAAC,IAAgB,EAAE,OAAe,EAAU,EAAE;QACrD,IAAI,OAAO,IAAI,OAAO,CAAC,UAAU;YAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC,KAAK,CAAC;IACvB,CAAC;CACF,CAAC,CAAC;AALU,QAAA,wBAAwB,4BAKlC;AAEI,MAAM,sBAAsB,GAAG,CAAC,OAA6B,EAA2B,EAAE,CAAC,CAAC;IACjG,OAAO,EAAE,CAAC,IAAgB,EAAE,OAAe,EAAU,EAAE;QACrD,IAAI,OAAO,IAAI,OAAO,CAAC,UAAU;YAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;IACjC,CAAC;CACF,CAAC,CAAC;AALU,QAAA,sBAAsB,0BAKhC;AAEU,QAAA,qBAAqB,GAAG;IACnC,qBAAqB,EAArB,6BAAqB;IACrB,wBAAwB,EAAxB,gCAAwB;IACxB,sBAAsB,EAAtB,8BAAsB;CACvB,CAAC"}
|
package/package.json
CHANGED
|
@@ -91,38 +91,54 @@ export class DefaultRestClient implements RestClient {
|
|
|
91
91
|
}
|
|
92
92
|
call = async (request: RestRequest): Promise<RestResponse> => {
|
|
93
93
|
const req = _.merge(request);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const axiosError = err as AxiosError;
|
|
110
|
-
const status = axiosError.response?.status ?? 500;
|
|
111
|
-
// ! DO NOT print the entire error here because axiosError.request likely contains sensitive data
|
|
112
|
-
this.logger.error(`[${status}] ${axiosError.message}`);
|
|
113
|
-
// ! DO NOT print the entire error here because axiosError.request likely contains sensitive data
|
|
114
|
-
if (this.strict && status >= 400) {
|
|
115
|
-
throw new Error(`[${status}] ${axiosError.message} (apc-hGRxLB-2)`);
|
|
94
|
+
let attempt = 0;
|
|
95
|
+
const processing = true;
|
|
96
|
+
retryLoop: while (processing) {
|
|
97
|
+
attempt++;
|
|
98
|
+
try {
|
|
99
|
+
await this.rateLimitStrategy.reserve(req);
|
|
100
|
+
this.logger.debug({req}); // noop logger by default
|
|
101
|
+
const res = await this.ampAxios.request(req);
|
|
102
|
+
if (this.strict && res.status >= 400) {
|
|
103
|
+
const delay = this.retryStrategy.onError({response: res} as AxiosError, attempt);
|
|
104
|
+
if (delay > 0) {
|
|
105
|
+
await sleep(delay);
|
|
106
|
+
continue retryLoop;
|
|
107
|
+
}
|
|
108
|
+
throw new Error(`[${res.status}] ${req.url} ${res.statusText} (apc-P8ZZJp-1)`);
|
|
116
109
|
}
|
|
117
110
|
return {
|
|
118
|
-
status: status,
|
|
119
|
-
headers:
|
|
120
|
-
data:
|
|
121
|
-
error:
|
|
111
|
+
status: res.status,
|
|
112
|
+
headers: convertHeaders(res),
|
|
113
|
+
data: res.data,
|
|
114
|
+
error: null,
|
|
122
115
|
};
|
|
116
|
+
} catch (err: unknown) {
|
|
117
|
+
if (err instanceof AxiosError) {
|
|
118
|
+
const axiosError = err as AxiosError;
|
|
119
|
+
const delay = this.retryStrategy.onError(axiosError, attempt);
|
|
120
|
+
if (delay > 0) {
|
|
121
|
+
await sleep(delay);
|
|
122
|
+
continue retryLoop;
|
|
123
|
+
}
|
|
124
|
+
const status = axiosError.response?.status ?? 500;
|
|
125
|
+
// ! DO NOT print the entire error here because axiosError.request likely contains sensitive data
|
|
126
|
+
this.logger.error(`[${status}] ${req.url} ${axiosError.message}`);
|
|
127
|
+
// ! DO NOT print the entire error here because axiosError.request likely contains sensitive data
|
|
128
|
+
if (this.strict && status >= 400) {
|
|
129
|
+
throw new Error(`[${status}] ${req.url} ${axiosError.message} (apc-hGRxLB-2)`);
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
status: status,
|
|
133
|
+
headers: axiosError.response ? convertHeaders(axiosError.response) : {},
|
|
134
|
+
data: null,
|
|
135
|
+
error: err,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
throw err;
|
|
123
139
|
}
|
|
124
|
-
throw err;
|
|
125
140
|
}
|
|
141
|
+
throw new Error('Unknown Error');
|
|
126
142
|
};
|
|
127
143
|
}
|
|
128
144
|
|
|
@@ -140,3 +156,6 @@ export const getAmpRestClient = (options: AmpRestClientOptions): RestClient => {
|
|
|
140
156
|
});
|
|
141
157
|
return ampClient;
|
|
142
158
|
};
|
|
159
|
+
function sleep(delay: number): Promise<void> {
|
|
160
|
+
return new Promise(resolve => setTimeout(resolve, delay));
|
|
161
|
+
}
|
|
@@ -1,21 +1,41 @@
|
|
|
1
1
|
import {AxiosError} from 'axios';
|
|
2
|
-
import {convertHeaders} from './utils';
|
|
3
|
-
import {RestRequest} from './RestRequest';
|
|
4
|
-
import {RestResponse} from './RestResponse';
|
|
5
2
|
|
|
6
3
|
export interface RestClientRetryStrategy {
|
|
7
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @param _err The error that caused the retry
|
|
6
|
+
* @param attempt The number of attempts that have been made
|
|
7
|
+
* @returns The delay in milliseconds before the next retry. Return 0 to stop retrying.
|
|
8
|
+
*/
|
|
9
|
+
onError(_err: AxiosError, attempt: number): number;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export const noopRestRetryStrategy: RestClientRetryStrategy = {
|
|
11
|
-
onError: (
|
|
12
|
-
|
|
13
|
-
const res: RestResponse = {
|
|
14
|
-
status: axiosError.response?.status ?? 500,
|
|
15
|
-
headers: axiosError.response ? convertHeaders(axiosError.response) : {},
|
|
16
|
-
data: null,
|
|
17
|
-
error: err,
|
|
18
|
-
};
|
|
19
|
-
return Promise.resolve(res);
|
|
13
|
+
onError: (_err: AxiosError, _attempt: number): number => {
|
|
14
|
+
return 0;
|
|
20
15
|
},
|
|
21
16
|
};
|
|
17
|
+
|
|
18
|
+
export type RetryStrategyOptions = {
|
|
19
|
+
delay: number;
|
|
20
|
+
maxRetries: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const getConstantRetryStrategy = (options: RetryStrategyOptions): RestClientRetryStrategy => ({
|
|
24
|
+
onError: (_err: AxiosError, attempt: number): number => {
|
|
25
|
+
if (attempt >= options.maxRetries) return 0;
|
|
26
|
+
return options.delay;
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export const getLinearRetryStrategy = (options: RetryStrategyOptions): RestClientRetryStrategy => ({
|
|
31
|
+
onError: (_err: AxiosError, attempt: number): number => {
|
|
32
|
+
if (attempt >= options.maxRetries) return 0;
|
|
33
|
+
return attempt * options.delay;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const REST_RETRY_STRATEGIES = {
|
|
38
|
+
noopRestRetryStrategy,
|
|
39
|
+
getConstantRetryStrategy,
|
|
40
|
+
getLinearRetryStrategy,
|
|
41
|
+
};
|