@algolia/client-common 5.0.0-alpha.3 → 5.0.0-alpha.30
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/client-common.cjs.js +58 -144
- package/dist/client-common.esm.node.js +58 -142
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/src/cache/createBrowserLocalStorageCache.d.ts.map +1 -1
- package/dist/src/cache/createFallbackableCache.d.ts.map +1 -1
- package/dist/src/cache/createMemoryCache.d.ts.map +1 -1
- package/dist/src/cache/createNullCache.d.ts.map +1 -1
- package/dist/src/cache/index.d.ts.map +1 -1
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/createAlgoliaAgent.d.ts.map +1 -1
- package/dist/src/createAuth.d.ts.map +1 -1
- package/dist/src/createEchoRequester.d.ts.map +1 -1
- package/dist/src/createIterablePromise.d.ts +13 -0
- package/dist/src/createIterablePromise.d.ts.map +1 -0
- package/dist/src/getAlgoliaAgent.d.ts.map +1 -1
- package/dist/src/transporter/createStatefulHost.d.ts.map +1 -1
- package/dist/src/transporter/createTransporter.d.ts.map +1 -1
- package/dist/src/transporter/errors.d.ts.map +1 -1
- package/dist/src/transporter/helpers.d.ts.map +1 -1
- package/dist/src/transporter/index.d.ts.map +1 -1
- package/dist/src/transporter/responses.d.ts.map +1 -1
- package/dist/src/transporter/stackTrace.d.ts.map +1 -1
- package/dist/src/types/{Cache.d.ts → cache.d.ts} +1 -1
- package/dist/src/types/cache.d.ts.map +1 -0
- package/dist/src/types/{CreateClient.d.ts → createClient.d.ts} +2 -2
- package/dist/src/types/createClient.d.ts.map +1 -0
- package/dist/src/types/createIterablePromise.d.ts +36 -0
- package/dist/src/types/createIterablePromise.d.ts.map +1 -0
- package/dist/src/types/{Host.d.ts → host.d.ts} +1 -1
- package/dist/src/types/host.d.ts.map +1 -0
- package/dist/src/types/index.d.ts +6 -6
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/{Requester.d.ts → requester.d.ts} +2 -2
- package/dist/src/types/requester.d.ts.map +1 -0
- package/dist/src/types/{Transporter.d.ts → transporter.d.ts} +4 -4
- package/dist/src/types/transporter.d.ts.map +1 -0
- package/index.ts +1 -1
- package/package.json +9 -8
- package/src/__tests__/create-iterable-promise.test.ts +238 -0
- package/src/createEchoRequester.ts +1 -1
- package/src/createIterablePromise.ts +47 -0
- package/src/transporter/createTransporter.ts +4 -1
- package/src/transporter/helpers.ts +2 -2
- package/src/types/{Cache.ts → cache.ts} +0 -0
- package/src/types/{CreateClient.ts → createClient.ts} +1 -1
- package/src/types/createIterablePromise.ts +40 -0
- package/src/types/{Host.ts → host.ts} +0 -0
- package/src/types/index.ts +6 -6
- package/src/types/{Requester.ts → requester.ts} +1 -1
- package/src/types/{Transporter.ts → transporter.ts} +3 -3
- package/dist/src/createRetryablePromise.d.ts +0 -14
- package/dist/src/createRetryablePromise.d.ts.map +0 -1
- package/dist/src/types/Cache.d.ts.map +0 -1
- package/dist/src/types/CreateClient.d.ts.map +0 -1
- package/dist/src/types/CreateRetryablePromise.d.ts +0 -19
- package/dist/src/types/CreateRetryablePromise.d.ts.map +0 -1
- package/dist/src/types/Host.d.ts.map +0 -1
- package/dist/src/types/Requester.d.ts.map +0 -1
- package/dist/src/types/Transporter.d.ts.map +0 -1
- package/src/__tests__/create-retryable-promise.test.ts +0 -86
- package/src/createRetryablePromise.ts +0 -52
- package/src/types/CreateRetryablePromise.ts +0 -21
|
@@ -11,11 +11,9 @@ function createAuth(appId, apiKey, authMode = 'WithinHeaders') {
|
|
|
11
11
|
headers() {
|
|
12
12
|
return authMode === 'WithinHeaders' ? credentials : {};
|
|
13
13
|
},
|
|
14
|
-
|
|
15
14
|
queryParameters() {
|
|
16
15
|
return authMode === 'WithinQueryParameters' ? credentials : {};
|
|
17
16
|
}
|
|
18
|
-
|
|
19
17
|
};
|
|
20
18
|
}
|
|
21
19
|
|
|
@@ -26,15 +24,12 @@ function getUrlParams({
|
|
|
26
24
|
}) {
|
|
27
25
|
const algoliaAgent = urlSearchParams.get('x-algolia-agent') || '';
|
|
28
26
|
const searchParams = {};
|
|
29
|
-
|
|
30
27
|
for (const [k, v] of urlSearchParams) {
|
|
31
28
|
if (k === 'x-algolia-agent') {
|
|
32
29
|
continue;
|
|
33
30
|
}
|
|
34
|
-
|
|
35
31
|
searchParams[k] = v;
|
|
36
32
|
}
|
|
37
|
-
|
|
38
33
|
return {
|
|
39
34
|
host,
|
|
40
35
|
algoliaAgent,
|
|
@@ -42,7 +37,6 @@ function getUrlParams({
|
|
|
42
37
|
path: pathname
|
|
43
38
|
};
|
|
44
39
|
}
|
|
45
|
-
|
|
46
40
|
function createEchoRequester({
|
|
47
41
|
getURL,
|
|
48
42
|
status = 200
|
|
@@ -54,11 +48,12 @@ function createEchoRequester({
|
|
|
54
48
|
algoliaAgent,
|
|
55
49
|
path
|
|
56
50
|
} = getUrlParams(getURL(request.url));
|
|
57
|
-
const content = {
|
|
51
|
+
const content = {
|
|
52
|
+
...request,
|
|
58
53
|
data: request.data ? JSON.parse(request.data) : undefined,
|
|
59
54
|
path,
|
|
60
55
|
host,
|
|
61
|
-
algoliaAgent:
|
|
56
|
+
algoliaAgent: encodeURIComponent(algoliaAgent),
|
|
62
57
|
searchParams
|
|
63
58
|
};
|
|
64
59
|
return Promise.resolve({
|
|
@@ -67,73 +62,64 @@ function createEchoRequester({
|
|
|
67
62
|
status
|
|
68
63
|
});
|
|
69
64
|
}
|
|
70
|
-
|
|
71
65
|
return {
|
|
72
66
|
send
|
|
73
67
|
};
|
|
74
68
|
}
|
|
75
69
|
|
|
76
|
-
const DEFAULT_MAX_RETRIES = 50;
|
|
77
|
-
const DEFAULT_TIMEOUT = retryCount => Math.min(retryCount * 200, 5000);
|
|
78
70
|
/**
|
|
79
|
-
*
|
|
71
|
+
* Helper: Returns the promise of a given `func` to iterate on, based on a given `validate` condition.
|
|
80
72
|
*
|
|
81
|
-
* @param
|
|
82
|
-
* @param
|
|
83
|
-
* @param
|
|
84
|
-
* @param
|
|
85
|
-
* @param
|
|
73
|
+
* @param createIterator - The createIterator options.
|
|
74
|
+
* @param createIterator.func - The function to run, which returns a promise.
|
|
75
|
+
* @param createIterator.validate - The validator function. It receives the resolved return of `func`.
|
|
76
|
+
* @param createIterator.aggregator - The function that runs right after the `func` method has been executed, allows you to do anything with the response before `validate`.
|
|
77
|
+
* @param createIterator.error - The `validate` condition to throw an error, and its message.
|
|
78
|
+
* @param createIterator.timeout - The function to decide how long to wait between iterations.
|
|
86
79
|
*/
|
|
87
|
-
|
|
88
|
-
function createRetryablePromise({
|
|
80
|
+
function createIterablePromise({
|
|
89
81
|
func,
|
|
90
82
|
validate,
|
|
91
|
-
|
|
92
|
-
|
|
83
|
+
aggregator,
|
|
84
|
+
error,
|
|
85
|
+
timeout = () => 0
|
|
93
86
|
}) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const retry = () => {
|
|
87
|
+
const retry = previousResponse => {
|
|
97
88
|
return new Promise((resolve, reject) => {
|
|
98
|
-
func().then(response => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (isValid) {
|
|
102
|
-
resolve(response);
|
|
103
|
-
} else if (retryCount + 1 >= maxRetries) {
|
|
104
|
-
reject(new Error(`The maximum number of retries exceeded. (${retryCount + 1}/${maxRetries})`));
|
|
105
|
-
} else {
|
|
106
|
-
retryCount += 1;
|
|
107
|
-
setTimeout(() => {
|
|
108
|
-
retry().then(resolve).catch(reject);
|
|
109
|
-
}, timeout(retryCount));
|
|
89
|
+
func(previousResponse).then(response => {
|
|
90
|
+
if (aggregator) {
|
|
91
|
+
aggregator(response);
|
|
110
92
|
}
|
|
111
|
-
|
|
112
|
-
|
|
93
|
+
if (validate(response)) {
|
|
94
|
+
return resolve(response);
|
|
95
|
+
}
|
|
96
|
+
if (error && error.validate(response)) {
|
|
97
|
+
return reject(new Error(error.message(response)));
|
|
98
|
+
}
|
|
99
|
+
return setTimeout(() => {
|
|
100
|
+
retry(response).then(resolve).catch(reject);
|
|
101
|
+
}, timeout());
|
|
102
|
+
}).catch(err => {
|
|
103
|
+
reject(err);
|
|
113
104
|
});
|
|
114
105
|
});
|
|
115
106
|
};
|
|
116
|
-
|
|
117
107
|
return retry();
|
|
118
108
|
}
|
|
119
109
|
|
|
120
110
|
function createBrowserLocalStorageCache(options) {
|
|
121
|
-
let storage;
|
|
122
|
-
|
|
111
|
+
let storage;
|
|
112
|
+
// We've changed the namespace to avoid conflicts with v4, as this version is a huge breaking change
|
|
123
113
|
const namespaceKey = `algolia-client-js-${options.key}`;
|
|
124
|
-
|
|
125
114
|
function getStorage() {
|
|
126
115
|
if (storage === undefined) {
|
|
127
116
|
storage = options.localStorage || window.localStorage;
|
|
128
117
|
}
|
|
129
|
-
|
|
130
118
|
return storage;
|
|
131
119
|
}
|
|
132
|
-
|
|
133
120
|
function getNamespace() {
|
|
134
121
|
return JSON.parse(getStorage().getItem(namespaceKey) || '{}');
|
|
135
122
|
}
|
|
136
|
-
|
|
137
123
|
return {
|
|
138
124
|
get(key, defaultValue, events = {
|
|
139
125
|
miss: () => Promise.resolve()
|
|
@@ -146,7 +132,6 @@ function createBrowserLocalStorageCache(options) {
|
|
|
146
132
|
return Promise.all([value, exists || events.miss(value)]);
|
|
147
133
|
}).then(([value]) => value);
|
|
148
134
|
},
|
|
149
|
-
|
|
150
135
|
set(key, value) {
|
|
151
136
|
return Promise.resolve().then(() => {
|
|
152
137
|
const namespace = getNamespace();
|
|
@@ -155,7 +140,6 @@ function createBrowserLocalStorageCache(options) {
|
|
|
155
140
|
return value;
|
|
156
141
|
});
|
|
157
142
|
},
|
|
158
|
-
|
|
159
143
|
delete(key) {
|
|
160
144
|
return Promise.resolve().then(() => {
|
|
161
145
|
const namespace = getNamespace();
|
|
@@ -163,13 +147,11 @@ function createBrowserLocalStorageCache(options) {
|
|
|
163
147
|
getStorage().setItem(namespaceKey, JSON.stringify(namespace));
|
|
164
148
|
});
|
|
165
149
|
},
|
|
166
|
-
|
|
167
150
|
clear() {
|
|
168
151
|
return Promise.resolve().then(() => {
|
|
169
152
|
getStorage().removeItem(namespaceKey);
|
|
170
153
|
});
|
|
171
154
|
}
|
|
172
|
-
|
|
173
155
|
};
|
|
174
156
|
}
|
|
175
157
|
|
|
@@ -181,30 +163,24 @@ function createNullCache() {
|
|
|
181
163
|
const value = defaultValue();
|
|
182
164
|
return value.then(result => Promise.all([result, events.miss(result)])).then(([result]) => result);
|
|
183
165
|
},
|
|
184
|
-
|
|
185
166
|
set(_key, value) {
|
|
186
167
|
return Promise.resolve(value);
|
|
187
168
|
},
|
|
188
|
-
|
|
189
169
|
delete(_key) {
|
|
190
170
|
return Promise.resolve();
|
|
191
171
|
},
|
|
192
|
-
|
|
193
172
|
clear() {
|
|
194
173
|
return Promise.resolve();
|
|
195
174
|
}
|
|
196
|
-
|
|
197
175
|
};
|
|
198
176
|
}
|
|
199
177
|
|
|
200
178
|
function createFallbackableCache(options) {
|
|
201
179
|
const caches = [...options.caches];
|
|
202
180
|
const current = caches.shift();
|
|
203
|
-
|
|
204
181
|
if (current === undefined) {
|
|
205
182
|
return createNullCache();
|
|
206
183
|
}
|
|
207
|
-
|
|
208
184
|
return {
|
|
209
185
|
get(key, defaultValue, events = {
|
|
210
186
|
miss: () => Promise.resolve()
|
|
@@ -215,7 +191,6 @@ function createFallbackableCache(options) {
|
|
|
215
191
|
}).get(key, defaultValue, events);
|
|
216
192
|
});
|
|
217
193
|
},
|
|
218
|
-
|
|
219
194
|
set(key, value) {
|
|
220
195
|
return current.set(key, value).catch(() => {
|
|
221
196
|
return createFallbackableCache({
|
|
@@ -223,7 +198,6 @@ function createFallbackableCache(options) {
|
|
|
223
198
|
}).set(key, value);
|
|
224
199
|
});
|
|
225
200
|
},
|
|
226
|
-
|
|
227
201
|
delete(key) {
|
|
228
202
|
return current.delete(key).catch(() => {
|
|
229
203
|
return createFallbackableCache({
|
|
@@ -231,7 +205,6 @@ function createFallbackableCache(options) {
|
|
|
231
205
|
}).delete(key);
|
|
232
206
|
});
|
|
233
207
|
},
|
|
234
|
-
|
|
235
208
|
clear() {
|
|
236
209
|
return current.clear().catch(() => {
|
|
237
210
|
return createFallbackableCache({
|
|
@@ -239,7 +212,6 @@ function createFallbackableCache(options) {
|
|
|
239
212
|
}).clear();
|
|
240
213
|
});
|
|
241
214
|
}
|
|
242
|
-
|
|
243
215
|
};
|
|
244
216
|
}
|
|
245
217
|
|
|
@@ -252,30 +224,24 @@ function createMemoryCache(options = {
|
|
|
252
224
|
miss: () => Promise.resolve()
|
|
253
225
|
}) {
|
|
254
226
|
const keyAsString = JSON.stringify(key);
|
|
255
|
-
|
|
256
227
|
if (keyAsString in cache) {
|
|
257
228
|
return Promise.resolve(options.serializable ? JSON.parse(cache[keyAsString]) : cache[keyAsString]);
|
|
258
229
|
}
|
|
259
|
-
|
|
260
230
|
const promise = defaultValue();
|
|
261
231
|
return promise.then(value => events.miss(value)).then(() => promise);
|
|
262
232
|
},
|
|
263
|
-
|
|
264
233
|
set(key, value) {
|
|
265
234
|
cache[JSON.stringify(key)] = options.serializable ? JSON.stringify(value) : value;
|
|
266
235
|
return Promise.resolve(value);
|
|
267
236
|
},
|
|
268
|
-
|
|
269
237
|
delete(key) {
|
|
270
238
|
delete cache[JSON.stringify(key)];
|
|
271
239
|
return Promise.resolve();
|
|
272
240
|
},
|
|
273
|
-
|
|
274
241
|
clear() {
|
|
275
242
|
cache = {};
|
|
276
243
|
return Promise.resolve();
|
|
277
244
|
}
|
|
278
|
-
|
|
279
245
|
};
|
|
280
246
|
}
|
|
281
247
|
|
|
@@ -284,16 +250,14 @@ function createMemoryCache(options = {
|
|
|
284
250
|
const EXPIRATION_DELAY = 2 * 60 * 1000;
|
|
285
251
|
function createStatefulHost(host, status = 'up') {
|
|
286
252
|
const lastUpdate = Date.now();
|
|
287
|
-
|
|
288
253
|
function isUp() {
|
|
289
254
|
return status === 'up' || Date.now() - lastUpdate > EXPIRATION_DELAY;
|
|
290
255
|
}
|
|
291
|
-
|
|
292
256
|
function isTimedOut() {
|
|
293
257
|
return status === 'timed out' && Date.now() - lastUpdate <= EXPIRATION_DELAY;
|
|
294
258
|
}
|
|
295
|
-
|
|
296
|
-
|
|
259
|
+
return {
|
|
260
|
+
...host,
|
|
297
261
|
status,
|
|
298
262
|
lastUpdate,
|
|
299
263
|
isUp,
|
|
@@ -312,92 +276,74 @@ function _defineProperty(obj, key, value) {
|
|
|
312
276
|
} else {
|
|
313
277
|
obj[key] = value;
|
|
314
278
|
}
|
|
315
|
-
|
|
316
279
|
return obj;
|
|
317
280
|
}
|
|
318
281
|
|
|
319
282
|
class AlgoliaError extends Error {
|
|
320
283
|
constructor(message, name) {
|
|
321
284
|
super(message);
|
|
322
|
-
|
|
323
285
|
_defineProperty(this, "name", 'AlgoliaError');
|
|
324
|
-
|
|
325
286
|
if (name) {
|
|
326
287
|
this.name = name;
|
|
327
288
|
}
|
|
328
289
|
}
|
|
329
|
-
|
|
330
290
|
}
|
|
331
291
|
class ErrorWithStackTrace extends AlgoliaError {
|
|
332
292
|
constructor(message, stackTrace, name) {
|
|
333
|
-
super(message, name);
|
|
334
|
-
|
|
293
|
+
super(message, name);
|
|
294
|
+
// the array and object should be frozen to reflect the stackTrace at the time of the error
|
|
335
295
|
_defineProperty(this, "stackTrace", void 0);
|
|
336
|
-
|
|
337
296
|
this.stackTrace = stackTrace;
|
|
338
297
|
}
|
|
339
|
-
|
|
340
298
|
}
|
|
341
299
|
class RetryError extends ErrorWithStackTrace {
|
|
342
300
|
constructor(stackTrace) {
|
|
343
301
|
super('Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.', stackTrace, 'RetryError');
|
|
344
302
|
}
|
|
345
|
-
|
|
346
303
|
}
|
|
347
304
|
class ApiError extends ErrorWithStackTrace {
|
|
348
305
|
constructor(message, status, stackTrace) {
|
|
349
306
|
super(message, stackTrace, 'ApiError');
|
|
350
|
-
|
|
351
307
|
_defineProperty(this, "status", void 0);
|
|
352
|
-
|
|
353
308
|
this.status = status;
|
|
354
309
|
}
|
|
355
|
-
|
|
356
310
|
}
|
|
357
311
|
class DeserializationError extends AlgoliaError {
|
|
358
312
|
constructor(message, response) {
|
|
359
313
|
super(message, 'DeserializationError');
|
|
360
|
-
|
|
361
314
|
_defineProperty(this, "response", void 0);
|
|
362
|
-
|
|
363
315
|
this.response = response;
|
|
364
316
|
}
|
|
365
|
-
|
|
366
317
|
}
|
|
367
318
|
|
|
368
319
|
function shuffle(array) {
|
|
369
320
|
const shuffledArray = array;
|
|
370
|
-
|
|
371
321
|
for (let c = array.length - 1; c > 0; c--) {
|
|
372
322
|
const b = Math.floor(Math.random() * (c + 1));
|
|
373
323
|
const a = array[c];
|
|
374
324
|
shuffledArray[c] = array[b];
|
|
375
325
|
shuffledArray[b] = a;
|
|
376
326
|
}
|
|
377
|
-
|
|
378
327
|
return shuffledArray;
|
|
379
328
|
}
|
|
380
329
|
function serializeUrl(host, path, queryParameters) {
|
|
381
330
|
const queryParametersAsString = serializeQueryParameters(queryParameters);
|
|
382
331
|
let url = `${host.protocol}://${host.url}/${path.charAt(0) === '/' ? path.substr(1) : path}`;
|
|
383
|
-
|
|
384
332
|
if (queryParametersAsString.length) {
|
|
385
333
|
url += `?${queryParametersAsString}`;
|
|
386
334
|
}
|
|
387
|
-
|
|
388
335
|
return url;
|
|
389
336
|
}
|
|
390
337
|
function serializeQueryParameters(parameters) {
|
|
391
338
|
const isObjectOrArray = value => Object.prototype.toString.call(value) === '[object Object]' || Object.prototype.toString.call(value) === '[object Array]';
|
|
392
|
-
|
|
393
|
-
return Object.keys(parameters).map(key => `${key}=${isObjectOrArray(parameters[key]) ? JSON.stringify(parameters[key]) : parameters[key]}`).join('&');
|
|
339
|
+
return Object.keys(parameters).map(key => `${key}=${encodeURIComponent(isObjectOrArray(parameters[key]) ? JSON.stringify(parameters[key]) : parameters[key])}`).join('&');
|
|
394
340
|
}
|
|
395
341
|
function serializeData(request, requestOptions) {
|
|
396
342
|
if (request.method === 'GET' || request.data === undefined && requestOptions.data === undefined) {
|
|
397
343
|
return undefined;
|
|
398
344
|
}
|
|
399
|
-
|
|
400
|
-
|
|
345
|
+
const data = Array.isArray(request.data) ? request.data : {
|
|
346
|
+
...request.data,
|
|
401
347
|
...requestOptions.data
|
|
402
348
|
};
|
|
403
349
|
return JSON.stringify(data);
|
|
@@ -428,12 +374,11 @@ function deserializeFailure({
|
|
|
428
374
|
status
|
|
429
375
|
}, stackFrame) {
|
|
430
376
|
let message = content;
|
|
431
|
-
|
|
432
377
|
try {
|
|
433
378
|
message = JSON.parse(content).message;
|
|
434
|
-
} catch (e) {
|
|
379
|
+
} catch (e) {
|
|
380
|
+
// ..
|
|
435
381
|
}
|
|
436
|
-
|
|
437
382
|
return new ApiError(message, status, stackFrame);
|
|
438
383
|
}
|
|
439
384
|
|
|
@@ -465,9 +410,12 @@ function stackFrameWithoutCredentials(stackFrame) {
|
|
|
465
410
|
const modifiedHeaders = stackFrame.request.headers['x-algolia-api-key'] ? {
|
|
466
411
|
'x-algolia-api-key': '*****'
|
|
467
412
|
} : {};
|
|
468
|
-
return {
|
|
469
|
-
|
|
470
|
-
|
|
413
|
+
return {
|
|
414
|
+
...stackFrame,
|
|
415
|
+
request: {
|
|
416
|
+
...stackFrame.request,
|
|
417
|
+
headers: {
|
|
418
|
+
...stackFrame.request.headers,
|
|
471
419
|
...modifiedHeaders
|
|
472
420
|
}
|
|
473
421
|
}
|
|
@@ -492,13 +440,12 @@ function createTransporter({
|
|
|
492
440
|
});
|
|
493
441
|
}));
|
|
494
442
|
const hostsUp = statefulHosts.filter(host => host.isUp());
|
|
495
|
-
const hostsTimedOut = statefulHosts.filter(host => host.isTimedOut());
|
|
496
|
-
|
|
443
|
+
const hostsTimedOut = statefulHosts.filter(host => host.isTimedOut());
|
|
444
|
+
// Note, we put the hosts that previously timed out on the end of the list.
|
|
497
445
|
const hostsAvailable = [...hostsUp, ...hostsTimedOut];
|
|
498
446
|
const compatibleHostsAvailable = hostsAvailable.length > 0 ? hostsAvailable : compatibleHosts;
|
|
499
447
|
return {
|
|
500
448
|
hosts: compatibleHostsAvailable,
|
|
501
|
-
|
|
502
449
|
getTimeout(timeoutsCount, baseTimeout) {
|
|
503
450
|
/**
|
|
504
451
|
* Imagine that you have 4 hosts, if timeouts will increase
|
|
@@ -514,29 +461,28 @@ function createTransporter({
|
|
|
514
461
|
const timeoutMultiplier = hostsTimedOut.length === 0 && timeoutsCount === 0 ? 1 : hostsTimedOut.length + 3 + timeoutsCount;
|
|
515
462
|
return timeoutMultiplier * baseTimeout;
|
|
516
463
|
}
|
|
517
|
-
|
|
518
464
|
};
|
|
519
465
|
}
|
|
520
|
-
|
|
521
466
|
async function retryableRequest(request, requestOptions, isRead = true) {
|
|
522
467
|
const stackTrace = [];
|
|
523
468
|
/**
|
|
524
469
|
* First we prepare the payload that do not depend from hosts.
|
|
525
470
|
*/
|
|
526
|
-
|
|
527
471
|
const data = serializeData(request, requestOptions);
|
|
528
|
-
const headers = serializeHeaders(baseHeaders, request.headers, requestOptions.headers);
|
|
529
|
-
|
|
530
|
-
const dataQueryParameters = request.method === 'GET' ? {
|
|
472
|
+
const headers = serializeHeaders(baseHeaders, request.headers, requestOptions.headers);
|
|
473
|
+
// On `GET`, the data is proxied to query parameters.
|
|
474
|
+
const dataQueryParameters = request.method === 'GET' ? {
|
|
475
|
+
...request.data,
|
|
531
476
|
...requestOptions.data
|
|
532
477
|
} : {};
|
|
533
478
|
const queryParameters = {
|
|
534
|
-
'x-algolia-agent': algoliaAgent.value,
|
|
535
479
|
...baseQueryParameters,
|
|
536
480
|
...request.queryParameters,
|
|
537
481
|
...dataQueryParameters
|
|
538
482
|
};
|
|
539
|
-
|
|
483
|
+
if (algoliaAgent.value) {
|
|
484
|
+
queryParameters['x-algolia-agent'] = algoliaAgent.value;
|
|
485
|
+
}
|
|
540
486
|
if (requestOptions && requestOptions.queryParameters) {
|
|
541
487
|
for (const key of Object.keys(requestOptions.queryParameters)) {
|
|
542
488
|
// We want to keep `undefined` and `null` values,
|
|
@@ -549,25 +495,19 @@ function createTransporter({
|
|
|
549
495
|
}
|
|
550
496
|
}
|
|
551
497
|
}
|
|
552
|
-
|
|
553
498
|
let timeoutsCount = 0;
|
|
554
|
-
|
|
555
499
|
const retry = async (retryableHosts, getTimeout) => {
|
|
556
500
|
/**
|
|
557
501
|
* We iterate on each host, until there is no host left.
|
|
558
502
|
*/
|
|
559
503
|
const host = retryableHosts.pop();
|
|
560
|
-
|
|
561
504
|
if (host === undefined) {
|
|
562
505
|
throw new RetryError(stackTraceWithoutCredentials(stackTrace));
|
|
563
506
|
}
|
|
564
|
-
|
|
565
507
|
let responseTimeout = requestOptions.timeout;
|
|
566
|
-
|
|
567
508
|
if (responseTimeout === undefined) {
|
|
568
509
|
responseTimeout = isRead ? timeouts.read : timeouts.write;
|
|
569
510
|
}
|
|
570
|
-
|
|
571
511
|
const payload = {
|
|
572
512
|
data,
|
|
573
513
|
headers,
|
|
@@ -581,7 +521,6 @@ function createTransporter({
|
|
|
581
521
|
* can have information about onRetry and onFailure
|
|
582
522
|
* decisions.
|
|
583
523
|
*/
|
|
584
|
-
|
|
585
524
|
const pushToStackTrace = response => {
|
|
586
525
|
const stackFrame = {
|
|
587
526
|
request: payload,
|
|
@@ -592,12 +531,10 @@ function createTransporter({
|
|
|
592
531
|
stackTrace.push(stackFrame);
|
|
593
532
|
return stackFrame;
|
|
594
533
|
};
|
|
595
|
-
|
|
596
534
|
const response = await requester.send(payload);
|
|
597
|
-
|
|
598
535
|
if (isRetryable(response)) {
|
|
599
|
-
const stackFrame = pushToStackTrace(response);
|
|
600
|
-
|
|
536
|
+
const stackFrame = pushToStackTrace(response);
|
|
537
|
+
// If response is a timeout, we increase the number of timeouts so we can increase the timeout later.
|
|
601
538
|
if (response.isTimedOut) {
|
|
602
539
|
timeoutsCount++;
|
|
603
540
|
}
|
|
@@ -607,23 +544,18 @@ function createTransporter({
|
|
|
607
544
|
* when a retry error does not happen.
|
|
608
545
|
*/
|
|
609
546
|
// eslint-disable-next-line no-console -- this will be fixed by exposing a `logger` to the transporter
|
|
610
|
-
|
|
611
|
-
|
|
612
547
|
console.log('Retryable failure', stackFrameWithoutCredentials(stackFrame));
|
|
613
548
|
/**
|
|
614
549
|
* We also store the state of the host in failure cases. If the host, is
|
|
615
550
|
* down it will remain down for the next 2 minutes. In a timeout situation,
|
|
616
551
|
* this host will be added end of the list of hosts on the next request.
|
|
617
552
|
*/
|
|
618
|
-
|
|
619
553
|
await hostsCache.set(host, createStatefulHost(host, response.isTimedOut ? 'timed out' : 'down'));
|
|
620
554
|
return retry(retryableHosts, getTimeout);
|
|
621
555
|
}
|
|
622
|
-
|
|
623
556
|
if (isSuccess(response)) {
|
|
624
557
|
return deserializeSuccess(response);
|
|
625
558
|
}
|
|
626
|
-
|
|
627
559
|
pushToStackTrace(response);
|
|
628
560
|
throw deserializeFailure(response, stackTrace);
|
|
629
561
|
};
|
|
@@ -635,20 +567,16 @@ function createTransporter({
|
|
|
635
567
|
* 2. We also get from the retryable options a timeout multiplier that is tailored
|
|
636
568
|
* for the current context.
|
|
637
569
|
*/
|
|
638
|
-
|
|
639
|
-
|
|
640
570
|
const compatibleHosts = hosts.filter(host => host.accept === 'readWrite' || (isRead ? host.accept === 'read' : host.accept === 'write'));
|
|
641
571
|
const options = await createRetryableOptions(compatibleHosts);
|
|
642
572
|
return retry([...options.hosts].reverse(), options.getTimeout);
|
|
643
573
|
}
|
|
644
|
-
|
|
645
574
|
function createRequest(request, requestOptions = {}) {
|
|
646
575
|
/**
|
|
647
576
|
* A read request is either a `GET` request, or a request that we make
|
|
648
577
|
* via the `read` transporter (e.g. `search`).
|
|
649
578
|
*/
|
|
650
579
|
const isRead = request.useReadTransporter || request.method === 'GET';
|
|
651
|
-
|
|
652
580
|
if (!isRead) {
|
|
653
581
|
/**
|
|
654
582
|
* On write requests, no cache mechanisms are applied, and we
|
|
@@ -656,7 +584,6 @@ function createTransporter({
|
|
|
656
584
|
*/
|
|
657
585
|
return retryableRequest(request, requestOptions, isRead);
|
|
658
586
|
}
|
|
659
|
-
|
|
660
587
|
const createRetryableRequest = () => {
|
|
661
588
|
/**
|
|
662
589
|
* Then, we prepare a function factory that contains the construction of
|
|
@@ -670,14 +597,11 @@ function createTransporter({
|
|
|
670
597
|
* request is "cacheable" - should be cached. Note that, once again,
|
|
671
598
|
* the user can force this option.
|
|
672
599
|
*/
|
|
673
|
-
|
|
674
|
-
|
|
675
600
|
const cacheable = requestOptions.cacheable || request.cacheable;
|
|
676
601
|
/**
|
|
677
602
|
* If is not "cacheable", we immediately trigger the retryable request, no
|
|
678
603
|
* need to check cache implementations.
|
|
679
604
|
*/
|
|
680
|
-
|
|
681
605
|
if (cacheable !== true) {
|
|
682
606
|
return createRetryableRequest();
|
|
683
607
|
}
|
|
@@ -686,8 +610,6 @@ function createTransporter({
|
|
|
686
610
|
* the cache implementations if this request is on progress or if the
|
|
687
611
|
* response already exists on the cache.
|
|
688
612
|
*/
|
|
689
|
-
|
|
690
|
-
|
|
691
613
|
const key = {
|
|
692
614
|
request,
|
|
693
615
|
requestOptions,
|
|
@@ -700,7 +622,6 @@ function createTransporter({
|
|
|
700
622
|
* With the computed key, we first ask the responses cache
|
|
701
623
|
* implementation if this request was been resolved before.
|
|
702
624
|
*/
|
|
703
|
-
|
|
704
625
|
return responsesCache.get(key, () => {
|
|
705
626
|
/**
|
|
706
627
|
* If the request has never resolved before, we actually ask if there
|
|
@@ -722,7 +643,6 @@ function createTransporter({
|
|
|
722
643
|
miss: response => responsesCache.set(key, response)
|
|
723
644
|
});
|
|
724
645
|
}
|
|
725
|
-
|
|
726
646
|
return {
|
|
727
647
|
hostsCache,
|
|
728
648
|
requester,
|
|
@@ -740,17 +660,13 @@ function createTransporter({
|
|
|
740
660
|
function createAlgoliaAgent(version) {
|
|
741
661
|
const algoliaAgent = {
|
|
742
662
|
value: `Algolia for JavaScript (${version})`,
|
|
743
|
-
|
|
744
663
|
add(options) {
|
|
745
664
|
const addedAlgoliaAgent = `; ${options.segment}${options.version !== undefined ? ` (${options.version})` : ''}`;
|
|
746
|
-
|
|
747
665
|
if (algoliaAgent.value.indexOf(addedAlgoliaAgent) === -1) {
|
|
748
666
|
algoliaAgent.value = `${algoliaAgent.value}${addedAlgoliaAgent}`;
|
|
749
667
|
}
|
|
750
|
-
|
|
751
668
|
return algoliaAgent;
|
|
752
669
|
}
|
|
753
|
-
|
|
754
670
|
};
|
|
755
671
|
return algoliaAgent;
|
|
756
672
|
}
|
|
@@ -779,10 +695,8 @@ exports.AlgoliaError = AlgoliaError;
|
|
|
779
695
|
exports.ApiError = ApiError;
|
|
780
696
|
exports.DEFAULT_CONNECT_TIMEOUT_BROWSER = DEFAULT_CONNECT_TIMEOUT_BROWSER;
|
|
781
697
|
exports.DEFAULT_CONNECT_TIMEOUT_NODE = DEFAULT_CONNECT_TIMEOUT_NODE;
|
|
782
|
-
exports.DEFAULT_MAX_RETRIES = DEFAULT_MAX_RETRIES;
|
|
783
698
|
exports.DEFAULT_READ_TIMEOUT_BROWSER = DEFAULT_READ_TIMEOUT_BROWSER;
|
|
784
699
|
exports.DEFAULT_READ_TIMEOUT_NODE = DEFAULT_READ_TIMEOUT_NODE;
|
|
785
|
-
exports.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
|
|
786
700
|
exports.DEFAULT_WRITE_TIMEOUT_BROWSER = DEFAULT_WRITE_TIMEOUT_BROWSER;
|
|
787
701
|
exports.DEFAULT_WRITE_TIMEOUT_NODE = DEFAULT_WRITE_TIMEOUT_NODE;
|
|
788
702
|
exports.DeserializationError = DeserializationError;
|
|
@@ -793,9 +707,9 @@ exports.createAuth = createAuth;
|
|
|
793
707
|
exports.createBrowserLocalStorageCache = createBrowserLocalStorageCache;
|
|
794
708
|
exports.createEchoRequester = createEchoRequester;
|
|
795
709
|
exports.createFallbackableCache = createFallbackableCache;
|
|
710
|
+
exports.createIterablePromise = createIterablePromise;
|
|
796
711
|
exports.createMemoryCache = createMemoryCache;
|
|
797
712
|
exports.createNullCache = createNullCache;
|
|
798
|
-
exports.createRetryablePromise = createRetryablePromise;
|
|
799
713
|
exports.createStatefulHost = createStatefulHost;
|
|
800
714
|
exports.createTransporter = createTransporter;
|
|
801
715
|
exports.deserializeFailure = deserializeFailure;
|