@mondaydotcomorg/monday-authorization 3.9.4-feat-shaime-fix-timeout-5ff7b3a → 3.9.4-feat-shaime-fix-timeout-53ee888
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/dist/authorization-internal-service.d.ts +4 -0
- package/dist/authorization-internal-service.d.ts.map +1 -1
- package/dist/authorization-internal-service.js +30 -19
- package/dist/esm/authorization-internal-service.d.ts +4 -0
- package/dist/esm/authorization-internal-service.d.ts.map +1 -1
- package/dist/esm/authorization-internal-service.mjs +30 -19
- package/package.json +1 -1
- package/src/authorization-internal-service.ts +44 -17
|
@@ -5,6 +5,9 @@ import type { AuthorizationFetchOptions } from './types/fetch-options';
|
|
|
5
5
|
export declare const MAX_RETRIES = 3;
|
|
6
6
|
export declare const RETRY_DELAY_MS = 20;
|
|
7
7
|
export declare const logger: import("bunyan");
|
|
8
|
+
/**
|
|
9
|
+
* Key used to retrieve retry configuration from Ignite.
|
|
10
|
+
*/
|
|
8
11
|
export declare const IGNITE_RETRY_CONFIG_KEY = "authorization_retry_config";
|
|
9
12
|
export declare const onRetryCallback: OnRetryCallback;
|
|
10
13
|
/**
|
|
@@ -26,6 +29,7 @@ export declare class AuthorizationInternalService {
|
|
|
26
29
|
static generateInternalAuthToken(accountId: number, userId: number): string;
|
|
27
30
|
static setRequestFetchOptions(customMondayFetchOptions: AuthorizationFetchOptions): void;
|
|
28
31
|
static getRequestFetchOptions(): AuthorizationFetchOptions;
|
|
32
|
+
static resetRequestFetchOptions(): void;
|
|
29
33
|
static setIgniteClient(client: IgniteClient): void;
|
|
30
34
|
static getRequestTimeout(): number;
|
|
31
35
|
static getRetriesPolicy(): RetryPolicy;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../src/authorization-internal-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,eAAe,EACf,QAAQ,EACR,WAAW,EAEZ,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAE/C,eAAO,MAAM,uBAAuB,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../src/authorization-internal-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,eAAe,EACf,QAAQ,EACR,WAAW,EAEZ,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,uBAAuB,+BAA+B,CAAC;AA8JpE,eAAO,MAAM,eAAe,EAAE,eAkB7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,kBAAkB;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,KAAG,MAOlF,CAAC;AAIF,qBAAa,4BAA4B;IACvC,MAAM,KAAK,YAAY,IAAI,YAAY,GAAG,SAAS,CAElD;IAED,MAAM,KAAK,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,EAEvD;IACD,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIpD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIjD,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMlE,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAc5E,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK;IAQjE,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIlE,MAAM,CAAC,sBAAsB,CAAC,wBAAwB,EAAE,yBAAyB;IAWjF,MAAM,CAAC,sBAAsB,IAAI,yBAAyB;IAI1D,MAAM,CAAC,wBAAwB;IAI/B,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,YAAY;IAI3C,MAAM,CAAC,iBAAiB;IA0BxB,MAAM,CAAC,gBAAgB,IAAI,WAAW;CA2BvC"}
|
|
@@ -27,6 +27,9 @@ const INTERNAL_APP_NAME = 'internal_ms';
|
|
|
27
27
|
const MAX_RETRIES = 3;
|
|
28
28
|
const RETRY_DELAY_MS = 20;
|
|
29
29
|
const logger = MondayLogger__namespace.getLogger();
|
|
30
|
+
/**
|
|
31
|
+
* Key used to retrieve retry configuration from Ignite.
|
|
32
|
+
*/
|
|
30
33
|
const IGNITE_RETRY_CONFIG_KEY = 'authorization_retry_config';
|
|
31
34
|
let igniteClient;
|
|
32
35
|
const defaultRetryConfig = {
|
|
@@ -41,11 +44,17 @@ const defaultRetryConfig = {
|
|
|
41
44
|
* Sanitizes retry configuration values to ensure they are within valid ranges
|
|
42
45
|
*/
|
|
43
46
|
function sanitizeRetryConfig(config) {
|
|
47
|
+
const merged = { ...defaultRetryConfig, ...config };
|
|
44
48
|
return {
|
|
45
|
-
...
|
|
46
|
-
retries: Math.max(0, Math.min(5,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
...merged,
|
|
50
|
+
retries: Math.max(0, Math.min(5, merged.retries)),
|
|
51
|
+
baseDelayMs: Math.max(0, merged.baseDelayMs),
|
|
52
|
+
exponentBase: Math.max(1, Math.min(100, merged.exponentBase)),
|
|
53
|
+
jitterMinMs: Math.max(0, merged.jitterMinMs),
|
|
54
|
+
jitterMaxMs: Math.max(0, merged.jitterMaxMs),
|
|
55
|
+
retryOnStatusPatterns: Array.isArray(merged.retryOnStatusPatterns)
|
|
56
|
+
? merged.retryOnStatusPatterns
|
|
57
|
+
: defaultRetryConfig.retryOnStatusPatterns,
|
|
49
58
|
};
|
|
50
59
|
}
|
|
51
60
|
function getRetryConfig() {
|
|
@@ -67,6 +76,10 @@ function randomIntInclusive(min, max) {
|
|
|
67
76
|
}
|
|
68
77
|
return Math.floor(min + Math.random() * (max - min + 1));
|
|
69
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Helper to build status matchers from config patterns.
|
|
81
|
+
* @param patterns Array of patterns like "429", "5**", "5*9"
|
|
82
|
+
*/
|
|
70
83
|
function buildHttpStatusMatchers(patterns) {
|
|
71
84
|
const matchers = [];
|
|
72
85
|
const addWildcardMatcher = (wildcard) => {
|
|
@@ -119,13 +132,6 @@ function buildHttpStatusMatchers(patterns) {
|
|
|
119
132
|
}
|
|
120
133
|
return matchers;
|
|
121
134
|
}
|
|
122
|
-
function shouldRetryOnResponseStatus(responseOrStatus, statusMatchers) {
|
|
123
|
-
const status = responseOrStatus?.status;
|
|
124
|
-
if (typeof status !== 'number') {
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
return statusMatchers.some(matcher => matcher(status));
|
|
128
|
-
}
|
|
129
135
|
const onRetryCallback = (attempt, error, response, isTimeoutError) => {
|
|
130
136
|
const effectiveMaxRetries = getRetryConfig().retries;
|
|
131
137
|
if (attempt == effectiveMaxRetries) {
|
|
@@ -148,9 +154,7 @@ const calcDelayDurationInMs = ({ attemptCount }) => {
|
|
|
148
154
|
const jitter = randomIntInclusive(jitterMin, jitterMax);
|
|
149
155
|
return expDelay + jitter;
|
|
150
156
|
};
|
|
151
|
-
let mondayFetchOptions = {
|
|
152
|
-
retries: defaultRetryConfig.retries,
|
|
153
|
-
};
|
|
157
|
+
let mondayFetchOptions = {};
|
|
154
158
|
class AuthorizationInternalService {
|
|
155
159
|
static get igniteClient() {
|
|
156
160
|
return igniteClient;
|
|
@@ -166,7 +170,7 @@ class AuthorizationInternalService {
|
|
|
166
170
|
}
|
|
167
171
|
static failIfNotCoveredByAuthorization(request) {
|
|
168
172
|
if (!request.authorizationCheckPerformed && !request.authorizationSkipPerformed) {
|
|
169
|
-
throw 'Endpoint is not covered by authorization check';
|
|
173
|
+
throw new Error('Endpoint is not covered by authorization check');
|
|
170
174
|
}
|
|
171
175
|
}
|
|
172
176
|
static throwOnHttpErrorIfNeeded(response, placement) {
|
|
@@ -190,13 +194,16 @@ class AuthorizationInternalService {
|
|
|
190
194
|
sanitizedOptions.retries = Math.max(0, Math.min(5, sanitizedOptions.retries));
|
|
191
195
|
}
|
|
192
196
|
mondayFetchOptions = {
|
|
193
|
-
...
|
|
197
|
+
...mondayFetchOptions,
|
|
194
198
|
...sanitizedOptions,
|
|
195
199
|
};
|
|
196
200
|
}
|
|
197
201
|
static getRequestFetchOptions() {
|
|
198
202
|
return mondayFetchOptions;
|
|
199
203
|
}
|
|
204
|
+
static resetRequestFetchOptions() {
|
|
205
|
+
mondayFetchOptions = {};
|
|
206
|
+
}
|
|
200
207
|
static setIgniteClient(client) {
|
|
201
208
|
igniteClient = client;
|
|
202
209
|
}
|
|
@@ -206,8 +213,8 @@ class AuthorizationInternalService {
|
|
|
206
213
|
if (!this.igniteClient) {
|
|
207
214
|
return defaultTimeout;
|
|
208
215
|
}
|
|
209
|
-
const overrideTimeouts = this.igniteClient.configuration.getObjectValue('override-outgoing-request-timeout-ms', {});
|
|
210
216
|
try {
|
|
217
|
+
const overrideTimeouts = this.igniteClient.configuration.getObjectValue('override-outgoing-request-timeout-ms', {});
|
|
211
218
|
if (process.env.APP_NAME && process.env.APP_NAME in overrideTimeouts) {
|
|
212
219
|
return overrideTimeouts[process.env.APP_NAME];
|
|
213
220
|
}
|
|
@@ -224,8 +231,12 @@ class AuthorizationInternalService {
|
|
|
224
231
|
const fetchOptions = AuthorizationInternalService.getRequestFetchOptions();
|
|
225
232
|
const retryConfig = getRetryConfig();
|
|
226
233
|
const statusMatchers = buildHttpStatusMatchers(retryConfig.retryOnStatusPatterns);
|
|
227
|
-
const defaultRetryOn = (_attempt,
|
|
228
|
-
|
|
234
|
+
const defaultRetryOn = (_attempt, error, response, isTimeoutError) => {
|
|
235
|
+
if (isTimeoutError) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
const status = response?.status ?? error?.status;
|
|
239
|
+
return typeof status === 'number' ? statusMatchers.some(matcher => matcher(status)) : false;
|
|
229
240
|
};
|
|
230
241
|
// Sanitize retries from fetchOptions: clamp between 0 and 5
|
|
231
242
|
const rawMaxRetries = fetchOptions?.retries ?? retryConfig.retries;
|
|
@@ -5,6 +5,9 @@ import type { AuthorizationFetchOptions } from './types/fetch-options';
|
|
|
5
5
|
export declare const MAX_RETRIES = 3;
|
|
6
6
|
export declare const RETRY_DELAY_MS = 20;
|
|
7
7
|
export declare const logger: import("bunyan");
|
|
8
|
+
/**
|
|
9
|
+
* Key used to retrieve retry configuration from Ignite.
|
|
10
|
+
*/
|
|
8
11
|
export declare const IGNITE_RETRY_CONFIG_KEY = "authorization_retry_config";
|
|
9
12
|
export declare const onRetryCallback: OnRetryCallback;
|
|
10
13
|
/**
|
|
@@ -26,6 +29,7 @@ export declare class AuthorizationInternalService {
|
|
|
26
29
|
static generateInternalAuthToken(accountId: number, userId: number): string;
|
|
27
30
|
static setRequestFetchOptions(customMondayFetchOptions: AuthorizationFetchOptions): void;
|
|
28
31
|
static getRequestFetchOptions(): AuthorizationFetchOptions;
|
|
32
|
+
static resetRequestFetchOptions(): void;
|
|
29
33
|
static setIgniteClient(client: IgniteClient): void;
|
|
30
34
|
static getRequestTimeout(): number;
|
|
31
35
|
static getRetriesPolicy(): RetryPolicy;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../../src/authorization-internal-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,eAAe,EACf,QAAQ,EACR,WAAW,EAEZ,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAE/C,eAAO,MAAM,uBAAuB,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../../src/authorization-internal-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,eAAe,EACf,QAAQ,EACR,WAAW,EAEZ,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,uBAAuB,+BAA+B,CAAC;AA8JpE,eAAO,MAAM,eAAe,EAAE,eAkB7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,kBAAkB;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,KAAG,MAOlF,CAAC;AAIF,qBAAa,4BAA4B;IACvC,MAAM,KAAK,YAAY,IAAI,YAAY,GAAG,SAAS,CAElD;IAED,MAAM,KAAK,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,EAEvD;IACD,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIpD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIjD,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMlE,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAc5E,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK;IAQjE,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIlE,MAAM,CAAC,sBAAsB,CAAC,wBAAwB,EAAE,yBAAyB;IAWjF,MAAM,CAAC,sBAAsB,IAAI,yBAAyB;IAI1D,MAAM,CAAC,wBAAwB;IAI/B,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,YAAY;IAI3C,MAAM,CAAC,iBAAiB;IA0BxB,MAAM,CAAC,gBAAgB,IAAI,WAAW;CA2BvC"}
|
|
@@ -5,6 +5,9 @@ const INTERNAL_APP_NAME = 'internal_ms';
|
|
|
5
5
|
const MAX_RETRIES = 3;
|
|
6
6
|
const RETRY_DELAY_MS = 20;
|
|
7
7
|
const logger = MondayLogger.getLogger();
|
|
8
|
+
/**
|
|
9
|
+
* Key used to retrieve retry configuration from Ignite.
|
|
10
|
+
*/
|
|
8
11
|
const IGNITE_RETRY_CONFIG_KEY = 'authorization_retry_config';
|
|
9
12
|
let igniteClient;
|
|
10
13
|
const defaultRetryConfig = {
|
|
@@ -19,11 +22,17 @@ const defaultRetryConfig = {
|
|
|
19
22
|
* Sanitizes retry configuration values to ensure they are within valid ranges
|
|
20
23
|
*/
|
|
21
24
|
function sanitizeRetryConfig(config) {
|
|
25
|
+
const merged = { ...defaultRetryConfig, ...config };
|
|
22
26
|
return {
|
|
23
|
-
...
|
|
24
|
-
retries: Math.max(0, Math.min(5,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
...merged,
|
|
28
|
+
retries: Math.max(0, Math.min(5, merged.retries)),
|
|
29
|
+
baseDelayMs: Math.max(0, merged.baseDelayMs),
|
|
30
|
+
exponentBase: Math.max(1, Math.min(100, merged.exponentBase)),
|
|
31
|
+
jitterMinMs: Math.max(0, merged.jitterMinMs),
|
|
32
|
+
jitterMaxMs: Math.max(0, merged.jitterMaxMs),
|
|
33
|
+
retryOnStatusPatterns: Array.isArray(merged.retryOnStatusPatterns)
|
|
34
|
+
? merged.retryOnStatusPatterns
|
|
35
|
+
: defaultRetryConfig.retryOnStatusPatterns,
|
|
27
36
|
};
|
|
28
37
|
}
|
|
29
38
|
function getRetryConfig() {
|
|
@@ -45,6 +54,10 @@ function randomIntInclusive(min, max) {
|
|
|
45
54
|
}
|
|
46
55
|
return Math.floor(min + Math.random() * (max - min + 1));
|
|
47
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Helper to build status matchers from config patterns.
|
|
59
|
+
* @param patterns Array of patterns like "429", "5**", "5*9"
|
|
60
|
+
*/
|
|
48
61
|
function buildHttpStatusMatchers(patterns) {
|
|
49
62
|
const matchers = [];
|
|
50
63
|
const addWildcardMatcher = (wildcard) => {
|
|
@@ -97,13 +110,6 @@ function buildHttpStatusMatchers(patterns) {
|
|
|
97
110
|
}
|
|
98
111
|
return matchers;
|
|
99
112
|
}
|
|
100
|
-
function shouldRetryOnResponseStatus(responseOrStatus, statusMatchers) {
|
|
101
|
-
const status = responseOrStatus?.status;
|
|
102
|
-
if (typeof status !== 'number') {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
return statusMatchers.some(matcher => matcher(status));
|
|
106
|
-
}
|
|
107
113
|
const onRetryCallback = (attempt, error, response, isTimeoutError) => {
|
|
108
114
|
const effectiveMaxRetries = getRetryConfig().retries;
|
|
109
115
|
if (attempt == effectiveMaxRetries) {
|
|
@@ -126,9 +132,7 @@ const calcDelayDurationInMs = ({ attemptCount }) => {
|
|
|
126
132
|
const jitter = randomIntInclusive(jitterMin, jitterMax);
|
|
127
133
|
return expDelay + jitter;
|
|
128
134
|
};
|
|
129
|
-
let mondayFetchOptions = {
|
|
130
|
-
retries: defaultRetryConfig.retries,
|
|
131
|
-
};
|
|
135
|
+
let mondayFetchOptions = {};
|
|
132
136
|
class AuthorizationInternalService {
|
|
133
137
|
static get igniteClient() {
|
|
134
138
|
return igniteClient;
|
|
@@ -144,7 +148,7 @@ class AuthorizationInternalService {
|
|
|
144
148
|
}
|
|
145
149
|
static failIfNotCoveredByAuthorization(request) {
|
|
146
150
|
if (!request.authorizationCheckPerformed && !request.authorizationSkipPerformed) {
|
|
147
|
-
throw 'Endpoint is not covered by authorization check';
|
|
151
|
+
throw new Error('Endpoint is not covered by authorization check');
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
154
|
static throwOnHttpErrorIfNeeded(response, placement) {
|
|
@@ -168,13 +172,16 @@ class AuthorizationInternalService {
|
|
|
168
172
|
sanitizedOptions.retries = Math.max(0, Math.min(5, sanitizedOptions.retries));
|
|
169
173
|
}
|
|
170
174
|
mondayFetchOptions = {
|
|
171
|
-
...
|
|
175
|
+
...mondayFetchOptions,
|
|
172
176
|
...sanitizedOptions,
|
|
173
177
|
};
|
|
174
178
|
}
|
|
175
179
|
static getRequestFetchOptions() {
|
|
176
180
|
return mondayFetchOptions;
|
|
177
181
|
}
|
|
182
|
+
static resetRequestFetchOptions() {
|
|
183
|
+
mondayFetchOptions = {};
|
|
184
|
+
}
|
|
178
185
|
static setIgniteClient(client) {
|
|
179
186
|
igniteClient = client;
|
|
180
187
|
}
|
|
@@ -184,8 +191,8 @@ class AuthorizationInternalService {
|
|
|
184
191
|
if (!this.igniteClient) {
|
|
185
192
|
return defaultTimeout;
|
|
186
193
|
}
|
|
187
|
-
const overrideTimeouts = this.igniteClient.configuration.getObjectValue('override-outgoing-request-timeout-ms', {});
|
|
188
194
|
try {
|
|
195
|
+
const overrideTimeouts = this.igniteClient.configuration.getObjectValue('override-outgoing-request-timeout-ms', {});
|
|
189
196
|
if (process.env.APP_NAME && process.env.APP_NAME in overrideTimeouts) {
|
|
190
197
|
return overrideTimeouts[process.env.APP_NAME];
|
|
191
198
|
}
|
|
@@ -202,8 +209,12 @@ class AuthorizationInternalService {
|
|
|
202
209
|
const fetchOptions = AuthorizationInternalService.getRequestFetchOptions();
|
|
203
210
|
const retryConfig = getRetryConfig();
|
|
204
211
|
const statusMatchers = buildHttpStatusMatchers(retryConfig.retryOnStatusPatterns);
|
|
205
|
-
const defaultRetryOn = (_attempt,
|
|
206
|
-
|
|
212
|
+
const defaultRetryOn = (_attempt, error, response, isTimeoutError) => {
|
|
213
|
+
if (isTimeoutError) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
const status = response?.status ?? error?.status;
|
|
217
|
+
return typeof status === 'number' ? statusMatchers.some(matcher => matcher(status)) : false;
|
|
207
218
|
};
|
|
208
219
|
// Sanitize retries from fetchOptions: clamp between 0 and 5
|
|
209
220
|
const rawMaxRetries = fetchOptions?.retries ?? retryConfig.retries;
|
package/package.json
CHANGED
|
@@ -16,6 +16,9 @@ export const MAX_RETRIES = 3;
|
|
|
16
16
|
export const RETRY_DELAY_MS = 20;
|
|
17
17
|
export const logger = MondayLogger.getLogger();
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Key used to retrieve retry configuration from Ignite.
|
|
21
|
+
*/
|
|
19
22
|
export const IGNITE_RETRY_CONFIG_KEY = 'authorization_retry_config';
|
|
20
23
|
|
|
21
24
|
let igniteClient: IgniteClient | undefined;
|
|
@@ -48,12 +51,18 @@ const defaultRetryConfig: RetryConfig = {
|
|
|
48
51
|
/**
|
|
49
52
|
* Sanitizes retry configuration values to ensure they are within valid ranges
|
|
50
53
|
*/
|
|
51
|
-
function sanitizeRetryConfig(config: RetryConfig): RetryConfig {
|
|
54
|
+
function sanitizeRetryConfig(config: Partial<RetryConfig>): RetryConfig {
|
|
55
|
+
const merged = { ...defaultRetryConfig, ...config };
|
|
52
56
|
return {
|
|
53
|
-
...
|
|
54
|
-
retries: Math.max(0, Math.min(5,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
...merged,
|
|
58
|
+
retries: Math.max(0, Math.min(5, merged.retries)),
|
|
59
|
+
baseDelayMs: Math.max(0, merged.baseDelayMs),
|
|
60
|
+
exponentBase: Math.max(1, Math.min(100, merged.exponentBase)),
|
|
61
|
+
jitterMinMs: Math.max(0, merged.jitterMinMs),
|
|
62
|
+
jitterMaxMs: Math.max(0, merged.jitterMaxMs),
|
|
63
|
+
retryOnStatusPatterns: Array.isArray(merged.retryOnStatusPatterns)
|
|
64
|
+
? merged.retryOnStatusPatterns
|
|
65
|
+
: defaultRetryConfig.retryOnStatusPatterns,
|
|
57
66
|
};
|
|
58
67
|
}
|
|
59
68
|
|
|
@@ -62,7 +71,10 @@ function getRetryConfig(): RetryConfig {
|
|
|
62
71
|
return defaultRetryConfig;
|
|
63
72
|
}
|
|
64
73
|
try {
|
|
65
|
-
const config = igniteClient.configuration.getObjectValue<RetryConfig
|
|
74
|
+
const config = igniteClient.configuration.getObjectValue<Partial<RetryConfig>>(
|
|
75
|
+
IGNITE_RETRY_CONFIG_KEY,
|
|
76
|
+
defaultRetryConfig
|
|
77
|
+
);
|
|
66
78
|
return sanitizeRetryConfig(config);
|
|
67
79
|
} catch (error) {
|
|
68
80
|
logger.error(
|
|
@@ -82,6 +94,10 @@ function randomIntInclusive(min: number, max: number): number {
|
|
|
82
94
|
|
|
83
95
|
type StatusMatcher = (status: number) => boolean;
|
|
84
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Helper to build status matchers from config patterns.
|
|
99
|
+
* @param patterns Array of patterns like "429", "5**", "5*9"
|
|
100
|
+
*/
|
|
85
101
|
function buildHttpStatusMatchers(patterns: string[]): StatusMatcher[] {
|
|
86
102
|
const matchers: StatusMatcher[] = [];
|
|
87
103
|
|
|
@@ -145,6 +161,11 @@ function buildHttpStatusMatchers(patterns: string[]): StatusMatcher[] {
|
|
|
145
161
|
return matchers;
|
|
146
162
|
}
|
|
147
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Determines if a request should be retried based on the response status.
|
|
166
|
+
* @param responseOrStatus The response object or null/undefined
|
|
167
|
+
* @param statusMatchers Array of matchers to check against
|
|
168
|
+
*/
|
|
148
169
|
function shouldRetryOnResponseStatus(
|
|
149
170
|
responseOrStatus: Response | null | undefined,
|
|
150
171
|
statusMatchers: StatusMatcher[]
|
|
@@ -190,9 +211,7 @@ export const calcDelayDurationInMs = ({ attemptCount }: { attemptCount: number }
|
|
|
190
211
|
return expDelay + jitter;
|
|
191
212
|
};
|
|
192
213
|
|
|
193
|
-
let mondayFetchOptions: AuthorizationFetchOptions = {
|
|
194
|
-
retries: defaultRetryConfig.retries,
|
|
195
|
-
};
|
|
214
|
+
let mondayFetchOptions: AuthorizationFetchOptions = {};
|
|
196
215
|
|
|
197
216
|
export class AuthorizationInternalService {
|
|
198
217
|
static get igniteClient(): IgniteClient | undefined {
|
|
@@ -212,7 +231,7 @@ export class AuthorizationInternalService {
|
|
|
212
231
|
|
|
213
232
|
static failIfNotCoveredByAuthorization(request: BaseRequest): void {
|
|
214
233
|
if (!request.authorizationCheckPerformed && !request.authorizationSkipPerformed) {
|
|
215
|
-
throw 'Endpoint is not covered by authorization check';
|
|
234
|
+
throw new Error('Endpoint is not covered by authorization check');
|
|
216
235
|
}
|
|
217
236
|
}
|
|
218
237
|
|
|
@@ -248,7 +267,7 @@ export class AuthorizationInternalService {
|
|
|
248
267
|
sanitizedOptions.retries = Math.max(0, Math.min(5, sanitizedOptions.retries));
|
|
249
268
|
}
|
|
250
269
|
mondayFetchOptions = {
|
|
251
|
-
...
|
|
270
|
+
...mondayFetchOptions,
|
|
252
271
|
...sanitizedOptions,
|
|
253
272
|
};
|
|
254
273
|
}
|
|
@@ -257,6 +276,10 @@ export class AuthorizationInternalService {
|
|
|
257
276
|
return mondayFetchOptions;
|
|
258
277
|
}
|
|
259
278
|
|
|
279
|
+
static resetRequestFetchOptions() {
|
|
280
|
+
mondayFetchOptions = {};
|
|
281
|
+
}
|
|
282
|
+
|
|
260
283
|
static setIgniteClient(client: IgniteClient) {
|
|
261
284
|
igniteClient = client;
|
|
262
285
|
}
|
|
@@ -268,11 +291,11 @@ export class AuthorizationInternalService {
|
|
|
268
291
|
return defaultTimeout;
|
|
269
292
|
}
|
|
270
293
|
|
|
271
|
-
const overrideTimeouts = this.igniteClient.configuration.getObjectValue<Record<string, number>>(
|
|
272
|
-
'override-outgoing-request-timeout-ms',
|
|
273
|
-
{}
|
|
274
|
-
);
|
|
275
294
|
try {
|
|
295
|
+
const overrideTimeouts = this.igniteClient.configuration.getObjectValue<Record<string, number>>(
|
|
296
|
+
'override-outgoing-request-timeout-ms',
|
|
297
|
+
{}
|
|
298
|
+
);
|
|
276
299
|
if (process.env.APP_NAME && process.env.APP_NAME in overrideTimeouts) {
|
|
277
300
|
return overrideTimeouts[process.env.APP_NAME];
|
|
278
301
|
} else {
|
|
@@ -291,8 +314,12 @@ export class AuthorizationInternalService {
|
|
|
291
314
|
const fetchOptions = AuthorizationInternalService.getRequestFetchOptions();
|
|
292
315
|
const retryConfig = getRetryConfig();
|
|
293
316
|
const statusMatchers = buildHttpStatusMatchers(retryConfig.retryOnStatusPatterns);
|
|
294
|
-
const defaultRetryOn = (_attempt,
|
|
295
|
-
|
|
317
|
+
const defaultRetryOn = (_attempt, error, response, isTimeoutError) => {
|
|
318
|
+
if (isTimeoutError) {
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
const status = response?.status ?? (error as any)?.status;
|
|
322
|
+
return typeof status === 'number' ? statusMatchers.some(matcher => matcher(status)) : false;
|
|
296
323
|
};
|
|
297
324
|
// Sanitize retries from fetchOptions: clamp between 0 and 5
|
|
298
325
|
const rawMaxRetries = fetchOptions?.retries ?? retryConfig.retries;
|