@workflow/core 5.0.0-beta.1 → 5.0.0-beta.11
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/README.md +1 -1
- package/dist/attribute-changes.d.ts +7 -0
- package/dist/attribute-changes.d.ts.map +1 -0
- package/dist/attribute-changes.js +25 -0
- package/dist/capabilities.js +1 -1
- package/dist/capture-stack.d.ts +16 -0
- package/dist/capture-stack.d.ts.map +1 -0
- package/dist/capture-stack.js +21 -0
- package/dist/class-serialization.js +1 -1
- package/dist/classify-error.d.ts +11 -3
- package/dist/classify-error.d.ts.map +1 -1
- package/dist/classify-error.js +56 -6
- package/dist/context-errors.d.ts +27 -0
- package/dist/context-errors.d.ts.map +1 -0
- package/dist/context-errors.js +101 -0
- package/dist/context-violation-error.d.ts +97 -0
- package/dist/context-violation-error.d.ts.map +1 -0
- package/dist/context-violation-error.js +147 -0
- package/dist/create-hook.d.ts.map +1 -1
- package/dist/create-hook.js +4 -3
- package/dist/define-hook.d.ts.map +1 -1
- package/dist/define-hook.js +20 -5
- package/dist/describe-error.d.ts +70 -0
- package/dist/describe-error.d.ts.map +1 -0
- package/dist/describe-error.js +165 -0
- package/dist/encryption.d.ts +22 -1
- package/dist/encryption.d.ts.map +1 -1
- package/dist/encryption.js +72 -27
- package/dist/events-consumer.d.ts +7 -0
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +18 -3
- package/dist/flushable-stream.d.ts +10 -10
- package/dist/flushable-stream.d.ts.map +1 -1
- package/dist/flushable-stream.js +18 -13
- package/dist/global.d.ts +4 -0
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +8 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/log-format.d.ts +25 -0
- package/dist/log-format.d.ts.map +1 -0
- package/dist/log-format.js +250 -0
- package/dist/logger.d.ts +28 -30
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +77 -31
- package/dist/private.js +3 -3
- package/dist/runtime/constants.d.ts +48 -0
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +91 -8
- package/dist/runtime/get-port-lazy.d.ts +10 -0
- package/dist/runtime/get-port-lazy.d.ts.map +1 -0
- package/dist/runtime/get-port-lazy.js +30 -0
- package/dist/runtime/get-world-lazy.d.ts +32 -0
- package/dist/runtime/get-world-lazy.d.ts.map +1 -0
- package/dist/runtime/get-world-lazy.js +56 -0
- package/dist/runtime/helpers.d.ts +38 -5
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +141 -25
- package/dist/runtime/replay-budget.d.ts +98 -0
- package/dist/runtime/replay-budget.d.ts.map +1 -0
- package/dist/runtime/replay-budget.js +191 -0
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +5 -4
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +31 -6
- package/dist/runtime/runs.d.ts.map +1 -1
- package/dist/runtime/runs.js +4 -1
- package/dist/runtime/start.js +9 -4
- package/dist/runtime/step-executor.d.ts +42 -0
- package/dist/runtime/step-executor.d.ts.map +1 -0
- package/dist/runtime/step-executor.js +493 -0
- package/dist/runtime/step-handler.d.ts.map +1 -1
- package/dist/runtime/step-handler.js +217 -115
- package/dist/runtime/suspension-handler.d.ts +22 -4
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +90 -73
- package/dist/runtime/world-init.d.ts +75 -0
- package/dist/runtime/world-init.d.ts.map +1 -0
- package/dist/runtime/world-init.js +75 -0
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +47 -18
- package/dist/runtime.d.ts +8 -7
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +802 -320
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +1 -1
- package/dist/serialization/client.d.ts +17 -0
- package/dist/serialization/client.d.ts.map +1 -0
- package/dist/serialization/client.js +45 -0
- package/dist/serialization/codec-devalue.d.ts +14 -0
- package/dist/serialization/codec-devalue.d.ts.map +1 -0
- package/dist/serialization/codec-devalue.js +98 -0
- package/dist/serialization/codec.d.ts +90 -0
- package/dist/serialization/codec.d.ts.map +1 -0
- package/dist/serialization/codec.js +17 -0
- package/dist/serialization/encryption.d.ts +32 -0
- package/dist/serialization/encryption.d.ts.map +1 -0
- package/dist/serialization/encryption.js +67 -0
- package/dist/serialization/errors.d.ts +34 -0
- package/dist/serialization/errors.d.ts.map +1 -0
- package/dist/serialization/errors.js +59 -0
- package/dist/serialization/format.d.ts +60 -0
- package/dist/serialization/format.d.ts.map +1 -0
- package/dist/serialization/format.js +97 -0
- package/dist/serialization/index.d.ts +18 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/serialization/index.js +20 -0
- package/dist/serialization/reducers/class.d.ts +11 -0
- package/dist/serialization/reducers/class.d.ts.map +1 -0
- package/dist/serialization/reducers/class.js +68 -0
- package/dist/serialization/reducers/common.d.ts +16 -0
- package/dist/serialization/reducers/common.d.ts.map +1 -0
- package/dist/serialization/reducers/common.js +417 -0
- package/dist/serialization/reducers/step-function.d.ts +35 -0
- package/dist/serialization/reducers/step-function.d.ts.map +1 -0
- package/dist/serialization/reducers/step-function.js +88 -0
- package/dist/serialization/step.d.ts +17 -0
- package/dist/serialization/step.d.ts.map +1 -0
- package/dist/serialization/step.js +45 -0
- package/dist/serialization/types.d.ts +228 -0
- package/dist/serialization/types.d.ts.map +1 -0
- package/dist/serialization/types.js +21 -0
- package/dist/serialization/workflow.d.ts +29 -0
- package/dist/serialization/workflow.d.ts.map +1 -0
- package/dist/serialization/workflow.js +54 -0
- package/dist/serialization-format.d.ts +16 -2
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +103 -5
- package/dist/serialization.d.ts +217 -226
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +956 -645
- package/dist/set-attributes.d.ts +13 -0
- package/dist/set-attributes.d.ts.map +1 -0
- package/dist/set-attributes.js +40 -0
- package/dist/sleep.d.ts.map +1 -1
- package/dist/sleep.js +3 -2
- package/dist/source-map.d.ts.map +1 -1
- package/dist/source-map.js +44 -6
- package/dist/step/context-storage.d.ts +16 -0
- package/dist/step/context-storage.d.ts.map +1 -1
- package/dist/step/context-storage.js +1 -1
- package/dist/step/get-closure-vars.d.ts.map +1 -1
- package/dist/step/get-closure-vars.js +3 -2
- package/dist/step/get-step-metadata.d.ts.map +1 -1
- package/dist/step/get-step-metadata.js +3 -2
- package/dist/step/get-workflow-metadata.d.ts.map +1 -1
- package/dist/step/get-workflow-metadata.js +3 -2
- package/dist/step/writable-stream.d.ts.map +1 -1
- package/dist/step/writable-stream.js +44 -4
- package/dist/step.d.ts.map +1 -1
- package/dist/step.js +97 -19
- package/dist/symbols.d.ts +26 -0
- package/dist/symbols.d.ts.map +1 -1
- package/dist/symbols.js +27 -1
- package/dist/telemetry/semantic-conventions.d.ts +2 -2
- package/dist/telemetry/semantic-conventions.js +1 -1
- package/dist/telemetry.js +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +23 -1
- package/dist/util.d.ts +18 -3
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +28 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.d.ts.map +1 -1
- package/dist/vm/index.js +3 -2
- package/dist/vm/uint8array-base64.js +1 -1
- package/dist/vm/uuid.js +1 -1
- package/dist/workflow/abort-controller.d.ts +65 -0
- package/dist/workflow/abort-controller.d.ts.map +1 -0
- package/dist/workflow/abort-controller.js +260 -0
- package/dist/workflow/create-hook.d.ts.map +1 -1
- package/dist/workflow/create-hook.js +3 -2
- package/dist/workflow/define-hook.d.ts +1 -1
- package/dist/workflow/define-hook.d.ts.map +1 -1
- package/dist/workflow/define-hook.js +8 -4
- package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
- package/dist/workflow/get-workflow-metadata.js +14 -3
- package/dist/workflow/hook.d.ts.map +1 -1
- package/dist/workflow/hook.js +13 -4
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +5 -3
- package/dist/workflow/set-attributes.d.ts +74 -0
- package/dist/workflow/set-attributes.d.ts.map +1 -0
- package/dist/workflow/set-attributes.js +66 -0
- package/dist/workflow/sleep.d.ts.map +1 -1
- package/dist/workflow/sleep.js +22 -3
- package/dist/workflow/world-init-stub.d.ts +15 -0
- package/dist/workflow/world-init-stub.d.ts.map +1 -0
- package/dist/workflow/world-init-stub.js +15 -0
- package/dist/workflow/writable-stream.js +1 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +83 -31
- package/docs/api-reference/create-webhook.mdx +37 -18
- package/docs/api-reference/experimental-set-attributes.mdx +63 -0
- package/docs/api-reference/get-workflow-metadata.mdx +34 -0
- package/docs/api-reference/index.mdx +3 -0
- package/docs/foundations/cancellation.mdx +460 -0
- package/docs/foundations/errors-and-retries.mdx +7 -3
- package/docs/foundations/index.mdx +3 -3
- package/docs/foundations/meta.json +3 -2
- package/docs/foundations/serialization.mdx +78 -42
- package/docs/foundations/starting-workflows.mdx +6 -2
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/how-it-works/cancellation.mdx +287 -0
- package/docs/how-it-works/code-transform.mdx +2 -2
- package/docs/how-it-works/event-sourcing.mdx +2 -2
- package/docs/how-it-works/meta.json +2 -1
- package/package.json +16 -7
- package/docs/foundations/common-patterns.mdx +0 -265
package/dist/runtime/helpers.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { RUN_ERROR_CODES, WorkflowWorldError } from '@workflow/errors';
|
|
1
2
|
import { HealthCheckPayloadSchema, SPEC_VERSION_CURRENT, SPEC_VERSION_LEGACY, } from '@workflow/world';
|
|
2
3
|
import { monotonicFactory } from 'ulid';
|
|
4
|
+
import { importKey } from '../encryption.js';
|
|
3
5
|
import { runtimeLogger } from '../logger.js';
|
|
4
6
|
import * as Attribute from '../telemetry/semantic-conventions.js';
|
|
5
7
|
import { getSpanKind, trace } from '../telemetry.js';
|
|
6
8
|
import { version as workflowCoreVersion } from '../version.js';
|
|
7
|
-
import {
|
|
9
|
+
import { getWorldLazy } from './get-world-lazy.js';
|
|
8
10
|
/** Default timeout for health checks in milliseconds */
|
|
9
11
|
const DEFAULT_HEALTH_CHECK_TIMEOUT = 30_000;
|
|
10
12
|
/**
|
|
@@ -59,7 +61,7 @@ function generateHealthCheckRunId(correlationId) {
|
|
|
59
61
|
* @param endpoint - Which endpoint is responding ('workflow' or 'step')
|
|
60
62
|
*/
|
|
61
63
|
export async function handleHealthCheckMessage(healthCheck, endpoint, worldSpecVersion) {
|
|
62
|
-
const world = await
|
|
64
|
+
const world = await getWorldLazy();
|
|
63
65
|
const streamName = getHealthCheckStreamName(healthCheck.correlationId);
|
|
64
66
|
const response = JSON.stringify({
|
|
65
67
|
healthy: true,
|
|
@@ -211,58 +213,133 @@ export async function healthCheck(world, endpoint, options) {
|
|
|
211
213
|
};
|
|
212
214
|
}
|
|
213
215
|
}
|
|
216
|
+
function eventPaginationContractError(runId, message) {
|
|
217
|
+
return new WorkflowWorldError(`Event pagination ${message} for workflow run "${runId}".`, { code: RUN_ERROR_CODES.WORLD_CONTRACT_ERROR });
|
|
218
|
+
}
|
|
219
|
+
function recordRequestedEventCursor(runId, cursor, requestedCursors) {
|
|
220
|
+
if (!cursor) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (requestedCursors.has(cursor)) {
|
|
224
|
+
throw eventPaginationContractError(runId, 'did not advance');
|
|
225
|
+
}
|
|
226
|
+
requestedCursors.add(cursor);
|
|
227
|
+
}
|
|
228
|
+
function appendUniqueEvents(target, targetIds, events) {
|
|
229
|
+
for (const event of events) {
|
|
230
|
+
if (!targetIds.has(event.eventId)) {
|
|
231
|
+
targetIds.add(event.eventId);
|
|
232
|
+
target.push(event);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function assertEventPaginationProgress(runId, hasMore, cursor, requestedCursors) {
|
|
237
|
+
if (!hasMore) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (cursor === null) {
|
|
241
|
+
throw eventPaginationContractError(runId, 'returned more pages without a cursor');
|
|
242
|
+
}
|
|
243
|
+
if (requestedCursors.has(cursor)) {
|
|
244
|
+
throw eventPaginationContractError(runId, 'repeated a cursor');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function shouldRetryWithoutEventCursor(error, cursor, alreadyRetried) {
|
|
248
|
+
return (cursor !== null &&
|
|
249
|
+
!alreadyRetried &&
|
|
250
|
+
WorkflowWorldError.is(error) &&
|
|
251
|
+
error.status === 400);
|
|
252
|
+
}
|
|
214
253
|
/**
|
|
215
|
-
* Loads
|
|
216
|
-
*
|
|
217
|
-
*
|
|
254
|
+
* Loads workflow run events by iterating through all pages of paginated
|
|
255
|
+
* results. Events are returned in chronological (ascending) order for
|
|
256
|
+
* deterministic workflow replay.
|
|
257
|
+
*
|
|
258
|
+
* @param runId - The workflow run ID.
|
|
259
|
+
* @param afterCursor - If provided, only events after this cursor are
|
|
260
|
+
* returned (incremental load). If omitted, all events are returned.
|
|
261
|
+
* The returned cursor can be passed back in on a subsequent call for
|
|
262
|
+
* incremental loading.
|
|
218
263
|
*/
|
|
219
|
-
export async function
|
|
220
|
-
|
|
264
|
+
export async function loadWorkflowRunEvents(runId, afterCursor) {
|
|
265
|
+
const incremental = afterCursor !== undefined;
|
|
266
|
+
return trace(incremental ? 'workflow.loadNewEvents' : 'workflow.loadEvents', async (span) => {
|
|
221
267
|
span?.setAttributes({
|
|
222
268
|
...Attribute.WorkflowRunId(runId),
|
|
223
269
|
});
|
|
224
|
-
const
|
|
225
|
-
|
|
270
|
+
const loadedEvents = [];
|
|
271
|
+
const loadedEventIds = new Set();
|
|
272
|
+
const requestedCursors = new Set();
|
|
273
|
+
let cursor = afterCursor ?? null;
|
|
226
274
|
let hasMore = true;
|
|
227
275
|
let pagesLoaded = 0;
|
|
228
|
-
|
|
276
|
+
let retriedWithoutCursor = false;
|
|
277
|
+
const world = await getWorldLazy();
|
|
229
278
|
const loadStart = Date.now();
|
|
230
279
|
while (hasMore) {
|
|
231
280
|
// TODO: we're currently loading all the data with resolveRef behaviour. We need to update this
|
|
232
281
|
// to lazyload the data from the world instead so that we can optimize and make the event log loading
|
|
233
282
|
// much faster and memory efficient
|
|
234
283
|
const pageStart = Date.now();
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
284
|
+
const requestedCursor = cursor;
|
|
285
|
+
recordRequestedEventCursor(runId, requestedCursor, requestedCursors);
|
|
286
|
+
let response;
|
|
287
|
+
try {
|
|
288
|
+
response = await world.events.list({
|
|
289
|
+
runId,
|
|
290
|
+
pagination: {
|
|
291
|
+
sortOrder: 'asc',
|
|
292
|
+
cursor: requestedCursor ?? undefined,
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
if (shouldRetryWithoutEventCursor(error, requestedCursor, retriedWithoutCursor)) {
|
|
298
|
+
runtimeLogger.warn('Event cursor was rejected; retrying with a full event reload.', { workflowRunId: runId });
|
|
299
|
+
loadedEvents.length = 0;
|
|
300
|
+
loadedEventIds.clear();
|
|
301
|
+
requestedCursors.clear();
|
|
302
|
+
cursor = null;
|
|
303
|
+
retriedWithoutCursor = true;
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
throw error;
|
|
307
|
+
}
|
|
308
|
+
appendUniqueEvents(loadedEvents, loadedEventIds, response.data);
|
|
243
309
|
hasMore = response.hasMore;
|
|
244
|
-
|
|
310
|
+
assertEventPaginationProgress(runId, hasMore, response.cursor, requestedCursors);
|
|
311
|
+
// Preserve the last non-null cursor across pages. A World may
|
|
312
|
+
// legitimately return `{ data: [], cursor: null, hasMore: false }`
|
|
313
|
+
// on a trailing empty page — for example when the previous page's
|
|
314
|
+
// underlying DB query hit the limit exactly and returned a
|
|
315
|
+
// `LastEvaluatedKey` "just in case". Overwriting with that null
|
|
316
|
+
// would lose the position past the last real event we loaded and
|
|
317
|
+
// force the runtime into the "no cursor after initial load" full-
|
|
318
|
+
// reload fallback on every subsequent replay iteration.
|
|
319
|
+
cursor = response.cursor ?? cursor;
|
|
245
320
|
pagesLoaded++;
|
|
246
321
|
runtimeLogger.debug('Loaded event page', {
|
|
247
322
|
workflowRunId: runId,
|
|
323
|
+
incremental,
|
|
248
324
|
page: pagesLoaded,
|
|
249
325
|
pageEvents: response.data.length,
|
|
250
|
-
totalEvents:
|
|
326
|
+
totalEvents: loadedEvents.length,
|
|
251
327
|
hasMore,
|
|
252
328
|
pageMs: Date.now() - pageStart,
|
|
253
329
|
});
|
|
254
330
|
}
|
|
255
|
-
runtimeLogger.debug('Event
|
|
331
|
+
runtimeLogger.debug('Event load complete', {
|
|
256
332
|
workflowRunId: runId,
|
|
257
|
-
|
|
333
|
+
incremental,
|
|
334
|
+
totalEvents: loadedEvents.length,
|
|
258
335
|
pagesLoaded,
|
|
259
336
|
totalMs: Date.now() - loadStart,
|
|
260
337
|
});
|
|
261
338
|
span?.setAttributes({
|
|
262
|
-
...Attribute.WorkflowEventsCount(
|
|
339
|
+
...Attribute.WorkflowEventsCount(loadedEvents.length),
|
|
263
340
|
...Attribute.WorkflowEventsPagesLoaded(pagesLoaded),
|
|
264
341
|
});
|
|
265
|
-
return
|
|
342
|
+
return { events: loadedEvents, cursor };
|
|
266
343
|
});
|
|
267
344
|
}
|
|
268
345
|
/**
|
|
@@ -344,4 +421,43 @@ export function getQueueOverhead(message) {
|
|
|
344
421
|
return;
|
|
345
422
|
}
|
|
346
423
|
}
|
|
347
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL2hlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTUEsT0FBTyxFQUNMLHdCQUF3QixFQUN4QixvQkFBb0IsRUFDcEIsbUJBQW1CLEdBQ3BCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXhDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDN0MsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxPQUFPLElBQUksbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV0Qyx3REFBd0Q7QUFDeEQsTUFBTSw0QkFBNEIsR0FBRyxNQUFNLENBQUM7QUFFNUM7Ozs7R0FJRztBQUNILE1BQU0sMEJBQTBCLEdBQUcsc0JBQXNCLENBQUM7QUFFMUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxZQUFvQjtJQUN2RCxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7UUFDbkQsTUFBTSxJQUFJLEtBQUssQ0FDYiwwQkFBMEIsWUFBWSx3R0FBd0csQ0FDL0ksQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLGtCQUFrQixZQUFZLEVBQW9CLENBQUM7QUFDNUQsQ0FBQztBQUVELE1BQU0sVUFBVSxHQUFHLGdCQUFnQixFQUFFLENBQUM7QUFFdEM7O0dBRUc7QUFDSCxTQUFTLHdCQUF3QixDQUFDLGFBQXFCO0lBQ3JELE9BQU8sbUJBQW1CLGFBQWEsRUFBRSxDQUFDO0FBQzVDLENBQUM7QUFlRDs7O0dBR0c7QUFD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
|
|
424
|
+
/**
|
|
425
|
+
* Returns a memoized accessor for the per-run AES-256 encryption key.
|
|
426
|
+
*
|
|
427
|
+
* The first call resolves the key via `world.getEncryptionKeyForRun` (which
|
|
428
|
+
* may do HKDF derivation locally on Vercel, or a network fetch from
|
|
429
|
+
* external contexts) and imports it as a `CryptoKey`; subsequent calls
|
|
430
|
+
* await the same cached promise. If the world doesn't support encryption
|
|
431
|
+
* or the run has no key configured, the cached value is `undefined`.
|
|
432
|
+
*
|
|
433
|
+
* Used by step / workflow handlers to defer the (potentially expensive)
|
|
434
|
+
* key fetch until the first code path that actually needs it — typically
|
|
435
|
+
* input hydration on the success path, or error dehydration on a failure
|
|
436
|
+
* path. Both paths can race-call the accessor without triggering duplicate
|
|
437
|
+
* fetches.
|
|
438
|
+
*
|
|
439
|
+
* Errors thrown by `getEncryptionKeyForRun` propagate to every caller
|
|
440
|
+
* (the cached promise rejects). This is intentional: when encryption is
|
|
441
|
+
* configured, we never want to silently fall back to plaintext
|
|
442
|
+
* serialization. A propagated error in an event-emission path leaves the
|
|
443
|
+
* outer try/catch to log and surface the issue; the queue's redelivery
|
|
444
|
+
* semantics will retry the key fetch on the next attempt.
|
|
445
|
+
*/
|
|
446
|
+
export function memoizeEncryptionKey(world, runOrId) {
|
|
447
|
+
let cached;
|
|
448
|
+
return () => {
|
|
449
|
+
if (!cached) {
|
|
450
|
+
cached = (async () => {
|
|
451
|
+
// The `getEncryptionKeyForRun` overload set takes either a
|
|
452
|
+
// `WorkflowRun` or a `runId: string` (with optional context). Branch
|
|
453
|
+
// here so TypeScript picks the right overload for each shape.
|
|
454
|
+
const rawKey = typeof runOrId === 'string'
|
|
455
|
+
? await world.getEncryptionKeyForRun?.(runOrId)
|
|
456
|
+
: await world.getEncryptionKeyForRun?.(runOrId);
|
|
457
|
+
return rawKey ? await importKey(rawKey) : undefined;
|
|
458
|
+
})();
|
|
459
|
+
}
|
|
460
|
+
return cached;
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL2hlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBUXZFLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsb0JBQW9CLEVBQ3BCLG1CQUFtQixHQUNwQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUV4QyxPQUFPLEVBQWtCLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzdELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDN0MsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxPQUFPLElBQUksbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRW5ELHdEQUF3RDtBQUN4RCxNQUFNLDRCQUE0QixHQUFHLE1BQU0sQ0FBQztBQUU1Qzs7OztHQUlHO0FBQ0gsTUFBTSwwQkFBMEIsR0FBRyxzQkFBc0IsQ0FBQztBQUUxRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLFlBQW9CO0lBQ3ZELElBQUksQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztRQUNuRCxNQUFNLElBQUksS0FBSyxDQUNiLDBCQUEwQixZQUFZLHdHQUF3RyxDQUMvSSxDQUFDO0lBQ0osQ0FBQztJQUNELE9BQU8sa0JBQWtCLFlBQVksRUFBb0IsQ0FBQztBQUM1RCxDQUFDO0FBRUQsTUFBTSxVQUFVLEdBQUcsZ0JBQWdCLEVBQUUsQ0FB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RCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUlVOX0VSUk9SX0NPREVTLCBXb3JrZmxvd1dvcmxkRXJyb3IgfSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB0eXBlIHtcbiAgRXZlbnQsXG4gIEhlYWx0aENoZWNrUGF5bG9hZCxcbiAgVmFsaWRRdWV1ZU5hbWUsXG4gIFdvcmtmbG93UnVuLFxuICBXb3JsZCxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7XG4gIEhlYWx0aENoZWNrUGF5bG9hZFNjaGVtYSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIFNQRUNfVkVSU0lPTl9MRUdBQ1ksXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBtb25vdG9uaWNGYWN0b3J5IH0gZnJvbSAndWxpZCc7XG5cbmltcG9ydCB7IHR5cGUgQ3J5cHRvS2V5LCBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0ICogYXMgQXR0cmlidXRlIGZyb20gJy4uL3RlbGVtZXRyeS9zZW1hbnRpYy1jb252ZW50aW9ucy5qcyc7XG5pbXBvcnQgeyBnZXRTcGFuS2luZCwgdHJhY2UgfSBmcm9tICcuLi90ZWxlbWV0cnkuanMnO1xuaW1wb3J0IHsgdmVyc2lvbiBhcyB3b3JrZmxvd0NvcmVWZXJzaW9uIH0gZnJvbSAnLi4vdmVyc2lvbi5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZExhenkgfSBmcm9tICcuL2dldC13b3JsZC1sYXp5LmpzJztcblxuLyoqIERlZmF1bHQgdGltZW91dCBmb3IgaGVhbHRoIGNoZWNrcyBpbiBtaWxsaXNlY29uZHMgKi9cbmNvbnN0IERFRkFVTFRfSEVBTFRIX0NIRUNLX1RJTUVPVVQgPSAzMF8wMDA7XG5cbi8qKlxuICogUGF0dGVybiBmb3Igc2FmZSB3b3JrZmxvdyBuYW1lcy4gT25seSBhbGxvd3MgYWxwaGFudW1lcmljIGNoYXJhY3RlcnMsXG4gKiB1bmRlcnNjb3JlcywgaHlwaGVucywgZG90cywgZm9yd2FyZCBzbGFzaGVzIChmb3IgbmFtZXNwYWNlZCB3b3JrZmxvd3MpLFxuICogYW5kIGF0IHNpZ25zIChmb3Igc2NvcGVkIHBhY2thZ2VzKS5cbiAqL1xuY29uc3QgU0FGRV9XT1JLRkxPV19OQU1FX1BBVFRFUk4gPSAvXlthLXpBLVowLTlfXFwtLi9AXSskLztcblxuLyoqXG4gKiBWYWxpZGF0ZXMgYSB3b3JrZmxvdyBuYW1lIGFuZCByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIHF1ZXVlIG5hbWUuXG4gKiBFbnN1cmVzIHRoZSB3b3JrZmxvdyBuYW1lIG9ubHkgY29udGFpbnMgc2FmZSBjaGFyYWN0ZXJzIGJlZm9yZVxuICogaW50ZXJwb2xhdGluZyBpdCBpbnRvIHRoZSBxdWV1ZSBuYW1lIHN0cmluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZTogc3RyaW5nKTogVmFsaWRRdWV1ZU5hbWUge1xuICBpZiAoIVNBRkVfV09SS0ZMT1dfTkFNRV9QQVRURVJOLnRlc3Qod29ya2Zsb3dOYW1lKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBJbnZhbGlkIHdvcmtmbG93IG5hbWUgXCIke3dvcmtmbG93TmFtZX1cIjogbXVzdCBvbmx5IGNvbnRhaW4gYWxwaGFudW1lcmljIGNoYXJhY3RlcnMsIHVuZGVyc2NvcmVzLCBoeXBoZW5zLCBkb3RzLCBmb3J3YXJkIHNsYXNoZXMsIG9yIGF0IHNpZ25zYFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIGBfX3drZl93b3JrZmxvd18ke3dvcmtmbG93TmFtZX1gIGFzIFZhbGlkUXVldWVOYW1lO1xufVxuXG5jb25zdCBnZW5lcmF0ZUlkID0gbW9ub3RvbmljRmFjdG9yeSgpO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0cmVhbSBuYW1lIGZvciBhIGhlYWx0aCBjaGVjayB3aXRoIHRoZSBnaXZlbiBjb3JyZWxhdGlvbiBJRC5cbiAqL1xuZnVuY3Rpb24gZ2V0SGVhbHRoQ2hlY2tTdHJlYW1OYW1lKGNvcnJlbGF0aW9uSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgX19oZWFsdGhfY2hlY2tfXyR7Y29ycmVsYXRpb25JZH1gO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBhIGhlYWx0aCBjaGVjayBvcGVyYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSGVhbHRoQ2hlY2tSZXN1bHQge1xuICBoZWFsdGh5OiBib29sZWFuO1xuICAvKiogRXJyb3IgbWVzc2FnZSBpZiBoZWFsdGggY2hlY2sgZmFpbGVkICovXG4gIGVycm9yPzogc3RyaW5nO1xuICAvKiogTGF0ZW5jeSBpZiB0aGUgaGVhbHRoIGNoZWNrIHdhcyBzdWNjZXNzZnVsICovXG4gIGxhdGVuY3lNcz86IG51bWJlcjtcbiAgLyoqIFNwZWMgdmVyc2lvbiBvZiB0aGUgcmVzcG9uZGluZyBkZXBsb3ltZW50ICovXG4gIHNwZWNWZXJzaW9uPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gbWVzc2FnZSBpcyBhIGhlYWx0aCBjaGVjayBwYXlsb2FkLlxuICogSWYgc28sIHJldHVybnMgdGhlIHBhcnNlZCBwYXlsb2FkLiBPdGhlcndpc2UgcmV0dXJucyB1bmRlZmluZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUhlYWx0aENoZWNrUGF5bG9hZChcbiAgbWVzc2FnZTogdW5rbm93blxuKTogSGVhbHRoQ2hlY2tQYXlsb2FkIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcmVzdWx0ID0gSGVhbHRoQ2hlY2tQYXlsb2FkU2NoZW1hLnNhZmVQYXJzZShtZXNzYWdlKTtcbiAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7XG4gICAgcmV0dXJuIHJlc3VsdC5kYXRhO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgZGV0ZXJtaW5pc3RpYyBmYWtlIHJ1bklkIGZvciBoZWFsdGggY2hlY2sgc3RyZWFtcy5cbiAqIEJvdGggdGhlIHdyaXRlciAoaGFuZGxlSGVhbHRoQ2hlY2tNZXNzYWdlKSBhbmQgcmVhZGVyIChoZWFsdGhDaGVjaykgZGVyaXZlXG4gKiB0aGUgc2FtZSBydW5JZCBmcm9tIHRoZSBjb3JyZWxhdGlvbklkIHNvIHRoYXQgaW1wbGVtZW50YXRpb25zIHRoYXQgc2NvcGVcbiAqIHN0cmVhbSByZWFkcyBieSBydW5JZCBzdGlsbCB3b3JrIGNvcnJlY3RseS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVIZWFsdGhDaGVja1J1bklkKGNvcnJlbGF0aW9uSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgd3J1bl9oY18ke2NvcnJlbGF0aW9uSWR9YDtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIGEgaGVhbHRoIGNoZWNrIG1lc3NhZ2UgYnkgd3JpdGluZyB0aGUgcmVzdWx0IHRvIHRoZSB3b3JsZCdzIHN0cmVhbS5cbiAqIFRoZSBjYWxsZXIgY2FuIGxpc3RlbiB0byB0aGlzIHN0cmVhbSB0byBnZXQgdGhlIGhlYWx0aCBjaGVjayByZXNwb25zZS5cbiAqXG4gKiBAcGFyYW0gaGVhbHRoQ2hlY2sgLSBUaGUgcGFyc2VkIGhlYWx0aCBjaGVjayBwYXlsb2FkXG4gKiBAcGFyYW0gZW5kcG9pbnQgLSBXaGljaCBlbmRwb2ludCBpcyByZXNwb25kaW5nICgnd29ya2Zsb3cnIG9yICdzdGVwJylcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZUhlYWx0aENoZWNrTWVzc2FnZShcbiAgaGVhbHRoQ2hlY2s6IEhlYWx0aENoZWNrUGF5bG9hZCxcbiAgZW5kcG9pbnQ6ICd3b3JrZmxvdycgfCAnc3RlcCcsXG4gIHdvcmxkU3BlY1ZlcnNpb24/OiBudW1iZXJcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuICBjb25zdCBzdHJlYW1OYW1lID0gZ2V0SGVhbHRoQ2hlY2tTdHJlYW1OYW1lKGhlYWx0aENoZWNrLmNvcnJlbGF0aW9uSWQpO1xuICBjb25zdCByZXNwb25zZSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICBoZWFsdGh5OiB0cnVlLFxuICAgIGVuZHBvaW50LFxuICAgIGNvcnJlbGF0aW9uSWQ6IGhlYWx0aENoZWNrLmNvcnJlbGF0aW9uSWQsXG4gICAgc3BlY1ZlcnNpb246IHdvcmxkU3BlY1ZlcnNpb24gPz8gU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgd29ya2Zsb3dDb3JlVmVyc2lvbixcbiAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gIH0pO1xuICAvLyBVc2UgYSBkZXRlcm1pbmlzdGljIGZha2UgcnVuSWQgZGVyaXZlZCBmcm9tIHRoZSBjb3JyZWxhdGlvbklkIHNvIHRoYXRcbiAgLy8gdGhlIHJlYWRlciBzaWRlIHByb2R1Y2VzIHRoZSBzYW1lIHZhbHVlLlxuICBjb25zdCBmYWtlUnVuSWQgPSBnZW5lcmF0ZUhlYWx0aENoZWNrUnVuSWQoaGVhbHRoQ2hlY2suY29ycmVsYXRpb25JZCk7XG4gIGF3YWl0IHdvcmxkLnN0cmVhbXMud3JpdGUoZmFrZVJ1bklkLCBzdHJlYW1OYW1lLCByZXNwb25zZSk7XG4gIGF3YWl0IHdvcmxkLnN0cmVhbXMuY2xvc2UoZmFrZVJ1bklkLCBzdHJlYW1OYW1lKTtcbn1cblxuZXhwb3J0IHR5cGUgSGVhbHRoQ2hlY2tFbmRwb2ludCA9ICd3b3JrZmxvdycgfCAnc3RlcCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSGVhbHRoQ2hlY2tPcHRpb25zIHtcbiAgLyoqIFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIHRvIHdhaXQgZm9yIGhlYWx0aCBjaGVjayByZXNwb25zZS4gRGVmYXVsdDogMzAwMDAgKDMwcykgKi9cbiAgdGltZW91dD86IG51bWJlcjtcbiAgLyoqIERlcGxveW1lbnQgSUQgdG8gc2VuZCB0aGUgaGVhbHRoIGNoZWNrIHRvLiBGYWxscyBiYWNrIHRvIHByb2Nlc3MuZW52LlZFUkNFTF9ERVBMT1lNRU5UX0lELiAqL1xuICBkZXBsb3ltZW50SWQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUGVyZm9ybXMgYSBoZWFsdGggY2hlY2sgYnkgc2VuZGluZyBhIG1lc3NhZ2UgdGhyb3VnaCB0aGUgcXVldWUgcGlwZWxpbmVcbiAqIGFuZCB2ZXJpZnlpbmcgaXQgaXMgcHJvY2Vzc2VkIGJ5IHRoZSBzcGVjaWZpZWQgZW5kcG9pbnQuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBieXBhc3NlcyBEZXBsb3ltZW50IFByb3RlY3Rpb24gb24gVmVyY2VsIGJlY2F1c2UgaXQgZ29lc1xuICogdGhyb3VnaCB0aGUgcXVldWUgaW5mcmFzdHJ1Y3R1cmUgcmF0aGVyIHRoYW4gZGlyZWN0IEhUVFAuXG4gKlxuICogQHBhcmFtIHdvcmxkIC0gVGhlIFdvcmxkIGluc3RhbmNlIHRvIHVzZSBmb3IgdGhlIGhlYWx0aCBjaGVja1xuICogQHBhcmFtIGVuZHBvaW50IC0gV2hpY2ggZW5kcG9pbnQgdG8gaGVhbHRoIGNoZWNrOiAnd29ya2Zsb3cnIG9yICdzdGVwJ1xuICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25hbCBjb25maWd1cmF0aW9uIGZvciB0aGUgaGVhbHRoIGNoZWNrXG4gKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byBoZWFsdGggY2hlY2sgcmVzdWx0XG4gKi9cbi8vIFBvbGwgaW50ZXJ2YWwgZm9yIGhlYWx0aCBjaGVjayByZXRyaWVzIChtcylcbmNvbnN0IEhFQUxUSF9DSEVDS19QT0xMX0lOVEVSVkFMID0gMTAwO1xuLy8gUGVyLXJlYWQgdGltZW91dCB0byBwcmV2ZW50IGJsb2NraW5nIGZvcmV2ZXIgb24gbG9jYWwgd29ybGQncyBFdmVudEVtaXR0ZXJcbi8vICh3aGljaCBkb2Vzbid0IHdvcmsgYWNyb3NzIHByb2Nlc3NlcylcbmNvbnN0IEhFQUxUSF9DSEVDS19SRUFEX1RJTUVPVVQgPSA1MDA7XG5cbi8qKlxuICogUmVhZCBjaHVua3MgZnJvbSBhIHN0cmVhbSB3aXRoIGEgdGltZW91dCBwZXIgcmVhZCBvcGVyYXRpb24uXG4gKiBSZXR1cm5zIHsgY2h1bmtzLCB0aW1lZE91dCB9IHdoZXJlIHRpbWVkT3V0IGluZGljYXRlcyBpZiBhIHJlYWQgdGltZWQgb3V0LlxuICovXG5hc3luYyBmdW5jdGlvbiByZWFkU3RyZWFtV2l0aFRpbWVvdXQoXG4gIHJlYWRlcjogUmVhZGFibGVTdHJlYW1EZWZhdWx0UmVhZGVyPFVpbnQ4QXJyYXk+LFxuICByZWFkVGltZW91dDogbnVtYmVyXG4pOiBQcm9taXNlPHsgY2h1bmtzOiBVaW50OEFycmF5W107IHRpbWVkT3V0OiBib29sZWFuIH0+IHtcbiAgY29uc3QgY2h1bmtzOiBVaW50OEFycmF5W10gPSBbXTtcbiAgbGV0IGRvbmUgPSBmYWxzZTtcbiAgbGV0IHRpbWVkT3V0ID0gZmFsc2U7XG5cbiAgd2hpbGUgKCFkb25lICYmICF0aW1lZE91dCkge1xuICAgIGNvbnN0IHJlYWRQcm9taXNlID0gcmVhZGVyLnJlYWQoKTtcbiAgICBjb25zdCB0aW1lb3V0UHJvbWlzZSA9IG5ldyBQcm9taXNlPHsgZG9uZTogdHJ1ZTsgdmFsdWU6IHVuZGVmaW5lZCB9PihcbiAgICAgIChyZXNvbHZlKSA9PlxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICB0aW1lZE91dCA9IHRydWU7XG4gICAgICAgICAgcmVzb2x2ZSh7IGRvbmU6IHRydWUsIHZhbHVlOiB1bmRlZmluZWQgfSk7XG4gICAgICAgIH0sIHJlYWRUaW1lb3V0KVxuICAgICk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLnJhY2UoW3JlYWRQcm9taXNlLCB0aW1lb3V0UHJvbWlzZV0pO1xuICAgIGRvbmUgPSByZXN1bHQuZG9uZTtcbiAgICBpZiAocmVzdWx0LnZhbHVlKSBjaHVua3MucHVzaChyZXN1bHQudmFsdWUpO1xuICB9XG5cbiAgcmV0dXJuIHsgY2h1bmtzLCB0aW1lZE91dCB9O1xufVxuXG4vKipcbiAqIFBhcnNlIGFuZCB2YWxpZGF0ZSBhIGhlYWx0aCBjaGVjayByZXNwb25zZSBmcm9tIHN0cmVhbSBjaHVua3MuXG4gKiBSZXR1cm5zIHRoZSBwYXJzZWQgcmVzcG9uc2Ugb3IgbnVsbCBpZiBpbnZhbGlkLlxuICovXG5mdW5jdGlvbiBwYXJzZUhlYWx0aENoZWNrUmVzcG9uc2UoXG4gIGNodW5rczogVWludDhBcnJheVtdXG4pOiB7IGhlYWx0aHk6IGJvb2xlYW4gfSB8IG51bGwge1xuICBpZiAoY2h1bmtzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgdG90YWxMZW5ndGggPSBjaHVua3MucmVkdWNlKChzdW0sIGNodW5rKSA9PiBzdW0gKyBjaHVuay5sZW5ndGgsIDApO1xuICBjb25zdCBjb21iaW5lZCA9IG5ldyBVaW50OEFycmF5KHRvdGFsTGVuZ3RoKTtcbiAgbGV0IG9mZnNldCA9IDA7XG4gIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzKSB7XG4gICAgY29tYmluZWQuc2V0KGNodW5rLCBvZmZzZXQpO1xuICAgIG9mZnNldCArPSBjaHVuay5sZW5ndGg7XG4gIH1cbiAgY29uc3QgcmVzcG9uc2VUZXh0ID0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGNvbWJpbmVkKTtcblxuICBsZXQgcmVzcG9uc2U6IHVua25vd247XG4gIHRyeSB7XG4gICAgcmVzcG9uc2UgPSBKU09OLnBhcnNlKHJlc3BvbnNlVGV4dCk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIE9sZCBkZXBsb3ltZW50cyAoc3BlY1ZlcnNpb24gPCAzKSByZXR1cm4gcGxhaW4gdGV4dCBsaWtlXG4gICAgLy8gJ1dvcmtmbG93IFNESyBcIi4uLlwiIGVuZHBvaW50IGlzIGhlYWx0aHknLiBUcmVhdCBhbnkgbm9uLWVtcHR5XG4gICAgLy8gdGV4dCByZXNwb25zZSBhcyBhIGhlYWx0aHkgZGVwbG95bWVudCB3aXRoIHVua25vd24gc3BlY1ZlcnNpb24uXG4gICAgaWYgKHJlc3BvbnNlVGV4dC5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4geyBoZWFsdGh5OiB0cnVlIH07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgaWYgKFxuICAgIHR5cGVvZiByZXNwb25zZSAhPT0gJ29iamVjdCcgfHxcbiAgICByZXNwb25zZSA9PT0gbnVsbCB8fFxuICAgICEoJ2hlYWx0aHknIGluIHJlc3BvbnNlKSB8fFxuICAgIHR5cGVvZiAocmVzcG9uc2UgYXMgeyBoZWFsdGh5OiB1bmtub3duIH0pLmhlYWx0aHkgIT09ICdib29sZWFuJ1xuICApIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IHIgPSByZXNwb25zZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgcGFyc2VkOiB7IGhlYWx0aHk6IGJvb2xlYW47IHNwZWNWZXJzaW9uPzogbnVtYmVyIH0gPSB7XG4gICAgaGVhbHRoeTogci5oZWFsdGh5IGFzIGJvb2xlYW4sXG4gIH07XG4gIGlmICh0eXBlb2Ygci5zcGVjVmVyc2lvbiA9PT0gJ251bWJlcicpIHtcbiAgICBwYXJzZWQuc3BlY1ZlcnNpb24gPSByLnNwZWNWZXJzaW9uO1xuICB9XG4gIHJldHVybiBwYXJzZWQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoZWFsdGhDaGVjayhcbiAgd29ybGQ6IFdvcmxkLFxuICBlbmRwb2ludDogSGVhbHRoQ2hlY2tFbmRwb2ludCxcbiAgb3B0aW9ucz86IEhlYWx0aENoZWNrT3B0aW9uc1xuKTogUHJvbWlzZTxIZWFsdGhDaGVja1Jlc3VsdD4ge1xuICBjb25zdCB0aW1lb3V0ID0gb3B0aW9ucz8udGltZW91dCA/PyBERUZBVUxUX0hFQUxUSF9DSEVDS19USU1FT1VUO1xuICBjb25zdCBjb3JyZWxhdGlvbklkID0gZ2VuZXJhdGVJZCgpO1xuICBjb25zdCBzdHJlYW1OYW1lID0gZ2V0SGVhbHRoQ2hlY2tTdHJlYW1OYW1lKGNvcnJlbGF0aW9uSWQpO1xuXG4gIGNvbnN0IHF1ZXVlTmFtZTogVmFsaWRRdWV1ZU5hbWUgPVxuICAgIGVuZHBvaW50ID09PSAnd29ya2Zsb3cnXG4gICAgICA/ICdfX3drZl93b3JrZmxvd19oZWFsdGhfY2hlY2snXG4gICAgICA6ICdfX3drZl9zdGVwX2hlYWx0aF9jaGVjayc7XG5cbiAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcblxuICB0cnkge1xuICAgIGF3YWl0IHdvcmxkLnF1ZXVlKFxuICAgICAgcXVldWVOYW1lLFxuICAgICAgeyBfX2hlYWx0aENoZWNrOiB0cnVlLCBjb3JyZWxhdGlvbklkIH0sXG4gICAgICB7XG4gICAgICAgIC8vIFVzZSBKU09OIHRyYW5zcG9ydCBzbyB0aGUgaGVhbHRoIGNoZWNrIHdvcmtzIGFnYWluc3QgYm90aFxuICAgICAgICAvLyBvbGQgKEpTT04tb25seSkgYW5kIG5ldyAoZHVhbCkgZGVwbG95bWVudHMuXG4gICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fTEVHQUNZLFxuICAgICAgICBkZXBsb3ltZW50SWQ6IG9wdGlvbnM/LmRlcGxveW1lbnRJZCxcbiAgICAgIH1cbiAgICApO1xuXG4gICAgd2hpbGUgKERhdGUubm93KCkgLSBzdGFydFRpbWUgPCB0aW1lb3V0KSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBzdHJlYW0gPSBhd2FpdCB3b3JsZC5zdHJlYW1zLmdldChcbiAgICAgICAgICBnZW5lcmF0ZUhlYWx0aENoZWNrUnVuSWQoY29ycmVsYXRpb25JZCksXG4gICAgICAgICAgc3RyZWFtTmFtZVxuICAgICAgICApO1xuICAgICAgICBjb25zdCByZWFkZXIgPSBzdHJlYW0uZ2V0UmVhZGVyKCk7XG4gICAgICAgIGNvbnN0IHsgY2h1bmtzLCB0aW1lZE91dCB9ID0gYXdhaXQgcmVhZFN0cmVhbVdpdGhUaW1lb3V0KFxuICAgICAgICAgIHJlYWRlcixcbiAgICAgICAgICBIRUFMVEhfQ0hFQ0tfUkVBRF9USU1FT1VUXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKHRpbWVkT3V0KSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlYWRlci5jYW5jZWwoKTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIElnbm9yZSBjYW5jZWwgZXJyb3JzXG4gICAgICAgICAgfVxuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PlxuICAgICAgICAgICAgc2V0VGltZW91dChyZXNvbHZlLCBIRUFMVEhfQ0hFQ0tfUE9MTF9JTlRFUlZBTClcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBwYXJzZUhlYWx0aENoZWNrUmVzcG9uc2UoY2h1bmtzKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnJlc3BvbnNlLFxuICAgICAgICAgICAgbGF0ZW5jeU1zOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT5cbiAgICAgICAgICBzZXRUaW1lb3V0KHJlc29sdmUsIEhFQUxUSF9DSEVDS19QT0xMX0lOVEVSVkFMKVxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PlxuICAgICAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgSEVBTFRIX0NIRUNLX1BPTExfSU5URVJWQUwpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBoZWFsdGh5OiBmYWxzZSxcbiAgICAgIGVycm9yOiBgSGVhbHRoIGNoZWNrIHRpbWVkIG91dCBhZnRlciAke3RpbWVvdXR9bXNgLFxuICAgIH07XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhlYWx0aHk6IGZhbHNlLFxuICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKSxcbiAgICB9O1xuICB9XG59XG5cbmZ1bmN0aW9uIGV2ZW50UGFnaW5hdGlvbkNvbnRyYWN0RXJyb3IoXG4gIHJ1bklkOiBzdHJpbmcsXG4gIG1lc3NhZ2U6IHN0cmluZ1xuKTogV29ya2Zsb3dXb3JsZEVycm9yIHtcbiAgcmV0dXJuIG5ldyBXb3JrZmxvd1dvcmxkRXJyb3IoXG4gICAgYEV2ZW50IHBhZ2luYXRpb24gJHttZXNzYWdlfSBmb3Igd29ya2Zsb3cgcnVuIFwiJHtydW5JZH1cIi5gLFxuICAgIHsgY29kZTogUlVOX0VSUk9SX0NPREVTLldPUkxEX0NPTlRSQUNUX0VSUk9SIH1cbiAgKTtcbn1cblxuZnVuY3Rpb24gcmVjb3JkUmVxdWVzdGVkRXZlbnRDdXJzb3IoXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGN1cnNvcjogc3RyaW5nIHwgbnVsbCxcbiAgcmVxdWVzdGVkQ3Vyc29yczogU2V0PHN0cmluZz5cbik6IHZvaWQge1xuICBpZiAoIWN1cnNvcikge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAocmVxdWVzdGVkQ3Vyc29ycy5oYXMoY3Vyc29yKSkge1xuICAgIHRocm93IGV2ZW50UGFnaW5hdGlvbkNvbnRyYWN0RXJyb3IocnVuSWQsICdkaWQgbm90IGFkdmFuY2UnKTtcbiAgfVxuICByZXF1ZXN0ZWRDdXJzb3JzLmFkZChjdXJzb3IpO1xufVxuXG5mdW5jdGlvbiBhcHBlbmRVbmlxdWVFdmVudHMoXG4gIHRhcmdldDogRXZlbnRbXSxcbiAgdGFyZ2V0SWRzOiBTZXQ8c3RyaW5nPixcbiAgZXZlbnRzOiBFdmVudFtdXG4pOiB2b2lkIHtcbiAgZm9yIChjb25zdCBldmVudCBvZiBldmVudHMpIHtcbiAgICBpZiAoIXRhcmdldElkcy5oYXMoZXZlbnQuZXZlbnRJZCkpIHtcbiAgICAgIHRhcmdldElkcy5hZGQoZXZlbnQuZXZlbnRJZCk7XG4gICAgICB0YXJnZXQucHVzaChldmVudCk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGFzc2VydEV2ZW50UGFnaW5hdGlvblByb2dyZXNzKFxuICBydW5JZDogc3RyaW5nLFxuICBoYXNNb3JlOiBib29sZWFuLFxuICBjdXJzb3I6IHN0cmluZyB8IG51bGwsXG4gIHJlcXVlc3RlZEN1cnNvcnM6IFNldDxzdHJpbmc+XG4pOiB2b2lkIHtcbiAgaWYgKCFoYXNNb3JlKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChjdXJzb3IgPT09IG51bGwpIHtcbiAgICB0aHJvdyBldmVudFBhZ2luYXRpb25Db250cmFjdEVycm9yKFxuICAgICAgcnVuSWQsXG4gICAgICAncmV0dXJuZWQgbW9yZSBwYWdlcyB3aXRob3V0IGEgY3Vyc29yJ1xuICAgICk7XG4gIH1cbiAgaWYgKHJlcXVlc3RlZEN1cnNvcnMuaGFzKGN1cnNvcikpIHtcbiAgICB0aHJvdyBldmVudFBhZ2luYXRpb25Db250cmFjdEVycm9yKHJ1bklkLCAncmVwZWF0ZWQgYSBjdXJzb3InKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzaG91bGRSZXRyeVdpdGhvdXRFdmVudEN1cnNvcihcbiAgZXJyb3I6IHVua25vd24sXG4gIGN1cnNvcjogc3RyaW5nIHwgbnVsbCxcbiAgYWxyZWFkeVJldHJpZWQ6IGJvb2xlYW5cbik6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIGN1cnNvciAhPT0gbnVsbCAmJlxuICAgICFhbHJlYWR5UmV0cmllZCAmJlxuICAgIFdvcmtmbG93V29ybGRFcnJvci5pcyhlcnJvcikgJiZcbiAgICBlcnJvci5zdGF0dXMgPT09IDQwMFxuICApO1xufVxuXG4vKipcbiAqIExvYWRzIHdvcmtmbG93IHJ1biBldmVudHMgYnkgaXRlcmF0aW5nIHRocm91Z2ggYWxsIHBhZ2VzIG9mIHBhZ2luYXRlZFxuICogcmVzdWx0cy4gRXZlbnRzIGFyZSByZXR1cm5lZCBpbiBjaHJvbm9sb2dpY2FsIChhc2NlbmRpbmcpIG9yZGVyIGZvclxuICogZGV0ZXJtaW5pc3RpYyB3b3JrZmxvdyByZXBsYXkuXG4gKlxuICogQHBhcmFtIHJ1bklkIC0gVGhlIHdvcmtmbG93IHJ1biBJRC5cbiAqIEBwYXJhbSBhZnRlckN1cnNvciAtIElmIHByb3ZpZGVkLCBvbmx5IGV2ZW50cyBhZnRlciB0aGlzIGN1cnNvciBhcmVcbiAqICAgcmV0dXJuZWQgKGluY3JlbWVudGFsIGxvYWQpLiBJZiBvbWl0dGVkLCBhbGwgZXZlbnRzIGFyZSByZXR1cm5lZC5cbiAqICAgVGhlIHJldHVybmVkIGN1cnNvciBjYW4gYmUgcGFzc2VkIGJhY2sgaW4gb24gYSBzdWJzZXF1ZW50IGNhbGwgZm9yXG4gKiAgIGluY3JlbWVudGFsIGxvYWRpbmcuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkV29ya2Zsb3dSdW5FdmVudHMoXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGFmdGVyQ3Vyc29yPzogc3RyaW5nXG4pOiBQcm9taXNlPHsgZXZlbnRzOiBFdmVudFtdOyBjdXJzb3I6IHN0cmluZyB8IG51bGwgfT4ge1xuICBjb25zdCBpbmNyZW1lbnRhbCA9IGFmdGVyQ3Vyc29yICE9PSB1bmRlZmluZWQ7XG4gIHJldHVybiB0cmFjZShcbiAgICBpbmNyZW1lbnRhbCA/ICd3b3JrZmxvdy5sb2FkTmV3RXZlbnRzJyA6ICd3b3JrZmxvdy5sb2FkRXZlbnRzJyxcbiAgICBhc3luYyAoc3BhbikgPT4ge1xuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKHJ1bklkKSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBsb2FkZWRFdmVudHM6IEV2ZW50W10gPSBbXTtcbiAgICAgIGNvbnN0IGxvYWRlZEV2ZW50SWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBjb25zdCByZXF1ZXN0ZWRDdXJzb3JzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBsZXQgY3Vyc29yOiBzdHJpbmcgfCBudWxsID0gYWZ0ZXJDdXJzb3IgPz8gbnVsbDtcbiAgICAgIGxldCBoYXNNb3JlID0gdHJ1ZTtcbiAgICAgIGxldCBwYWdlc0xvYWRlZCA9IDA7XG4gICAgICBsZXQgcmV0cmllZFdpdGhvdXRDdXJzb3IgPSBmYWxzZTtcblxuICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZExhenkoKTtcbiAgICAgIGNvbnN0IGxvYWRTdGFydCA9IERhdGUubm93KCk7XG4gICAgICB3aGlsZSAoaGFzTW9yZSkge1xuICAgICAgICAvLyBUT0RPOiB3ZSdyZSBjdXJyZW50bHkgbG9hZGluZyBhbGwgdGhlIGRhdGEgd2l0aCByZXNvbHZlUmVmIGJlaGF2aW91ci4gV2UgbmVlZCB0byB1cGRhdGUgdGhpc1xuICAgICAgICAvLyB0byBsYXp5bG9hZCB0aGUgZGF0YSBmcm9tIHRoZSB3b3JsZCBpbnN0ZWFkIHNvIHRoYXQgd2UgY2FuIG9wdGltaXplIGFuZCBtYWtlIHRoZSBldmVudCBsb2cgbG9hZGluZ1xuICAgICAgICAvLyBtdWNoIGZhc3RlciBhbmQgbWVtb3J5IGVmZmljaWVudFxuICAgICAgICBjb25zdCBwYWdlU3RhcnQgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCByZXF1ZXN0ZWRDdXJzb3IgPSBjdXJzb3I7XG4gICAgICAgIHJlY29yZFJlcXVlc3RlZEV2ZW50Q3Vyc29yKHJ1bklkLCByZXF1ZXN0ZWRDdXJzb3IsIHJlcXVlc3RlZEN1cnNvcnMpO1xuXG4gICAgICAgIGxldCByZXNwb25zZTogQXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiB3b3JsZC5ldmVudHMubGlzdD4+O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJlc3BvbnNlID0gYXdhaXQgd29ybGQuZXZlbnRzLmxpc3Qoe1xuICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICBwYWdpbmF0aW9uOiB7XG4gICAgICAgICAgICAgIHNvcnRPcmRlcjogJ2FzYycsXG4gICAgICAgICAgICAgIGN1cnNvcjogcmVxdWVzdGVkQ3Vyc29yID8/IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgc2hvdWxkUmV0cnlXaXRob3V0RXZlbnRDdXJzb3IoXG4gICAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICAgICByZXF1ZXN0ZWRDdXJzb3IsXG4gICAgICAgICAgICAgIHJldHJpZWRXaXRob3V0Q3Vyc29yXG4gICAgICAgICAgICApXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLndhcm4oXG4gICAgICAgICAgICAgICdFdmVudCBjdXJzb3Igd2FzIHJlamVjdGVkOyByZXRyeWluZyB3aXRoIGEgZnVsbCBldmVudCByZWxvYWQuJyxcbiAgICAgICAgICAgICAgeyB3b3JrZmxvd1J1bklkOiBydW5JZCB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgbG9hZGVkRXZlbnRzLmxlbmd0aCA9IDA7XG4gICAgICAgICAgICBsb2FkZWRFdmVudElkcy5jbGVhcigpO1xuICAgICAgICAgICAgcmVxdWVzdGVkQ3Vyc29ycy5jbGVhcigpO1xuICAgICAgICAgICAgY3Vyc29yID0gbnVsbDtcbiAgICAgICAgICAgIHJldHJpZWRXaXRob3V0Q3Vyc29yID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGFwcGVuZFVuaXF1ZUV2ZW50cyhsb2FkZWRFdmVudHMsIGxvYWRlZEV2ZW50SWRzLCByZXNwb25zZS5kYXRhKTtcbiAgICAgICAgaGFzTW9yZSA9IHJlc3BvbnNlLmhhc01vcmU7XG4gICAgICAgIGFzc2VydEV2ZW50UGFnaW5hdGlvblByb2dyZXNzKFxuICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgIGhhc01vcmUsXG4gICAgICAgICAgcmVzcG9uc2UuY3Vyc29yLFxuICAgICAgICAgIHJlcXVlc3RlZEN1cnNvcnNcbiAgICAgICAgKTtcbiAgICAgICAgLy8gUHJlc2VydmUgdGhlIGxhc3Qgbm9uLW51bGwgY3Vyc29yIGFjcm9zcyBwYWdlcy4gQSBXb3JsZCBtYXlcbiAgICAgICAgLy8gbGVnaXRpbWF0ZWx5IHJldHVybiBgeyBkYXRhOiBbXSwgY3Vyc29yOiBudWxsLCBoYXNNb3JlOiBmYWxzZSB9YFxuICAgICAgICAvLyBvbiBhIHRyYWlsaW5nIGVtcHR5IHBhZ2Ug4oCUIGZvciBleGFtcGxlIHdoZW4gdGhlIHByZXZpb3VzIHBhZ2Unc1xuICAgICAgICAvLyB1bmRlcmx5aW5nIERCIHF1ZXJ5IGhpdCB0aGUgbGltaXQgZXhhY3RseSBhbmQgcmV0dXJuZWQgYVxuICAgICAgICAvLyBgTGFzdEV2YWx1YXRlZEtleWAgXCJqdXN0IGluIGNhc2VcIi4gT3ZlcndyaXRpbmcgd2l0aCB0aGF0IG51bGxcbiAgICAgICAgLy8gd291bGQgbG9zZSB0aGUgcG9zaXRpb24gcGFzdCB0aGUgbGFzdCByZWFsIGV2ZW50IHdlIGxvYWRlZCBhbmRcbiAgICAgICAgLy8gZm9yY2UgdGhlIHJ1bnRpbWUgaW50byB0aGUgXCJubyBjdXJzb3IgYWZ0ZXIgaW5pdGlhbCBsb2FkXCIgZnVsbC1cbiAgICAgICAgLy8gcmVsb2FkIGZhbGxiYWNrIG9uIGV2ZXJ5IHN1YnNlcXVlbnQgcmVwbGF5IGl0ZXJhdGlvbi5cbiAgICAgICAgY3Vyc29yID0gcmVzcG9uc2UuY3Vyc29yID8/IGN1cnNvcjtcbiAgICAgICAgcGFnZXNMb2FkZWQrKztcblxuICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdMb2FkZWQgZXZlbnQgcGFnZScsIHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICBpbmNyZW1lbnRhbCxcbiAgICAgICAgICBwYWdlOiBwYWdlc0xvYWRlZCxcbiAgICAgICAgICBwYWdlRXZlbnRzOiByZXNwb25zZS5kYXRhLmxlbmd0aCxcbiAgICAgICAgICB0b3RhbEV2ZW50czogbG9hZGVkRXZlbnRzLmxlbmd0aCxcbiAgICAgICAgICBoYXNNb3JlLFxuICAgICAgICAgIHBhZ2VNczogRGF0ZS5ub3coKSAtIHBhZ2VTdGFydCxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ0V2ZW50IGxvYWQgY29tcGxldGUnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBpbmNyZW1lbnRhbCxcbiAgICAgICAgdG90YWxFdmVudHM6IGxvYWRlZEV2ZW50cy5sZW5ndGgsXG4gICAgICAgIHBhZ2VzTG9hZGVkLFxuICAgICAgICB0b3RhbE1zOiBEYXRlLm5vdygpIC0gbG9hZFN0YXJ0LFxuICAgICAgfSk7XG5cbiAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFdmVudHNDb3VudChsb2FkZWRFdmVudHMubGVuZ3RoKSxcbiAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93RXZlbnRzUGFnZXNMb2FkZWQocGFnZXNMb2FkZWQpLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB7IGV2ZW50czogbG9hZGVkRXZlbnRzLCBjdXJzb3IgfTtcbiAgICB9XG4gICk7XG59XG5cbi8qKlxuICogQ09SUyBoZWFkZXJzIGZvciBoZWFsdGggY2hlY2sgcmVzcG9uc2VzLlxuICogQWxsb3dzIHRoZSBvYnNlcnZhYmlsaXR5IFVJIHRvIGNoZWNrIGVuZHBvaW50IGhlYWx0aCBmcm9tIGEgZGlmZmVyZW50IG9yaWdpbi5cbiAqL1xuY29uc3QgSEVBTFRIX0NIRUNLX0NPUlNfSEVBREVSUyA9IHtcbiAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbic6ICcqJyxcbiAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMnOiAnUE9TVCwgT1BUSU9OUywgR0VULCBIRUFEJyxcbiAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnOiAnQ29udGVudC1UeXBlJyxcbn07XG5cbi8qKlxuICogV3JhcHMgYSByZXF1ZXN0L3Jlc3BvbnNlIGhhbmRsZXIgYW5kIGFkZHMgYSBoZWFsdGggY2hlY2sgXCJtb2RlXCJcbiAqIGJhc2VkIG9uIHRoZSBwcmVzZW5jZSBvZiBhIGBfX2hlYWx0aGAgcXVlcnkgcGFyYW1ldGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2l0aEhlYWx0aENoZWNrKFxuICBoYW5kbGVyOiAocmVxOiBSZXF1ZXN0KSA9PiBQcm9taXNlPFJlc3BvbnNlPixcbiAgd29ybGRTcGVjVmVyc2lvbj86IG51bWJlclxuKTogKHJlcTogUmVxdWVzdCkgPT4gUHJvbWlzZTxSZXNwb25zZT4ge1xuICByZXR1cm4gYXN5bmMgKHJlcTogUmVxdWVzdCkgPT4ge1xuICAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxLnVybCk7XG4gICAgY29uc3QgaXNIZWFsdGhDaGVjayA9IHVybC5zZWFyY2hQYXJhbXMuaGFzKCdfX2hlYWx0aCcpO1xuICAgIGlmIChpc0hlYWx0aENoZWNrKSB7XG4gICAgICAvLyBIYW5kbGUgQ09SUyBwcmVmbGlnaHQgZm9yIGhlYWx0aCBjaGVja1xuICAgICAgaWYgKHJlcS5tZXRob2QgPT09ICdPUFRJT05TJykge1xuICAgICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKG51bGwsIHtcbiAgICAgICAgICBzdGF0dXM6IDIwNCxcbiAgICAgICAgICBoZWFkZXJzOiBIRUFMVEhfQ0hFQ0tfQ09SU19IRUFERVJTLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgUmVzcG9uc2UoXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBoZWFsdGh5OiB0cnVlLFxuICAgICAgICAgIGVuZHBvaW50OiB1cmwucGF0aG5hbWUsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IHdvcmxkU3BlY1ZlcnNpb24gPz8gU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgd29ya2Zsb3dDb3JlVmVyc2lvbixcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBzdGF0dXM6IDIwMCxcbiAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICAgLi4uSEVBTFRIX0NIRUNLX0NPUlNfSEVBREVSUyxcbiAgICAgICAgICB9LFxuICAgICAgICB9XG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgaGFuZGxlcihyZXEpO1xuICB9O1xufVxuXG4vKipcbiAqIFF1ZXVlcyBhIG1lc3NhZ2UgdG8gdGhlIHNwZWNpZmllZCBxdWV1ZSB3aXRoIHRyYWNpbmcuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBxdWV1ZU1lc3NhZ2UoXG4gIHdvcmxkOiBXb3JsZCxcbiAgLi4uYXJnczogUGFyYW1ldGVyczx0eXBlb2Ygd29ybGQucXVldWU+XG4pIHtcbiAgY29uc3QgcXVldWVOYW1lID0gYXJnc1swXTtcbiAgYXdhaXQgdHJhY2UoXG4gICAgJ3F1ZXVlLnB1Ymxpc2gnLFxuICAgIHtcbiAgICAgIC8vIFN0YW5kYXJkIE9URUwgbWVzc2FnaW5nIGNvbnZlbnRpb25zXG4gICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdTeXN0ZW0oJ3ZlcmNlbC1xdWV1ZScpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nRGVzdGluYXRpb25OYW1lKHF1ZXVlTmFtZSksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdPcGVyYXRpb25UeXBlKCdwdWJsaXNoJyksXG4gICAgICAgIC8vIFBlZXIgc2VydmljZSBmb3IgRGF0YWRvZyBzZXJ2aWNlIG1hcHNcbiAgICAgICAgLi4uQXR0cmlidXRlLlBlZXJTZXJ2aWNlKCd2ZXJjZWwtcXVldWUnKSxcbiAgICAgICAgLi4uQXR0cmlidXRlLlJwY1N5c3RlbSgndmVyY2VsLXF1ZXVlJyksXG4gICAgICAgIC4uLkF0dHJpYnV0ZS5ScGNTZXJ2aWNlKCd2cXMnKSxcbiAgICAgICAgLi4uQXR0cmlidXRlLlJwY01ldGhvZCgncHVibGlzaCcpLFxuICAgICAgfSxcbiAgICAgIGtpbmQ6IGF3YWl0IGdldFNwYW5LaW5kKCdQUk9EVUNFUicpLFxuICAgIH0sXG4gICAgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgIGNvbnN0IHsgbWVzc2FnZUlkIH0gPSBhd2FpdCB3b3JsZC5xdWV1ZSguLi5hcmdzKTtcbiAgICAgIGlmIChtZXNzYWdlSWQpIHtcbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyhBdHRyaWJ1dGUuTWVzc2FnaW5nTWVzc2FnZUlkKG1lc3NhZ2VJZCkpO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBxdWV1ZSBvdmVyaGVhZCB0aW1lIGluIG1pbGxpc2Vjb25kcyBmb3IgYSBnaXZlbiBtZXNzYWdlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UXVldWVPdmVyaGVhZChtZXNzYWdlOiB7IHJlcXVlc3RlZEF0PzogRGF0ZSB9KSB7XG4gIGlmICghbWVzc2FnZS5yZXF1ZXN0ZWRBdCkgcmV0dXJuO1xuICB0cnkge1xuICAgIHJldHVybiBBdHRyaWJ1dGUuUXVldWVPdmVyaGVhZE1zKFxuICAgICAgRGF0ZS5ub3coKSAtIG1lc3NhZ2UucmVxdWVzdGVkQXQuZ2V0VGltZSgpXG4gICAgKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIG1lbW9pemVkIGFjY2Vzc29yIGZvciB0aGUgcGVyLXJ1biBBRVMtMjU2IGVuY3J5cHRpb24ga2V5LlxuICpcbiAqIFRoZSBmaXJzdCBjYWxsIHJlc29sdmVzIHRoZSBrZXkgdmlhIGB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuYCAod2hpY2hcbiAqIG1heSBkbyBIS0RGIGRlcml2YXRpb24gbG9jYWxseSBvbiBWZXJjZWwsIG9yIGEgbmV0d29yayBmZXRjaCBmcm9tXG4gKiBleHRlcm5hbCBjb250ZXh0cykgYW5kIGltcG9ydHMgaXQgYXMgYSBgQ3J5cHRvS2V5YDsgc3Vic2VxdWVudCBjYWxsc1xuICogYXdhaXQgdGhlIHNhbWUgY2FjaGVkIHByb21pc2UuIElmIHRoZSB3b3JsZCBkb2Vzbid0IHN1cHBvcnQgZW5jcnlwdGlvblxuICogb3IgdGhlIHJ1biBoYXMgbm8ga2V5IGNvbmZpZ3VyZWQsIHRoZSBjYWNoZWQgdmFsdWUgaXMgYHVuZGVmaW5lZGAuXG4gKlxuICogVXNlZCBieSBzdGVwIC8gd29ya2Zsb3cgaGFuZGxlcnMgdG8gZGVmZXIgdGhlIChwb3RlbnRpYWxseSBleHBlbnNpdmUpXG4gKiBrZXkgZmV0Y2ggdW50aWwgdGhlIGZpcnN0IGNvZGUgcGF0aCB0aGF0IGFjdHVhbGx5IG5lZWRzIGl0IOKAlCB0eXBpY2FsbHlcbiAqIGlucHV0IGh5ZHJhdGlvbiBvbiB0aGUgc3VjY2VzcyBwYXRoLCBvciBlcnJvciBkZWh5ZHJhdGlvbiBvbiBhIGZhaWx1cmVcbiAqIHBhdGguIEJvdGggcGF0aHMgY2FuIHJhY2UtY2FsbCB0aGUgYWNjZXNzb3Igd2l0aG91dCB0cmlnZ2VyaW5nIGR1cGxpY2F0ZVxuICogZmV0Y2hlcy5cbiAqXG4gKiBFcnJvcnMgdGhyb3duIGJ5IGBnZXRFbmNyeXB0aW9uS2V5Rm9yUnVuYCBwcm9wYWdhdGUgdG8gZXZlcnkgY2FsbGVyXG4gKiAodGhlIGNhY2hlZCBwcm9taXNlIHJlamVjdHMpLiBUaGlzIGlzIGludGVudGlvbmFsOiB3aGVuIGVuY3J5cHRpb24gaXNcbiAqIGNvbmZpZ3VyZWQsIHdlIG5ldmVyIHdhbnQgdG8gc2lsZW50bHkgZmFsbCBiYWNrIHRvIHBsYWludGV4dFxuICogc2VyaWFsaXphdGlvbi4gQSBwcm9wYWdhdGVkIGVycm9yIGluIGFuIGV2ZW50LWVtaXNzaW9uIHBhdGggbGVhdmVzIHRoZVxuICogb3V0ZXIgdHJ5L2NhdGNoIHRvIGxvZyBhbmQgc3VyZmFjZSB0aGUgaXNzdWU7IHRoZSBxdWV1ZSdzIHJlZGVsaXZlcnlcbiAqIHNlbWFudGljcyB3aWxsIHJldHJ5IHRoZSBrZXkgZmV0Y2ggb24gdGhlIG5leHQgYXR0ZW1wdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lbW9pemVFbmNyeXB0aW9uS2V5KFxuICB3b3JsZDogV29ybGQsXG4gIHJ1bk9ySWQ6IFdvcmtmbG93UnVuIHwgc3RyaW5nXG4pOiAoKSA9PiBQcm9taXNlPENyeXB0b0tleSB8IHVuZGVmaW5lZD4ge1xuICBsZXQgY2FjaGVkOiBQcm9taXNlPENyeXB0b0tleSB8IHVuZGVmaW5lZD4gfCB1bmRlZmluZWQ7XG4gIHJldHVybiAoKSA9PiB7XG4gICAgaWYgKCFjYWNoZWQpIHtcbiAgICAgIGNhY2hlZCA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIFRoZSBgZ2V0RW5jcnlwdGlvbktleUZvclJ1bmAgb3ZlcmxvYWQgc2V0IHRha2VzIGVpdGhlciBhXG4gICAgICAgIC8vIGBXb3JrZmxvd1J1bmAgb3IgYSBgcnVuSWQ6IHN0cmluZ2AgKHdpdGggb3B0aW9uYWwgY29udGV4dCkuIEJyYW5jaFxuICAgICAgICAvLyBoZXJlIHNvIFR5cGVTY3JpcHQgcGlja3MgdGhlIHJpZ2h0IG92ZXJsb2FkIGZvciBlYWNoIHNoYXBlLlxuICAgICAgICBjb25zdCByYXdLZXkgPVxuICAgICAgICAgIHR5cGVvZiBydW5PcklkID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgPyBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4ocnVuT3JJZClcbiAgICAgICAgICAgIDogYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKHJ1bk9ySWQpO1xuICAgICAgICByZXR1cm4gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG4gICAgICB9KSgpO1xuICAgIH1cbiAgICByZXR1cm4gY2FjaGVkO1xuICB9O1xufVxuIl19
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-invocation accounting of the *non-step* portion of a workflow
|
|
3
|
+
* handler run: deterministic event-log replay, workflow-VM execution
|
|
4
|
+
* between step boundaries, suspension handling, queue round-trips, etc.
|
|
5
|
+
* Inline step bodies (`"use step"` functions invoked via `executeStep`)
|
|
6
|
+
* are intentionally excluded — they are bounded by the platform's
|
|
7
|
+
* function `maxDuration` and the `NO_INLINE_REPLAY_AFTER_MS` early-return
|
|
8
|
+
* guard.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const budget = new ReplayBudget();
|
|
14
|
+
* // …non-step work happens here, accumulates against the budget…
|
|
15
|
+
* budget.pause();
|
|
16
|
+
* try {
|
|
17
|
+
* await executeStep(...); // not charged
|
|
18
|
+
* } finally {
|
|
19
|
+
* budget.resume();
|
|
20
|
+
* }
|
|
21
|
+
* // back to charging
|
|
22
|
+
* if (budget.isExhausted()) { ... }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* Implementation notes:
|
|
26
|
+
*
|
|
27
|
+
* - `pause()` and `resume()` are idempotent: calling `pause()` while
|
|
28
|
+
* already paused (or `resume()` while already resumed) is a no-op.
|
|
29
|
+
* This protects against double-counting in future refactors that nest
|
|
30
|
+
* step execution or take an early-return path between a `pause()` and
|
|
31
|
+
* the matching `resume()`.
|
|
32
|
+
* - `isExhausted()` is checked at loop boundaries by the caller — the
|
|
33
|
+
* budget itself does not arm any timers. This means an in-flight
|
|
34
|
+
* pathological `runWorkflow` call (e.g. a huge event-log replay) can
|
|
35
|
+
* overshoot the budget by up to one iteration's worth of work before
|
|
36
|
+
* the next check fires. In practice the 20s headroom built into
|
|
37
|
+
* `MAX_REPLAY_TIMEOUT_MS` (and the function `maxDuration` ceiling)
|
|
38
|
+
* gives us slack; the old `setTimeout`-based approach also ultimately
|
|
39
|
+
* relied on the platform SIGTERM as the hard backstop.
|
|
40
|
+
*/
|
|
41
|
+
export declare class ReplayBudget {
|
|
42
|
+
private readonly limitMs;
|
|
43
|
+
private elapsedMs;
|
|
44
|
+
private intervalStart;
|
|
45
|
+
constructor(limitMs?: number);
|
|
46
|
+
/**
|
|
47
|
+
* The configured replay-timeout limit, in ms. Useful for log messages.
|
|
48
|
+
*/
|
|
49
|
+
get configuredLimitMs(): number;
|
|
50
|
+
/**
|
|
51
|
+
* Total non-step time accumulated so far, in ms. Includes the
|
|
52
|
+
* currently-active interval if the budget is not paused.
|
|
53
|
+
*/
|
|
54
|
+
elapsed(): number;
|
|
55
|
+
/**
|
|
56
|
+
* Stop counting elapsed time toward the budget. Idempotent — safe to
|
|
57
|
+
* call multiple times in a row; subsequent calls are no-ops until
|
|
58
|
+
* `resume()` reopens an interval.
|
|
59
|
+
*/
|
|
60
|
+
pause(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Resume counting elapsed time toward the budget. Idempotent — safe to
|
|
63
|
+
* call multiple times in a row; subsequent calls re-anchor the
|
|
64
|
+
* interval start to `now()`, which is fine because no time accrues
|
|
65
|
+
* between back-to-back `resume()` calls.
|
|
66
|
+
*/
|
|
67
|
+
resume(): void;
|
|
68
|
+
/**
|
|
69
|
+
* True if the budget has been exhausted (`elapsed() >= limitMs`).
|
|
70
|
+
* Callers should invoke `handleExhausted(...)` afterward and return
|
|
71
|
+
* from the handler.
|
|
72
|
+
*/
|
|
73
|
+
isExhausted(): boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fail the run (or retry, on early attempts) when the replay budget is
|
|
77
|
+
* exhausted. The handling depends on whether the underlying World
|
|
78
|
+
* supports `process.exit(1)` as a queue redelivery signal (see
|
|
79
|
+
* `World.processExitTriggersQueueRedelivery`):
|
|
80
|
+
*
|
|
81
|
+
* - **Managed-platform Worlds** (`world-vercel`): on attempts <=
|
|
82
|
+
* `REPLAY_TIMEOUT_MAX_RETRIES` exit the process so the platform fails
|
|
83
|
+
* the invocation and the queue redelivers; on the next attempt write
|
|
84
|
+
* `run_failed` with `RUN_ERROR_CODES.REPLAY_TIMEOUT` and exit.
|
|
85
|
+
*
|
|
86
|
+
* - **In-process Worlds** (`world-local`, dev servers): calling
|
|
87
|
+
* `process.exit()` would terminate the host (e.g. `pnpm dev`), so
|
|
88
|
+
* instead log a warning, write `run_failed` best-effort, and return.
|
|
89
|
+
* The framework completes the request normally.
|
|
90
|
+
*/
|
|
91
|
+
export declare function handleReplayBudgetExhausted(args: {
|
|
92
|
+
runId: string;
|
|
93
|
+
workflowName: string;
|
|
94
|
+
requestId: string | undefined;
|
|
95
|
+
attempt: number;
|
|
96
|
+
limitMs: number;
|
|
97
|
+
}): Promise<void>;
|
|
98
|
+
//# sourceMappingURL=replay-budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay-budget.d.ts","sourceRoot":"","sources":["../../src/runtime/replay-budget.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,aAAa,CAAgB;gBAEzB,OAAO,GAAE,MAA6B;IAKlD;;OAEG;IACH,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED;;;OAGG;IACH,OAAO,IAAI,MAAM;IAMjB;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAMb;;;;;OAKG;IACH,MAAM,IAAI,IAAI;IAId;;;;OAIG;IACH,WAAW,IAAI,OAAO;CAGvB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,2BAA2B,CAAC,IAAI,EAAE;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiHhB"}
|