@bleedingdev/modern-js-bff-effect 3.9.0-ultramodern.11 → 3.9.0-ultramodern.12
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/cjs/data-platform/batch/options.js +48 -0
- package/dist/cjs/data-platform/batch/queue.js +48 -83
- package/dist/cjs/effect/handler/batch-handler.js +2 -3
- package/dist/cjs/effect/handler/batch.js +0 -9
- package/dist/cjs/effect-client/cross-project.js +5 -8
- package/dist/esm/data-platform/batch/options.mjs +10 -0
- package/dist/esm/data-platform/batch/queue.mjs +48 -83
- package/dist/esm/effect/handler/batch-handler.mjs +3 -4
- package/dist/esm/effect/handler/batch.mjs +1 -7
- package/dist/esm/effect-client/cross-project.mjs +6 -9
- package/dist/esm-node/data-platform/batch/options.mjs +11 -0
- package/dist/esm-node/data-platform/batch/queue.mjs +48 -83
- package/dist/esm-node/effect/handler/batch-handler.mjs +3 -4
- package/dist/esm-node/effect/handler/batch.mjs +1 -7
- package/dist/esm-node/effect-client/cross-project.mjs +6 -9
- package/dist/types/data-platform/batch/options.d.ts +7 -0
- package/dist/types/data-platform/batch/queue.d.ts +0 -1
- package/dist/types/effect/handler/batch.d.ts +0 -1
- package/package.json +5 -5
- package/src/data-platform/batch/options.ts +20 -0
- package/src/data-platform/batch/queue.ts +61 -89
- package/src/effect/handler/batch-handler.ts +6 -12
- package/src/effect/handler/batch.ts +0 -10
- package/src/effect-client/cross-project.ts +9 -14
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
+
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.r = (exports1)=>{
|
|
20
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
+
value: 'Module'
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
+
value: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __webpack_exports__ = {};
|
|
29
|
+
__webpack_require__.r(__webpack_exports__);
|
|
30
|
+
function normalizeBatchLimits(options = {}) {
|
|
31
|
+
return {
|
|
32
|
+
maxBatchSize: Math.max(1, options.maxBatchSize ?? 16),
|
|
33
|
+
maxBatchBytes: Math.max(1024, options.maxBatchBytes ?? 65536),
|
|
34
|
+
allowedMethods: new Set((void 0 !== options.allowedMethods && options.allowedMethods.length > 0 ? options.allowedMethods : [
|
|
35
|
+
'GET'
|
|
36
|
+
]).map((method)=>method.toUpperCase()))
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
40
|
+
normalizeBatchLimits: ()=>normalizeBatchLimits
|
|
41
|
+
});
|
|
42
|
+
exports.normalizeBatchLimits = __webpack_exports__.normalizeBatchLimits;
|
|
43
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
44
|
+
"normalizeBatchLimits"
|
|
45
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
46
|
+
Object.defineProperty(exports, '__esModule', {
|
|
47
|
+
value: true
|
|
48
|
+
});
|
|
@@ -33,6 +33,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
33
33
|
});
|
|
34
34
|
const external_codec_js_namespaceObject = require("../codec.js");
|
|
35
35
|
const external_types_js_namespaceObject = require("../types.js");
|
|
36
|
+
const external_options_js_namespaceObject = require("./options.js");
|
|
36
37
|
const external_protocol_js_namespaceObject = require("./protocol.js");
|
|
37
38
|
const external_request_js_namespaceObject = require("./request.js");
|
|
38
39
|
const external_response_js_namespaceObject = require("./response.js");
|
|
@@ -111,7 +112,6 @@ class BatchBucketRegistry {
|
|
|
111
112
|
if (existing) return existing;
|
|
112
113
|
const next = {
|
|
113
114
|
items: [],
|
|
114
|
-
bytes: 0,
|
|
115
115
|
batchId: (0, external_request_js_namespaceObject.createBatchId)(),
|
|
116
116
|
sentAt: Date.now(),
|
|
117
117
|
timer: null,
|
|
@@ -130,12 +130,8 @@ class BatchBucketRegistry {
|
|
|
130
130
|
}
|
|
131
131
|
function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
132
132
|
const flushIntervalMs = Math.max(0, options.flushIntervalMs ?? 8);
|
|
133
|
-
const maxBatchSize =
|
|
134
|
-
const maxBatchBytes = Math.max(1024, options.maxBatchBytes ?? 65536);
|
|
133
|
+
const { maxBatchSize, maxBatchBytes, allowedMethods } = (0, external_options_js_namespaceObject.normalizeBatchLimits)(options);
|
|
135
134
|
const requestTimeoutMs = options.requestTimeoutMs;
|
|
136
|
-
const allowedMethods = new Set((options.allowedMethods && options.allowedMethods.length > 0 ? options.allowedMethods : [
|
|
137
|
-
'GET'
|
|
138
|
-
]).map((method)=>method.toUpperCase()));
|
|
139
135
|
const onEvent = options.onEvent;
|
|
140
136
|
const buckets = bucketRegistry ?? new BatchBucketRegistry();
|
|
141
137
|
const pendingByKey = new Map();
|
|
@@ -168,7 +164,6 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
168
164
|
const index = bucket.items.indexOf(request);
|
|
169
165
|
if (-1 === index) return;
|
|
170
166
|
bucket.items.splice(index, 1);
|
|
171
|
-
bucket.bytes = measurePayload(bucket, bucket.items);
|
|
172
167
|
if (0 === bucket.items.length && bucket.timer) {
|
|
173
168
|
clearTimeout(bucket.timer);
|
|
174
169
|
bucket.timer = null;
|
|
@@ -210,7 +205,11 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
210
205
|
if (!SAFE_REPLAY_METHODS.has(request.item.method)) throw new Error(`Batch result is unknown for ${request.item.method}; automatic replay is disabled (${reason}).`);
|
|
211
206
|
return runSingle(request);
|
|
212
207
|
};
|
|
213
|
-
const
|
|
208
|
+
const finishFlush = (bucketKey, bucket)=>{
|
|
209
|
+
bucket.flushing = false;
|
|
210
|
+
if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
|
|
211
|
+
buckets.releaseIfIdle(bucketKey, bucket);
|
|
212
|
+
};
|
|
214
213
|
const flushBucket = async (bucketKey)=>{
|
|
215
214
|
const bucket = buckets.get(bucketKey);
|
|
216
215
|
if (!bucket || bucket.flushing) return;
|
|
@@ -227,7 +226,6 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
227
226
|
sentAt: bucket.sentAt
|
|
228
227
|
};
|
|
229
228
|
bucket.items = [];
|
|
230
|
-
bucket.bytes = 0;
|
|
231
229
|
rotatePayloadIdentity(bucket);
|
|
232
230
|
const firstItem = items[0];
|
|
233
231
|
if (!firstItem) {
|
|
@@ -243,14 +241,25 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
243
241
|
size: items.length,
|
|
244
242
|
reason: disabledEndpoints.has(endpoint) ? 'batch-disabled' : void 0
|
|
245
243
|
});
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
244
|
+
try {
|
|
245
|
+
await settleRequests(items, runSingle);
|
|
246
|
+
} finally{
|
|
247
|
+
finishFlush(bucketKey, bucket);
|
|
248
|
+
}
|
|
250
249
|
return;
|
|
251
250
|
}
|
|
252
251
|
const payload = createPayload(payloadIdentity, items);
|
|
253
252
|
const batchId = payload.batchId;
|
|
253
|
+
const settleAmbiguousBatchRequests = (reason)=>{
|
|
254
|
+
(0, external_telemetry_js_namespaceObject.emitDataBatchTransportEvent)(onEvent, {
|
|
255
|
+
type: 'fallback',
|
|
256
|
+
endpoint,
|
|
257
|
+
batchId,
|
|
258
|
+
size: items.length,
|
|
259
|
+
reason
|
|
260
|
+
});
|
|
261
|
+
return settleRequests(items, (request)=>runAfterAmbiguousBatch(request, reason));
|
|
262
|
+
};
|
|
254
263
|
(0, external_telemetry_js_namespaceObject.emitDataBatchTransportEvent)(onEvent, {
|
|
255
264
|
type: 'flush',
|
|
256
265
|
endpoint,
|
|
@@ -301,42 +310,13 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
301
310
|
batchId,
|
|
302
311
|
reason: `batch-endpoint-unavailable-${String(response.status)}`
|
|
303
312
|
});
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
endpoint,
|
|
307
|
-
batchId,
|
|
308
|
-
size: items.length,
|
|
309
|
-
reason: `batch-response-${String(response.status)}`
|
|
310
|
-
});
|
|
311
|
-
await settleAmbiguousBatchRequests(items, `batch-response-${String(response.status)}`);
|
|
312
|
-
bucket.flushing = false;
|
|
313
|
+
await settleRequests(items, (request)=>runAfterAmbiguousBatch(request, `batch-response-${String(response.status)}`));
|
|
314
|
+
} else await settleAmbiguousBatchRequests(`batch-response-${String(response.status)}`);
|
|
313
315
|
return;
|
|
314
316
|
}
|
|
315
317
|
const result = await runWithSignal(controller.signal, async ()=>response.json());
|
|
316
|
-
if (!(0, external_response_js_namespaceObject.isBatchResponsePayload)(result))
|
|
317
|
-
|
|
318
|
-
type: 'fallback',
|
|
319
|
-
endpoint,
|
|
320
|
-
batchId,
|
|
321
|
-
size: items.length,
|
|
322
|
-
reason: 'invalid-batch-response'
|
|
323
|
-
});
|
|
324
|
-
await settleAmbiguousBatchRequests(items, 'invalid-batch-response');
|
|
325
|
-
bucket.flushing = false;
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
if (result.batchId !== batchId) {
|
|
329
|
-
(0, external_telemetry_js_namespaceObject.emitDataBatchTransportEvent)(onEvent, {
|
|
330
|
-
type: 'fallback',
|
|
331
|
-
endpoint,
|
|
332
|
-
batchId,
|
|
333
|
-
size: items.length,
|
|
334
|
-
reason: 'mismatched-batch-id'
|
|
335
|
-
});
|
|
336
|
-
await settleAmbiguousBatchRequests(items, 'mismatched-batch-id');
|
|
337
|
-
bucket.flushing = false;
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
318
|
+
if (!(0, external_response_js_namespaceObject.isBatchResponsePayload)(result)) return void await settleAmbiguousBatchRequests('invalid-batch-response');
|
|
319
|
+
if (result.batchId !== batchId) return void await settleAmbiguousBatchRequests('mismatched-batch-id');
|
|
340
320
|
const itemMap = new Map();
|
|
341
321
|
for (const item of result.items)itemMap.set(item.id, item);
|
|
342
322
|
await settleRequests(items, async (request)=>{
|
|
@@ -360,19 +340,10 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
360
340
|
});
|
|
361
341
|
return;
|
|
362
342
|
}
|
|
363
|
-
(
|
|
364
|
-
type: 'fallback',
|
|
365
|
-
endpoint,
|
|
366
|
-
batchId,
|
|
367
|
-
size: items.length,
|
|
368
|
-
reason: 'batch-transport-error'
|
|
369
|
-
});
|
|
370
|
-
await settleAmbiguousBatchRequests(items, 'batch-transport-error');
|
|
343
|
+
await settleAmbiguousBatchRequests('batch-transport-error');
|
|
371
344
|
} finally{
|
|
372
345
|
for (const item of items)item.abortBatchIfUnused = void 0;
|
|
373
|
-
bucket
|
|
374
|
-
if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
|
|
375
|
-
buckets.releaseIfIdle(bucketKey, bucket);
|
|
346
|
+
finishFlush(bucketKey, bucket);
|
|
376
347
|
}
|
|
377
348
|
};
|
|
378
349
|
const pendingReadPromises = new Map();
|
|
@@ -396,7 +367,20 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
396
367
|
const sourceSignal = initDefinesSignal ? initSignal ?? void 0 : sourceRequest?.signal;
|
|
397
368
|
const requestUrl = (0, external_url_js_namespaceObject.toAbsoluteUrl)(input);
|
|
398
369
|
const endpoint = (0, external_url_js_namespaceObject.normalizeBatchEndpoint)(requestUrl, options.endpoint).toString();
|
|
370
|
+
const itemHeaders = {
|
|
371
|
+
...headers
|
|
372
|
+
};
|
|
373
|
+
delete itemHeaders.authorization;
|
|
374
|
+
delete itemHeaders.cookie;
|
|
399
375
|
return {
|
|
376
|
+
itemHeaders,
|
|
377
|
+
itemPath: `${requestUrl.pathname}${requestUrl.search}`,
|
|
378
|
+
bucketKey: (0, external_codec_js_namespaceObject.stableStringify)({
|
|
379
|
+
endpoint,
|
|
380
|
+
authorization: headers.authorization ?? null,
|
|
381
|
+
cookie: headers.cookie ?? null,
|
|
382
|
+
credentials
|
|
383
|
+
}),
|
|
400
384
|
requestUrl,
|
|
401
385
|
endpoint,
|
|
402
386
|
method,
|
|
@@ -429,22 +413,11 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
429
413
|
batchEndpoint: request.endpoint,
|
|
430
414
|
requestUrl: request.requestUrl
|
|
431
415
|
})) return;
|
|
432
|
-
const itemHeaders = {
|
|
433
|
-
...request.headers
|
|
434
|
-
};
|
|
435
|
-
delete itemHeaders.authorization;
|
|
436
|
-
delete itemHeaders.cookie;
|
|
437
|
-
const bucketKey = (0, external_codec_js_namespaceObject.stableStringify)({
|
|
438
|
-
endpoint: request.endpoint,
|
|
439
|
-
authorization: request.headers.authorization ?? null,
|
|
440
|
-
cookie: request.headers.cookie ?? null,
|
|
441
|
-
credentials: request.credentials
|
|
442
|
-
});
|
|
443
416
|
return (0, external_codec_js_namespaceObject.stableStringify)({
|
|
444
|
-
bucketKey,
|
|
445
|
-
path:
|
|
417
|
+
bucketKey: request.bucketKey,
|
|
418
|
+
path: request.itemPath,
|
|
446
419
|
method: request.method,
|
|
447
|
-
headers: itemHeaders,
|
|
420
|
+
headers: request.itemHeaders,
|
|
448
421
|
body: null
|
|
449
422
|
});
|
|
450
423
|
};
|
|
@@ -462,26 +435,19 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
462
435
|
const itemId = `${Date.now().toString(36)}_${nextItemId.toString(36)}_${Math.random().toString(16).slice(2, 8)}`;
|
|
463
436
|
nextItemId += 1;
|
|
464
437
|
const itemHeaders = {
|
|
465
|
-
...request.
|
|
438
|
+
...request.itemHeaders
|
|
466
439
|
};
|
|
467
|
-
delete itemHeaders.authorization;
|
|
468
|
-
delete itemHeaders.cookie;
|
|
469
440
|
if (preparedBody.body && preparedBody.inferredContentType && !itemHeaders['content-type']) itemHeaders['content-type'] = preparedBody.inferredContentType;
|
|
470
441
|
const item = {
|
|
471
442
|
id: itemId,
|
|
472
|
-
path:
|
|
443
|
+
path: request.itemPath,
|
|
473
444
|
method: request.method,
|
|
474
445
|
headers: itemHeaders,
|
|
475
446
|
...preparedBody.body ? {
|
|
476
447
|
body: preparedBody.body
|
|
477
448
|
} : {}
|
|
478
449
|
};
|
|
479
|
-
const bucketKey =
|
|
480
|
-
endpoint: request.endpoint,
|
|
481
|
-
authorization: request.headers.authorization ?? null,
|
|
482
|
-
cookie: request.headers.cookie ?? null,
|
|
483
|
-
credentials: request.credentials
|
|
484
|
-
});
|
|
450
|
+
const { bucketKey } = request;
|
|
485
451
|
const key = (0, external_codec_js_namespaceObject.stableStringify)({
|
|
486
452
|
bucketKey,
|
|
487
453
|
path: item.path,
|
|
@@ -575,13 +541,12 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
575
541
|
}
|
|
576
542
|
}
|
|
577
543
|
bucket.items.push(queued);
|
|
578
|
-
bucket.bytes = measurePayload(bucket, bucket.items);
|
|
579
544
|
(0, external_telemetry_js_namespaceObject.emitDataBatchTransportEvent)(onEvent, {
|
|
580
545
|
type: 'enqueue',
|
|
581
546
|
endpoint: request.endpoint,
|
|
582
547
|
size: bucket.items.length
|
|
583
548
|
});
|
|
584
|
-
if (bucket.items.length >= maxBatchSize || bucket.
|
|
549
|
+
if (bucket.items.length >= maxBatchSize || measurePayload(bucket, bucket.items) >= maxBatchBytes) {
|
|
585
550
|
flushBucket(bucketKey);
|
|
586
551
|
return queued.promise;
|
|
587
552
|
}
|
|
@@ -32,6 +32,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
32
32
|
});
|
|
33
33
|
const Effect_namespaceObject = require("effect/Effect");
|
|
34
34
|
const index_js_namespaceObject = require("../../data-platform/index.js");
|
|
35
|
+
const options_js_namespaceObject = require("../../data-platform/batch/options.js");
|
|
35
36
|
const protocol_js_namespaceObject = require("../../data-platform/batch/protocol.js");
|
|
36
37
|
const external_batch_js_namespaceObject = require("./batch.js");
|
|
37
38
|
const external_routing_js_namespaceObject = require("./routing.js");
|
|
@@ -123,11 +124,9 @@ function createDataPlatformBatchRequestHandler(options) {
|
|
|
123
124
|
const dataPlatformBatchOptions = options.dataPlatform?.batch;
|
|
124
125
|
const batchEnabled = dataPlatformBatchOptions?.enabled !== false;
|
|
125
126
|
const batchPath = (0, external_batch_js_namespaceObject.normalizeBatchPath)(dataPlatformBatchOptions?.endpoint);
|
|
126
|
-
const batchMaxSize =
|
|
127
|
-
const batchMaxBytes = Math.max(1024, dataPlatformBatchOptions?.maxBatchBytes ?? 65536);
|
|
127
|
+
const { maxBatchSize: batchMaxSize, maxBatchBytes: batchMaxBytes, allowedMethods: batchAllowedMethods } = (0, options_js_namespaceObject.normalizeBatchLimits)(dataPlatformBatchOptions);
|
|
128
128
|
const batchConcurrency = Math.max(1, dataPlatformBatchOptions?.maxConcurrency ?? 4);
|
|
129
129
|
const batchItemTimeoutMs = Math.max(0, dataPlatformBatchOptions?.requestTimeoutMs ?? 10000);
|
|
130
|
-
const batchAllowedMethods = (0, external_batch_js_namespaceObject.normalizeBatchAllowedMethods)(dataPlatformBatchOptions?.allowedMethods);
|
|
131
130
|
const envelopeHeader = options.dataPlatform?.envelopeHeader || index_js_namespaceObject.DEFAULT_DATA_ENVELOPE_HEADER;
|
|
132
131
|
const normalizedEnvelopeHeader = envelopeHeader.toLowerCase();
|
|
133
132
|
const handle = async (request, context)=>{
|
|
@@ -32,7 +32,6 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
32
32
|
createBatchValidationResponse: ()=>createBatchValidationResponse,
|
|
33
33
|
isBatchRequestPayload: ()=>isBatchRequestPayload,
|
|
34
34
|
mapWithConcurrency: ()=>mapWithConcurrency,
|
|
35
|
-
normalizeBatchAllowedMethods: ()=>normalizeBatchAllowedMethods,
|
|
36
35
|
normalizeBatchPath: ()=>normalizeBatchPath,
|
|
37
36
|
prepareJsonRequestBody: ()=>prepareJsonRequestBody,
|
|
38
37
|
promiseWithTimeout: ()=>promiseWithTimeout,
|
|
@@ -48,12 +47,6 @@ function normalizeBatchPath(pathname) {
|
|
|
48
47
|
if (!pathname.startsWith('/')) return `/${pathname}`;
|
|
49
48
|
return pathname;
|
|
50
49
|
}
|
|
51
|
-
function normalizeBatchAllowedMethods(allowedMethods) {
|
|
52
|
-
const source = Array.isArray(allowedMethods) && allowedMethods.length > 0 ? allowedMethods : [
|
|
53
|
-
'GET'
|
|
54
|
-
];
|
|
55
|
-
return new Set(source.map((method)=>method.toUpperCase()));
|
|
56
|
-
}
|
|
57
50
|
function isBatchRequestPayload(value) {
|
|
58
51
|
return (0, index_js_namespaceObject.isPlainObject)(value) && 2 === value.protocolVersion && 'string' == typeof value.batchId && 'number' == typeof value.sentAt && Array.isArray(value.items);
|
|
59
52
|
}
|
|
@@ -154,7 +147,6 @@ exports.BatchItemTimeoutError = __webpack_exports__.BatchItemTimeoutError;
|
|
|
154
147
|
exports.createBatchValidationResponse = __webpack_exports__.createBatchValidationResponse;
|
|
155
148
|
exports.isBatchRequestPayload = __webpack_exports__.isBatchRequestPayload;
|
|
156
149
|
exports.mapWithConcurrency = __webpack_exports__.mapWithConcurrency;
|
|
157
|
-
exports.normalizeBatchAllowedMethods = __webpack_exports__.normalizeBatchAllowedMethods;
|
|
158
150
|
exports.normalizeBatchPath = __webpack_exports__.normalizeBatchPath;
|
|
159
151
|
exports.prepareJsonRequestBody = __webpack_exports__.prepareJsonRequestBody;
|
|
160
152
|
exports.promiseWithTimeout = __webpack_exports__.promiseWithTimeout;
|
|
@@ -165,7 +157,6 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
|
165
157
|
"createBatchValidationResponse",
|
|
166
158
|
"isBatchRequestPayload",
|
|
167
159
|
"mapWithConcurrency",
|
|
168
|
-
"normalizeBatchAllowedMethods",
|
|
169
160
|
"normalizeBatchPath",
|
|
170
161
|
"prepareJsonRequestBody",
|
|
171
162
|
"promiseWithTimeout",
|
|
@@ -62,14 +62,11 @@ function withCrossProjectPolicy(api, options, client) {
|
|
|
62
62
|
const contract = observed && contracts[`${observed.method}:${observed.routePath}`];
|
|
63
63
|
if (void 0 === contract) return Effect_namespaceObject.die(new Error('[BFF][Effect] Request has no matching shared operation contract.'));
|
|
64
64
|
return Effect_namespaceObject.gen(function*() {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
});
|
|
71
|
-
const digest = yield* Effect_namespaceObject.promise(()=>globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(input)));
|
|
72
|
-
const schemaHash = Array.from(new Uint8Array(digest), (value)=>value.toString(16).padStart(2, '0')).join('');
|
|
65
|
+
const schemaHash = yield* Effect_namespaceObject.promise(()=>(0, bff_policy_namespaceObject.digestOperationContract)({
|
|
66
|
+
httpMethod: contract.method,
|
|
67
|
+
name: contract.name,
|
|
68
|
+
routePath: contract.routePath
|
|
69
|
+
}, options.requestId));
|
|
73
70
|
return request.pipe(http_namespaceObject.HttpClientRequest.setHeader(bff_policy_namespaceObject.BFF_ENVELOPE_HEADER, encodeJson({
|
|
74
71
|
requestId: options.requestId
|
|
75
72
|
})), http_namespaceObject.HttpClientRequest.setHeader(bff_policy_namespaceObject.BFF_OPERATION_CONTEXT_HEADER, contract.operationId), http_namespaceObject.HttpClientRequest.setHeader(bff_policy_namespaceObject.BFF_OPERATION_CONTEXT_DETAIL_HEADER, encodeJson({
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function normalizeBatchLimits(options = {}) {
|
|
2
|
+
return {
|
|
3
|
+
maxBatchSize: Math.max(1, options.maxBatchSize ?? 16),
|
|
4
|
+
maxBatchBytes: Math.max(1024, options.maxBatchBytes ?? 65536),
|
|
5
|
+
allowedMethods: new Set((void 0 !== options.allowedMethods && options.allowedMethods.length > 0 ? options.allowedMethods : [
|
|
6
|
+
'GET'
|
|
7
|
+
]).map((method)=>method.toUpperCase()))
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export { normalizeBatchLimits };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { stableStringify } from "../codec.mjs";
|
|
2
2
|
import { DEFAULT_DATA_BATCH_HEADER } from "../types.mjs";
|
|
3
|
+
import { normalizeBatchLimits } from "./options.mjs";
|
|
3
4
|
import { decodeBatchBody, isNullBodyStatus } from "./protocol.mjs";
|
|
4
5
|
import { createBatchId, measureTextBytes, normalizeMethod, shouldBatchRequest, toHeaderRecord, toRequestBody } from "./request.mjs";
|
|
5
6
|
import { isBatchResponsePayload, parseResponseLikeCreateRequest } from "./response.mjs";
|
|
@@ -78,7 +79,6 @@ class BatchBucketRegistry {
|
|
|
78
79
|
if (existing) return existing;
|
|
79
80
|
const next = {
|
|
80
81
|
items: [],
|
|
81
|
-
bytes: 0,
|
|
82
82
|
batchId: createBatchId(),
|
|
83
83
|
sentAt: Date.now(),
|
|
84
84
|
timer: null,
|
|
@@ -97,12 +97,8 @@ class BatchBucketRegistry {
|
|
|
97
97
|
}
|
|
98
98
|
function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
99
99
|
const flushIntervalMs = Math.max(0, options.flushIntervalMs ?? 8);
|
|
100
|
-
const maxBatchSize =
|
|
101
|
-
const maxBatchBytes = Math.max(1024, options.maxBatchBytes ?? 65536);
|
|
100
|
+
const { maxBatchSize, maxBatchBytes, allowedMethods } = normalizeBatchLimits(options);
|
|
102
101
|
const requestTimeoutMs = options.requestTimeoutMs;
|
|
103
|
-
const allowedMethods = new Set((options.allowedMethods && options.allowedMethods.length > 0 ? options.allowedMethods : [
|
|
104
|
-
'GET'
|
|
105
|
-
]).map((method)=>method.toUpperCase()));
|
|
106
102
|
const onEvent = options.onEvent;
|
|
107
103
|
const buckets = bucketRegistry ?? new BatchBucketRegistry();
|
|
108
104
|
const pendingByKey = new Map();
|
|
@@ -135,7 +131,6 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
135
131
|
const index = bucket.items.indexOf(request);
|
|
136
132
|
if (-1 === index) return;
|
|
137
133
|
bucket.items.splice(index, 1);
|
|
138
|
-
bucket.bytes = measurePayload(bucket, bucket.items);
|
|
139
134
|
if (0 === bucket.items.length && bucket.timer) {
|
|
140
135
|
clearTimeout(bucket.timer);
|
|
141
136
|
bucket.timer = null;
|
|
@@ -177,7 +172,11 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
177
172
|
if (!SAFE_REPLAY_METHODS.has(request.item.method)) throw new Error(`Batch result is unknown for ${request.item.method}; automatic replay is disabled (${reason}).`);
|
|
178
173
|
return runSingle(request);
|
|
179
174
|
};
|
|
180
|
-
const
|
|
175
|
+
const finishFlush = (bucketKey, bucket)=>{
|
|
176
|
+
bucket.flushing = false;
|
|
177
|
+
if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
|
|
178
|
+
buckets.releaseIfIdle(bucketKey, bucket);
|
|
179
|
+
};
|
|
181
180
|
const flushBucket = async (bucketKey)=>{
|
|
182
181
|
const bucket = buckets.get(bucketKey);
|
|
183
182
|
if (!bucket || bucket.flushing) return;
|
|
@@ -194,7 +193,6 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
194
193
|
sentAt: bucket.sentAt
|
|
195
194
|
};
|
|
196
195
|
bucket.items = [];
|
|
197
|
-
bucket.bytes = 0;
|
|
198
196
|
rotatePayloadIdentity(bucket);
|
|
199
197
|
const firstItem = items[0];
|
|
200
198
|
if (!firstItem) {
|
|
@@ -210,14 +208,25 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
210
208
|
size: items.length,
|
|
211
209
|
reason: disabledEndpoints.has(endpoint) ? 'batch-disabled' : void 0
|
|
212
210
|
});
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
211
|
+
try {
|
|
212
|
+
await settleRequests(items, runSingle);
|
|
213
|
+
} finally{
|
|
214
|
+
finishFlush(bucketKey, bucket);
|
|
215
|
+
}
|
|
217
216
|
return;
|
|
218
217
|
}
|
|
219
218
|
const payload = createPayload(payloadIdentity, items);
|
|
220
219
|
const batchId = payload.batchId;
|
|
220
|
+
const settleAmbiguousBatchRequests = (reason)=>{
|
|
221
|
+
emitDataBatchTransportEvent(onEvent, {
|
|
222
|
+
type: 'fallback',
|
|
223
|
+
endpoint,
|
|
224
|
+
batchId,
|
|
225
|
+
size: items.length,
|
|
226
|
+
reason
|
|
227
|
+
});
|
|
228
|
+
return settleRequests(items, (request)=>runAfterAmbiguousBatch(request, reason));
|
|
229
|
+
};
|
|
221
230
|
emitDataBatchTransportEvent(onEvent, {
|
|
222
231
|
type: 'flush',
|
|
223
232
|
endpoint,
|
|
@@ -268,42 +277,13 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
268
277
|
batchId,
|
|
269
278
|
reason: `batch-endpoint-unavailable-${String(response.status)}`
|
|
270
279
|
});
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
endpoint,
|
|
274
|
-
batchId,
|
|
275
|
-
size: items.length,
|
|
276
|
-
reason: `batch-response-${String(response.status)}`
|
|
277
|
-
});
|
|
278
|
-
await settleAmbiguousBatchRequests(items, `batch-response-${String(response.status)}`);
|
|
279
|
-
bucket.flushing = false;
|
|
280
|
+
await settleRequests(items, (request)=>runAfterAmbiguousBatch(request, `batch-response-${String(response.status)}`));
|
|
281
|
+
} else await settleAmbiguousBatchRequests(`batch-response-${String(response.status)}`);
|
|
280
282
|
return;
|
|
281
283
|
}
|
|
282
284
|
const result = await runWithSignal(controller.signal, async ()=>response.json());
|
|
283
|
-
if (!isBatchResponsePayload(result))
|
|
284
|
-
|
|
285
|
-
type: 'fallback',
|
|
286
|
-
endpoint,
|
|
287
|
-
batchId,
|
|
288
|
-
size: items.length,
|
|
289
|
-
reason: 'invalid-batch-response'
|
|
290
|
-
});
|
|
291
|
-
await settleAmbiguousBatchRequests(items, 'invalid-batch-response');
|
|
292
|
-
bucket.flushing = false;
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
if (result.batchId !== batchId) {
|
|
296
|
-
emitDataBatchTransportEvent(onEvent, {
|
|
297
|
-
type: 'fallback',
|
|
298
|
-
endpoint,
|
|
299
|
-
batchId,
|
|
300
|
-
size: items.length,
|
|
301
|
-
reason: 'mismatched-batch-id'
|
|
302
|
-
});
|
|
303
|
-
await settleAmbiguousBatchRequests(items, 'mismatched-batch-id');
|
|
304
|
-
bucket.flushing = false;
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
285
|
+
if (!isBatchResponsePayload(result)) return void await settleAmbiguousBatchRequests('invalid-batch-response');
|
|
286
|
+
if (result.batchId !== batchId) return void await settleAmbiguousBatchRequests('mismatched-batch-id');
|
|
307
287
|
const itemMap = new Map();
|
|
308
288
|
for (const item of result.items)itemMap.set(item.id, item);
|
|
309
289
|
await settleRequests(items, async (request)=>{
|
|
@@ -327,19 +307,10 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
327
307
|
});
|
|
328
308
|
return;
|
|
329
309
|
}
|
|
330
|
-
|
|
331
|
-
type: 'fallback',
|
|
332
|
-
endpoint,
|
|
333
|
-
batchId,
|
|
334
|
-
size: items.length,
|
|
335
|
-
reason: 'batch-transport-error'
|
|
336
|
-
});
|
|
337
|
-
await settleAmbiguousBatchRequests(items, 'batch-transport-error');
|
|
310
|
+
await settleAmbiguousBatchRequests('batch-transport-error');
|
|
338
311
|
} finally{
|
|
339
312
|
for (const item of items)item.abortBatchIfUnused = void 0;
|
|
340
|
-
bucket
|
|
341
|
-
if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
|
|
342
|
-
buckets.releaseIfIdle(bucketKey, bucket);
|
|
313
|
+
finishFlush(bucketKey, bucket);
|
|
343
314
|
}
|
|
344
315
|
};
|
|
345
316
|
const pendingReadPromises = new Map();
|
|
@@ -363,7 +334,20 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
363
334
|
const sourceSignal = initDefinesSignal ? initSignal ?? void 0 : sourceRequest?.signal;
|
|
364
335
|
const requestUrl = toAbsoluteUrl(input);
|
|
365
336
|
const endpoint = normalizeBatchEndpoint(requestUrl, options.endpoint).toString();
|
|
337
|
+
const itemHeaders = {
|
|
338
|
+
...headers
|
|
339
|
+
};
|
|
340
|
+
delete itemHeaders.authorization;
|
|
341
|
+
delete itemHeaders.cookie;
|
|
366
342
|
return {
|
|
343
|
+
itemHeaders,
|
|
344
|
+
itemPath: `${requestUrl.pathname}${requestUrl.search}`,
|
|
345
|
+
bucketKey: stableStringify({
|
|
346
|
+
endpoint,
|
|
347
|
+
authorization: headers.authorization ?? null,
|
|
348
|
+
cookie: headers.cookie ?? null,
|
|
349
|
+
credentials
|
|
350
|
+
}),
|
|
367
351
|
requestUrl,
|
|
368
352
|
endpoint,
|
|
369
353
|
method,
|
|
@@ -396,22 +380,11 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
396
380
|
batchEndpoint: request.endpoint,
|
|
397
381
|
requestUrl: request.requestUrl
|
|
398
382
|
})) return;
|
|
399
|
-
const itemHeaders = {
|
|
400
|
-
...request.headers
|
|
401
|
-
};
|
|
402
|
-
delete itemHeaders.authorization;
|
|
403
|
-
delete itemHeaders.cookie;
|
|
404
|
-
const bucketKey = stableStringify({
|
|
405
|
-
endpoint: request.endpoint,
|
|
406
|
-
authorization: request.headers.authorization ?? null,
|
|
407
|
-
cookie: request.headers.cookie ?? null,
|
|
408
|
-
credentials: request.credentials
|
|
409
|
-
});
|
|
410
383
|
return stableStringify({
|
|
411
|
-
bucketKey,
|
|
412
|
-
path:
|
|
384
|
+
bucketKey: request.bucketKey,
|
|
385
|
+
path: request.itemPath,
|
|
413
386
|
method: request.method,
|
|
414
|
-
headers: itemHeaders,
|
|
387
|
+
headers: request.itemHeaders,
|
|
415
388
|
body: null
|
|
416
389
|
});
|
|
417
390
|
};
|
|
@@ -429,26 +402,19 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
429
402
|
const itemId = `${Date.now().toString(36)}_${nextItemId.toString(36)}_${Math.random().toString(16).slice(2, 8)}`;
|
|
430
403
|
nextItemId += 1;
|
|
431
404
|
const itemHeaders = {
|
|
432
|
-
...request.
|
|
405
|
+
...request.itemHeaders
|
|
433
406
|
};
|
|
434
|
-
delete itemHeaders.authorization;
|
|
435
|
-
delete itemHeaders.cookie;
|
|
436
407
|
if (preparedBody.body && preparedBody.inferredContentType && !itemHeaders['content-type']) itemHeaders['content-type'] = preparedBody.inferredContentType;
|
|
437
408
|
const item = {
|
|
438
409
|
id: itemId,
|
|
439
|
-
path:
|
|
410
|
+
path: request.itemPath,
|
|
440
411
|
method: request.method,
|
|
441
412
|
headers: itemHeaders,
|
|
442
413
|
...preparedBody.body ? {
|
|
443
414
|
body: preparedBody.body
|
|
444
415
|
} : {}
|
|
445
416
|
};
|
|
446
|
-
const bucketKey =
|
|
447
|
-
endpoint: request.endpoint,
|
|
448
|
-
authorization: request.headers.authorization ?? null,
|
|
449
|
-
cookie: request.headers.cookie ?? null,
|
|
450
|
-
credentials: request.credentials
|
|
451
|
-
});
|
|
417
|
+
const { bucketKey } = request;
|
|
452
418
|
const key = stableStringify({
|
|
453
419
|
bucketKey,
|
|
454
420
|
path: item.path,
|
|
@@ -542,13 +508,12 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
|
|
|
542
508
|
}
|
|
543
509
|
}
|
|
544
510
|
bucket.items.push(queued);
|
|
545
|
-
bucket.bytes = measurePayload(bucket, bucket.items);
|
|
546
511
|
emitDataBatchTransportEvent(onEvent, {
|
|
547
512
|
type: 'enqueue',
|
|
548
513
|
endpoint: request.endpoint,
|
|
549
514
|
size: bucket.items.length
|
|
550
515
|
});
|
|
551
|
-
if (bucket.items.length >= maxBatchSize || bucket.
|
|
516
|
+
if (bucket.items.length >= maxBatchSize || measurePayload(bucket, bucket.items) >= maxBatchBytes) {
|
|
552
517
|
flushBucket(bucketKey);
|
|
553
518
|
return queued.promise;
|
|
554
519
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_DATA_BATCH_HEADER, DEFAULT_DATA_ENVELOPE_HEADER, decodeRequestEnvelopeHeader, isPlainObject, normalizeMethod } from "../../data-platform/index.mjs";
|
|
2
|
+
import { normalizeBatchLimits } from "../../data-platform/batch/options.mjs";
|
|
2
3
|
import { decodeBatchBody, isBatchBody, toBatchResponseItem } from "../../data-platform/batch/protocol.mjs";
|
|
3
|
-
import { BatchItemTimeoutError, createBatchValidationResponse, isBatchRequestPayload, mapWithConcurrency,
|
|
4
|
+
import { BatchItemTimeoutError, createBatchValidationResponse, isBatchRequestPayload, mapWithConcurrency, normalizeBatchPath, promiseWithTimeout, toBatchItemError } from "./batch.mjs";
|
|
4
5
|
import { getMountedPrefixFromContext, removeMountedPrefixFromBatchPath } from "./routing.mjs";
|
|
5
6
|
import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
|
|
6
7
|
const HOP_BY_HOP_BATCH_ITEM_HEADERS = new Set([
|
|
@@ -91,11 +92,9 @@ function createDataPlatformBatchRequestHandler(options) {
|
|
|
91
92
|
const dataPlatformBatchOptions = options.dataPlatform?.batch;
|
|
92
93
|
const batchEnabled = dataPlatformBatchOptions?.enabled !== false;
|
|
93
94
|
const batchPath = normalizeBatchPath(dataPlatformBatchOptions?.endpoint);
|
|
94
|
-
const batchMaxSize
|
|
95
|
-
const batchMaxBytes = Math.max(1024, dataPlatformBatchOptions?.maxBatchBytes ?? 65536);
|
|
95
|
+
const { maxBatchSize: batchMaxSize, maxBatchBytes: batchMaxBytes, allowedMethods: batchAllowedMethods } = normalizeBatchLimits(dataPlatformBatchOptions);
|
|
96
96
|
const batchConcurrency = Math.max(1, dataPlatformBatchOptions?.maxConcurrency ?? 4);
|
|
97
97
|
const batchItemTimeoutMs = Math.max(0, dataPlatformBatchOptions?.requestTimeoutMs ?? 10000);
|
|
98
|
-
const batchAllowedMethods = normalizeBatchAllowedMethods(dataPlatformBatchOptions?.allowedMethods);
|
|
99
98
|
const envelopeHeader = options.dataPlatform?.envelopeHeader || DEFAULT_DATA_ENVELOPE_HEADER;
|
|
100
99
|
const normalizedEnvelopeHeader = envelopeHeader.toLowerCase();
|
|
101
100
|
const handle = async (request, context)=>{
|