@vtex/api 6.45.25-beta.0 → 6.46.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/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [6.46.0] - 2023-10-25
|
|
11
|
+
### Added
|
|
12
|
+
- Add disk cache steps and retry count to tracing
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Stop updating client cache when revalidated and still expired
|
|
16
|
+
|
|
10
17
|
## [6.45.24] - 2023-10-05
|
|
11
18
|
### Added
|
|
12
19
|
|
|
13
20
|
- Allow disabling memoization for all requests of a client
|
|
21
|
+
|
|
14
22
|
## [6.45.23] - 2023-10-04
|
|
15
23
|
|
|
16
24
|
### Fixed
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const constants_1 = require("../../constants");
|
|
4
|
+
const tracing_1 = require("../../tracing");
|
|
4
5
|
const RANGE_HEADER_QS_KEY = '__range_header';
|
|
5
6
|
const cacheableStatusCodes = [200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501]; // https://tools.ietf.org/html/rfc7231#section-6.1
|
|
6
7
|
exports.cacheKey = (config) => {
|
|
@@ -59,7 +60,7 @@ exports.cacheMiddleware = ({ type, storage }) => {
|
|
|
59
60
|
if (!isLocallyCacheable(ctx.config, type)) {
|
|
60
61
|
return await next();
|
|
61
62
|
}
|
|
62
|
-
const span = (_a = ctx.tracing)
|
|
63
|
+
const { rootSpan: span, tracer, logger } = (_a = ctx.tracing) !== null && _a !== void 0 ? _a : {};
|
|
63
64
|
const key = exports.cacheKey(ctx.config);
|
|
64
65
|
const segmentToken = ctx.config.headers[constants_1.SEGMENT_HEADER];
|
|
65
66
|
const keyWithSegment = key + segmentToken;
|
|
@@ -69,8 +70,19 @@ exports.cacheMiddleware = ({ type, storage }) => {
|
|
|
69
70
|
["key" /* KEY */]: key,
|
|
70
71
|
["key-with-segment" /* KEY_WITH_SEGMENT */]: keyWithSegment,
|
|
71
72
|
});
|
|
72
|
-
const
|
|
73
|
-
|
|
73
|
+
const cacheReadSpan = createCacheSpan(cacheType, 'read', tracer, span);
|
|
74
|
+
let cached;
|
|
75
|
+
try {
|
|
76
|
+
const cacheHasWithSegment = await storage.has(keyWithSegment);
|
|
77
|
+
cached = cacheHasWithSegment ? await storage.get(keyWithSegment) : await storage.get(key);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
tracing_1.ErrorReport.create({ originalError: error }).injectOnSpan(cacheReadSpan);
|
|
81
|
+
logger === null || logger === void 0 ? void 0 : logger.warn({ message: 'Error reading from the HttpClient cache', error });
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
cacheReadSpan === null || cacheReadSpan === void 0 ? void 0 : cacheReadSpan.finish();
|
|
85
|
+
}
|
|
74
86
|
if (cached && cached.response) {
|
|
75
87
|
const { etag: cachedEtag, response, expiration, responseType, responseEncoding } = cached;
|
|
76
88
|
if (type === CacheType.Disk && responseType === 'arraybuffer') {
|
|
@@ -149,26 +161,48 @@ exports.cacheMiddleware = ({ type, storage }) => {
|
|
|
149
161
|
const cacheableData = type === CacheType.Disk && responseType === 'arraybuffer'
|
|
150
162
|
? data.toString(responseEncoding)
|
|
151
163
|
: data;
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
const now = Date.now();
|
|
165
|
+
const expiration = now + (maxAge - currentAge) * 1000;
|
|
166
|
+
const alreadyExpired = expiration <= now;
|
|
167
|
+
const reusingRevalidatedCache = cached && (ctx.response === cached.response);
|
|
168
|
+
const shouldSkipCacheUpdate = alreadyExpired && reusingRevalidatedCache;
|
|
169
|
+
if (shouldSkipCacheUpdate) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const cacheWriteSpan = createCacheSpan(cacheType, 'write', tracer, span);
|
|
173
|
+
try {
|
|
174
|
+
await storage.set(setKey, {
|
|
175
|
+
etag,
|
|
176
|
+
expiration,
|
|
177
|
+
response: { data: cacheableData, headers, status },
|
|
178
|
+
responseEncoding,
|
|
179
|
+
responseType,
|
|
180
|
+
});
|
|
181
|
+
span === null || span === void 0 ? void 0 : span.log({
|
|
182
|
+
event: "local-cache-saved" /* LOCAL_CACHE_SAVED */,
|
|
183
|
+
["cache-type" /* CACHE_TYPE */]: cacheType,
|
|
184
|
+
["key-set" /* KEY_SET */]: setKey,
|
|
185
|
+
["age" /* AGE */]: currentAge,
|
|
186
|
+
["etag" /* ETAG */]: etag,
|
|
187
|
+
["expiration-time" /* EXPIRATION_TIME */]: (expiration - Date.now()) / 1000,
|
|
188
|
+
["response-encoding" /* RESPONSE_ENCONDING */]: responseEncoding,
|
|
189
|
+
["response-type" /* RESPONSE_TYPE */]: responseType,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
tracing_1.ErrorReport.create({ originalError: error }).injectOnSpan(cacheWriteSpan);
|
|
194
|
+
logger === null || logger === void 0 ? void 0 : logger.warn({ message: 'Error writing to the HttpClient cache', error });
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
cacheWriteSpan === null || cacheWriteSpan === void 0 ? void 0 : cacheWriteSpan.finish();
|
|
198
|
+
}
|
|
170
199
|
return;
|
|
171
200
|
}
|
|
172
201
|
span === null || span === void 0 ? void 0 : span.log({ event: "no-local-cache-save" /* NO_LOCAL_CACHE_SAVE */, ["cache-type" /* CACHE_TYPE */]: cacheType });
|
|
173
202
|
};
|
|
174
203
|
};
|
|
204
|
+
const createCacheSpan = (cacheType, operation, tracer, parentSpan) => {
|
|
205
|
+
if (tracer && tracer.isTraceSampled && cacheType === 'disk') {
|
|
206
|
+
return tracer.startSpan(`${operation}-disk-cache`, { childOf: parentSpan });
|
|
207
|
+
}
|
|
208
|
+
};
|
|
@@ -18,7 +18,7 @@ const exponentialDelay = (initialBackoffDelay, exponentialBackoffCoefficient, re
|
|
|
18
18
|
// A lot of this code is based on:
|
|
19
19
|
// https://github.com/softonic/axios-retry/blob/ffd4327f31d063522e58c525d28d4c5053d0ea7b/es/index.js#L109
|
|
20
20
|
const onResponseError = (http) => (error) => {
|
|
21
|
-
var _a, _b;
|
|
21
|
+
var _a, _b, _c, _d;
|
|
22
22
|
if (error.config == null) {
|
|
23
23
|
return Promise.reject(error);
|
|
24
24
|
}
|
|
@@ -40,6 +40,10 @@ const onResponseError = (http) => (error) => {
|
|
|
40
40
|
: config.timeout;
|
|
41
41
|
config.transformRequest = [data => data];
|
|
42
42
|
(_b = (_a = config.tracing) === null || _a === void 0 ? void 0 : _a.rootSpan) === null || _b === void 0 ? void 0 : _b.log({ event: "setup-request-retry" /* SETUP_REQUEST_RETRY */, ["retry-number" /* RETRY_NUMBER */]: config.retryCount, ["retry-in" /* RETRY_IN */]: delay });
|
|
43
|
+
(_d = (_c = config.tracing) === null || _c === void 0 ? void 0 : _c.rootSpan) === null || _d === void 0 ? void 0 : _d.addTags({
|
|
44
|
+
["http.retry.count" /* HTTP_RETRY_COUNT */]: config.retryCount,
|
|
45
|
+
["http.retry.error.code" /* HTTP_RETRY_ERROR_CODE */]: error.code,
|
|
46
|
+
});
|
|
43
47
|
return new Promise(resolve => setTimeout(() => resolve(http(config)), delay));
|
|
44
48
|
}
|
|
45
49
|
return Promise.reject(error);
|
package/lib/tracing/Tags.d.ts
CHANGED
|
@@ -51,7 +51,9 @@ export declare const enum CustomHttpTags {
|
|
|
51
51
|
HTTP_MEMORY_CACHE_RESULT = "http.cache.memory",
|
|
52
52
|
HTTP_MEMOIZATION_CACHE_RESULT = "http.cache.memoization",
|
|
53
53
|
HTTP_DISK_CACHE_RESULT = "http.cache.disk",
|
|
54
|
-
HTTP_ROUTER_CACHE_RESULT = "http.cache.router"
|
|
54
|
+
HTTP_ROUTER_CACHE_RESULT = "http.cache.router",
|
|
55
|
+
HTTP_RETRY_ERROR_CODE = "http.retry.error.code",
|
|
56
|
+
HTTP_RETRY_COUNT = "http.retry.count"
|
|
55
57
|
}
|
|
56
58
|
export declare const UserlandTags: {
|
|
57
59
|
SPAN_KIND: "span.kind";
|