@workflow/core 5.0.0-beta.13 → 5.0.0-beta.14
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/runtime/helpers.d.ts +4 -2
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +6 -7
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +18 -8
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +13 -10
- package/dist/runtime/step-executor.d.ts.map +1 -1
- package/dist/runtime/step-executor.js +22 -8
- package/dist/runtime/step-handler.d.ts.map +1 -1
- package/dist/runtime/step-handler.js +636 -630
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +9 -7
- package/dist/runtime/wait-until.d.ts +18 -0
- package/dist/runtime/wait-until.d.ts.map +1 -0
- package/dist/runtime/wait-until.js +42 -0
- package/dist/runtime.d.ts +3 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +13 -11
- package/dist/serialization.d.ts +41 -0
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +167 -3
- package/dist/util.d.ts +0 -5
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +1 -15
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/package.json +4 -4
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { waitUntil } from '@vercel/functions';
|
|
2
1
|
import { EntityConflictError, FatalError, RetryableError, RunExpiredError, StepNotRegisteredError, ThrottleError, TooEarlyError, WorkflowRuntimeError, WorkflowWorldError, } from '@workflow/errors';
|
|
3
2
|
import { formatStepName, pluralize } from '@workflow/utils';
|
|
4
3
|
import { getPort } from '@workflow/utils/get-port';
|
|
5
|
-
import { SPEC_VERSION_CURRENT, StepInvokePayloadSchema } from '@workflow/world';
|
|
4
|
+
import { getQueueTopicPrefix, resolveQueueNamespace, SPEC_VERSION_CURRENT, StepInvokePayloadSchema, } from '@workflow/world';
|
|
6
5
|
import { describeError } from '../describe-error.js';
|
|
7
6
|
import { runtimeLogger, stepLogger } from '../logger.js';
|
|
8
7
|
import { getStepFunction } from '../private.js';
|
|
@@ -13,520 +12,289 @@ import { getSpanKind, linkToCurrentContext, serializeTraceCarrier, trace, withTr
|
|
|
13
12
|
import { getErrorName, getErrorStack, normalizeUnknownError, promoteAbortErrorToFatal, } from '../types.js';
|
|
14
13
|
import { MAX_QUEUE_DELIVERIES } from './constants.js';
|
|
15
14
|
import { getQueueOverhead, getWorkflowQueueName, handleHealthCheckMessage, memoizeEncryptionKey, parseHealthCheckPayload, queueMessage, withHealthCheck, } from './helpers.js';
|
|
15
|
+
import { safeWaitUntil } from './wait-until.js';
|
|
16
16
|
import { getWorld, getWorldHandlers } from './world.js';
|
|
17
17
|
const DEFAULT_STEP_MAX_RETRIES = 3;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// --- Max delivery check ---
|
|
31
|
-
// Enforce max delivery limit before any infrastructure calls.
|
|
32
|
-
// This prevents runaway steps from consuming infinite queue deliveries.
|
|
33
|
-
// At this point, we want to do the minimal amount of work (no fetching
|
|
34
|
-
// of the step details, etc. We simply attempt to mark the step as failed
|
|
35
|
-
// and enqueue the workflow once, and if either of those fails, the message
|
|
36
|
-
// is still consumed but with adequate logging that an error occurred.
|
|
37
|
-
// Scoped logger for this step invocation — attaches run/step context to
|
|
38
|
-
// every log line below so callers don't repeat it.
|
|
39
|
-
const stepNameFromQueue = metadata.queueName.slice('__wkf_step_'.length);
|
|
40
|
-
const stepRuntimeLogger = runtimeLogger.forRun(workflowRunId, workflowName, { stepId, stepName: stepNameFromQueue });
|
|
41
|
-
if (metadata.attempt > MAX_QUEUE_DELIVERIES) {
|
|
42
|
-
stepRuntimeLogger.error(`Step handler exceeded max deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`, {
|
|
43
|
-
attempt: metadata.attempt,
|
|
44
|
-
});
|
|
45
|
-
try {
|
|
46
|
-
const world = await getWorld();
|
|
47
|
-
const getEncryptionKey = memoizeEncryptionKey(world, workflowRunId);
|
|
48
|
-
const err = new FatalError(`Step exceeded maximum queue deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`);
|
|
49
|
-
await world.events.create(workflowRunId, {
|
|
50
|
-
eventType: 'step_failed',
|
|
51
|
-
specVersion: SPEC_VERSION_CURRENT,
|
|
52
|
-
correlationId: stepId,
|
|
53
|
-
eventData: {
|
|
54
|
-
stepName: stepNameFromQueue,
|
|
55
|
-
error: await dehydrateStepError(err, workflowRunId, await getEncryptionKey()),
|
|
56
|
-
},
|
|
57
|
-
}, { requestId });
|
|
58
|
-
// Re-queue the workflow to handle the failed step
|
|
59
|
-
await queueMessage(world, getWorkflowQueueName(workflowName), {
|
|
60
|
-
runId: workflowRunId,
|
|
61
|
-
traceCarrier: await serializeTraceCarrier(),
|
|
62
|
-
requestedAt: new Date(),
|
|
63
|
-
});
|
|
18
|
+
function createStepHandler(namespace) {
|
|
19
|
+
const resolvedNamespace = resolveQueueNamespace(namespace);
|
|
20
|
+
const stepPrefix = getQueueTopicPrefix('step', resolvedNamespace);
|
|
21
|
+
return (worldHandlers) => worldHandlers.createQueueHandler(stepPrefix, async (message_, metadata) => {
|
|
22
|
+
// Check if this is a health check message
|
|
23
|
+
// NOTE: Health check messages are intentionally unauthenticated for monitoring purposes.
|
|
24
|
+
// They only write a simple status response to a stream and do not expose sensitive data.
|
|
25
|
+
// The stream name includes a unique correlationId that must be known by the caller.
|
|
26
|
+
const healthCheck = parseHealthCheckPayload(message_);
|
|
27
|
+
if (healthCheck) {
|
|
28
|
+
await handleHealthCheckMessage(healthCheck, 'step', worldHandlers.specVersion);
|
|
29
|
+
return;
|
|
64
30
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
31
|
+
const { workflowName, workflowRunId, workflowStartedAt, stepId, traceCarrier: traceContext, requestedAt, } = StepInvokePayloadSchema.parse(message_);
|
|
32
|
+
const { requestId } = metadata;
|
|
33
|
+
// --- Max delivery check ---
|
|
34
|
+
// Enforce max delivery limit before any infrastructure calls.
|
|
35
|
+
// This prevents runaway steps from consuming infinite queue deliveries.
|
|
36
|
+
// At this point, we want to do the minimal amount of work (no fetching
|
|
37
|
+
// of the step details, etc. We simply attempt to mark the step as failed
|
|
38
|
+
// and enqueue the workflow once, and if either of those fails, the message
|
|
39
|
+
// is still consumed but with adequate logging that an error occurred.
|
|
40
|
+
// Scoped logger for this step invocation — attaches run/step context to
|
|
41
|
+
// every log line below so callers don't repeat it.
|
|
42
|
+
const stepNameFromQueue = metadata.queueName.slice(stepPrefix.length);
|
|
43
|
+
const stepRuntimeLogger = runtimeLogger.forRun(workflowRunId, workflowName, { stepId, stepName: stepNameFromQueue });
|
|
44
|
+
if (metadata.attempt > MAX_QUEUE_DELIVERIES) {
|
|
45
|
+
stepRuntimeLogger.error(`Step handler exceeded max deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`, {
|
|
76
46
|
attempt: metadata.attempt,
|
|
77
|
-
errorName: err instanceof Error ? err.name : 'UnknownError',
|
|
78
|
-
errorMessage: err instanceof Error ? err.message : String(err),
|
|
79
|
-
errorStack: err instanceof Error ? err.stack : undefined,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const spanLinks = await linkToCurrentContext();
|
|
85
|
-
// Execute step within the propagated trace context
|
|
86
|
-
return await withTraceContext(traceContext, async () => {
|
|
87
|
-
// Extract the step name from the topic name
|
|
88
|
-
const stepName = metadata.queueName.slice('__wkf_step_'.length);
|
|
89
|
-
const world = await getWorld();
|
|
90
|
-
const isVercel = process.env.VERCEL_URL !== undefined;
|
|
91
|
-
// Memoized accessor for the per-run AES-256 encryption key. The first
|
|
92
|
-
// caller (typically `hydrateStepArguments` for input deserialization,
|
|
93
|
-
// or one of the early-return dehydrateStepError paths if step_started
|
|
94
|
-
// fails) triggers the actual fetch / HKDF derivation; subsequent
|
|
95
|
-
// callers await the cached promise. Steps that fail before any
|
|
96
|
-
// encryption-aware work happens (e.g. an immediate step_started
|
|
97
|
-
// conflict) skip the fetch entirely.
|
|
98
|
-
const getEncryptionKey = memoizeEncryptionKey(world, workflowRunId);
|
|
99
|
-
// Resolve local async values concurrently before entering the trace span
|
|
100
|
-
const [port, spanKind] = await Promise.all([
|
|
101
|
-
isVercel ? undefined : getPort(),
|
|
102
|
-
getSpanKind('CONSUMER'),
|
|
103
|
-
]);
|
|
104
|
-
return trace(`STEP ${stepName}`, { kind: spanKind, links: spanLinks }, async (span) => {
|
|
105
|
-
span?.setAttributes({
|
|
106
|
-
...Attribute.StepName(stepName),
|
|
107
|
-
...Attribute.StepAttempt(metadata.attempt),
|
|
108
|
-
// Standard OTEL messaging conventions
|
|
109
|
-
...Attribute.MessagingSystem('vercel-queue'),
|
|
110
|
-
...Attribute.MessagingDestinationName(metadata.queueName),
|
|
111
|
-
...Attribute.MessagingMessageId(metadata.messageId),
|
|
112
|
-
...Attribute.MessagingOperationType('process'),
|
|
113
|
-
...getQueueOverhead({ requestedAt }),
|
|
114
|
-
});
|
|
115
|
-
// Note: Step function validation happens after step_started so we can
|
|
116
|
-
// properly fail the step (not the run) if the function is not registered.
|
|
117
|
-
// This allows the workflow to handle the step failure gracefully.
|
|
118
|
-
const stepFn = getStepFunction(stepName);
|
|
119
|
-
span?.setAttributes({
|
|
120
|
-
...Attribute.WorkflowName(workflowName),
|
|
121
|
-
...Attribute.WorkflowRunId(workflowRunId),
|
|
122
|
-
...Attribute.StepId(stepId),
|
|
123
|
-
...Attribute.StepTracePropagated(!!traceContext),
|
|
124
47
|
});
|
|
125
|
-
// step_started validates state and returns the step entity, so no separate
|
|
126
|
-
// world.steps.get() call is needed. The server checks:
|
|
127
|
-
// - Step not in terminal state (returns 409)
|
|
128
|
-
// - retryAfter timestamp reached (returns 425 with Retry-After header)
|
|
129
|
-
// - Workflow still active (returns 410 if completed)
|
|
130
|
-
let step;
|
|
131
48
|
try {
|
|
132
|
-
const
|
|
133
|
-
|
|
49
|
+
const world = await getWorld();
|
|
50
|
+
const getEncryptionKey = memoizeEncryptionKey(world, workflowRunId);
|
|
51
|
+
const err = new FatalError(`Step exceeded maximum queue deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`);
|
|
52
|
+
await world.events.create(workflowRunId, {
|
|
53
|
+
eventType: 'step_failed',
|
|
134
54
|
specVersion: SPEC_VERSION_CURRENT,
|
|
135
55
|
correlationId: stepId,
|
|
136
|
-
eventData: {
|
|
56
|
+
eventData: {
|
|
57
|
+
stepName: stepNameFromQueue,
|
|
58
|
+
error: await dehydrateStepError(err, workflowRunId, await getEncryptionKey()),
|
|
59
|
+
},
|
|
137
60
|
}, { requestId });
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
61
|
+
// Re-queue the workflow to handle the failed step
|
|
62
|
+
await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
|
|
63
|
+
runId: workflowRunId,
|
|
64
|
+
traceCarrier: await serializeTraceCarrier(),
|
|
65
|
+
requestedAt: new Date(),
|
|
66
|
+
});
|
|
142
67
|
}
|
|
143
68
|
catch (err) {
|
|
144
|
-
if (
|
|
145
|
-
const retryRetryAfter = Math.max(1, typeof err.retryAfter === 'number' ? err.retryAfter : 1);
|
|
146
|
-
stepRuntimeLogger.info('Throttled again on retry, deferring to queue', {
|
|
147
|
-
retryAfterSeconds: retryRetryAfter,
|
|
148
|
-
});
|
|
149
|
-
return { timeoutSeconds: retryRetryAfter };
|
|
150
|
-
}
|
|
151
|
-
if (RunExpiredError.is(err)) {
|
|
152
|
-
// Expected when a run is cancelled while a step is in-flight.
|
|
153
|
-
stepRuntimeLogger.info('Workflow run has already completed, skipping step', { errorName: err.name, errorMessage: err.message });
|
|
69
|
+
if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
|
|
154
70
|
return;
|
|
155
71
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
});
|
|
168
|
-
span?.addEvent?.('step.skipped', {
|
|
169
|
-
'skip.reason': 'terminal_state',
|
|
170
|
-
'step.name': stepName,
|
|
171
|
-
'step.id': stepId,
|
|
172
|
-
});
|
|
173
|
-
await queueMessage(world, getWorkflowQueueName(workflowName), {
|
|
174
|
-
runId: workflowRunId,
|
|
175
|
-
traceCarrier: await serializeTraceCarrier(),
|
|
176
|
-
requestedAt: new Date(),
|
|
177
|
-
});
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
// Too early: retryAfter timestamp not reached yet
|
|
181
|
-
// Return timeout to queue so it retries later
|
|
182
|
-
if (TooEarlyError.is(err)) {
|
|
183
|
-
const timeoutSeconds = Math.max(1, err.retryAfter ?? 1);
|
|
184
|
-
span?.setAttributes({
|
|
185
|
-
...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
|
|
186
|
-
});
|
|
187
|
-
// Add span event for delayed retry
|
|
188
|
-
span?.addEvent?.('step.delayed', {
|
|
189
|
-
'delay.reason': 'retry_after_not_reached',
|
|
190
|
-
'delay.timeout_seconds': timeoutSeconds,
|
|
191
|
-
});
|
|
192
|
-
stepRuntimeLogger.debug('Step retryAfter timestamp not yet reached', {
|
|
193
|
-
retryAfterSeconds: err.retryAfter,
|
|
194
|
-
timeoutSeconds,
|
|
195
|
-
});
|
|
196
|
-
return { timeoutSeconds };
|
|
197
|
-
}
|
|
198
|
-
// Re-throw other errors
|
|
199
|
-
throw err;
|
|
200
|
-
}
|
|
201
|
-
stepRuntimeLogger.debug('Step execution details', {
|
|
202
|
-
status: step.status,
|
|
203
|
-
attempt: step.attempt,
|
|
204
|
-
});
|
|
205
|
-
span?.setAttributes({
|
|
206
|
-
...Attribute.StepStatus(step.status),
|
|
207
|
-
});
|
|
208
|
-
// Validate step function exists AFTER step_started so we can
|
|
209
|
-
// properly fail the step (not the run) if the function is missing.
|
|
210
|
-
// This allows the workflow to handle the step failure gracefully,
|
|
211
|
-
// similar to how FatalError is handled.
|
|
212
|
-
if (!stepFn || typeof stepFn !== 'function') {
|
|
213
|
-
const err = new StepNotRegisteredError(stepName);
|
|
214
|
-
stepRuntimeLogger.error('Step function not registered, failing step (not run)', {
|
|
215
|
-
errorName: err.name,
|
|
216
|
-
errorMessage: err.message,
|
|
217
|
-
errorStack: err.stack,
|
|
72
|
+
// Can't even mark the step as failed. Consume the message to stop
|
|
73
|
+
// further retries. The run will remain in its current state.
|
|
74
|
+
stepRuntimeLogger.error(`Failed to mark step as failed after ${metadata.attempt} delivery attempts. ` +
|
|
75
|
+
`A persistent error is preventing the step from being terminated. ` +
|
|
76
|
+
`The run will remain in its current state until manually resolved. ` +
|
|
77
|
+
`This is most likely due to a persistent outage of the workflow backend ` +
|
|
78
|
+
`or a bug in the workflow runtime and should be reported to the Workflow team.`, {
|
|
79
|
+
attempt: metadata.attempt,
|
|
80
|
+
errorName: err instanceof Error ? err.name : 'UnknownError',
|
|
81
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
82
|
+
errorStack: err instanceof Error ? err.stack : undefined,
|
|
218
83
|
});
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const spanLinks = await linkToCurrentContext();
|
|
88
|
+
// Execute step within the propagated trace context
|
|
89
|
+
return await withTraceContext(traceContext, async () => {
|
|
90
|
+
// Extract the step name from the topic name
|
|
91
|
+
const stepName = metadata.queueName.slice(stepPrefix.length);
|
|
92
|
+
const world = await getWorld();
|
|
93
|
+
const isVercel = process.env.VERCEL_URL !== undefined;
|
|
94
|
+
// Memoized accessor for the per-run AES-256 encryption key. The first
|
|
95
|
+
// caller (typically `hydrateStepArguments` for input deserialization,
|
|
96
|
+
// or one of the early-return dehydrateStepError paths if step_started
|
|
97
|
+
// fails) triggers the actual fetch / HKDF derivation; subsequent
|
|
98
|
+
// callers await the cached promise. Steps that fail before any
|
|
99
|
+
// encryption-aware work happens (e.g. an immediate step_started
|
|
100
|
+
// conflict) skip the fetch entirely.
|
|
101
|
+
const getEncryptionKey = memoizeEncryptionKey(world, workflowRunId);
|
|
102
|
+
// Resolve local async values concurrently before entering the trace span
|
|
103
|
+
const [port, spanKind] = await Promise.all([
|
|
104
|
+
isVercel ? undefined : getPort(),
|
|
105
|
+
getSpanKind('CONSUMER'),
|
|
106
|
+
]);
|
|
107
|
+
return trace(`STEP ${stepName}`, { kind: spanKind, links: spanLinks }, async (span) => {
|
|
244
108
|
span?.setAttributes({
|
|
245
|
-
...Attribute.
|
|
246
|
-
...Attribute.
|
|
109
|
+
...Attribute.StepName(stepName),
|
|
110
|
+
...Attribute.StepAttempt(metadata.attempt),
|
|
111
|
+
// Standard OTEL messaging conventions
|
|
112
|
+
...Attribute.MessagingSystem('vercel-queue'),
|
|
113
|
+
...Attribute.MessagingDestinationName(metadata.queueName),
|
|
114
|
+
...Attribute.MessagingMessageId(metadata.messageId),
|
|
115
|
+
...Attribute.MessagingOperationType('process'),
|
|
116
|
+
...getQueueOverhead({ requestedAt }),
|
|
247
117
|
});
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
span?.setAttributes({
|
|
258
|
-
...Attribute.StepMaxRetries(maxRetries),
|
|
259
|
-
});
|
|
260
|
-
let result;
|
|
261
|
-
// Check max retries AFTER step_started (attempt was just incremented)
|
|
262
|
-
// step.attempt tracks how many times step_started has been called.
|
|
263
|
-
// Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
|
|
264
|
-
// Use > here (not >=) because this guards against re-invocation AFTER all attempts are used.
|
|
265
|
-
// The post-failure check uses >= to decide whether to retry after a failure.
|
|
266
|
-
if (step.attempt > maxRetries + 1) {
|
|
267
|
-
const retryCount = step.attempt - 1;
|
|
268
|
-
// Persisted message — kept short, no machine `stepName`,
|
|
269
|
-
// since observability already attributes the event to a
|
|
270
|
-
// specific step.
|
|
271
|
-
const errorMessage = `Step exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`;
|
|
272
|
-
stepLogger.error(`Step ${formatStepName(stepName)} exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`, {
|
|
273
|
-
workflowRunId,
|
|
274
|
-
workflowName,
|
|
275
|
-
stepId,
|
|
276
|
-
stepName,
|
|
277
|
-
retryCount,
|
|
118
|
+
// Note: Step function validation happens after step_started so we can
|
|
119
|
+
// properly fail the step (not the run) if the function is not registered.
|
|
120
|
+
// This allows the workflow to handle the step failure gracefully.
|
|
121
|
+
const stepFn = getStepFunction(stepName);
|
|
122
|
+
span?.setAttributes({
|
|
123
|
+
...Attribute.WorkflowName(workflowName),
|
|
124
|
+
...Attribute.WorkflowRunId(workflowRunId),
|
|
125
|
+
...Attribute.StepId(stepId),
|
|
126
|
+
...Attribute.StepTracePropagated(!!traceContext),
|
|
278
127
|
});
|
|
279
|
-
//
|
|
280
|
-
//
|
|
281
|
-
//
|
|
282
|
-
//
|
|
283
|
-
//
|
|
284
|
-
|
|
285
|
-
const wrappedError = new FatalError(errorMessage);
|
|
286
|
-
if (step.error != null) {
|
|
287
|
-
try {
|
|
288
|
-
wrappedError.cause = await hydrateStepError(step.error, workflowRunId, await getEncryptionKey());
|
|
289
|
-
}
|
|
290
|
-
catch {
|
|
291
|
-
// Ignore: best-effort cause attachment, the wrapping
|
|
292
|
-
// FatalError stack/message still surface the failure.
|
|
293
|
-
}
|
|
294
|
-
}
|
|
128
|
+
// step_started validates state and returns the step entity, so no separate
|
|
129
|
+
// world.steps.get() call is needed. The server checks:
|
|
130
|
+
// - Step not in terminal state (returns 409)
|
|
131
|
+
// - retryAfter timestamp reached (returns 425 with Retry-After header)
|
|
132
|
+
// - Workflow still active (returns 410 if completed)
|
|
133
|
+
let step;
|
|
295
134
|
try {
|
|
296
|
-
await world.events.create(workflowRunId, {
|
|
297
|
-
eventType: '
|
|
135
|
+
const startResult = await world.events.create(workflowRunId, {
|
|
136
|
+
eventType: 'step_started',
|
|
298
137
|
specVersion: SPEC_VERSION_CURRENT,
|
|
299
138
|
correlationId: stepId,
|
|
300
|
-
eventData: {
|
|
301
|
-
stepName,
|
|
302
|
-
error: await dehydrateStepError(wrappedError, workflowRunId, await getEncryptionKey()),
|
|
303
|
-
},
|
|
139
|
+
eventData: { stepName },
|
|
304
140
|
}, { requestId });
|
|
141
|
+
if (!startResult.step) {
|
|
142
|
+
throw new WorkflowRuntimeError(`step_started event for "${stepId}" did not return step entity`);
|
|
143
|
+
}
|
|
144
|
+
step = startResult.step;
|
|
305
145
|
}
|
|
306
146
|
catch (err) {
|
|
147
|
+
if (ThrottleError.is(err)) {
|
|
148
|
+
const retryRetryAfter = Math.max(1, typeof err.retryAfter === 'number' ? err.retryAfter : 1);
|
|
149
|
+
stepRuntimeLogger.info('Throttled again on retry, deferring to queue', {
|
|
150
|
+
retryAfterSeconds: retryRetryAfter,
|
|
151
|
+
});
|
|
152
|
+
return { timeoutSeconds: retryRetryAfter };
|
|
153
|
+
}
|
|
154
|
+
if (RunExpiredError.is(err)) {
|
|
155
|
+
// Expected when a run is cancelled while a step is in-flight.
|
|
156
|
+
stepRuntimeLogger.info('Workflow run has already completed, skipping step', { errorName: err.name, errorMessage: err.message });
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
307
159
|
if (EntityConflictError.is(err)) {
|
|
308
|
-
// Step already
|
|
309
|
-
//
|
|
310
|
-
|
|
160
|
+
// Step already in a terminal state — another worker finished
|
|
161
|
+
// it or it was retried to completion. Re-enqueue the parent
|
|
162
|
+
// workflow so it can observe the outcome.
|
|
163
|
+
stepRuntimeLogger.debug('Step in terminal state, re-enqueuing workflow', {
|
|
311
164
|
errorName: err.name,
|
|
312
165
|
errorMessage: err.message,
|
|
313
166
|
});
|
|
167
|
+
span?.setAttributes({
|
|
168
|
+
...Attribute.StepSkipped(true),
|
|
169
|
+
...Attribute.StepSkipReason('completed'),
|
|
170
|
+
});
|
|
171
|
+
span?.addEvent?.('step.skipped', {
|
|
172
|
+
'skip.reason': 'terminal_state',
|
|
173
|
+
'step.name': stepName,
|
|
174
|
+
'step.id': stepId,
|
|
175
|
+
});
|
|
176
|
+
await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
|
|
177
|
+
runId: workflowRunId,
|
|
178
|
+
traceCarrier: await serializeTraceCarrier(),
|
|
179
|
+
requestedAt: new Date(),
|
|
180
|
+
});
|
|
314
181
|
return;
|
|
315
182
|
}
|
|
183
|
+
// Too early: retryAfter timestamp not reached yet
|
|
184
|
+
// Return timeout to queue so it retries later
|
|
185
|
+
if (TooEarlyError.is(err)) {
|
|
186
|
+
const timeoutSeconds = Math.max(1, err.retryAfter ?? 1);
|
|
187
|
+
span?.setAttributes({
|
|
188
|
+
...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
|
|
189
|
+
});
|
|
190
|
+
// Add span event for delayed retry
|
|
191
|
+
span?.addEvent?.('step.delayed', {
|
|
192
|
+
'delay.reason': 'retry_after_not_reached',
|
|
193
|
+
'delay.timeout_seconds': timeoutSeconds,
|
|
194
|
+
});
|
|
195
|
+
stepRuntimeLogger.debug('Step retryAfter timestamp not yet reached', {
|
|
196
|
+
retryAfterSeconds: err.retryAfter,
|
|
197
|
+
timeoutSeconds,
|
|
198
|
+
});
|
|
199
|
+
return { timeoutSeconds };
|
|
200
|
+
}
|
|
201
|
+
// Re-throw other errors
|
|
316
202
|
throw err;
|
|
317
203
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
});
|
|
322
|
-
// Re-invoke the workflow to handle the failed step
|
|
323
|
-
await queueMessage(world, getWorkflowQueueName(workflowName), {
|
|
324
|
-
runId: workflowRunId,
|
|
325
|
-
traceCarrier: await serializeTraceCarrier(),
|
|
326
|
-
requestedAt: new Date(),
|
|
204
|
+
stepRuntimeLogger.debug('Step execution details', {
|
|
205
|
+
status: step.status,
|
|
206
|
+
attempt: step.attempt,
|
|
327
207
|
});
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
// --- Infrastructure: prepare step input ---
|
|
331
|
-
// Network/server errors propagate to the queue handler for retry.
|
|
332
|
-
// WorkflowRuntimeError (data integrity issues) are fatal — retrying
|
|
333
|
-
// won't fix them, so we re-queue the workflow to surface the error.
|
|
334
|
-
// step_started already validated the step is in valid state (pending/running)
|
|
335
|
-
// and returned the updated step entity with incremented attempt
|
|
336
|
-
// step.attempt is now the current attempt number (after increment)
|
|
337
|
-
const attempt = step.attempt;
|
|
338
|
-
if (!step.startedAt) {
|
|
339
|
-
const errorMessage = `Step "${stepId}" has no "startedAt" timestamp`;
|
|
340
|
-
stepRuntimeLogger.error('Fatal runtime error during step setup', {
|
|
341
|
-
errorMessage,
|
|
208
|
+
span?.setAttributes({
|
|
209
|
+
...Attribute.StepStatus(step.status),
|
|
342
210
|
});
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
211
|
+
// Validate step function exists AFTER step_started so we can
|
|
212
|
+
// properly fail the step (not the run) if the function is missing.
|
|
213
|
+
// This allows the workflow to handle the step failure gracefully,
|
|
214
|
+
// similar to how FatalError is handled.
|
|
215
|
+
if (!stepFn || typeof stepFn !== 'function') {
|
|
216
|
+
const err = new StepNotRegisteredError(stepName);
|
|
217
|
+
stepRuntimeLogger.error('Step function not registered, failing step (not run)', {
|
|
218
|
+
errorName: err.name,
|
|
219
|
+
errorMessage: err.message,
|
|
220
|
+
errorStack: err.stack,
|
|
221
|
+
});
|
|
222
|
+
// Fail the step via event (event-sourced architecture)
|
|
223
|
+
// This matches the FatalError pattern - fail the step and re-queue workflow
|
|
224
|
+
try {
|
|
225
|
+
await world.events.create(workflowRunId, {
|
|
226
|
+
eventType: 'step_failed',
|
|
227
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
228
|
+
correlationId: stepId,
|
|
229
|
+
eventData: {
|
|
230
|
+
stepName,
|
|
231
|
+
error: await dehydrateStepError(err, workflowRunId, await getEncryptionKey()),
|
|
232
|
+
},
|
|
233
|
+
}, { requestId });
|
|
357
234
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
// value. Triggers the underlying world / KMS fetch once, with
|
|
374
|
-
// subsequent dehydrate paths reusing the memoized result.
|
|
375
|
-
const encryptionKey = await getEncryptionKey();
|
|
376
|
-
// Hydrate the step input arguments, closure variables, and thisVal
|
|
377
|
-
// NOTE: This captures only the synchronous portion of hydration. Any async
|
|
378
|
-
// operations (e.g., stream loading) are added to `ops` and executed later
|
|
379
|
-
// via Promise.all(ops) - their timing is not included in this measurement.
|
|
380
|
-
const ops = [];
|
|
381
|
-
const hydratedInput = await trace('step.hydrate', {}, async (hydrateSpan) => {
|
|
382
|
-
const startTime = Date.now();
|
|
383
|
-
const result = await hydrateStepArguments(step.input, workflowRunId, encryptionKey, ops, globalThis, {}, process.env.VERCEL_DEPLOYMENT_ID);
|
|
384
|
-
const durationMs = Date.now() - startTime;
|
|
385
|
-
hydrateSpan?.setAttributes({
|
|
386
|
-
...Attribute.StepArgumentsCount(result.args.length),
|
|
387
|
-
...Attribute.QueueDeserializeTimeMs(durationMs),
|
|
388
|
-
});
|
|
389
|
-
return result;
|
|
390
|
-
});
|
|
391
|
-
const args = hydratedInput.args;
|
|
392
|
-
const thisVal = hydratedInput.thisVal ?? null;
|
|
393
|
-
// --- User code execution ---
|
|
394
|
-
// Only errors from stepFn.apply() (user step code) should produce
|
|
395
|
-
// step_failed/step_retrying. Infrastructure errors (network, server)
|
|
396
|
-
// must propagate to the queue handler for automatic retry.
|
|
397
|
-
let userCodeError;
|
|
398
|
-
let userCodeFailed = false;
|
|
399
|
-
const executionStartTime = Date.now();
|
|
400
|
-
try {
|
|
401
|
-
result = await trace('step.execute', {}, async () => {
|
|
402
|
-
return await contextStorage.run({
|
|
403
|
-
stepMetadata: {
|
|
404
|
-
stepName,
|
|
405
|
-
stepId,
|
|
406
|
-
stepStartedAt: new Date(+stepStartedAt),
|
|
407
|
-
attempt,
|
|
408
|
-
},
|
|
409
|
-
workflowMetadata: {
|
|
410
|
-
workflowName,
|
|
411
|
-
workflowRunId,
|
|
412
|
-
workflowStartedAt: new Date(+workflowStartedAt),
|
|
413
|
-
// TODO: there should be a getUrl method on the world interface itself. This
|
|
414
|
-
// solution only works for vercel + local worlds.
|
|
415
|
-
url: isVercel
|
|
416
|
-
? `https://${process.env.VERCEL_URL}`
|
|
417
|
-
: `http://localhost:${port ?? 3000}`,
|
|
418
|
-
features: { encryption: !!encryptionKey },
|
|
419
|
-
},
|
|
420
|
-
workflowDeploymentId: process.env.VERCEL_DEPLOYMENT_ID,
|
|
421
|
-
ops,
|
|
422
|
-
closureVars: hydratedInput.closureVars,
|
|
423
|
-
encryptionKey,
|
|
424
|
-
}, () => stepFn.apply(thisVal, args));
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
catch (err) {
|
|
428
|
-
userCodeError = err;
|
|
429
|
-
userCodeFailed = true;
|
|
430
|
-
}
|
|
431
|
-
const executionTimeMs = Date.now() - executionStartTime;
|
|
432
|
-
cancelAbortReaders(...args, thisVal, hydratedInput.closureVars);
|
|
433
|
-
span?.setAttributes({
|
|
434
|
-
...Attribute.QueueExecutionTimeMs(executionTimeMs),
|
|
435
|
-
});
|
|
436
|
-
// --- Dehydrate (serialize) the step's return value ---
|
|
437
|
-
// A non-serializable return value is a user-code bug, not an
|
|
438
|
-
// infrastructure failure. Route it through the same step-failure
|
|
439
|
-
// path as a thrown error so SerializationError (which is marked
|
|
440
|
-
// `fatal: true`) short-circuits the retry loop instead of
|
|
441
|
-
// bubbling as an HTTP 500 and burning through all 4 queue
|
|
442
|
-
// deliveries on a guaranteed-to-fail message.
|
|
443
|
-
if (!userCodeFailed) {
|
|
444
|
-
try {
|
|
445
|
-
result = await trace('step.dehydrate', {}, async (dehydrateSpan) => {
|
|
446
|
-
const startTime = Date.now();
|
|
447
|
-
const dehydrated = await dehydrateStepReturnValue(result, workflowRunId, encryptionKey, ops);
|
|
448
|
-
const durationMs = Date.now() - startTime;
|
|
449
|
-
dehydrateSpan?.setAttributes({
|
|
450
|
-
...Attribute.QueueSerializeTimeMs(durationMs),
|
|
451
|
-
...Attribute.StepResultType(typeof dehydrated),
|
|
452
|
-
});
|
|
453
|
-
return dehydrated;
|
|
235
|
+
catch (stepFailErr) {
|
|
236
|
+
if (EntityConflictError.is(stepFailErr)) {
|
|
237
|
+
// Step already transitioned to a terminal state — duplicate
|
|
238
|
+
// delivery or concurrent cancellation. Drop silently.
|
|
239
|
+
stepRuntimeLogger.info('Tried failing step for missing function, but step has already finished.', {
|
|
240
|
+
errorName: stepFailErr.name,
|
|
241
|
+
errorMessage: stepFailErr.message,
|
|
242
|
+
});
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
throw stepFailErr;
|
|
246
|
+
}
|
|
247
|
+
span?.setAttributes({
|
|
248
|
+
...Attribute.StepStatus('failed'),
|
|
249
|
+
...Attribute.StepFatalError(true),
|
|
454
250
|
});
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
461
|
-
// --- Handle user code errors ---
|
|
462
|
-
if (userCodeFailed) {
|
|
463
|
-
const err = userCodeError;
|
|
464
|
-
// Infrastructure errors that somehow surfaced through user code
|
|
465
|
-
// should propagate to the queue handler for retry, not consume
|
|
466
|
-
// step attempts.
|
|
467
|
-
if (RunExpiredError.is(err)) {
|
|
468
|
-
// Workflow has already completed, so no-op
|
|
469
|
-
stepLogger.info('Workflow run already completed, skipping step', {
|
|
470
|
-
workflowRunId,
|
|
471
|
-
stepId,
|
|
472
|
-
message: err.message,
|
|
251
|
+
// Re-invoke the workflow to handle the failed step
|
|
252
|
+
await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
|
|
253
|
+
runId: workflowRunId,
|
|
254
|
+
traceCarrier: await serializeTraceCarrier(),
|
|
255
|
+
requestedAt: new Date(),
|
|
473
256
|
});
|
|
474
257
|
return;
|
|
475
258
|
}
|
|
476
|
-
|
|
477
|
-
if (err.status !== undefined && err.status >= 500) {
|
|
478
|
-
throw err;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
// Abort failures can cross VM/serialization realms, where
|
|
482
|
-
// `instanceof Error` is not reliable.
|
|
483
|
-
const effectiveErr = promoteAbortErrorToFatal(err);
|
|
484
|
-
const normalizedError = await normalizeUnknownError(effectiveErr);
|
|
485
|
-
const normalizedStack = normalizedError.stack || getErrorStack(effectiveErr) || '';
|
|
486
|
-
// Record exception for OTEL error tracking
|
|
487
|
-
if (effectiveErr instanceof Error) {
|
|
488
|
-
span?.recordException?.(effectiveErr);
|
|
489
|
-
}
|
|
490
|
-
// Determine error category and retryability
|
|
491
|
-
const isFatal = FatalError.is(effectiveErr);
|
|
492
|
-
const isRetryable = RetryableError.is(effectiveErr);
|
|
493
|
-
const errorCategory = isFatal
|
|
494
|
-
? 'fatal'
|
|
495
|
-
: isRetryable
|
|
496
|
-
? 'retryable'
|
|
497
|
-
: 'transient';
|
|
259
|
+
const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
|
|
498
260
|
span?.setAttributes({
|
|
499
|
-
...Attribute.
|
|
500
|
-
...Attribute.StepErrorMessage(normalizedError.message),
|
|
501
|
-
...Attribute.ErrorType(getErrorName(effectiveErr)),
|
|
502
|
-
...Attribute.ErrorCategory(errorCategory),
|
|
503
|
-
...Attribute.ErrorRetryable(!isFatal),
|
|
261
|
+
...Attribute.StepMaxRetries(maxRetries),
|
|
504
262
|
});
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
//
|
|
514
|
-
//
|
|
515
|
-
//
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
// again here just duplicates it on stderr.
|
|
519
|
-
stepLogger.error(`${framing}\n${normalizedStack || normalizedError.message}`, {
|
|
263
|
+
let result;
|
|
264
|
+
// Check max retries AFTER step_started (attempt was just incremented)
|
|
265
|
+
// step.attempt tracks how many times step_started has been called.
|
|
266
|
+
// Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
|
|
267
|
+
// Use > here (not >=) because this guards against re-invocation AFTER all attempts are used.
|
|
268
|
+
// The post-failure check uses >= to decide whether to retry after a failure.
|
|
269
|
+
if (step.attempt > maxRetries + 1) {
|
|
270
|
+
const retryCount = step.attempt - 1;
|
|
271
|
+
// Persisted message — kept short, no machine `stepName`,
|
|
272
|
+
// since observability already attributes the event to a
|
|
273
|
+
// specific step.
|
|
274
|
+
const errorMessage = `Step exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`;
|
|
275
|
+
stepLogger.error(`Step ${formatStepName(stepName)} exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`, {
|
|
520
276
|
workflowRunId,
|
|
277
|
+
workflowName,
|
|
521
278
|
stepId,
|
|
522
279
|
stepName,
|
|
523
|
-
|
|
524
|
-
errorName: normalizedError.name,
|
|
525
|
-
errorMessage: normalizedError.message,
|
|
280
|
+
retryCount,
|
|
526
281
|
});
|
|
527
282
|
// Fail the step via event (event-sourced architecture).
|
|
528
|
-
//
|
|
529
|
-
//
|
|
283
|
+
// Preserve the prior attempt's serialized error as the cause so
|
|
284
|
+
// the underlying failure is recoverable from `step.error.cause`
|
|
285
|
+
// after hydration, without forcing consumers to walk the
|
|
286
|
+
// step_retrying event history. Mirrors the post-failure path
|
|
287
|
+
// below that wraps the live `err` as cause.
|
|
288
|
+
const wrappedError = new FatalError(errorMessage);
|
|
289
|
+
if (step.error != null) {
|
|
290
|
+
try {
|
|
291
|
+
wrappedError.cause = await hydrateStepError(step.error, workflowRunId, await getEncryptionKey());
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// Ignore: best-effort cause attachment, the wrapping
|
|
295
|
+
// FatalError stack/message still surface the failure.
|
|
296
|
+
}
|
|
297
|
+
}
|
|
530
298
|
try {
|
|
531
299
|
await world.events.create(workflowRunId, {
|
|
532
300
|
eventType: 'step_failed',
|
|
@@ -534,68 +302,234 @@ const stepHandler = (worldHandlers) => worldHandlers.createQueueHandler('__wkf_s
|
|
|
534
302
|
correlationId: stepId,
|
|
535
303
|
eventData: {
|
|
536
304
|
stepName,
|
|
537
|
-
error: await dehydrateStepError(
|
|
305
|
+
error: await dehydrateStepError(wrappedError, workflowRunId, await getEncryptionKey()),
|
|
538
306
|
},
|
|
539
307
|
}, { requestId });
|
|
540
308
|
}
|
|
541
|
-
catch (
|
|
542
|
-
if (EntityConflictError.is(
|
|
543
|
-
// Step already
|
|
309
|
+
catch (err) {
|
|
310
|
+
if (EntityConflictError.is(err)) {
|
|
311
|
+
// Step already transitioned to a terminal state — duplicate
|
|
312
|
+
// delivery or concurrent completion. Drop silently.
|
|
544
313
|
stepRuntimeLogger.info('Tried failing step, but step has already finished.', {
|
|
545
|
-
errorName:
|
|
546
|
-
errorMessage:
|
|
314
|
+
errorName: err.name,
|
|
315
|
+
errorMessage: err.message,
|
|
547
316
|
});
|
|
548
317
|
return;
|
|
549
318
|
}
|
|
550
|
-
throw
|
|
319
|
+
throw err;
|
|
551
320
|
}
|
|
552
321
|
span?.setAttributes({
|
|
553
322
|
...Attribute.StepStatus('failed'),
|
|
554
|
-
...Attribute.
|
|
323
|
+
...Attribute.StepRetryExhausted(true),
|
|
324
|
+
});
|
|
325
|
+
// Re-invoke the workflow to handle the failed step
|
|
326
|
+
await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
|
|
327
|
+
runId: workflowRunId,
|
|
328
|
+
traceCarrier: await serializeTraceCarrier(),
|
|
329
|
+
requestedAt: new Date(),
|
|
330
|
+
});
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
// --- Infrastructure: prepare step input ---
|
|
334
|
+
// Network/server errors propagate to the queue handler for retry.
|
|
335
|
+
// WorkflowRuntimeError (data integrity issues) are fatal — retrying
|
|
336
|
+
// won't fix them, so we re-queue the workflow to surface the error.
|
|
337
|
+
// step_started already validated the step is in valid state (pending/running)
|
|
338
|
+
// and returned the updated step entity with incremented attempt
|
|
339
|
+
// step.attempt is now the current attempt number (after increment)
|
|
340
|
+
const attempt = step.attempt;
|
|
341
|
+
if (!step.startedAt) {
|
|
342
|
+
const errorMessage = `Step "${stepId}" has no "startedAt" timestamp`;
|
|
343
|
+
stepRuntimeLogger.error('Fatal runtime error during step setup', {
|
|
344
|
+
errorMessage,
|
|
345
|
+
});
|
|
346
|
+
try {
|
|
347
|
+
await world.events.create(workflowRunId, {
|
|
348
|
+
eventType: 'step_failed',
|
|
349
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
350
|
+
correlationId: stepId,
|
|
351
|
+
eventData: {
|
|
352
|
+
stepName,
|
|
353
|
+
error: await dehydrateStepError(new FatalError(errorMessage), workflowRunId, await getEncryptionKey()),
|
|
354
|
+
},
|
|
355
|
+
}, { requestId });
|
|
356
|
+
}
|
|
357
|
+
catch (failErr) {
|
|
358
|
+
if (EntityConflictError.is(failErr)) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
throw failErr;
|
|
362
|
+
}
|
|
363
|
+
// Re-queue the workflow so it can process the step failure
|
|
364
|
+
await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
|
|
365
|
+
runId: workflowRunId,
|
|
366
|
+
traceCarrier: await serializeTraceCarrier(),
|
|
367
|
+
requestedAt: new Date(),
|
|
368
|
+
});
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
// Capture startedAt for use in async callback (TypeScript narrowing doesn't persist)
|
|
372
|
+
const stepStartedAt = step.startedAt;
|
|
373
|
+
// Resolve the encryption key now that we're committed to running
|
|
374
|
+
// user code: input hydration needs it, and `contextStorage` (and
|
|
375
|
+
// any user-code paths that run inside it) capture the resolved
|
|
376
|
+
// value. Triggers the underlying world / KMS fetch once, with
|
|
377
|
+
// subsequent dehydrate paths reusing the memoized result.
|
|
378
|
+
const encryptionKey = await getEncryptionKey();
|
|
379
|
+
// Hydrate the step input arguments, closure variables, and thisVal
|
|
380
|
+
// NOTE: This captures only the synchronous portion of hydration. Any async
|
|
381
|
+
// operations (e.g., stream loading) are added to `ops` and executed later
|
|
382
|
+
// via Promise.all(ops) - their timing is not included in this measurement.
|
|
383
|
+
const ops = [];
|
|
384
|
+
const hydratedInput = await trace('step.hydrate', {}, async (hydrateSpan) => {
|
|
385
|
+
const startTime = Date.now();
|
|
386
|
+
const result = await hydrateStepArguments(step.input, workflowRunId, encryptionKey, ops, globalThis, {}, process.env.VERCEL_DEPLOYMENT_ID);
|
|
387
|
+
const durationMs = Date.now() - startTime;
|
|
388
|
+
hydrateSpan?.setAttributes({
|
|
389
|
+
...Attribute.StepArgumentsCount(result.args.length),
|
|
390
|
+
...Attribute.QueueDeserializeTimeMs(durationMs),
|
|
391
|
+
});
|
|
392
|
+
return result;
|
|
393
|
+
});
|
|
394
|
+
const args = hydratedInput.args;
|
|
395
|
+
const thisVal = hydratedInput.thisVal ?? null;
|
|
396
|
+
// --- User code execution ---
|
|
397
|
+
// Only errors from stepFn.apply() (user step code) should produce
|
|
398
|
+
// step_failed/step_retrying. Infrastructure errors (network, server)
|
|
399
|
+
// must propagate to the queue handler for automatic retry.
|
|
400
|
+
let userCodeError;
|
|
401
|
+
let userCodeFailed = false;
|
|
402
|
+
const executionStartTime = Date.now();
|
|
403
|
+
try {
|
|
404
|
+
result = await trace('step.execute', {}, async () => {
|
|
405
|
+
return await contextStorage.run({
|
|
406
|
+
stepMetadata: {
|
|
407
|
+
stepName,
|
|
408
|
+
stepId,
|
|
409
|
+
stepStartedAt: new Date(+stepStartedAt),
|
|
410
|
+
attempt,
|
|
411
|
+
},
|
|
412
|
+
workflowMetadata: {
|
|
413
|
+
workflowName,
|
|
414
|
+
workflowRunId,
|
|
415
|
+
workflowStartedAt: new Date(+workflowStartedAt),
|
|
416
|
+
// TODO: there should be a getUrl method on the world interface itself. This
|
|
417
|
+
// solution only works for vercel + local worlds.
|
|
418
|
+
url: isVercel
|
|
419
|
+
? `https://${process.env.VERCEL_URL}`
|
|
420
|
+
: `http://localhost:${port ?? 3000}`,
|
|
421
|
+
features: { encryption: !!encryptionKey },
|
|
422
|
+
},
|
|
423
|
+
workflowDeploymentId: process.env.VERCEL_DEPLOYMENT_ID,
|
|
424
|
+
ops,
|
|
425
|
+
closureVars: hydratedInput.closureVars,
|
|
426
|
+
encryptionKey,
|
|
427
|
+
}, () => stepFn.apply(thisVal, args));
|
|
555
428
|
});
|
|
556
429
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
430
|
+
catch (err) {
|
|
431
|
+
userCodeError = err;
|
|
432
|
+
userCodeFailed = true;
|
|
433
|
+
}
|
|
434
|
+
const executionTimeMs = Date.now() - executionStartTime;
|
|
435
|
+
cancelAbortReaders(...args, thisVal, hydratedInput.closureVars);
|
|
436
|
+
span?.setAttributes({
|
|
437
|
+
...Attribute.QueueExecutionTimeMs(executionTimeMs),
|
|
438
|
+
});
|
|
439
|
+
// --- Dehydrate (serialize) the step's return value ---
|
|
440
|
+
// A non-serializable return value is a user-code bug, not an
|
|
441
|
+
// infrastructure failure. Route it through the same step-failure
|
|
442
|
+
// path as a thrown error so SerializationError (which is marked
|
|
443
|
+
// `fatal: true`) short-circuits the retry loop instead of
|
|
444
|
+
// bubbling as an HTTP 500 and burning through all 4 queue
|
|
445
|
+
// deliveries on a guaranteed-to-fail message.
|
|
446
|
+
if (!userCodeFailed) {
|
|
447
|
+
try {
|
|
448
|
+
result = await trace('step.dehydrate', {}, async (dehydrateSpan) => {
|
|
449
|
+
const startTime = Date.now();
|
|
450
|
+
const dehydrated = await dehydrateStepReturnValue(result, workflowRunId, encryptionKey, ops);
|
|
451
|
+
const durationMs = Date.now() - startTime;
|
|
452
|
+
dehydrateSpan?.setAttributes({
|
|
453
|
+
...Attribute.QueueSerializeTimeMs(durationMs),
|
|
454
|
+
...Attribute.StepResultType(typeof dehydrated),
|
|
455
|
+
});
|
|
456
|
+
return dehydrated;
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
catch (err) {
|
|
460
|
+
userCodeError = err;
|
|
461
|
+
userCodeFailed = true;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
// --- Handle user code errors ---
|
|
465
|
+
if (userCodeFailed) {
|
|
466
|
+
const err = userCodeError;
|
|
467
|
+
// Infrastructure errors that somehow surfaced through user code
|
|
468
|
+
// should propagate to the queue handler for retry, not consume
|
|
469
|
+
// step attempts.
|
|
470
|
+
if (RunExpiredError.is(err)) {
|
|
471
|
+
// Workflow has already completed, so no-op
|
|
472
|
+
stepLogger.info('Workflow run already completed, skipping step', {
|
|
473
|
+
workflowRunId,
|
|
474
|
+
stepId,
|
|
475
|
+
message: err.message,
|
|
476
|
+
});
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
if (WorkflowWorldError.is(err)) {
|
|
480
|
+
if (err.status !== undefined && err.status >= 500) {
|
|
481
|
+
throw err;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
// Abort failures can cross VM/serialization realms, where
|
|
485
|
+
// `instanceof Error` is not reliable.
|
|
486
|
+
const effectiveErr = promoteAbortErrorToFatal(err);
|
|
487
|
+
const normalizedError = await normalizeUnknownError(effectiveErr);
|
|
488
|
+
const normalizedStack = normalizedError.stack || getErrorStack(effectiveErr) || '';
|
|
489
|
+
// Record exception for OTEL error tracking
|
|
490
|
+
if (effectiveErr instanceof Error) {
|
|
491
|
+
span?.recordException?.(effectiveErr);
|
|
492
|
+
}
|
|
493
|
+
// Determine error category and retryability
|
|
494
|
+
const isFatal = FatalError.is(effectiveErr);
|
|
495
|
+
const isRetryable = RetryableError.is(effectiveErr);
|
|
496
|
+
const errorCategory = isFatal
|
|
497
|
+
? 'fatal'
|
|
498
|
+
: isRetryable
|
|
499
|
+
? 'retryable'
|
|
500
|
+
: 'transient';
|
|
561
501
|
span?.setAttributes({
|
|
562
|
-
...Attribute.
|
|
563
|
-
...Attribute.
|
|
502
|
+
...Attribute.StepErrorName(getErrorName(effectiveErr)),
|
|
503
|
+
...Attribute.StepErrorMessage(normalizedError.message),
|
|
504
|
+
...Attribute.ErrorType(getErrorName(effectiveErr)),
|
|
505
|
+
...Attribute.ErrorCategory(errorCategory),
|
|
506
|
+
...Attribute.ErrorRetryable(!isFatal),
|
|
564
507
|
});
|
|
565
|
-
|
|
566
|
-
if (currentAttempt >= maxRetries + 1) {
|
|
567
|
-
// Max retries reached
|
|
568
|
-
const retryCount = step.attempt - 1;
|
|
508
|
+
if (isFatal) {
|
|
569
509
|
const description = describeError(err);
|
|
570
510
|
const friendlyStep = formatStepName(stepName);
|
|
571
511
|
const framing = description.attribution === 'sdk'
|
|
572
|
-
? `Step ${friendlyStep}
|
|
573
|
-
: `Step ${friendlyStep}
|
|
512
|
+
? `Step ${friendlyStep} failed with a FatalError from the SDK runtime — bubbling up to parent workflow`
|
|
513
|
+
: `Step ${friendlyStep} threw a FatalError — bubbling up to parent workflow`;
|
|
514
|
+
// Mirror the workflow-level log formatting: put the framing +
|
|
515
|
+
// stack into the message so console.error renders the stack
|
|
516
|
+
// inline, and keep the metadata object small with only the
|
|
517
|
+
// structured fields that log drains want to index.
|
|
518
|
+
// No `hint` field here — actionable hint text lives on the
|
|
519
|
+
// error message itself (so it survives serialization →
|
|
520
|
+
// event log → observability rehydrate), and adding it
|
|
521
|
+
// again here just duplicates it on stderr.
|
|
574
522
|
stepLogger.error(`${framing}\n${normalizedStack || normalizedError.message}`, {
|
|
575
523
|
workflowRunId,
|
|
576
|
-
workflowName,
|
|
577
524
|
stepId,
|
|
578
525
|
stepName,
|
|
579
|
-
attempt: step.attempt,
|
|
580
|
-
retryCount,
|
|
581
526
|
errorAttribution: description.attribution,
|
|
582
527
|
errorName: normalizedError.name,
|
|
583
528
|
errorMessage: normalizedError.message,
|
|
584
529
|
});
|
|
585
|
-
// Don't include the machine step name in the persisted
|
|
586
|
-
// error message — observability already shows which step
|
|
587
|
-
// produced the event, and `stepName: 'step//./.../foo'`
|
|
588
|
-
// in the title is just noise. The CLI logger renders
|
|
589
|
-
// `Step foo (./...) hit max retries` separately.
|
|
590
|
-
const errorMessage = `Step failed after ${maxRetries} ${pluralize('retry', 'retries', maxRetries)}: ${normalizedError.message}`;
|
|
591
530
|
// Fail the step via event (event-sourced architecture).
|
|
592
|
-
//
|
|
593
|
-
//
|
|
594
|
-
// `cause` so it's recoverable after hydration.
|
|
595
|
-
const wrappedError = new FatalError(errorMessage);
|
|
596
|
-
wrappedError.cause = err;
|
|
597
|
-
if (normalizedStack)
|
|
598
|
-
wrappedError.stack = normalizedStack;
|
|
531
|
+
// Persist the promoted FatalError for aborts so the parent
|
|
532
|
+
// workflow can distinguish cancellation from retry exhaustion.
|
|
599
533
|
try {
|
|
600
534
|
await world.events.create(workflowRunId, {
|
|
601
535
|
eventType: 'step_failed',
|
|
@@ -603,7 +537,7 @@ const stepHandler = (worldHandlers) => worldHandlers.createQueueHandler('__wkf_s
|
|
|
603
537
|
correlationId: stepId,
|
|
604
538
|
eventData: {
|
|
605
539
|
stepName,
|
|
606
|
-
error: await dehydrateStepError(
|
|
540
|
+
error: await dehydrateStepError(effectiveErr, workflowRunId, encryptionKey),
|
|
607
541
|
},
|
|
608
542
|
}, { requestId });
|
|
609
543
|
}
|
|
@@ -620,150 +554,222 @@ const stepHandler = (worldHandlers) => worldHandlers.createQueueHandler('__wkf_s
|
|
|
620
554
|
}
|
|
621
555
|
span?.setAttributes({
|
|
622
556
|
...Attribute.StepStatus('failed'),
|
|
623
|
-
...Attribute.
|
|
557
|
+
...Attribute.StepFatalError(true),
|
|
624
558
|
});
|
|
625
559
|
}
|
|
626
560
|
else {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
561
|
+
const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
|
|
562
|
+
// step.attempt was incremented by step_started, use it here
|
|
563
|
+
const currentAttempt = step.attempt;
|
|
564
|
+
span?.setAttributes({
|
|
565
|
+
...Attribute.StepAttempt(currentAttempt),
|
|
566
|
+
...Attribute.StepMaxRetries(maxRetries),
|
|
567
|
+
});
|
|
568
|
+
// Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
|
|
569
|
+
if (currentAttempt >= maxRetries + 1) {
|
|
570
|
+
// Max retries reached
|
|
571
|
+
const retryCount = step.attempt - 1;
|
|
572
|
+
const description = describeError(err);
|
|
573
|
+
const friendlyStep = formatStepName(stepName);
|
|
574
|
+
const framing = description.attribution === 'sdk'
|
|
575
|
+
? `Step ${friendlyStep} hit max retries on an SDK runtime error — bubbling to parent workflow`
|
|
576
|
+
: `Step ${friendlyStep} hit max retries — bubbling error thrown by your step to the parent workflow`;
|
|
577
|
+
stepLogger.error(`${framing}\n${normalizedStack || normalizedError.message}`, {
|
|
642
578
|
workflowRunId,
|
|
643
579
|
workflowName,
|
|
644
580
|
stepId,
|
|
645
581
|
stepName,
|
|
646
|
-
attempt:
|
|
582
|
+
attempt: step.attempt,
|
|
583
|
+
retryCount,
|
|
584
|
+
errorAttribution: description.attribution,
|
|
647
585
|
errorName: normalizedError.name,
|
|
648
586
|
errorMessage: normalizedError.message,
|
|
649
|
-
|
|
587
|
+
});
|
|
588
|
+
// Don't include the machine step name in the persisted
|
|
589
|
+
// error message — observability already shows which step
|
|
590
|
+
// produced the event, and `stepName: 'step//./.../foo'`
|
|
591
|
+
// in the title is just noise. The CLI logger renders
|
|
592
|
+
// `Step foo (./...) hit max retries` separately.
|
|
593
|
+
const errorMessage = `Step failed after ${maxRetries} ${pluralize('retry', 'retries', maxRetries)}: ${normalizedError.message}`;
|
|
594
|
+
// Fail the step via event (event-sourced architecture).
|
|
595
|
+
// Wrap the original error with a FatalError that preserves
|
|
596
|
+
// the wrapped message plus the original thrown value as
|
|
597
|
+
// `cause` so it's recoverable after hydration.
|
|
598
|
+
const wrappedError = new FatalError(errorMessage);
|
|
599
|
+
wrappedError.cause = err;
|
|
600
|
+
if (normalizedStack)
|
|
601
|
+
wrappedError.stack = normalizedStack;
|
|
602
|
+
try {
|
|
603
|
+
await world.events.create(workflowRunId, {
|
|
604
|
+
eventType: 'step_failed',
|
|
605
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
606
|
+
correlationId: stepId,
|
|
607
|
+
eventData: {
|
|
608
|
+
stepName,
|
|
609
|
+
error: await dehydrateStepError(wrappedError, workflowRunId, encryptionKey),
|
|
610
|
+
},
|
|
611
|
+
}, { requestId });
|
|
612
|
+
}
|
|
613
|
+
catch (stepFailErr) {
|
|
614
|
+
if (EntityConflictError.is(stepFailErr)) {
|
|
615
|
+
// Step already in terminal state — idempotent.
|
|
616
|
+
stepRuntimeLogger.info('Tried failing step, but step has already finished.', {
|
|
617
|
+
errorName: stepFailErr.name,
|
|
618
|
+
errorMessage: stepFailErr.message,
|
|
619
|
+
});
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
throw stepFailErr;
|
|
623
|
+
}
|
|
624
|
+
span?.setAttributes({
|
|
625
|
+
...Attribute.StepStatus('failed'),
|
|
626
|
+
...Attribute.StepRetryExhausted(true),
|
|
650
627
|
});
|
|
651
628
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
specVersion: SPEC_VERSION_CURRENT,
|
|
660
|
-
correlationId: stepId,
|
|
661
|
-
eventData: {
|
|
629
|
+
else {
|
|
630
|
+
// Not at max retries yet - log as a retryable error
|
|
631
|
+
if (RetryableError.is(err)) {
|
|
632
|
+
stepLogger.info('Encountered RetryableError, step will be retried', {
|
|
633
|
+
workflowRunId,
|
|
634
|
+
workflowName,
|
|
635
|
+
stepId,
|
|
662
636
|
stepName,
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
},
|
|
668
|
-
}, { requestId });
|
|
669
|
-
}
|
|
670
|
-
catch (stepRetryErr) {
|
|
671
|
-
if (EntityConflictError.is(stepRetryErr)) {
|
|
672
|
-
// Step already in terminal state — idempotent.
|
|
673
|
-
stepRuntimeLogger.info('Tried retrying step, but step has already finished.', {
|
|
674
|
-
errorName: stepRetryErr.name,
|
|
675
|
-
errorMessage: stepRetryErr.message,
|
|
637
|
+
attempt: currentAttempt,
|
|
638
|
+
errorName: err.name,
|
|
639
|
+
errorMessage: err.message,
|
|
640
|
+
errorStack: normalizedStack,
|
|
676
641
|
});
|
|
677
|
-
return;
|
|
678
642
|
}
|
|
679
|
-
|
|
643
|
+
else {
|
|
644
|
+
stepLogger.info('Encountered Error, step will be retried', {
|
|
645
|
+
workflowRunId,
|
|
646
|
+
workflowName,
|
|
647
|
+
stepId,
|
|
648
|
+
stepName,
|
|
649
|
+
attempt: currentAttempt,
|
|
650
|
+
errorName: normalizedError.name,
|
|
651
|
+
errorMessage: normalizedError.message,
|
|
652
|
+
errorStack: normalizedStack,
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
// Set step to pending for retry via event (event-sourced architecture)
|
|
656
|
+
// step_retrying records the error and sets status to pending.
|
|
657
|
+
// Serialize the original thrown value so its full type identity
|
|
658
|
+
// and custom properties round-trip through the event log.
|
|
659
|
+
try {
|
|
660
|
+
await world.events.create(workflowRunId, {
|
|
661
|
+
eventType: 'step_retrying',
|
|
662
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
663
|
+
correlationId: stepId,
|
|
664
|
+
eventData: {
|
|
665
|
+
stepName,
|
|
666
|
+
error: await dehydrateStepError(err, workflowRunId, encryptionKey),
|
|
667
|
+
...(RetryableError.is(err) && {
|
|
668
|
+
retryAfter: err.retryAfter,
|
|
669
|
+
}),
|
|
670
|
+
},
|
|
671
|
+
}, { requestId });
|
|
672
|
+
}
|
|
673
|
+
catch (stepRetryErr) {
|
|
674
|
+
if (EntityConflictError.is(stepRetryErr)) {
|
|
675
|
+
// Step already in terminal state — idempotent.
|
|
676
|
+
stepRuntimeLogger.info('Tried retrying step, but step has already finished.', {
|
|
677
|
+
errorName: stepRetryErr.name,
|
|
678
|
+
errorMessage: stepRetryErr.message,
|
|
679
|
+
});
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
throw stepRetryErr;
|
|
683
|
+
}
|
|
684
|
+
const timeoutSeconds = Math.max(1, RetryableError.is(err)
|
|
685
|
+
? Math.ceil((+err.retryAfter.getTime() - Date.now()) / 1000)
|
|
686
|
+
: 1);
|
|
687
|
+
span?.setAttributes({
|
|
688
|
+
...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
|
|
689
|
+
...Attribute.StepRetryWillRetry(true),
|
|
690
|
+
});
|
|
691
|
+
// Add span event for retry scheduling
|
|
692
|
+
span?.addEvent?.('retry.scheduled', {
|
|
693
|
+
'retry.timeout_seconds': timeoutSeconds,
|
|
694
|
+
'retry.attempt': currentAttempt,
|
|
695
|
+
'retry.max_retries': maxRetries,
|
|
696
|
+
});
|
|
697
|
+
// It's a retryable error - so have the queue keep the message visible
|
|
698
|
+
// so that it gets retried.
|
|
699
|
+
return { timeoutSeconds };
|
|
680
700
|
}
|
|
681
|
-
const timeoutSeconds = Math.max(1, RetryableError.is(err)
|
|
682
|
-
? Math.ceil((+err.retryAfter.getTime() - Date.now()) / 1000)
|
|
683
|
-
: 1);
|
|
684
|
-
span?.setAttributes({
|
|
685
|
-
...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
|
|
686
|
-
...Attribute.StepRetryWillRetry(true),
|
|
687
|
-
});
|
|
688
|
-
// Add span event for retry scheduling
|
|
689
|
-
span?.addEvent?.('retry.scheduled', {
|
|
690
|
-
'retry.timeout_seconds': timeoutSeconds,
|
|
691
|
-
'retry.attempt': currentAttempt,
|
|
692
|
-
'retry.max_retries': maxRetries,
|
|
693
|
-
});
|
|
694
|
-
// It's a retryable error - so have the queue keep the message visible
|
|
695
|
-
// so that it gets retried.
|
|
696
|
-
return { timeoutSeconds };
|
|
697
701
|
}
|
|
702
|
+
// Re-invoke the workflow to handle the failed/retrying step
|
|
703
|
+
await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
|
|
704
|
+
runId: workflowRunId,
|
|
705
|
+
traceCarrier: await serializeTraceCarrier(),
|
|
706
|
+
requestedAt: new Date(),
|
|
707
|
+
});
|
|
708
|
+
return;
|
|
698
709
|
}
|
|
699
|
-
//
|
|
700
|
-
|
|
710
|
+
// --- Infrastructure: complete the step ---
|
|
711
|
+
// Errors here (network failures, server errors) propagate to the
|
|
712
|
+
// queue handler for automatic retry.
|
|
713
|
+
//
|
|
714
|
+
// NOTE: None of the code from this point is guaranteed to run.
|
|
715
|
+
// Since the step might fail or cause a function timeout and the
|
|
716
|
+
// process might be SIGKILL'd, the workflow runtime must be
|
|
717
|
+
// resilient to the below code not executing on a failed step.
|
|
718
|
+
// (Dehydration already happened above and is accounted for in the
|
|
719
|
+
// userCodeFailed path.)
|
|
720
|
+
// These stream ops are flushed in the background; the promise
|
|
721
|
+
// handed to waitUntil must never reject (an unconsumed waitUntil
|
|
722
|
+
// rejection crashes the process as unhandledRejection), so
|
|
723
|
+
// unexpected failures are logged instead.
|
|
724
|
+
safeWaitUntil(Promise.all(ops), (err) => {
|
|
725
|
+
stepRuntimeLogger.warn('Background flush of step stream ops failed', { error: err instanceof Error ? err.message : String(err) });
|
|
726
|
+
});
|
|
727
|
+
// Run step_completed and trace serialization concurrently;
|
|
728
|
+
// the trace carrier is used in the final queueMessage call below
|
|
729
|
+
let stepCompleted409 = false;
|
|
730
|
+
const [, traceCarrier] = await Promise.all([
|
|
731
|
+
world.events
|
|
732
|
+
.create(workflowRunId, {
|
|
733
|
+
eventType: 'step_completed',
|
|
734
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
735
|
+
correlationId: stepId,
|
|
736
|
+
eventData: {
|
|
737
|
+
stepName,
|
|
738
|
+
result: result,
|
|
739
|
+
},
|
|
740
|
+
}, { requestId })
|
|
741
|
+
.catch((err) => {
|
|
742
|
+
if (EntityConflictError.is(err)) {
|
|
743
|
+
// Step already in terminal state — idempotent.
|
|
744
|
+
stepRuntimeLogger.info('Tried completing step, but step has already finished.', {
|
|
745
|
+
errorName: err.name,
|
|
746
|
+
errorMessage: err.message,
|
|
747
|
+
});
|
|
748
|
+
stepCompleted409 = true;
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
throw err;
|
|
752
|
+
}),
|
|
753
|
+
serializeTraceCarrier(),
|
|
754
|
+
]);
|
|
755
|
+
if (stepCompleted409) {
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
span?.setAttributes({
|
|
759
|
+
...Attribute.StepStatus('completed'),
|
|
760
|
+
...Attribute.StepResultType(typeof result),
|
|
761
|
+
});
|
|
762
|
+
// Queue the workflow continuation with the concurrently-resolved trace carrier
|
|
763
|
+
await queueMessage(world, getWorkflowQueueName(workflowName, resolvedNamespace), {
|
|
701
764
|
runId: workflowRunId,
|
|
702
|
-
traceCarrier
|
|
765
|
+
traceCarrier,
|
|
703
766
|
requestedAt: new Date(),
|
|
704
767
|
});
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
// --- Infrastructure: complete the step ---
|
|
708
|
-
// Errors here (network failures, server errors) propagate to the
|
|
709
|
-
// queue handler for automatic retry.
|
|
710
|
-
//
|
|
711
|
-
// NOTE: None of the code from this point is guaranteed to run.
|
|
712
|
-
// Since the step might fail or cause a function timeout and the
|
|
713
|
-
// process might be SIGKILL'd, the workflow runtime must be
|
|
714
|
-
// resilient to the below code not executing on a failed step.
|
|
715
|
-
// (Dehydration already happened above and is accounted for in the
|
|
716
|
-
// userCodeFailed path.)
|
|
717
|
-
waitUntil(Promise.all(ops).catch((err) => {
|
|
718
|
-
// Ignore expected client disconnect errors (e.g., browser refresh during streaming)
|
|
719
|
-
const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
|
|
720
|
-
if (!isAbortError)
|
|
721
|
-
throw err;
|
|
722
|
-
}));
|
|
723
|
-
// Run step_completed and trace serialization concurrently;
|
|
724
|
-
// the trace carrier is used in the final queueMessage call below
|
|
725
|
-
let stepCompleted409 = false;
|
|
726
|
-
const [, traceCarrier] = await Promise.all([
|
|
727
|
-
world.events
|
|
728
|
-
.create(workflowRunId, {
|
|
729
|
-
eventType: 'step_completed',
|
|
730
|
-
specVersion: SPEC_VERSION_CURRENT,
|
|
731
|
-
correlationId: stepId,
|
|
732
|
-
eventData: {
|
|
733
|
-
stepName,
|
|
734
|
-
result: result,
|
|
735
|
-
},
|
|
736
|
-
}, { requestId })
|
|
737
|
-
.catch((err) => {
|
|
738
|
-
if (EntityConflictError.is(err)) {
|
|
739
|
-
// Step already in terminal state — idempotent.
|
|
740
|
-
stepRuntimeLogger.info('Tried completing step, but step has already finished.', {
|
|
741
|
-
errorName: err.name,
|
|
742
|
-
errorMessage: err.message,
|
|
743
|
-
});
|
|
744
|
-
stepCompleted409 = true;
|
|
745
|
-
return;
|
|
746
|
-
}
|
|
747
|
-
throw err;
|
|
748
|
-
}),
|
|
749
|
-
serializeTraceCarrier(),
|
|
750
|
-
]);
|
|
751
|
-
if (stepCompleted409) {
|
|
752
|
-
return;
|
|
753
|
-
}
|
|
754
|
-
span?.setAttributes({
|
|
755
|
-
...Attribute.StepStatus('completed'),
|
|
756
|
-
...Attribute.StepResultType(typeof result),
|
|
757
|
-
});
|
|
758
|
-
// Queue the workflow continuation with the concurrently-resolved trace carrier
|
|
759
|
-
await queueMessage(world, getWorkflowQueueName(workflowName), {
|
|
760
|
-
runId: workflowRunId,
|
|
761
|
-
traceCarrier,
|
|
762
|
-
requestedAt: new Date(),
|
|
763
768
|
});
|
|
764
769
|
});
|
|
765
770
|
});
|
|
766
|
-
}
|
|
771
|
+
}
|
|
772
|
+
const stepHandler = createStepHandler();
|
|
767
773
|
/**
|
|
768
774
|
* A single route that handles any step execution request and routes to the
|
|
769
775
|
* appropriate step function. We may eventually want to create different bundles
|
|
@@ -777,4 +783,4 @@ export const stepEntrypoint =
|
|
|
777
783
|
}
|
|
778
784
|
return cachedStepHandler(req);
|
|
779
785
|
});
|
|
780
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3RlcC1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFVBQVUsRUFDVixjQUFjLEVBQ2QsZUFBZSxFQUNmLHNCQUFzQixFQUN0QixhQUFhLEVBQ2IsYUFBYSxFQUNiLG9CQUFvQixFQUNwQixrQkFBa0IsR0FDbkIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDckQsT0FBTyxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRCxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLGtCQUFrQixFQUNsQix3QkFBd0IsRUFDeEIsb0JBQW9CLEVBQ3BCLGdCQUFnQixHQUNqQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBQ2xFLE9BQU8sRUFDTCxXQUFXLEVBQ1gsb0JBQW9CLEVBQ3BCLHFCQUFxQixFQUNyQixLQUFLLEVBQ0wsZ0JBQWdCLEdBQ2pCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUNMLFlBQVksRUFDWixhQUFhLEVBQ2IscUJB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QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgd2FpdFVudGlsIH0gZnJvbSAnQHZlcmNlbC9mdW5jdGlvbnMnO1xuaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgRmF0YWxFcnJvcixcbiAgUmV0cnlhYmxlRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbiAgU3RlcE5vdFJlZ2lzdGVyZWRFcnJvcixcbiAgVGhyb3R0bGVFcnJvcixcbiAgVG9vRWFybHlFcnJvcixcbiAgV29ya2Zsb3dSdW50aW1lRXJyb3IsXG4gIFdvcmtmbG93V29ybGRFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQgeyBmb3JtYXRTdGVwTmFtZSwgcGx1cmFsaXplIH0gZnJvbSAnQHdvcmtmbG93L3V0aWxzJztcbmltcG9ydCB7IGdldFBvcnQgfSBmcm9tICdAd29ya2Zsb3cvdXRpbHMvZ2V0LXBvcnQnO1xuaW1wb3J0IHsgU1BFQ19WRVJTSU9OX0NVUlJFTlQsIFN0ZXBJbnZva2VQYXlsb2FkU2NoZW1hIH0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IGRlc2NyaWJlRXJyb3IgfSBmcm9tICcuLi9kZXNjcmliZS1lcnJvci5qcyc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyLCBzdGVwTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IGdldFN0ZXBGdW5jdGlvbiB9IGZyb20gJy4uL3ByaXZhdGUuanMnO1xuaW1wb3J0IHtcbiAgY2FuY2VsQWJvcnRSZWFkZXJzLFxuICBkZWh5ZHJhdGVTdGVwRXJyb3IsXG4gIGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZSxcbiAgaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIGh5ZHJhdGVTdGVwRXJyb3IsXG59IGZyb20gJy4uL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0IHsgY29udGV4dFN0b3JhZ2UgfSBmcm9tICcuLi9zdGVwL2NvbnRleHQtc3RvcmFnZS5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7XG4gIGdldFNwYW5LaW5kLFxuICBsaW5rVG9DdXJyZW50Q29udGV4dCxcbiAgc2VyaWFsaXplVHJhY2VDYXJyaWVyLFxuICB0cmFjZSxcbiAgd2l0aFRyYWNlQ29udGV4dCxcbn0gZnJvbSAnLi4vdGVsZW1ldHJ5LmpzJztcbmltcG9ydCB7XG4gIGdldEVycm9yTmFtZSxcbiAgZ2V0RXJyb3JTdGFjayxcbiAgbm9ybWFsaXplVW5rbm93bkVycm9yLFxuICBwcm9tb3RlQWJvcnRFcnJvclRvRmF0YWwsXG59IGZyb20gJy4uL3R5cGVzLmpzJztcbmltcG9ydCB7IE1BWF9RVUVVRV9ERUxJVkVSSUVTIH0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHtcbiAgZ2V0UXVldWVPdmVyaGVhZCxcbiAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUsXG4gIGhhbmRsZUhlYWx0aENoZWNrTWVzc2FnZSxcbiAgbWVtb2l6ZUVuY3J5cHRpb25LZXksXG4gIHBhcnNlSGVhbHRoQ2hlY2tQYXlsb2FkLFxuICBxdWV1ZU1lc3NhZ2UsXG4gIHdpdGhIZWFsdGhDaGVjayxcbn0gZnJvbSAnLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IGdldFdvcmxkLCBnZXRXb3JsZEhhbmRsZXJzLCB0eXBlIFdvcmxkSGFuZGxlcnMgfSBmcm9tICcuL3dvcmxkLmpzJztcblxuY29uc3QgREVGQVVMVF9TVEVQX01BWF9SRVRSSUVTID0gMztcblxuY29uc3Qgc3RlcEhhbmRsZXIgPSAod29ybGRIYW5kbGVyczogV29ybGRIYW5kbGVycykgPT5cbiAgd29ybGRIYW5kbGVycy5jcmVhdGVRdWV1ZUhhbmRsZXIoXG4gICAgJ19fd2tmX3N0ZXBfJyxcbiAgICBhc3luYyAobWVzc2FnZV8sIG1ldGFkYXRhKSA9PiB7XG4gICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGEgaGVhbHRoIGNoZWNrIG1lc3NhZ2VcbiAgICAgIC8vIE5PVEU6IEhlYWx0aCBjaGVjayBtZXNzYWdlcyBhcmUgaW50ZW50aW9uYWxseSB1bmF1dGhlbnRpY2F0ZWQgZm9yIG1vbml0b3JpbmcgcHVycG9zZXMuXG4gICAgICAvLyBUaGV5IG9ubHkgd3JpdGUgYSBzaW1wbGUgc3RhdHVzIHJlc3BvbnNlIHRvIGEgc3RyZWFtIGFuZCBkbyBub3QgZXhwb3NlIHNlbnNpdGl2ZSBkYXRhLlxuICAgICAgLy8gVGhlIHN0cmVhbSBuYW1lIGluY2x1ZGVzIGEgdW5pcXVlIGNvcnJlbGF0aW9uSWQgdGhhdCBtdXN0IGJlIGtub3duIGJ5IHRoZSBjYWxsZXIuXG4gICAgICBjb25zdCBoZWFsdGhDaGVjayA9IHBhcnNlSGVhbHRoQ2hlY2tQYXlsb2FkKG1lc3NhZ2VfKTtcbiAgICAgIGlmIChoZWFsdGhDaGVjaykge1xuICAgICAgICBhd2FpdCBoYW5kbGVIZWFsdGhDaGVja01lc3NhZ2UoXG4gICAgICAgICAgaGVhbHRoQ2hlY2ssXG4gICAgICAgICAgJ3N0ZXAnLFxuICAgICAgICAgIHdvcmxkSGFuZGxlcnMuc3BlY1ZlcnNpb25cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7XG4gICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQsXG4gICAgICAgIHN0ZXBJZCxcbiAgICAgICAgdHJhY2VDYXJyaWVyOiB0cmFjZUNvbnRleHQsXG4gICAgICAgIHJlcXVlc3RlZEF0LFxuICAgICAgfSA9IFN0ZXBJbnZva2VQYXlsb2FkU2NoZW1hLnBhcnNlKG1lc3NhZ2VfKTtcbiAgICAgIGNvbnN0IHsgcmVxdWVzdElkIH0gPSBtZXRhZGF0YTtcblxuICAgICAgLy8gLS0tIE1heCBkZWxpdmVyeSBjaGVjayAtLS1cbiAgICAgIC8vIEVuZm9yY2UgbWF4IGRlbGl2ZXJ5IGxpbWl0IGJlZm9yZSBhbnkgaW5mcmFzdHJ1Y3R1cmUgY2FsbHMuXG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHJ1bmF3YXkgc3RlcHMgZnJvbSBjb25zdW1pbmcgaW5maW5pdGUgcXVldWUgZGVsaXZlcmllcy5cbiAgICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIHdhbnQgdG8gZG8gdGhlIG1pbmltYWwgYW1vdW50IG9mIHdvcmsgKG5vIGZldGNoaW5nXG4gICAgICAvLyBvZiB0aGUgc3RlcCBkZXRhaWxzLCBldGMuIFdlIHNpbXBseSBhdHRlbXB0IHRvIG1hcmsgdGhlIHN0ZXAgYXMgZmFpbGVkXG4gICAgICAvLyBhbmQgZW5xdWV1ZSB0aGUgd29ya2Zsb3cgb25jZSwgYW5kIGlmIGVpdGhlciBvZiB0aG9zZSBmYWlscywgdGhlIG1lc3NhZ2VcbiAgICAgIC8vIGlzIHN0aWxsIGNvbnN1bWVkIGJ1dCB3aXRoIGFkZXF1YXRlIGxvZ2dpbmcgdGhhdCBhbiBlcnJvciBvY2N1cnJlZC5cbiAgICAgIC8vIFNjb3BlZCBsb2dnZXIgZm9yIHRoaXMgc3RlcCBpbnZvY2F0aW9uIOKAlCBhdHRhY2hlcyBydW4vc3RlcCBjb250ZXh0IHRvXG4gICAgICAvLyBldmVyeSBsb2cgbGluZSBiZWxvdyBzbyBjYWxsZXJzIGRvbid0IHJlcGVhdCBpdC5cbiAgICAgIGNvbnN0IHN0ZXBOYW1lRnJvbVF1ZXVlID0gbWV0YWRhdGEucXVldWVOYW1lLnNsaWNlKCdfX3drZl9zdGVwXycubGVuZ3RoKTtcbiAgICAgIGNvbnN0IHN0ZXBSdW50aW1lTG9nZ2VyID0gcnVudGltZUxvZ2dlci5mb3JSdW4oXG4gICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgeyBzdGVwSWQsIHN0ZXBOYW1lOiBzdGVwTmFtZUZyb21RdWV1ZSB9XG4gICAgICApO1xuXG4gICAgICBpZiAobWV0YWRhdGEuYXR0ZW1wdCA+IE1BWF9RVUVVRV9ERUxJVkVSSUVTKSB7XG4gICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmVycm9yKFxuICAgICAgICAgIGBTdGVwIGhhbmRsZXIgZXhjZWVkZWQgbWF4IGRlbGl2ZXJpZXMgKCR7bWV0YWRhdGEuYXR0ZW1wdH0vJHtNQVhfUVVFVUVfREVMSVZFUklFU30pYCxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhdHRlbXB0OiBtZXRhZGF0YS5hdHRlbXB0LFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkKCk7XG4gICAgICAgICAgY29uc3QgZ2V0RW5jcnlwdGlvbktleSA9IG1lbW9pemVFbmNyeXB0aW9uS2V5KHdvcmxkLCB3b3JrZmxvd1J1bklkKTtcbiAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgRmF0YWxFcnJvcihcbiAgICAgICAgICAgIGBTdGVwIGV4Y2VlZGVkIG1heGltdW0gcXVldWUgZGVsaXZlcmllcyAoJHttZXRhZGF0YS5hdHRlbXB0fS8ke01BWF9RVUVVRV9ERUxJVkVSSUVTfSlgXG4gICAgICAgICAgKTtcbiAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgc3RlcE5hbWU6IHN0ZXBOYW1lRnJvbVF1ZXVlLFxuICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICBlcnIsXG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICAvLyBSZS1xdWV1ZSB0aGUgd29ya2Zsb3cgdG8gaGFuZGxlIHRoZSBmYWlsZWQgc3RlcFxuICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZSh3b3JsZCwgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lKSwge1xuICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHwgUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ2FuJ3QgZXZlbiBtYXJrIHRoZSBzdGVwIGFzIGZhaWxlZC4gQ29uc3VtZSB0aGUgbWVzc2FnZSB0byBzdG9wXG4gICAgICAgICAgLy8gZnVydGhlciByZXRyaWVzLiBUaGUgcnVuIHdpbGwgcmVtYWluIGluIGl0cyBjdXJyZW50IHN0YXRlLlxuICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgYEZhaWxlZCB0byBtYXJrIHN0ZXAgYXMgZmFpbGVkIGFmdGVyICR7bWV0YWRhdGEuYXR0ZW1wdH0gZGVsaXZlcnkgYXR0ZW1wdHMuIGAgK1xuICAgICAgICAgICAgICBgQSBwZXJzaXN0ZW50IGVycm9yIGlzIHByZXZlbnRpbmcgdGhlIHN0ZXAgZnJvbSBiZWluZyB0ZXJtaW5hdGVkLiBgICtcbiAgICAgICAgICAgICAgYFRoZSBydW4gd2lsbCByZW1haW4gaW4gaXRzIGN1cnJlbnQgc3RhdGUgdW50aWwgbWFudWFsbHkgcmVzb2x2ZWQuIGAgK1xuICAgICAgICAgICAgICBgVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYSBwZXJzaXN0ZW50IG91dGFnZSBvZiB0aGUgd29ya2Zsb3cgYmFja2VuZCBgICtcbiAgICAgICAgICAgICAgYG9yIGEgYnVnIGluIHRoZSB3b3JrZmxvdyBydW50aW1lIGFuZCBzaG91bGQgYmUgcmVwb3J0ZWQgdG8gdGhlIFdvcmtmbG93IHRlYW0uYCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYXR0ZW1wdDogbWV0YWRhdGEuYXR0ZW1wdCxcbiAgICAgICAgICAgICAgZXJyb3JOYW1lOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5uYW1lIDogJ1Vua25vd25FcnJvcicsXG4gICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICAgICAgICBlcnJvclN0YWNrOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5zdGFjayA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3BhbkxpbmtzID0gYXdhaXQgbGlua1RvQ3VycmVudENvbnRleHQoKTtcbiAgICAgIC8vIEV4ZWN1dGUgc3RlcCB3aXRoaW4gdGhlIHByb3BhZ2F0ZWQgdHJhY2UgY29udGV4dFxuICAgICAgcmV0dXJuIGF3YWl0IHdpdGhUcmFjZUNvbnRleHQodHJhY2VDb250ZXh0LCBhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIEV4dHJhY3QgdGhlIHN0ZXAgbmFtZSBmcm9tIHRoZSB0b3BpYyBuYW1lXG4gICAgICAgIGNvbnN0IHN0ZXBOYW1lID0gbWV0YWRhdGEucXVldWVOYW1lLnNsaWNlKCdfX3drZl9zdGVwXycubGVuZ3RoKTtcbiAgICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICAgICAgICBjb25zdCBpc1ZlcmNlbCA9IHByb2Nlc3MuZW52LlZFUkNFTF9VUkwgIT09IHVuZGVmaW5lZDtcblxuICAgICAgICAvLyBNZW1vaXplZCBhY2Nlc3NvciBmb3IgdGhlIHBlci1ydW4gQUVTLTI1NiBlbmNyeXB0aW9uIGtleS4gVGhlIGZpcnN0XG4gICAgICAgIC8vIGNhbGxlciAodHlwaWNhbGx5IGBoeWRyYXRlU3RlcEFyZ3VtZW50c2AgZm9yIGlucHV0IGRlc2VyaWFsaXphdGlvbixcbiAgICAgICAgLy8gb3Igb25lIG9mIHRoZSBlYXJseS1yZXR1cm4gZGVoeWRyYXRlU3RlcEVycm9yIHBhdGhzIGlmIHN0ZXBfc3RhcnRlZFxuICAgICAgICAvLyBmYWlscykgdHJpZ2dlcnMgdGhlIGFjdHVhbCBmZXRjaCAvIEhLREYgZGVyaXZhdGlvbjsgc3Vic2VxdWVudFxuICAgICAgICAvLyBjYWxsZXJzIGF3YWl0IHRoZSBjYWNoZWQgcHJvbWlzZS4gU3RlcHMgdGhhdCBmYWlsIGJlZm9yZSBhbnlcbiAgICAgICAgLy8gZW5jcnlwdGlvbi1hd2FyZSB3b3JrIGhhcHBlbnMgKGUuZy4gYW4gaW1tZWRpYXRlIHN0ZXBfc3RhcnRlZFxuICAgICAgICAvLyBjb25mbGljdCkgc2tpcCB0aGUgZmV0Y2ggZW50aXJlbHkuXG4gICAgICAgIGNvbnN0IGdldEVuY3J5cHRpb25LZXkgPSBtZW1vaXplRW5jcnlwdGlvbktleSh3b3JsZCwgd29ya2Zsb3dSdW5JZCk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBsb2NhbCBhc3luYyB2YWx1ZXMgY29uY3VycmVudGx5IGJlZm9yZSBlbnRlcmluZyB0aGUgdHJhY2Ugc3BhblxuICAgICAgICBjb25zdCBbcG9ydCwgc3BhbktpbmRdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgIGlzVmVyY2VsID8gdW5kZWZpbmVkIDogZ2V0UG9ydCgpLFxuICAgICAgICAgIGdldFNwYW5LaW5kKCdDT05TVU1FUicpLFxuICAgICAgICBdKTtcblxuICAgICAgICByZXR1cm4gdHJhY2UoXG4gICAgICAgICAgYFNURVAgJHtzdGVwTmFtZX1gLFxuICAgICAgICAgIHsga2luZDogc3BhbktpbmQsIGxpbmtzOiBzcGFuTGlua3MgfSxcbiAgICAgICAgICBhc3luYyAoc3BhbikgPT4ge1xuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwTmFtZShzdGVwTmFtZSksXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwQXR0ZW1wdChtZXRhZGF0YS5hdHRlbXB0KSxcbiAgICAgICAgICAgICAgLy8gU3RhbmRhcmQgT1RFTCBtZXNzYWdpbmcgY29udmVudGlvbnNcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLk1lc3NhZ2luZ1N5c3RlbSgndmVyY2VsLXF1ZXVlJyksXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdEZXN0aW5hdGlvbk5hbWUobWV0YWRhdGEucXVldWVOYW1lKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLk1lc3NhZ2luZ01lc3NhZ2VJZChtZXRhZGF0YS5tZXNzYWdlSWQpLFxuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nT3BlcmF0aW9uVHlwZSgncHJvY2VzcycpLFxuICAgICAgICAgICAgICAuLi5nZXRRdWV1ZU92ZXJoZWFkKHsgcmVxdWVzdGVkQXQgfSksXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gTm90ZTogU3RlcCBmdW5jdGlvbiB2YWxpZGF0aW9uIGhhcHBlbnMgYWZ0ZXIgc3RlcF9zdGFydGVkIHNvIHdlIGNhblxuICAgICAgICAgICAgLy8gcHJvcGVybHkgZmFpbCB0aGUgc3RlcCAobm90IHRoZSBydW4pIGlmIHRoZSBmdW5jdGlvbiBpcyBub3QgcmVnaXN0ZXJlZC5cbiAgICAgICAgICAgIC8vIFRoaXMgYWxsb3dzIHRoZSB3b3JrZmxvdyB0byBoYW5kbGUgdGhlIHN0ZXAgZmFpbHVyZSBncmFjZWZ1bGx5LlxuICAgICAgICAgICAgY29uc3Qgc3RlcEZuID0gZ2V0U3RlcEZ1bmN0aW9uKHN0ZXBOYW1lKTtcblxuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd05hbWUod29ya2Zsb3dOYW1lKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuSWQod29ya2Zsb3dSdW5JZCksXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwSWQoc3RlcElkKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBUcmFjZVByb3BhZ2F0ZWQoISF0cmFjZUNvbnRleHQpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIHN0ZXBfc3RhcnRlZCB2YWxpZGF0ZXMgc3RhdGUgYW5kIHJldHVybnMgdGhlIHN0ZXAgZW50aXR5LCBzbyBubyBzZXBhcmF0ZVxuICAgICAgICAgICAgLy8gd29ybGQuc3RlcHMuZ2V0KCkgY2FsbCBpcyBuZWVkZWQuIFRoZSBzZXJ2ZXIgY2hlY2tzOlxuICAgICAgICAgICAgLy8gLSBTdGVwIG5vdCBpbiB0ZXJtaW5hbCBzdGF0ZSAocmV0dXJucyA0MDkpXG4gICAgICAgICAgICAvLyAtIHJldHJ5QWZ0ZXIgdGltZXN0YW1wIHJlYWNoZWQgKHJldHVybnMgNDI1IHdpdGggUmV0cnktQWZ0ZXIgaGVhZGVyKVxuICAgICAgICAgICAgLy8gLSBXb3JrZmxvdyBzdGlsbCBhY3RpdmUgKHJldHVybnMgNDEwIGlmIGNvbXBsZXRlZClcbiAgICAgICAgICAgIGxldCBzdGVwO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3Qgc3RhcnRSZXN1bHQgPSBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9zdGFydGVkJyxcbiAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YTogeyBzdGVwTmFtZSB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgIGlmICghc3RhcnRSZXN1bHQuc3RlcCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgICAgICAgIGBzdGVwX3N0YXJ0ZWQgZXZlbnQgZm9yIFwiJHtzdGVwSWR9XCIgZGlkIG5vdCByZXR1cm4gc3RlcCBlbnRpdHlgXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBzdGVwID0gc3RhcnRSZXN1bHQuc3RlcDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICBpZiAoVGhyb3R0bGVFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmV0cnlSZXRyeUFmdGVyID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgdHlwZW9mIGVyci5yZXRyeUFmdGVyID09PSAnbnVtYmVyJyA/IGVyci5yZXRyeUFmdGVyIDogMVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICdUaHJvdHRsZWQgYWdhaW4gb24gcmV0cnksIGRlZmVycmluZyB0byBxdWV1ZScsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHJldHJ5QWZ0ZXJTZWNvbmRzOiByZXRyeVJldHJ5QWZ0ZXIsXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm4geyB0aW1lb3V0U2Vjb25kczogcmV0cnlSZXRyeUFmdGVyIH07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgLy8gRXhwZWN0ZWQgd2hlbiBhIHJ1biBpcyBjYW5jZWxsZWQgd2hpbGUgYSBzdGVwIGlzIGluLWZsaWdodC5cbiAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgJ1dvcmtmbG93IHJ1biBoYXMgYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIHN0ZXAnLFxuICAgICAgICAgICAgICAgICAgeyBlcnJvck5hbWU6IGVyci5uYW1lLCBlcnJvck1lc3NhZ2U6IGVyci5tZXNzYWdlIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgLy8gU3RlcCBhbHJlYWR5IGluIGEgdGVybWluYWwgc3RhdGUg4oCUIGFub3RoZXIgd29ya2VyIGZpbmlzaGVkXG4gICAgICAgICAgICAgICAgLy8gaXQgb3IgaXQgd2FzIHJldHJpZWQgdG8gY29tcGxldGlvbi4gUmUtZW5xdWV1ZSB0aGUgcGFyZW50XG4gICAgICAgICAgICAgICAgLy8gd29ya2Zsb3cgc28gaXQgY2FuIG9ic2VydmUgdGhlIG91dGNvbWUuXG4gICAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuZGVidWcoXG4gICAgICAgICAgICAgICAgICAnU3RlcCBpbiB0ZXJtaW5hbCBzdGF0ZSwgcmUtZW5xdWV1aW5nIHdvcmtmbG93JyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBlcnIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTa2lwcGVkKHRydWUpLFxuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTa2lwUmVhc29uKCdjb21wbGV0ZWQnKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzcGFuPy5hZGRFdmVudD8uKCdzdGVwLnNraXBwZWQnLCB7XG4gICAgICAgICAgICAgICAgICAnc2tpcC5yZWFzb24nOiAndGVybWluYWxfc3RhdGUnLFxuICAgICAgICAgICAgICAgICAgJ3N0ZXAubmFtZSc6IHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgJ3N0ZXAuaWQnOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgYXdhaXQgcXVldWVNZXNzYWdlKHdvcmxkLCBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd05hbWUpLCB7XG4gICAgICAgICAgICAgICAgICBydW5JZDogd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAvLyBUb28gZWFybHk6IHJldHJ5QWZ0ZXIgdGltZXN0YW1wIG5vdCByZWFjaGVkIHlldFxuICAgICAgICAgICAgICAvLyBSZXR1cm4gdGltZW91dCB0byBxdWV1ZSBzbyBpdCByZXRyaWVzIGxhdGVyXG4gICAgICAgICAgICAgIGlmIChUb29FYXJseUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGgubWF4KDEsIGVyci5yZXRyeUFmdGVyID8/IDEpO1xuICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXRyeVRpbWVvdXRTZWNvbmRzKHRpbWVvdXRTZWNvbmRzKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAvLyBBZGQgc3BhbiBldmVudCBmb3IgZGVsYXllZCByZXRyeVxuICAgICAgICAgICAgICAgIHNwYW4/LmFkZEV2ZW50Py4oJ3N0ZXAuZGVsYXllZCcsIHtcbiAgICAgICAgICAgICAgICAgICdkZWxheS5yZWFzb24nOiAncmV0cnlfYWZ0ZXJfbm90X3JlYWNoZWQnLFxuICAgICAgICAgICAgICAgICAgJ2RlbGF5LnRpbWVvdXRfc2Vjb25kcyc6IHRpbWVvdXRTZWNvbmRzLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgICAgJ1N0ZXAgcmV0cnlBZnRlciB0aW1lc3RhbXAgbm90IHlldCByZWFjaGVkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0cnlBZnRlclNlY29uZHM6IGVyci5yZXRyeUFmdGVyLFxuICAgICAgICAgICAgICAgICAgICB0aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzIH07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgLy8gUmUtdGhyb3cgb3RoZXIgZXJyb3JzXG4gICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuZGVidWcoJ1N0ZXAgZXhlY3V0aW9uIGRldGFpbHMnLCB7XG4gICAgICAgICAgICAgIHN0YXR1czogc3RlcC5zdGF0dXMsXG4gICAgICAgICAgICAgIGF0dGVtcHQ6IHN0ZXAuYXR0ZW1wdCxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoc3RlcC5zdGF0dXMpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFZhbGlkYXRlIHN0ZXAgZnVuY3Rpb24gZXhpc3RzIEFGVEVSIHN0ZXBfc3RhcnRlZCBzbyB3ZSBjYW5cbiAgICAgICAgICAgIC8vIHByb3Blcmx5IGZhaWwgdGhlIHN0ZXAgKG5vdCB0aGUgcnVuKSBpZiB0aGUgZnVuY3Rpb24gaXMgbWlzc2luZy5cbiAgICAgICAgICAgIC8vIFRoaXMgYWxsb3dzIHRoZSB3b3JrZmxvdyB0byBoYW5kbGUgdGhlIHN0ZXAgZmFpbHVyZSBncmFjZWZ1bGx5LFxuICAgICAgICAgICAgLy8gc2ltaWxhciB0byBob3cgRmF0YWxFcnJvciBpcyBoYW5kbGVkLlxuICAgICAgICAgICAgaWYgKCFzdGVwRm4gfHwgdHlwZW9mIHN0ZXBGbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgU3RlcE5vdFJlZ2lzdGVyZWRFcnJvcihzdGVwTmFtZSk7XG5cbiAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgICAgJ1N0ZXAgZnVuY3Rpb24gbm90IHJlZ2lzdGVyZWQsIGZhaWxpbmcgc3RlcCAobm90IHJ1biknLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogZXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgZXJyb3JTdGFjazogZXJyLnN0YWNrLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAvLyBGYWlsIHRoZSBzdGVwIHZpYSBldmVudCAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpXG4gICAgICAgICAgICAgIC8vIFRoaXMgbWF0Y2hlcyB0aGUgRmF0YWxFcnJvciBwYXR0ZXJuIC0gZmFpbCB0aGUgc3RlcCBhbmQgcmUtcXVldWUgd29ya2Zsb3dcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycixcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KClcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChzdGVwRmFpbEVycikge1xuICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgLy8gU3RlcCBhbHJlYWR5IHRyYW5zaXRpb25lZCB0byBhIHRlcm1pbmFsIHN0YXRlIOKAlCBkdXBsaWNhdGVcbiAgICAgICAgICAgICAgICAgIC8vIGRlbGl2ZXJ5IG9yIGNvbmN1cnJlbnQgY2FuY2VsbGF0aW9uLiBEcm9wIHNpbGVudGx5LlxuICAgICAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCBmb3IgbWlzc2luZyBmdW5jdGlvbiwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogc3RlcEZhaWxFcnIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IHN0ZXBGYWlsRXJyO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2ZhaWxlZCcpLFxuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRmF0YWxFcnJvcih0cnVlKSxcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgLy8gUmUtaW52b2tlIHRoZSB3b3JrZmxvdyB0byBoYW5kbGUgdGhlIGZhaWxlZCBzdGVwXG4gICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZSh3b3JsZCwgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lKSwge1xuICAgICAgICAgICAgICAgIHJ1bklkOiB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IG1heFJldHJpZXMgPSBzdGVwRm4ubWF4UmV0cmllcyA/PyBERUZBVUxUX1NURVBfTUFYX1JFVFJJRVM7XG5cbiAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcE1heFJldHJpZXMobWF4UmV0cmllcyksXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgbGV0IHJlc3VsdDogdW5rbm93bjtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgbWF4IHJldHJpZXMgQUZURVIgc3RlcF9zdGFydGVkIChhdHRlbXB0IHdhcyBqdXN0IGluY3JlbWVudGVkKVxuICAgICAgICAgICAgLy8gc3RlcC5hdHRlbXB0IHRyYWNrcyBob3cgbWFueSB0aW1lcyBzdGVwX3N0YXJ0ZWQgaGFzIGJlZW4gY2FsbGVkLlxuICAgICAgICAgICAgLy8gTm90ZTogbWF4UmV0cmllcyBpcyB0aGUgbnVtYmVyIG9mIFJFVFJJRVMgYWZ0ZXIgdGhlIGZpcnN0IGF0dGVtcHQsIHNvIHRvdGFsIGF0dGVtcHRzID0gbWF4UmV0cmllcyArIDFcbiAgICAgICAgICAgIC8vIFVzZSA+IGhlcmUgKG5vdCA+PSkgYmVjYXVzZSB0aGlzIGd1YXJkcyBhZ2FpbnN0IHJlLWludm9jYXRpb24gQUZURVIgYWxsIGF0dGVtcHRzIGFyZSB1c2VkLlxuICAgICAgICAgICAgLy8gVGhlIHBvc3QtZmFpbHVyZSBjaGVjayB1c2VzID49IHRvIGRlY2lkZSB3aGV0aGVyIHRvIHJldHJ5IGFmdGVyIGEgZmFpbHVyZS5cbiAgICAgICAgICAgIGlmIChzdGVwLmF0dGVtcHQgPiBtYXhSZXRyaWVzICsgMSkge1xuICAgICAgICAgICAgICBjb25zdCByZXRyeUNvdW50ID0gc3RlcC5hdHRlbXB0IC0gMTtcbiAgICAgICAgICAgICAgLy8gUGVyc2lzdGVkIG1lc3NhZ2Ug4oCUIGtlcHQgc2hvcnQsIG5vIG1hY2hpbmUgYHN0ZXBOYW1lYCxcbiAgICAgICAgICAgICAgLy8gc2luY2Ugb2JzZXJ2YWJpbGl0eSBhbHJlYWR5IGF0dHJpYnV0ZXMgdGhlIGV2ZW50IHRvIGFcbiAgICAgICAgICAgICAgLy8gc3BlY2lmaWMgc3RlcC5cbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYFN0ZXAgZXhjZWVkZWQgbWF4IHJldHJpZXMgKCR7cmV0cnlDb3VudH0gJHtwbHVyYWxpemUoJ3JldHJ5JywgJ3JldHJpZXMnLCByZXRyeUNvdW50KX0pYDtcbiAgICAgICAgICAgICAgc3RlcExvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICBgU3RlcCAke2Zvcm1hdFN0ZXBOYW1lKHN0ZXBOYW1lKX0gZXhjZWVkZWQgbWF4IHJldHJpZXMgKCR7cmV0cnlDb3VudH0gJHtwbHVyYWxpemUoJ3JldHJ5JywgJ3JldHJpZXMnLCByZXRyeUNvdW50KX0pYCxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICByZXRyeUNvdW50LFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgc3RlcCB2aWEgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKS5cbiAgICAgICAgICAgICAgLy8gUHJlc2VydmUgdGhlIHByaW9yIGF0dGVtcHQncyBzZXJpYWxpemVkIGVycm9yIGFzIHRoZSBjYXVzZSBzb1xuICAgICAgICAgICAgICAvLyB0aGUgdW5kZXJseWluZyBmYWlsdXJlIGlzIHJlY292ZXJhYmxlIGZyb20gYHN0ZXAuZXJyb3IuY2F1c2VgXG4gICAgICAgICAgICAgIC8vIGFmdGVyIGh5ZHJhdGlvbiwgd2l0aG91dCBmb3JjaW5nIGNvbnN1bWVycyB0byB3YWxrIHRoZVxuICAgICAgICAgICAgICAvLyBzdGVwX3JldHJ5aW5nIGV2ZW50IGhpc3RvcnkuIE1pcnJvcnMgdGhlIHBvc3QtZmFpbHVyZSBwYXRoXG4gICAgICAgICAgICAgIC8vIGJlbG93IHRoYXQgd3JhcHMgdGhlIGxpdmUgYGVycmAgYXMgY2F1c2UuXG4gICAgICAgICAgICAgIGNvbnN0IHdyYXBwZWRFcnJvciA9IG5ldyBGYXRhbEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgIGlmIChzdGVwLmVycm9yICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgKHdyYXBwZWRFcnJvciBhcyBFcnJvcikuY2F1c2UgPSBhd2FpdCBoeWRyYXRlU3RlcEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBzdGVwLmVycm9yLFxuICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KClcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgICAvLyBJZ25vcmU6IGJlc3QtZWZmb3J0IGNhdXNlIGF0dGFjaG1lbnQsIHRoZSB3cmFwcGluZ1xuICAgICAgICAgICAgICAgICAgLy8gRmF0YWxFcnJvciBzdGFjay9tZXNzYWdlIHN0aWxsIHN1cmZhY2UgdGhlIGZhaWx1cmUuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICB3cmFwcGVkRXJyb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICAgICAgLy8gU3RlcCBhbHJlYWR5IHRyYW5zaXRpb25lZCB0byBhIHRlcm1pbmFsIHN0YXRlIOKAlCBkdXBsaWNhdGVcbiAgICAgICAgICAgICAgICAgIC8vIGRlbGl2ZXJ5IG9yIGNvbmN1cnJlbnQgY29tcGxldGlvbi4gRHJvcCBzaWxlbnRseS5cbiAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICdUcmllZCBmYWlsaW5nIHN0ZXAsIGJ1dCBzdGVwIGhhcyBhbHJlYWR5IGZpbmlzaGVkLicsXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdmYWlsZWQnKSxcbiAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJldHJ5RXhoYXVzdGVkKHRydWUpLFxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAvLyBSZS1pbnZva2UgdGhlIHdvcmtmbG93IHRvIGhhbmRsZSB0aGUgZmFpbGVkIHN0ZXBcbiAgICAgICAgICAgICAgYXdhaXQgcXVldWVNZXNzYWdlKHdvcmxkLCBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd05hbWUpLCB7XG4gICAgICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyOiBhd2FpdCBzZXJpYWxpemVUcmFjZUNhcnJpZXIoKSxcbiAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gLS0tIEluZnJhc3RydWN0dXJlOiBwcmVwYXJlIHN0ZXAgaW5wdXQgLS0tXG4gICAgICAgICAgICAvLyBOZXR3b3JrL3NlcnZlciBlcnJvcnMgcHJvcGFnYXRlIHRvIHRoZSBxdWV1ZSBoYW5kbGVyIGZvciByZXRyeS5cbiAgICAgICAgICAgIC8vIFdvcmtmbG93UnVudGltZUVycm9yIChkYXRhIGludGVncml0eSBpc3N1ZXMpIGFyZSBmYXRhbCDigJQgcmV0cnlpbmdcbiAgICAgICAgICAgIC8vIHdvbid0IGZpeCB0aGVtLCBzbyB3ZSByZS1xdWV1ZSB0aGUgd29ya2Zsb3cgdG8gc3VyZmFjZSB0aGUgZXJyb3IuXG4gICAgICAgICAgICAvLyBzdGVwX3N0YXJ0ZWQgYWxyZWFkeSB2YWxpZGF0ZWQgdGhlIHN0ZXAgaXMgaW4gdmFsaWQgc3RhdGUgKHBlbmRpbmcvcnVubmluZylcbiAgICAgICAgICAgIC8vIGFuZCByZXR1cm5lZCB0aGUgdXBkYXRlZCBzdGVwIGVudGl0eSB3aXRoIGluY3JlbWVudGVkIGF0dGVtcHRcblxuICAgICAgICAgICAgLy8gc3RlcC5hdHRlbXB0IGlzIG5vdyB0aGUgY3VycmVudCBhdHRlbXB0IG51bWJlciAoYWZ0ZXIgaW5jcmVtZW50KVxuICAgICAgICAgICAgY29uc3QgYXR0ZW1wdCA9IHN0ZXAuYXR0ZW1wdDtcblxuICAgICAgICAgICAgaWYgKCFzdGVwLnN0YXJ0ZWRBdCkge1xuICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgU3RlcCBcIiR7c3RlcElkfVwiIGhhcyBubyBcInN0YXJ0ZWRBdFwiIHRpbWVzdGFtcGA7XG4gICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmVycm9yKCdGYXRhbCBydW50aW1lIGVycm9yIGR1cmluZyBzdGVwIHNldHVwJywge1xuICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgRmF0YWxFcnJvcihlcnJvck1lc3NhZ2UpLFxuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKVxuICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhmYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvdyBmYWlsRXJyO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIFJlLXF1ZXVlIHRoZSB3b3JrZmxvdyBzbyBpdCBjYW4gcHJvY2VzcyB0aGUgc3RlcCBmYWlsdXJlXG4gICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZSh3b3JsZCwgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lKSwge1xuICAgICAgICAgICAgICAgIHJ1bklkOiB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDYXB0dXJlIHN0YXJ0ZWRBdCBmb3IgdXNlIGluIGFzeW5jIGNhbGxiYWNrIChUeXBlU2NyaXB0IG5hcnJvd2luZyBkb2Vzbid0IHBlcnNpc3QpXG4gICAgICAgICAgICBjb25zdCBzdGVwU3RhcnRlZEF0ID0gc3RlcC5zdGFydGVkQXQ7XG5cbiAgICAgICAgICAgIC8vIFJlc29sdmUgdGhlIGVuY3J5cHRpb24ga2V5IG5vdyB0aGF0IHdlJ3JlIGNvbW1pdHRlZCB0byBydW5uaW5nXG4gICAgICAgICAgICAvLyB1c2VyIGNvZGU6IGlucHV0IGh5ZHJhdGlvbiBuZWVkcyBpdCwgYW5kIGBjb250ZXh0U3RvcmFnZWAgKGFuZFxuICAgICAgICAgICAgLy8gYW55IHVzZXItY29kZSBwYXRocyB0aGF0IHJ1biBpbnNpZGUgaXQpIGNhcHR1cmUgdGhlIHJlc29sdmVkXG4gICAgICAgICAgICAvLyB2YWx1ZS4gVHJpZ2dlcnMgdGhlIHVuZGVybHlpbmcgd29ybGQgLyBLTVMgZmV0Y2ggb25jZSwgd2l0aFxuICAgICAgICAgICAgLy8gc3Vic2VxdWVudCBkZWh5ZHJhdGUgcGF0aHMgcmV1c2luZyB0aGUgbWVtb2l6ZWQgcmVzdWx0LlxuICAgICAgICAgICAgY29uc3QgZW5jcnlwdGlvbktleSA9IGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKTtcblxuICAgICAgICAgICAgLy8gSHlkcmF0ZSB0aGUgc3RlcCBpbnB1dCBhcmd1bWVudHMsIGNsb3N1cmUgdmFyaWFibGVzLCBhbmQgdGhpc1ZhbFxuICAgICAgICAgICAgLy8gTk9URTogVGhpcyBjYXB0dXJlcyBvbmx5IHRoZSBzeW5jaHJvbm91cyBwb3J0aW9uIG9mIGh5ZHJhdGlvbi4gQW55IGFzeW5jXG4gICAgICAgICAgICAvLyBvcGVyYXRpb25zIChlLmcuLCBzdHJlYW0gbG9hZGluZykgYXJlIGFkZGVkIHRvIGBvcHNgIGFuZCBleGVjdXRlZCBsYXRlclxuICAgICAgICAgICAgLy8gdmlhIFByb21pc2UuYWxsKG9wcykgLSB0aGVpciB0aW1pbmcgaXMgbm90IGluY2x1ZGVkIGluIHRoaXMgbWVhc3VyZW1lbnQuXG4gICAgICAgICAgICBjb25zdCBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuICAgICAgICAgICAgY29uc3QgaHlkcmF0ZWRJbnB1dCA9IGF3YWl0IHRyYWNlKFxuICAgICAgICAgICAgICAnc3RlcC5oeWRyYXRlJyxcbiAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgIGFzeW5jIChoeWRyYXRlU3BhbikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICAgICAgICBzdGVwLmlucHV0LFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICAgICAgICBvcHMsXG4gICAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICBwcm9jZXNzLmVudi5WRVJDRUxfREVQTE9ZTUVOVF9JRFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29uc3QgZHVyYXRpb25NcyA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XG4gICAgICAgICAgICAgICAgaHlkcmF0ZVNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBBcmd1bWVudHNDb3VudChyZXN1bHQuYXJncy5sZW5ndGgpLFxuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlF1ZXVlRGVzZXJpYWxpemVUaW1lTXMoZHVyYXRpb25NcyksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgY29uc3QgYXJncyA9IGh5ZHJhdGVkSW5wdXQuYXJncztcbiAgICAgICAgICAgIGNvbnN0IHRoaXNWYWwgPSBoeWRyYXRlZElucHV0LnRoaXNWYWwgPz8gbnVsbDtcblxuICAgICAgICAgICAgLy8gLS0tIFVzZXIgY29kZSBleGVjdXRpb24gLS0tXG4gICAgICAgICAgICAvLyBPbmx5IGVycm9ycyBmcm9tIHN0ZXBGbi5hcHBseSgpICh1c2VyIHN0ZXAgY29kZSkgc2hvdWxkIHByb2R1Y2VcbiAgICAgICAgICAgIC8vIHN0ZXBfZmFpbGVkL3N0ZXBfcmV0cnlpbmcuIEluZnJhc3RydWN0dXJlIGVycm9ycyAobmV0d29yaywgc2VydmVyKVxuICAgICAgICAgICAgLy8gbXVzdCBwcm9wYWdhdGUgdG8gdGhlIHF1ZXVlIGhhbmRsZXIgZm9yIGF1dG9tYXRpYyByZXRyeS5cbiAgICAgICAgICAgIGxldCB1c2VyQ29kZUVycm9yOiB1bmtub3duO1xuICAgICAgICAgICAgbGV0IHVzZXJDb2RlRmFpbGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIGNvbnN0IGV4ZWN1dGlvblN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZXN1bHQgPSBhd2FpdCB0cmFjZSgnc3RlcC5leGVjdXRlJywge30sIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgY29udGV4dFN0b3JhZ2UucnVuKFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdGVwTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcFN0YXJ0ZWRBdDogbmV3IERhdGUoK3N0ZXBTdGFydGVkQXQpLFxuICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93TWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1N0YXJ0ZWRBdDogbmV3IERhdGUoK3dvcmtmbG93U3RhcnRlZEF0KSxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiB0aGVyZSBzaG91bGQgYmUgYSBnZXRVcmwgbWV0aG9kIG9uIHRoZSB3b3JsZCBpbnRlcmZhY2UgaXRzZWxmLiBUaGlzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gc29sdXRpb24gb25seSB3b3JrcyBmb3IgdmVyY2VsICsgbG9jYWwgd29ybGRzLlxuICAgICAgICAgICAgICAgICAgICAgIHVybDogaXNWZXJjZWxcbiAgICAgICAgICAgICAgICAgICAgICAgID8gYGh0dHBzOi8vJHtwcm9jZXNzLmVudi5WRVJDRUxfVVJMfWBcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0ID8/IDMwMDB9YCxcbiAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlczogeyBlbmNyeXB0aW9uOiAhIWVuY3J5cHRpb25LZXkgfSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dEZXBsb3ltZW50SWQ6IHByb2Nlc3MuZW52LlZFUkNFTF9ERVBMT1lNRU5UX0lELFxuICAgICAgICAgICAgICAgICAgICBvcHMsXG4gICAgICAgICAgICAgICAgICAgIGNsb3N1cmVWYXJzOiBoeWRyYXRlZElucHV0LmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICgpID0+IHN0ZXBGbi5hcHBseSh0aGlzVmFsLCBhcmdzKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIHVzZXJDb2RlRXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgIHVzZXJDb2RlRmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGV4ZWN1dGlvblRpbWVNcyA9IERhdGUubm93KCkgLSBleGVjdXRpb25TdGFydFRpbWU7XG5cbiAgICAgICAgICAgIGNhbmNlbEFib3J0UmVhZGVycyguLi5hcmdzLCB0aGlzVmFsLCBoeWRyYXRlZElucHV0LmNsb3N1cmVWYXJzKTtcblxuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5RdWV1ZUV4ZWN1dGlvblRpbWVNcyhleGVjdXRpb25UaW1lTXMpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIC0tLSBEZWh5ZHJhdGUgKHNlcmlhbGl6ZSkgdGhlIHN0ZXAncyByZXR1cm4gdmFsdWUgLS0tXG4gICAgICAgICAgICAvLyBBIG5vbi1zZXJpYWxpemFibGUgcmV0dXJuIHZhbHVlIGlzIGEgdXNlci1jb2RlIGJ1Zywgbm90IGFuXG4gICAgICAgICAgICAvLyBpbmZyYXN0cnVjdHVyZSBmYWlsdXJlLiBSb3V0ZSBpdCB0aHJvdWdoIHRoZSBzYW1lIHN0ZXAtZmFpbHVyZVxuICAgICAgICAgICAgLy8gcGF0aCBhcyBhIHRocm93biBlcnJvciBzbyBTZXJpYWxpemF0aW9uRXJyb3IgKHdoaWNoIGlzIG1hcmtlZFxuICAgICAgICAgICAgLy8gYGZhdGFsOiB0cnVlYCkgc2hvcnQtY2lyY3VpdHMgdGhlIHJldHJ5IGxvb3AgaW5zdGVhZCBvZlxuICAgICAgICAgICAgLy8gYnViYmxpbmcgYXMgYW4gSFRUUCA1MDAgYW5kIGJ1cm5pbmcgdGhyb3VnaCBhbGwgNCBxdWV1ZVxuICAgICAgICAgICAgLy8gZGVsaXZlcmllcyBvbiBhIGd1YXJhbnRlZWQtdG8tZmFpbCBtZXNzYWdlLlxuICAgICAgICAgICAgaWYgKCF1c2VyQ29kZUZhaWxlZCkge1xuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IHRyYWNlKFxuICAgICAgICAgICAgICAgICAgJ3N0ZXAuZGVoeWRyYXRlJyxcbiAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICAgYXN5bmMgKGRlaHlkcmF0ZVNwYW4pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVoeWRyYXRlZCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZShcbiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICAgIG9wc1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkdXJhdGlvbk1zID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcbiAgICAgICAgICAgICAgICAgICAgZGVoeWRyYXRlU3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlF1ZXVlU2VyaWFsaXplVGltZU1zKGR1cmF0aW9uTXMpLFxuICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmVzdWx0VHlwZSh0eXBlb2YgZGVoeWRyYXRlZCksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVoeWRyYXRlZDtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB1c2VyQ29kZUVycm9yID0gZXJyO1xuICAgICAgICAgICAgICAgIHVzZXJDb2RlRmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyAtLS0gSGFuZGxlIHVzZXIgY29kZSBlcnJvcnMgLS0tXG4gICAgICAgICAgICBpZiAodXNlckNvZGVGYWlsZWQpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyID0gdXNlckNvZGVFcnJvcjtcblxuICAgICAgICAgICAgICAvLyBJbmZyYXN0cnVjdHVyZSBlcnJvcnMgdGhhdCBzb21laG93IHN1cmZhY2VkIHRocm91Z2ggdXNlciBjb2RlXG4gICAgICAgICAgICAgIC8vIHNob3VsZCBwcm9wYWdhdGUgdG8gdGhlIHF1ZXVlIGhhbmRsZXIgZm9yIHJldHJ5LCBub3QgY29uc3VtZVxuICAgICAgICAgICAgICAvLyBzdGVwIGF0dGVtcHRzLlxuICAgICAgICAgICAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAvLyBXb3JrZmxvdyBoYXMgYWxyZWFkeSBjb21wbGV0ZWQsIHNvIG5vLW9wXG4gICAgICAgICAgICAgICAgc3RlcExvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgc3RlcCcsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKFdvcmtmbG93V29ybGRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVyci5zdGF0dXMgIT09IHVuZGVmaW5lZCAmJiBlcnIuc3RhdHVzID49IDUwMCkge1xuICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIC8vIEFib3J0IGZhaWx1cmVzIGNhbiBjcm9zcyBWTS9zZXJpYWxpemF0aW9uIHJlYWxtcywgd2hlcmVcbiAgICAgICAgICAgICAgLy8gYGluc3RhbmNlb2YgRXJyb3JgIGlzIG5vdCByZWxpYWJsZS5cbiAgICAgICAgICAgICAgY29uc3QgZWZmZWN0aXZlRXJyID0gcHJvbW90ZUFib3J0RXJyb3JUb0ZhdGFsKGVycik7XG4gICAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRFcnJvciA9IGF3YWl0IG5vcm1hbGl6ZVVua25vd25FcnJvcihlZmZlY3RpdmVFcnIpO1xuICAgICAgICAgICAgICBjb25zdCBub3JtYWxpemVkU3RhY2sgPVxuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRFcnJvci5zdGFjayB8fCBnZXRFcnJvclN0YWNrKGVmZmVjdGl2ZUVycikgfHwgJyc7XG5cbiAgICAgICAgICAgICAgLy8gUmVjb3JkIGV4Y2VwdGlvbiBmb3IgT1RFTCBlcnJvciB0cmFja2luZ1xuICAgICAgICAgICAgICBpZiAoZWZmZWN0aXZlRXJyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgICAgICBzcGFuPy5yZWNvcmRFeGNlcHRpb24/LihlZmZlY3RpdmVFcnIpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIGVycm9yIGNhdGVnb3J5IGFuZCByZXRyeWFiaWxpdHlcbiAgICAgICAgICAgICAgY29uc3QgaXNGYXRhbCA9IEZhdGFsRXJyb3IuaXMoZWZmZWN0aXZlRXJyKTtcbiAgICAgICAgICAgICAgY29uc3QgaXNSZXRyeWFibGUgPSBSZXRyeWFibGVFcnJvci5pcyhlZmZlY3RpdmVFcnIpO1xuICAgICAgICAgICAgICBjb25zdCBlcnJvckNhdGVnb3J5ID0gaXNGYXRhbFxuICAgICAgICAgICAgICAgID8gJ2ZhdGFsJ1xuICAgICAgICAgICAgICAgIDogaXNSZXRyeWFibGVcbiAgICAgICAgICAgICAgICAgID8gJ3JldHJ5YWJsZSdcbiAgICAgICAgICAgICAgICAgIDogJ3RyYW5zaWVudCc7XG5cbiAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBFcnJvck5hbWUoZ2V0RXJyb3JOYW1lKGVmZmVjdGl2ZUVycikpLFxuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRXJyb3JNZXNzYWdlKG5vcm1hbGl6ZWRFcnJvci5tZXNzYWdlKSxcbiAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JUeXBlKGdldEVycm9yTmFtZShlZmZlY3RpdmVFcnIpKSxcbiAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JDYXRlZ29yeShlcnJvckNhdGVnb3J5KSxcbiAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JSZXRyeWFibGUoIWlzRmF0YWwpLFxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBpZiAoaXNGYXRhbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gZGVzY3JpYmVFcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyaWVuZGx5U3RlcCA9IGZvcm1hdFN0ZXBOYW1lKHN0ZXBOYW1lKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmcmFtaW5nID1cbiAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uLmF0dHJpYnV0aW9uID09PSAnc2RrJ1xuICAgICAgICAgICAgICAgICAgICA/IGBTdGVwICR7ZnJpZW5kbHlTdGVwfSBmYWlsZWQgd2l0aCBhIEZhdGFsRXJyb3IgZnJvbSB0aGUgU0RLIHJ1bnRpbWUg4oCUIGJ1YmJsaW5nIHVwIHRvIHBhcmVudCB3b3JrZmxvd2BcbiAgICAgICAgICAgICAgICAgICAgOiBgU3RlcCAke2ZyaWVuZGx5U3RlcH0gdGhyZXcgYSBGYXRhbEVycm9yIOKAlCBidWJibGluZyB1cCB0byBwYXJlbnQgd29ya2Zsb3dgO1xuICAgICAgICAgICAgICAgIC8vIE1pcnJvciB0aGUgd29ya2Zsb3ctbGV2ZWwgbG9nIGZvcm1hdHRpbmc6IHB1dCB0aGUgZnJhbWluZyArXG4gICAgICAgICAgICAgICAgLy8gc3RhY2sgaW50byB0aGUgbWVzc2FnZSBzbyBjb25zb2xlLmVycm9yIHJlbmRlcnMgdGhlIHN0YWNrXG4gICAgICAgICAgICAgICAgLy8gaW5saW5lLCBhbmQga2VlcCB0aGUgbWV0YWRhdGEgb2JqZWN0IHNtYWxsIHdpdGggb25seSB0aGVcbiAgICAgICAgICAgICAgICAvLyBzdHJ1Y3R1cmVkIGZpZWxkcyB0aGF0IGxvZyBkcmFpbnMgd2FudCB0byBpbmRleC5cbiAgICAgICAgICAgICAgICAvLyBObyBgaGludGAgZmllbGQgaGVyZSDigJQgYWN0aW9uYWJsZSBoaW50IHRleHQgbGl2ZXMgb24gdGhlXG4gICAgICAgICAgICAgICAgLy8gZXJyb3IgbWVzc2FnZSBpdHNlbGYgKHNvIGl0IHN1cnZpdmVzIHNlcmlhbGl6YXRpb24g4oaSXG4gICAgICAgICAgICAgICAgLy8gZXZlbnQgbG9nIOKGkiBvYnNlcnZhYmlsaXR5IHJlaHlkcmF0ZSksIGFuZCBhZGRpbmcgaXRcbiAgICAgICAgICAgICAgICAvLyBhZ2FpbiBoZXJlIGp1c3QgZHVwbGljYXRlcyBpdCBvbiBzdGRlcnIuXG4gICAgICAgICAgICAgICAgc3RlcExvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICAgIGAke2ZyYW1pbmd9XFxuJHtub3JtYWxpemVkU3RhY2sgfHwgbm9ybWFsaXplZEVycm9yLm1lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JBdHRyaWJ1dGlvbjogZGVzY3JpcHRpb24uYXR0cmlidXRpb24sXG4gICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogbm9ybWFsaXplZEVycm9yLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogbm9ybWFsaXplZEVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAvLyBGYWlsIHRoZSBzdGVwIHZpYSBldmVudCAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpLlxuICAgICAgICAgICAgICAgIC8vIFBlcnNpc3QgdGhlIHByb21vdGVkIEZhdGFsRXJyb3IgZm9yIGFib3J0cyBzbyB0aGUgcGFyZW50XG4gICAgICAgICAgICAgICAgLy8gd29ya2Zsb3cgY2FuIGRpc3Rpbmd1aXNoIGNhbmNlbGxhdGlvbiBmcm9tIHJldHJ5IGV4aGF1c3Rpb24uXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZWZmZWN0aXZlRXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5XG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoc3RlcEZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgaW4gdGVybWluYWwgc3RhdGUg4oCUIGlkZW1wb3RlbnQuXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IHN0ZXBGYWlsRXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB0aHJvdyBzdGVwRmFpbEVycjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdmYWlsZWQnKSxcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRmF0YWxFcnJvcih0cnVlKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXhSZXRyaWVzID1cbiAgICAgICAgICAgICAgICAgIHN0ZXBGbi5tYXhSZXRyaWVzID8/IERFRkFVTFRfU1RFUF9NQVhfUkVUUklFUztcbiAgICAgICAgICAgICAgICAvLyBzdGVwLmF0dGVtcHQgd2FzIGluY3JlbWVudGVkIGJ5IHN0ZXBfc3RhcnRlZCwgdXNlIGl0IGhlcmVcbiAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50QXR0ZW1wdCA9IHN0ZXAuYXR0ZW1wdDtcblxuICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBBdHRlbXB0KGN1cnJlbnRBdHRlbXB0KSxcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwTWF4UmV0cmllcyhtYXhSZXRyaWVzKSxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIE5vdGU6IG1heFJldHJpZXMgaXMgdGhlIG51bWJlciBvZiBSRVRSSUVTIGFmdGVyIHRoZSBmaXJzdCBhdHRlbXB0LCBzbyB0b3RhbCBhdHRlbXB0cyA9IG1heFJldHJpZXMgKyAxXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRBdHRlbXB0ID49IG1heFJldHJpZXMgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAvLyBNYXggcmV0cmllcyByZWFjaGVkXG4gICAgICAgICAgICAgICAgICBjb25zdCByZXRyeUNvdW50ID0gc3RlcC5hdHRlbXB0IC0gMTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gZGVzY3JpYmVFcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgZnJpZW5kbHlTdGVwID0gZm9ybWF0U3RlcE5hbWUoc3RlcE5hbWUpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgZnJhbWluZyA9XG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uLmF0dHJpYnV0aW9uID09PSAnc2RrJ1xuICAgICAgICAgICAgICAgICAgICAgID8gYFN0ZXAgJHtmcmllbmRseVN0ZXB9IGhpdCBtYXggcmV0cmllcyBvbiBhbiBTREsgcnVudGltZSBlcnJvciDigJQgYnViYmxpbmcgdG8gcGFyZW50IHdvcmtmbG93YFxuICAgICAgICAgICAgICAgICAgICAgIDogYFN0ZXAgJHtmcmllbmRseVN0ZXB9IGhpdCBtYXggcmV0cmllcyDigJQgYnViYmxpbmcgZXJyb3IgdGhyb3duIGJ5IHlvdXIgc3RlcCB0byB0aGUgcGFyZW50IHdvcmtmbG93YDtcbiAgICAgICAgICAgICAgICAgIHN0ZXBMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGAke2ZyYW1pbmd9XFxuJHtub3JtYWxpemVkU3RhY2sgfHwgbm9ybWFsaXplZEVycm9yLm1lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBhdHRlbXB0OiBzdGVwLmF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgICAgcmV0cnlDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvckF0dHJpYnV0aW9uOiBkZXNjcmlwdGlvbi5hdHRyaWJ1dGlvbixcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IG5vcm1hbGl6ZWRFcnJvci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogbm9ybWFsaXplZEVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAvLyBEb24ndCBpbmNsdWRlIHRoZSBtYWNoaW5lIHN0ZXAgbmFtZSBpbiB0aGUgcGVyc2lzdGVkXG4gICAgICAgICAgICAgICAgICAvLyBlcnJvciBtZXNzYWdlIOKAlCBvYnNlcnZhYmlsaXR5IGFscmVhZHkgc2hvd3Mgd2hpY2ggc3RlcFxuICAgICAgICAgICAgICAgICAgLy8gcHJvZHVjZWQgdGhlIGV2ZW50LCBhbmQgYHN0ZXBOYW1lOiAnc3RlcC8vLi8uLi4vZm9vJ2BcbiAgICAgICAgICAgICAgICAgIC8vIGluIHRoZSB0aXRsZSBpcyBqdXN0IG5vaXNlLiBUaGUgQ0xJIGxvZ2dlciByZW5kZXJzXG4gICAgICAgICAgICAgICAgICAvLyBgU3RlcCBmb28gKC4vLi4uKSBoaXQgbWF4IHJldHJpZXNgIHNlcGFyYXRlbHkuXG4gICAgICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgU3RlcCBmYWlsZWQgYWZ0ZXIgJHttYXhSZXRyaWVzfSAke3BsdXJhbGl6ZSgncmV0cnknLCAncmV0cmllcycsIG1heFJldHJpZXMpfTogJHtub3JtYWxpemVkRXJyb3IubWVzc2FnZX1gO1xuICAgICAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgc3RlcCB2aWEgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKS5cbiAgICAgICAgICAgICAgICAgIC8vIFdyYXAgdGhlIG9yaWdpbmFsIGVycm9yIHdpdGggYSBGYXRhbEVycm9yIHRoYXQgcHJlc2VydmVzXG4gICAgICAgICAgICAgICAgICAvLyB0aGUgd3JhcHBlZCBtZXNzYWdlIHBsdXMgdGhlIG9yaWdpbmFsIHRocm93biB2YWx1ZSBhc1xuICAgICAgICAgICAgICAgICAgLy8gYGNhdXNlYCBzbyBpdCdzIHJlY292ZXJhYmxlIGFmdGVyIGh5ZHJhdGlvbi5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHdyYXBwZWRFcnJvciA9IG5ldyBGYXRhbEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAod3JhcHBlZEVycm9yIGFzIEVycm9yKS5jYXVzZSA9IGVycjtcbiAgICAgICAgICAgICAgICAgIGlmIChub3JtYWxpemVkU3RhY2spIHdyYXBwZWRFcnJvci5zdGFjayA9IG5vcm1hbGl6ZWRTdGFjaztcbiAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JhcHBlZEVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleVxuICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKHN0ZXBGYWlsRXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAgIC8vIFN0ZXAgYWxyZWFkeSBpbiB0ZXJtaW5hbCBzdGF0ZSDigJQgaWRlbXBvdGVudC5cbiAgICAgICAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBzdGVwRmFpbEVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgc3RlcEZhaWxFcnI7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlFeGhhdXN0ZWQodHJ1ZSksXG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgLy8gTm90IGF0IG1heCByZXRyaWVzIHlldCAtIGxvZyBhcyBhIHJldHJ5YWJsZSBlcnJvclxuICAgICAgICAgICAgICAgICAgaWYgKFJldHJ5YWJsZUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RlcExvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICdFbmNvdW50ZXJlZCBSZXRyeWFibGVFcnJvciwgc3RlcCB3aWxsIGJlIHJldHJpZWQnLFxuICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQ6IGN1cnJlbnRBdHRlbXB0LFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBlcnIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrOiBub3JtYWxpemVkU3RhY2ssXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3RlcExvZ2dlci5pbmZvKCdFbmNvdW50ZXJlZCBFcnJvciwgc3RlcCB3aWxsIGJlIHJldHJpZWQnLCB7XG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQ6IGN1cnJlbnRBdHRlbXB0LFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogbm9ybWFsaXplZEVycm9yLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBub3JtYWxpemVkRXJyb3IubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrOiBub3JtYWxpemVkU3RhY2ssXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgLy8gU2V0IHN0ZXAgdG8gcGVuZGluZyBmb3IgcmV0cnkgdmlhIGV2ZW50IChldmVudC1zb3VyY2VkIGFyY2hpdGVjdHVyZSlcbiAgICAgICAgICAgICAgICAgIC8vIHN0ZXBfcmV0cnlpbmcgcmVjb3JkcyB0aGUgZXJyb3IgYW5kIHNldHMgc3RhdHVzIHRvIHBlbmRpbmcuXG4gICAgICAgICAgICAgICAgICAvLyBTZXJpYWxpemUgdGhlIG9yaWdpbmFsIHRocm93biB2YWx1ZSBzbyBpdHMgZnVsbCB0eXBlIGlkZW50aXR5XG4gICAgICAgICAgICAgICAgICAvLyBhbmQgY3VzdG9tIHByb3BlcnRpZXMgcm91bmQtdHJpcCB0aHJvdWdoIHRoZSBldmVudCBsb2cuXG4gICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9yZXRyeWluZycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleVxuICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4oUmV0cnlhYmxlRXJyb3IuaXMoZXJyKSAmJiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0cnlBZnRlcjogZXJyLnJldHJ5QWZ0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKHN0ZXBSZXRyeUVycikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhzdGVwUmV0cnlFcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gU3RlcCBhbHJlYWR5IGluIHRlcm1pbmFsIHN0YXRlIOKAlCBpZGVtcG90ZW50LlxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAnVHJpZWQgcmV0cnlpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBzdGVwUmV0cnlFcnIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBzdGVwUmV0cnlFcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBzdGVwUmV0cnlFcnI7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbWVvdXRTZWNvbmRzID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIFJldHJ5YWJsZUVycm9yLmlzKGVycilcbiAgICAgICAgICAgICAgICAgICAgICA/IE1hdGguY2VpbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKCtlcnIucmV0cnlBZnRlci5nZXRUaW1lKCkgLSBEYXRlLm5vdygpKSAvIDEwMDBcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICA6IDFcbiAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJldHJ5VGltZW91dFNlY29uZHModGltZW91dFNlY29uZHMpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJldHJ5V2lsbFJldHJ5KHRydWUpLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIC8vIEFkZCBzcGFuIGV2ZW50IGZvciByZXRyeSBzY2hlZHVsaW5nXG4gICAgICAgICAgICAgICAgICBzcGFuPy5hZGRFdmVudD8uKCdyZXRyeS5zY2hlZHVsZWQnLCB7XG4gICAgICAgICAgICAgICAgICAgICdyZXRyeS50aW1lb3V0X3NlY29uZHMnOiB0aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgICAgICAgICAgICAgJ3JldHJ5LmF0dGVtcHQnOiBjdXJyZW50QXR0ZW1wdCxcbiAgICAgICAgICAgICAgICAgICAgJ3JldHJ5Lm1heF9yZXRyaWVzJzogbWF4UmV0cmllcyxcbiAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAvLyBJdCdzIGEgcmV0cnlhYmxlIGVycm9yIC0gc28gaGF2ZSB0aGUgcXVldWUga2VlcCB0aGUgbWVzc2FnZSB2aXNpYmxlXG4gICAgICAgICAgICAgICAgICAvLyBzbyB0aGF0IGl0IGdldHMgcmV0cmllZC5cbiAgICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgLy8gUmUtaW52b2tlIHRoZSB3b3JrZmxvdyB0byBoYW5kbGUgdGhlIGZhaWxlZC9yZXRyeWluZyBzdGVwXG4gICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZSh3b3JsZCwgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lKSwge1xuICAgICAgICAgICAgICAgIHJ1bklkOiB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIC0tLSBJbmZyYXN0cnVjdHVyZTogY29tcGxldGUgdGhlIHN0ZXAgLS0tXG4gICAgICAgICAgICAvLyBFcnJvcnMgaGVyZSAobmV0d29yayBmYWlsdXJlcywgc2VydmVyIGVycm9ycykgcHJvcGFnYXRlIHRvIHRoZVxuICAgICAgICAgICAgLy8gcXVldWUgaGFuZGxlciBmb3IgYXV0b21hdGljIHJldHJ5LlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIE5PVEU6IE5vbmUgb2YgdGhlIGNvZGUgZnJvbSB0aGlzIHBvaW50IGlzIGd1YXJhbnRlZWQgdG8gcnVuLlxuICAgICAgICAgICAgLy8gU2luY2UgdGhlIHN0ZXAgbWlnaHQgZmFpbCBvciBjYXVzZSBhIGZ1bmN0aW9uIHRpbWVvdXQgYW5kIHRoZVxuICAgICAgICAgICAgLy8gcHJvY2VzcyBtaWdodCBiZSBTSUdLSUxMJ2QsIHRoZSB3b3JrZmxvdyBydW50aW1lIG11c3QgYmVcbiAgICAgICAgICAgIC8vIHJlc2lsaWVudCB0byB0aGUgYmVsb3cgY29kZSBub3QgZXhlY3V0aW5nIG9uIGEgZmFpbGVkIHN0ZXAuXG4gICAgICAgICAgICAvLyAoRGVoeWRyYXRpb24gYWxyZWFkeSBoYXBwZW5lZCBhYm92ZSBhbmQgaXMgYWNjb3VudGVkIGZvciBpbiB0aGVcbiAgICAgICAgICAgIC8vIHVzZXJDb2RlRmFpbGVkIHBhdGguKVxuICAgICAgICAgICAgd2FpdFVudGlsKFxuICAgICAgICAgICAgICBQcm9taXNlLmFsbChvcHMpLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBJZ25vcmUgZXhwZWN0ZWQgY2xpZW50IGRpc2Nvbm5lY3QgZXJyb3JzIChlLmcuLCBicm93c2VyIHJlZnJlc2ggZHVyaW5nIHN0cmVhbWluZylcbiAgICAgICAgICAgICAgICBjb25zdCBpc0Fib3J0RXJyb3IgPVxuICAgICAgICAgICAgICAgICAgZXJyPy5uYW1lID09PSAnQWJvcnRFcnJvcicgfHwgZXJyPy5uYW1lID09PSAnUmVzcG9uc2VBYm9ydGVkJztcbiAgICAgICAgICAgICAgICBpZiAoIWlzQWJvcnRFcnJvcikgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgLy8gUnVuIHN0ZXBfY29tcGxldGVkIGFuZCB0cmFjZSBzZXJpYWxpemF0aW9uIGNvbmN1cnJlbnRseTtcbiAgICAgICAgICAgIC8vIHRoZSB0cmFjZSBjYXJyaWVyIGlzIHVzZWQgaW4gdGhlIGZpbmFsIHF1ZXVlTWVzc2FnZSBjYWxsIGJlbG93XG4gICAgICAgICAgICBsZXQgc3RlcENvbXBsZXRlZDQwOSA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgWywgdHJhY2VDYXJyaWVyXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgd29ybGQuZXZlbnRzXG4gICAgICAgICAgICAgICAgLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY29tcGxldGVkJyxcbiAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdDogcmVzdWx0IGFzIFVpbnQ4QXJyYXksXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAuY2F0Y2goKGVycjogdW5rbm93bikgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgaW4gdGVybWluYWwgc3RhdGUg4oCUIGlkZW1wb3RlbnQuXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGNvbXBsZXRpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIHN0ZXBDb21wbGV0ZWQ0MDkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgIGlmIChzdGVwQ29tcGxldGVkNDA5KSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdjb21wbGV0ZWQnKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXN1bHRUeXBlKHR5cGVvZiByZXN1bHQpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFF1ZXVlIHRoZSB3b3JrZmxvdyBjb250aW51YXRpb24gd2l0aCB0aGUgY29uY3VycmVudGx5LXJlc29sdmVkIHRyYWNlIGNhcnJpZXJcbiAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZSh3b3JsZCwgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lKSwge1xuICAgICAgICAgICAgICBydW5JZDogd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgKTtcblxuLyoqXG4gKiBBIHNpbmdsZSByb3V0ZSB0aGF0IGhhbmRsZXMgYW55IHN0ZXAgZXhlY3V0aW9uIHJlcXVlc3QgYW5kIHJvdXRlcyB0byB0aGVcbiAqIGFwcHJvcHJpYXRlIHN0ZXAgZnVuY3Rpb24uIFdlIG1heSBldmVudHVhbGx5IHdhbnQgdG8gY3JlYXRlIGRpZmZlcmVudCBidW5kbGVzXG4gKiBmb3IgZWFjaCBzdGVwLCB0aGlzIGlzIHRlbXBvcmFyeS5cbiAqL1xubGV0IGNhY2hlZFN0ZXBIYW5kbGVyOiAoKHJlcTogUmVxdWVzdCkgPT4gUHJvbWlzZTxSZXNwb25zZT4pIHwgdW5kZWZpbmVkO1xuZXhwb3J0IGNvbnN0IHN0ZXBFbnRyeXBvaW50OiAocmVxOiBSZXF1ZXN0KSA9PiBQcm9taXNlPFJlc3BvbnNlPiA9XG4gIC8qIEBfX1BVUkVfXyAqLyB3aXRoSGVhbHRoQ2hlY2soYXN5bmMgKHJlcSkgPT4ge1xuICAgIGlmICghY2FjaGVkU3RlcEhhbmRsZXIpIHtcbiAgICAgIGNhY2hlZFN0ZXBIYW5kbGVyID0gc3RlcEhhbmRsZXIoYXdhaXQgZ2V0V29ybGRIYW5kbGVycygpKTtcbiAgICB9XG4gICAgcmV0dXJuIGNhY2hlZFN0ZXBIYW5kbGVyKHJlcSk7XG4gIH0pO1xuIl19
|
|
786
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3RlcC1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGNBQWMsRUFDZCxlQUFlLEVBQ2Ysc0JBQXNCLEVBQ3RCLGFBQWEsRUFDYixhQUFhLEVBQ2Isb0JBQW9CLEVBQ3BCLGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxjQUFjLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ25ELE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIscUJBQXFCLEVBQ3JCLG9CQUFvQixFQUVwQix1QkFBdUIsR0FDeEIsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDckQsT0FBTyxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRCxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLGtCQUFrQixFQUNsQix3QkFBd0IsRUFDeEIsb0JBQW9CLEVBQ3BCLGdCQUFnQixHQUNqQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBQ2xFLE9BQU8sRUFDTCxXQUFXLEVBQ1gsb0JBQW9CLEVBQ3BCLHFCQUFxQixFQUNyQixLQUFLLEVBQ0wsZ0JBQWdCLEdBQ2pCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUNMLFlBQVksRUFDWixhQUFhLEVBQ2IscUJBQXFCLEVBQ3JCLHdCQUF3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QUMsWUFBWSxFQUFFLGlCQUFpQixDQUFDLEVBQ3JEO29CQUNFLEtBQUssRUFBRSxhQUFhO29CQUNwQixZQUFZO29CQUNaLFdBQVcsRUFBRSxJQUFJLElBQUksRUFBRTtpQkFDeEIsQ0FDRixDQUFDO1lBQ0osQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVELE1BQU0sV0FBVyxHQUFHLGlCQUFpQixFQUFFLENBQUM7QUFFeEM7Ozs7R0FJRztBQUNILElBQUksaUJBQW9FLENBQUM7QUFDekUsTUFBTSxDQUFDLE1BQU0sY0FBYztBQUN6QixlQUFlLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtJQUM1QyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN2QixpQkFBaUIsR0FBRyxXQUFXLENBQUMsTUFBTSxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUNELE9BQU8saUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDaEMsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBGYXRhbEVycm9yLFxuICBSZXRyeWFibGVFcnJvcixcbiAgUnVuRXhwaXJlZEVycm9yLFxuICBTdGVwTm90UmVnaXN0ZXJlZEVycm9yLFxuICBUaHJvdHRsZUVycm9yLFxuICBUb29FYXJseUVycm9yLFxuICBXb3JrZmxvd1J1bnRpbWVFcnJvcixcbiAgV29ya2Zsb3dXb3JsZEVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7IGZvcm1hdFN0ZXBOYW1lLCBwbHVyYWxpemUgfSBmcm9tICdAd29ya2Zsb3cvdXRpbHMnO1xuaW1wb3J0IHsgZ2V0UG9ydCB9IGZyb20gJ0B3b3JrZmxvdy91dGlscy9nZXQtcG9ydCc7XG5pbXBvcnQge1xuICBnZXRRdWV1ZVRvcGljUHJlZml4LFxuICByZXNvbHZlUXVldWVOYW1lc3BhY2UsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICB0eXBlIFN0ZXAsXG4gIFN0ZXBJbnZva2VQYXlsb2FkU2NoZW1hLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgZGVzY3JpYmVFcnJvciB9IGZyb20gJy4uL2Rlc2NyaWJlLWVycm9yLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIsIHN0ZXBMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZ2V0U3RlcEZ1bmN0aW9uIH0gZnJvbSAnLi4vcHJpdmF0ZS5qcyc7XG5pbXBvcnQge1xuICBjYW5jZWxBYm9ydFJlYWRlcnMsXG4gIGRlaHlkcmF0ZVN0ZXBFcnJvcixcbiAgZGVoeWRyYXRlU3RlcFJldHVyblZhbHVlLFxuICBoeWRyYXRlU3RlcEFyZ3VtZW50cyxcbiAgaHlkcmF0ZVN0ZXBFcnJvcixcbn0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQgeyBjb250ZXh0U3RvcmFnZSB9IGZyb20gJy4uL3N0ZXAvY29udGV4dC1zdG9yYWdlLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHtcbiAgZ2V0U3BhbktpbmQsXG4gIGxpbmtUb0N1cnJlbnRDb250ZXh0LFxuICBzZXJpYWxpemVUcmFjZUNhcnJpZXIsXG4gIHRyYWNlLFxuICB3aXRoVHJhY2VDb250ZXh0LFxufSBmcm9tICcuLi90ZWxlbWV0cnkuanMnO1xuaW1wb3J0IHtcbiAgZ2V0RXJyb3JOYW1lLFxuICBnZXRFcnJvclN0YWNrLFxuICBub3JtYWxpemVVbmtub3duRXJyb3IsXG4gIHByb21vdGVBYm9ydEVycm9yVG9GYXRhbCxcbn0gZnJvbSAnLi4vdHlwZXMuanMnO1xuXG5pbXBvcnQgeyBNQVhfUVVFVUVfREVMSVZFUklFUyB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7XG4gIGdldFF1ZXVlT3ZlcmhlYWQsXG4gIGdldFdvcmtmbG93UXVldWVOYW1lLFxuICBoYW5kbGVIZWFsdGhDaGVja01lc3NhZ2UsXG4gIG1lbW9pemVFbmNyeXB0aW9uS2V5LFxuICBwYXJzZUhlYWx0aENoZWNrUGF5bG9hZCxcbiAgcXVldWVNZXNzYWdlLFxuICB3aXRoSGVhbHRoQ2hlY2ssXG59IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBzYWZlV2FpdFVudGlsIH0gZnJvbSAnLi93YWl0LXVudGlsLmpzJztcbmltcG9ydCB7IGdldFdvcmxkLCBnZXRXb3JsZEhhbmRsZXJzLCB0eXBlIFdvcmxkSGFuZGxlcnMgfSBmcm9tICcuL3dvcmxkLmpzJztcblxuY29uc3QgREVGQVVMVF9TVEVQX01BWF9SRVRSSUVTID0gMztcblxuZnVuY3Rpb24gY3JlYXRlU3RlcEhhbmRsZXIobmFtZXNwYWNlPzogc3RyaW5nKSB7XG4gIGNvbnN0IHJlc29sdmVkTmFtZXNwYWNlID0gcmVzb2x2ZVF1ZXVlTmFtZXNwYWNlKG5hbWVzcGFjZSk7XG4gIGNvbnN0IHN0ZXBQcmVmaXggPSBnZXRRdWV1ZVRvcGljUHJlZml4KCdzdGVwJywgcmVzb2x2ZWROYW1lc3BhY2UpO1xuXG4gIHJldHVybiAod29ybGRIYW5kbGVyczogV29ybGRIYW5kbGVycykgPT5cbiAgICB3b3JsZEhhbmRsZXJzLmNyZWF0ZVF1ZXVlSGFuZGxlcihzdGVwUHJlZml4LCBhc3luYyAobWVzc2FnZV8sIG1ldGFkYXRhKSA9PiB7XG4gICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGEgaGVhbHRoIGNoZWNrIG1lc3NhZ2VcbiAgICAgIC8vIE5PVEU6IEhlYWx0aCBjaGVjayBtZXNzYWdlcyBhcmUgaW50ZW50aW9uYWxseSB1bmF1dGhlbnRpY2F0ZWQgZm9yIG1vbml0b3JpbmcgcHVycG9zZXMuXG4gICAgICAvLyBUaGV5IG9ubHkgd3JpdGUgYSBzaW1wbGUgc3RhdHVzIHJlc3BvbnNlIHRvIGEgc3RyZWFtIGFuZCBkbyBub3QgZXhwb3NlIHNlbnNpdGl2ZSBkYXRhLlxuICAgICAgLy8gVGhlIHN0cmVhbSBuYW1lIGluY2x1ZGVzIGEgdW5pcXVlIGNvcnJlbGF0aW9uSWQgdGhhdCBtdXN0IGJlIGtub3duIGJ5IHRoZSBjYWxsZXIuXG4gICAgICBjb25zdCBoZWFsdGhDaGVjayA9IHBhcnNlSGVhbHRoQ2hlY2tQYXlsb2FkKG1lc3NhZ2VfKTtcbiAgICAgIGlmIChoZWFsdGhDaGVjaykge1xuICAgICAgICBhd2FpdCBoYW5kbGVIZWFsdGhDaGVja01lc3NhZ2UoXG4gICAgICAgICAgaGVhbHRoQ2hlY2ssXG4gICAgICAgICAgJ3N0ZXAnLFxuICAgICAgICAgIHdvcmxkSGFuZGxlcnMuc3BlY1ZlcnNpb25cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7XG4gICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQsXG4gICAgICAgIHN0ZXBJZCxcbiAgICAgICAgdHJhY2VDYXJyaWVyOiB0cmFjZUNvbnRleHQsXG4gICAgICAgIHJlcXVlc3RlZEF0LFxuICAgICAgfSA9IFN0ZXBJbnZva2VQYXlsb2FkU2NoZW1hLnBhcnNlKG1lc3NhZ2VfKTtcbiAgICAgIGNvbnN0IHsgcmVxdWVzdElkIH0gPSBtZXRhZGF0YTtcblxuICAgICAgLy8gLS0tIE1heCBkZWxpdmVyeSBjaGVjayAtLS1cbiAgICAgIC8vIEVuZm9yY2UgbWF4IGRlbGl2ZXJ5IGxpbWl0IGJlZm9yZSBhbnkgaW5mcmFzdHJ1Y3R1cmUgY2FsbHMuXG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHJ1bmF3YXkgc3RlcHMgZnJvbSBjb25zdW1pbmcgaW5maW5pdGUgcXVldWUgZGVsaXZlcmllcy5cbiAgICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIHdhbnQgdG8gZG8gdGhlIG1pbmltYWwgYW1vdW50IG9mIHdvcmsgKG5vIGZldGNoaW5nXG4gICAgICAvLyBvZiB0aGUgc3RlcCBkZXRhaWxzLCBldGMuIFdlIHNpbXBseSBhdHRlbXB0IHRvIG1hcmsgdGhlIHN0ZXAgYXMgZmFpbGVkXG4gICAgICAvLyBhbmQgZW5xdWV1ZSB0aGUgd29ya2Zsb3cgb25jZSwgYW5kIGlmIGVpdGhlciBvZiB0aG9zZSBmYWlscywgdGhlIG1lc3NhZ2VcbiAgICAgIC8vIGlzIHN0aWxsIGNvbnN1bWVkIGJ1dCB3aXRoIGFkZXF1YXRlIGxvZ2dpbmcgdGhhdCBhbiBlcnJvciBvY2N1cnJlZC5cbiAgICAgIC8vIFNjb3BlZCBsb2dnZXIgZm9yIHRoaXMgc3RlcCBpbnZvY2F0aW9uIOKAlCBhdHRhY2hlcyBydW4vc3RlcCBjb250ZXh0IHRvXG4gICAgICAvLyBldmVyeSBsb2cgbGluZSBiZWxvdyBzbyBjYWxsZXJzIGRvbid0IHJlcGVhdCBpdC5cbiAgICAgIGNvbnN0IHN0ZXBOYW1lRnJvbVF1ZXVlID0gbWV0YWRhdGEucXVldWVOYW1lLnNsaWNlKHN0ZXBQcmVmaXgubGVuZ3RoKTtcbiAgICAgIGNvbnN0IHN0ZXBSdW50aW1lTG9nZ2VyID0gcnVudGltZUxvZ2dlci5mb3JSdW4oXG4gICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgeyBzdGVwSWQsIHN0ZXBOYW1lOiBzdGVwTmFtZUZyb21RdWV1ZSB9XG4gICAgICApO1xuXG4gICAgICBpZiAobWV0YWRhdGEuYXR0ZW1wdCA+IE1BWF9RVUVVRV9ERUxJVkVSSUVTKSB7XG4gICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmVycm9yKFxuICAgICAgICAgIGBTdGVwIGhhbmRsZXIgZXhjZWVkZWQgbWF4IGRlbGl2ZXJpZXMgKCR7bWV0YWRhdGEuYXR0ZW1wdH0vJHtNQVhfUVVFVUVfREVMSVZFUklFU30pYCxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhdHRlbXB0OiBtZXRhZGF0YS5hdHRlbXB0LFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkKCk7XG4gICAgICAgICAgY29uc3QgZ2V0RW5jcnlwdGlvbktleSA9IG1lbW9pemVFbmNyeXB0aW9uS2V5KHdvcmxkLCB3b3JrZmxvd1J1bklkKTtcbiAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgRmF0YWxFcnJvcihcbiAgICAgICAgICAgIGBTdGVwIGV4Y2VlZGVkIG1heGltdW0gcXVldWUgZGVsaXZlcmllcyAoJHttZXRhZGF0YS5hdHRlbXB0fS8ke01BWF9RVUVVRV9ERUxJVkVSSUVTfSlgXG4gICAgICAgICAgKTtcbiAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgc3RlcE5hbWU6IHN0ZXBOYW1lRnJvbVF1ZXVlLFxuICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICBlcnIsXG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgYXdhaXQgZ2V0RW5jcnlwdGlvbktleSgpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICAvLyBSZS1xdWV1ZSB0aGUgd29ya2Zsb3cgdG8gaGFuZGxlIHRoZSBmYWlsZWQgc3RlcFxuICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCByZXNvbHZlZE5hbWVzcGFjZSksXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHJ1bklkOiB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIENhbid0IGV2ZW4gbWFyayB0aGUgc3RlcCBhcyBmYWlsZWQuIENvbnN1bWUgdGhlIG1lc3NhZ2UgdG8gc3RvcFxuICAgICAgICAgIC8vIGZ1cnRoZXIgcmV0cmllcy4gVGhlIHJ1biB3aWxsIHJlbWFpbiBpbiBpdHMgY3VycmVudCBzdGF0ZS5cbiAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgIGBGYWlsZWQgdG8gbWFyayBzdGVwIGFzIGZhaWxlZCBhZnRlciAke21ldGFkYXRhLmF0dGVtcHR9IGRlbGl2ZXJ5IGF0dGVtcHRzLiBgICtcbiAgICAgICAgICAgICAgYEEgcGVyc2lzdGVudCBlcnJvciBpcyBwcmV2ZW50aW5nIHRoZSBzdGVwIGZyb20gYmVpbmcgdGVybWluYXRlZC4gYCArXG4gICAgICAgICAgICAgIGBUaGUgcnVuIHdpbGwgcmVtYWluIGluIGl0cyBjdXJyZW50IHN0YXRlIHVudGlsIG1hbnVhbGx5IHJlc29sdmVkLiBgICtcbiAgICAgICAgICAgICAgYFRoaXMgaXMgbW9zdCBsaWtlbHkgZHVlIHRvIGEgcGVyc2lzdGVudCBvdXRhZ2Ugb2YgdGhlIHdvcmtmbG93IGJhY2tlbmQgYCArXG4gICAgICAgICAgICAgIGBvciBhIGJ1ZyBpbiB0aGUgd29ya2Zsb3cgcnVudGltZSBhbmQgc2hvdWxkIGJlIHJlcG9ydGVkIHRvIHRoZSBXb3JrZmxvdyB0ZWFtLmAsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGF0dGVtcHQ6IG1ldGFkYXRhLmF0dGVtcHQsXG4gICAgICAgICAgICAgIGVycm9yTmFtZTogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubmFtZSA6ICdVbmtub3duRXJyb3InLFxuICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgICAgICAgZXJyb3JTdGFjazogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIuc3RhY2sgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNwYW5MaW5rcyA9IGF3YWl0IGxpbmtUb0N1cnJlbnRDb250ZXh0KCk7XG4gICAgICAvLyBFeGVjdXRlIHN0ZXAgd2l0aGluIHRoZSBwcm9wYWdhdGVkIHRyYWNlIGNvbnRleHRcbiAgICAgIHJldHVybiBhd2FpdCB3aXRoVHJhY2VDb250ZXh0KHRyYWNlQ29udGV4dCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAvLyBFeHRyYWN0IHRoZSBzdGVwIG5hbWUgZnJvbSB0aGUgdG9waWMgbmFtZVxuICAgICAgICBjb25zdCBzdGVwTmFtZSA9IG1ldGFkYXRhLnF1ZXVlTmFtZS5zbGljZShzdGVwUHJlZml4Lmxlbmd0aCk7XG4gICAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGQoKTtcbiAgICAgICAgY29uc3QgaXNWZXJjZWwgPSBwcm9jZXNzLmVudi5WRVJDRUxfVVJMICE9PSB1bmRlZmluZWQ7XG5cbiAgICAgICAgLy8gTWVtb2l6ZWQgYWNjZXNzb3IgZm9yIHRoZSBwZXItcnVuIEFFUy0yNTYgZW5jcnlwdGlvbiBrZXkuIFRoZSBmaXJzdFxuICAgICAgICAvLyBjYWxsZXIgKHR5cGljYWxseSBgaHlkcmF0ZVN0ZXBBcmd1bWVudHNgIGZvciBpbnB1dCBkZXNlcmlhbGl6YXRpb24sXG4gICAgICAgIC8vIG9yIG9uZSBvZiB0aGUgZWFybHktcmV0dXJuIGRlaHlkcmF0ZVN0ZXBFcnJvciBwYXRocyBpZiBzdGVwX3N0YXJ0ZWRcbiAgICAgICAgLy8gZmFpbHMpIHRyaWdnZXJzIHRoZSBhY3R1YWwgZmV0Y2ggLyBIS0RGIGRlcml2YXRpb247IHN1YnNlcXVlbnRcbiAgICAgICAgLy8gY2FsbGVycyBhd2FpdCB0aGUgY2FjaGVkIHByb21pc2UuIFN0ZXBzIHRoYXQgZmFpbCBiZWZvcmUgYW55XG4gICAgICAgIC8vIGVuY3J5cHRpb24tYXdhcmUgd29yayBoYXBwZW5zIChlLmcuIGFuIGltbWVkaWF0ZSBzdGVwX3N0YXJ0ZWRcbiAgICAgICAgLy8gY29uZmxpY3QpIHNraXAgdGhlIGZldGNoIGVudGlyZWx5LlxuICAgICAgICBjb25zdCBnZXRFbmNyeXB0aW9uS2V5ID0gbWVtb2l6ZUVuY3J5cHRpb25LZXkod29ybGQsIHdvcmtmbG93UnVuSWQpO1xuXG4gICAgICAgIC8vIFJlc29sdmUgbG9jYWwgYXN5bmMgdmFsdWVzIGNvbmN1cnJlbnRseSBiZWZvcmUgZW50ZXJpbmcgdGhlIHRyYWNlIHNwYW5cbiAgICAgICAgY29uc3QgW3BvcnQsIHNwYW5LaW5kXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICBpc1ZlcmNlbCA/IHVuZGVmaW5lZCA6IGdldFBvcnQoKSxcbiAgICAgICAgICBnZXRTcGFuS2luZCgnQ09OU1VNRVInKSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgcmV0dXJuIHRyYWNlKFxuICAgICAgICAgIGBTVEVQICR7c3RlcE5hbWV9YCxcbiAgICAgICAgICB7IGtpbmQ6IHNwYW5LaW5kLCBsaW5rczogc3BhbkxpbmtzIH0sXG4gICAgICAgICAgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcE5hbWUoc3RlcE5hbWUpLFxuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcEF0dGVtcHQobWV0YWRhdGEuYXR0ZW1wdCksXG4gICAgICAgICAgICAgIC8vIFN0YW5kYXJkIE9URUwgbWVzc2FnaW5nIGNvbnZlbnRpb25zXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdTeXN0ZW0oJ3ZlcmNlbC1xdWV1ZScpLFxuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nRGVzdGluYXRpb25OYW1lKG1ldGFkYXRhLnF1ZXVlTmFtZSksXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdNZXNzYWdlSWQobWV0YWRhdGEubWVzc2FnZUlkKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLk1lc3NhZ2luZ09wZXJhdGlvblR5cGUoJ3Byb2Nlc3MnKSxcbiAgICAgICAgICAgICAgLi4uZ2V0UXVldWVPdmVyaGVhZCh7IHJlcXVlc3RlZEF0IH0pLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIE5vdGU6IFN0ZXAgZnVuY3Rpb24gdmFsaWRhdGlvbiBoYXBwZW5zIGFmdGVyIHN0ZXBfc3RhcnRlZCBzbyB3ZSBjYW5cbiAgICAgICAgICAgIC8vIHByb3Blcmx5IGZhaWwgdGhlIHN0ZXAgKG5vdCB0aGUgcnVuKSBpZiB0aGUgZnVuY3Rpb24gaXMgbm90IHJlZ2lzdGVyZWQuXG4gICAgICAgICAgICAvLyBUaGlzIGFsbG93cyB0aGUgd29ya2Zsb3cgdG8gaGFuZGxlIHRoZSBzdGVwIGZhaWx1cmUgZ3JhY2VmdWxseS5cbiAgICAgICAgICAgIGNvbnN0IHN0ZXBGbiA9IGdldFN0ZXBGdW5jdGlvbihzdGVwTmFtZSk7XG5cbiAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHdvcmtmbG93TmFtZSksXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKHdvcmtmbG93UnVuSWQpLFxuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcElkKHN0ZXBJZCksXG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwVHJhY2VQcm9wYWdhdGVkKCEhdHJhY2VDb250ZXh0KSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBzdGVwX3N0YXJ0ZWQgdmFsaWRhdGVzIHN0YXRlIGFuZCByZXR1cm5zIHRoZSBzdGVwIGVudGl0eSwgc28gbm8gc2VwYXJhdGVcbiAgICAgICAgICAgIC8vIHdvcmxkLnN0ZXBzLmdldCgpIGNhbGwgaXMgbmVlZGVkLiBUaGUgc2VydmVyIGNoZWNrczpcbiAgICAgICAgICAgIC8vIC0gU3RlcCBub3QgaW4gdGVybWluYWwgc3RhdGUgKHJldHVybnMgNDA5KVxuICAgICAgICAgICAgLy8gLSByZXRyeUFmdGVyIHRpbWVzdGFtcCByZWFjaGVkIChyZXR1cm5zIDQyNSB3aXRoIFJldHJ5LUFmdGVyIGhlYWRlcilcbiAgICAgICAgICAgIC8vIC0gV29ya2Zsb3cgc3RpbGwgYWN0aXZlIChyZXR1cm5zIDQxMCBpZiBjb21wbGV0ZWQpXG4gICAgICAgICAgICBsZXQgc3RlcCE6IFN0ZXA7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBzdGFydFJlc3VsdCA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX3N0YXJ0ZWQnLFxuICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7IHN0ZXBOYW1lIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgaWYgKCFzdGFydFJlc3VsdC5zdGVwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgICAgICAgICAgYHN0ZXBfc3RhcnRlZCBldmVudCBmb3IgXCIke3N0ZXBJZH1cIiBkaWQgbm90IHJldHVybiBzdGVwIGVudGl0eWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHN0ZXAgPSBzdGFydFJlc3VsdC5zdGVwO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIGlmIChUaHJvdHRsZUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXRyeVJldHJ5QWZ0ZXIgPSBNYXRoLm1heChcbiAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICB0eXBlb2YgZXJyLnJldHJ5QWZ0ZXIgPT09ICdudW1iZXInID8gZXJyLnJldHJ5QWZ0ZXIgOiAxXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgJ1Rocm90dGxlZCBhZ2FpbiBvbiByZXRyeSwgZGVmZXJyaW5nIHRvIHF1ZXVlJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0cnlBZnRlclNlY29uZHM6IHJldHJ5UmV0cnlBZnRlcixcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzOiByZXRyeVJldHJ5QWZ0ZXIgfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAvLyBFeHBlY3RlZCB3aGVuIGEgcnVuIGlzIGNhbmNlbGxlZCB3aGlsZSBhIHN0ZXAgaXMgaW4tZmxpZ2h0LlxuICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGhhcyBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgc3RlcCcsXG4gICAgICAgICAgICAgICAgICB7IGVycm9yTmFtZTogZXJyLm5hbWUsIGVycm9yTWVzc2FnZTogZXJyLm1lc3NhZ2UgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgaW4gYSB0ZXJtaW5hbCBzdGF0ZSDigJQgYW5vdGhlciB3b3JrZXIgZmluaXNoZWRcbiAgICAgICAgICAgICAgICAvLyBpdCBvciBpdCB3YXMgcmV0cmllZCB0byBjb21wbGV0aW9uLiBSZS1lbnF1ZXVlIHRoZSBwYXJlbnRcbiAgICAgICAgICAgICAgICAvLyB3b3JrZmxvdyBzbyBpdCBjYW4gb2JzZXJ2ZSB0aGUgb3V0Y29tZS5cbiAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICdTdGVwIGluIHRlcm1pbmFsIHN0YXRlLCByZS1lbnF1ZXVpbmcgd29ya2Zsb3cnLFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFNraXBwZWQodHJ1ZSksXG4gICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFNraXBSZWFzb24oJ2NvbXBsZXRlZCcpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNwYW4/LmFkZEV2ZW50Py4oJ3N0ZXAuc2tpcHBlZCcsIHtcbiAgICAgICAgICAgICAgICAgICdza2lwLnJlYXNvbic6ICd0ZXJtaW5hbF9zdGF0ZScsXG4gICAgICAgICAgICAgICAgICAnc3RlcC5uYW1lJzogc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAnc3RlcC5pZCc6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgcmVzb2x2ZWROYW1lc3BhY2UpLFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBydW5JZDogd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyOiBhd2FpdCBzZXJpYWxpemVUcmFjZUNhcnJpZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAvLyBUb28gZWFybHk6IHJldHJ5QWZ0ZXIgdGltZXN0YW1wIG5vdCByZWFjaGVkIHlldFxuICAgICAgICAgICAgICAvLyBSZXR1cm4gdGltZW91dCB0byBxdWV1ZSBzbyBpdCByZXRyaWVzIGxhdGVyXG4gICAgICAgICAgICAgIGlmIChUb29FYXJseUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGgubWF4KDEsIGVyci5yZXRyeUFmdGVyID8/IDEpO1xuICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXRyeVRpbWVvdXRTZWNvbmRzKHRpbWVvdXRTZWNvbmRzKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAvLyBBZGQgc3BhbiBldmVudCBmb3IgZGVsYXllZCByZXRyeVxuICAgICAgICAgICAgICAgIHNwYW4/LmFkZEV2ZW50Py4oJ3N0ZXAuZGVsYXllZCcsIHtcbiAgICAgICAgICAgICAgICAgICdkZWxheS5yZWFzb24nOiAncmV0cnlfYWZ0ZXJfbm90X3JlYWNoZWQnLFxuICAgICAgICAgICAgICAgICAgJ2RlbGF5LnRpbWVvdXRfc2Vjb25kcyc6IHRpbWVvdXRTZWNvbmRzLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgICAgJ1N0ZXAgcmV0cnlBZnRlciB0aW1lc3RhbXAgbm90IHlldCByZWFjaGVkJyxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0cnlBZnRlclNlY29uZHM6IGVyci5yZXRyeUFmdGVyLFxuICAgICAgICAgICAgICAgICAgICB0aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzIH07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgLy8gUmUtdGhyb3cgb3RoZXIgZXJyb3JzXG4gICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuZGVidWcoJ1N0ZXAgZXhlY3V0aW9uIGRldGFpbHMnLCB7XG4gICAgICAgICAgICAgIHN0YXR1czogc3RlcC5zdGF0dXMsXG4gICAgICAgICAgICAgIGF0dGVtcHQ6IHN0ZXAuYXR0ZW1wdCxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoc3RlcC5zdGF0dXMpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFZhbGlkYXRlIHN0ZXAgZnVuY3Rpb24gZXhpc3RzIEFGVEVSIHN0ZXBfc3RhcnRlZCBzbyB3ZSBjYW5cbiAgICAgICAgICAgIC8vIHByb3Blcmx5IGZhaWwgdGhlIHN0ZXAgKG5vdCB0aGUgcnVuKSBpZiB0aGUgZnVuY3Rpb24gaXMgbWlzc2luZy5cbiAgICAgICAgICAgIC8vIFRoaXMgYWxsb3dzIHRoZSB3b3JrZmxvdyB0byBoYW5kbGUgdGhlIHN0ZXAgZmFpbHVyZSBncmFjZWZ1bGx5LFxuICAgICAgICAgICAgLy8gc2ltaWxhciB0byBob3cgRmF0YWxFcnJvciBpcyBoYW5kbGVkLlxuICAgICAgICAgICAgaWYgKCFzdGVwRm4gfHwgdHlwZW9mIHN0ZXBGbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgU3RlcE5vdFJlZ2lzdGVyZWRFcnJvcihzdGVwTmFtZSk7XG5cbiAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgICAgJ1N0ZXAgZnVuY3Rpb24gbm90IHJlZ2lzdGVyZWQsIGZhaWxpbmcgc3RlcCAobm90IHJ1biknLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogZXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgZXJyb3JTdGFjazogZXJyLnN0YWNrLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAvLyBGYWlsIHRoZSBzdGVwIHZpYSBldmVudCAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpXG4gICAgICAgICAgICAgIC8vIFRoaXMgbWF0Y2hlcyB0aGUgRmF0YWxFcnJvciBwYXR0ZXJuIC0gZmFpbCB0aGUgc3RlcCBhbmQgcmUtcXVldWUgd29ya2Zsb3dcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycixcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KClcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChzdGVwRmFpbEVycikge1xuICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgLy8gU3RlcCBhbHJlYWR5IHRyYW5zaXRpb25lZCB0byBhIHRlcm1pbmFsIHN0YXRlIOKAlCBkdXBsaWNhdGVcbiAgICAgICAgICAgICAgICAgIC8vIGRlbGl2ZXJ5IG9yIGNvbmN1cnJlbnQgY2FuY2VsbGF0aW9uLiBEcm9wIHNpbGVudGx5LlxuICAgICAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCBmb3IgbWlzc2luZyBmdW5jdGlvbiwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogc3RlcEZhaWxFcnIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IHN0ZXBGYWlsRXJyO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2ZhaWxlZCcpLFxuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRmF0YWxFcnJvcih0cnVlKSxcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgLy8gUmUtaW52b2tlIHRoZSB3b3JrZmxvdyB0byBoYW5kbGUgdGhlIGZhaWxlZCBzdGVwXG4gICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd05hbWUsIHJlc29sdmVkTmFtZXNwYWNlKSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBydW5JZDogd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbWF4UmV0cmllcyA9IHN0ZXBGbi5tYXhSZXRyaWVzID8/IERFRkFVTFRfU1RFUF9NQVhfUkVUUklFUztcblxuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwTWF4UmV0cmllcyhtYXhSZXRyaWVzKSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBsZXQgcmVzdWx0OiB1bmtub3duO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBtYXggcmV0cmllcyBBRlRFUiBzdGVwX3N0YXJ0ZWQgKGF0dGVtcHQgd2FzIGp1c3QgaW5jcmVtZW50ZWQpXG4gICAgICAgICAgICAvLyBzdGVwLmF0dGVtcHQgdHJhY2tzIGhvdyBtYW55IHRpbWVzIHN0ZXBfc3RhcnRlZCBoYXMgYmVlbiBjYWxsZWQuXG4gICAgICAgICAgICAvLyBOb3RlOiBtYXhSZXRyaWVzIGlzIHRoZSBudW1iZXIgb2YgUkVUUklFUyBhZnRlciB0aGUgZmlyc3QgYXR0ZW1wdCwgc28gdG90YWwgYXR0ZW1wdHMgPSBtYXhSZXRyaWVzICsgMVxuICAgICAgICAgICAgLy8gVXNlID4gaGVyZSAobm90ID49KSBiZWNhdXNlIHRoaXMgZ3VhcmRzIGFnYWluc3QgcmUtaW52b2NhdGlvbiBBRlRFUiBhbGwgYXR0ZW1wdHMgYXJlIHVzZWQuXG4gICAgICAgICAgICAvLyBUaGUgcG9zdC1mYWlsdXJlIGNoZWNrIHVzZXMgPj0gdG8gZGVjaWRlIHdoZXRoZXIgdG8gcmV0cnkgYWZ0ZXIgYSBmYWlsdXJlLlxuICAgICAgICAgICAgaWYgKHN0ZXAuYXR0ZW1wdCA+IG1heFJldHJpZXMgKyAxKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHJldHJ5Q291bnQgPSBzdGVwLmF0dGVtcHQgLSAxO1xuICAgICAgICAgICAgICAvLyBQZXJzaXN0ZWQgbWVzc2FnZSDigJQga2VwdCBzaG9ydCwgbm8gbWFjaGluZSBgc3RlcE5hbWVgLFxuICAgICAgICAgICAgICAvLyBzaW5jZSBvYnNlcnZhYmlsaXR5IGFscmVhZHkgYXR0cmlidXRlcyB0aGUgZXZlbnQgdG8gYVxuICAgICAgICAgICAgICAvLyBzcGVjaWZpYyBzdGVwLlxuICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgU3RlcCBleGNlZWRlZCBtYXggcmV0cmllcyAoJHtyZXRyeUNvdW50fSAke3BsdXJhbGl6ZSgncmV0cnknLCAncmV0cmllcycsIHJldHJ5Q291bnQpfSlgO1xuICAgICAgICAgICAgICBzdGVwTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgIGBTdGVwICR7Zm9ybWF0U3RlcE5hbWUoc3RlcE5hbWUpfSBleGNlZWRlZCBtYXggcmV0cmllcyAoJHtyZXRyeUNvdW50fSAke3BsdXJhbGl6ZSgncmV0cnknLCAncmV0cmllcycsIHJldHJ5Q291bnQpfSlgLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIHJldHJ5Q291bnQsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAvLyBGYWlsIHRoZSBzdGVwIHZpYSBldmVudCAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpLlxuICAgICAgICAgICAgICAvLyBQcmVzZXJ2ZSB0aGUgcHJpb3IgYXR0ZW1wdCdzIHNlcmlhbGl6ZWQgZXJyb3IgYXMgdGhlIGNhdXNlIHNvXG4gICAgICAgICAgICAgIC8vIHRoZSB1bmRlcmx5aW5nIGZhaWx1cmUgaXMgcmVjb3ZlcmFibGUgZnJvbSBgc3RlcC5lcnJvci5jYXVzZWBcbiAgICAgICAgICAgICAgLy8gYWZ0ZXIgaHlkcmF0aW9uLCB3aXRob3V0IGZvcmNpbmcgY29uc3VtZXJzIHRvIHdhbGsgdGhlXG4gICAgICAgICAgICAgIC8vIHN0ZXBfcmV0cnlpbmcgZXZlbnQgaGlzdG9yeS4gTWlycm9ycyB0aGUgcG9zdC1mYWlsdXJlIHBhdGhcbiAgICAgICAgICAgICAgLy8gYmVsb3cgdGhhdCB3cmFwcyB0aGUgbGl2ZSBgZXJyYCBhcyBjYXVzZS5cbiAgICAgICAgICAgICAgY29uc3Qgd3JhcHBlZEVycm9yID0gbmV3IEZhdGFsRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgICAgICAgICAgICAgaWYgKHN0ZXAuZXJyb3IgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAod3JhcHBlZEVycm9yIGFzIEVycm9yKS5jYXVzZSA9IGF3YWl0IGh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIHN0ZXAuZXJyb3IsXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKVxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgIC8vIElnbm9yZTogYmVzdC1lZmZvcnQgY2F1c2UgYXR0YWNobWVudCwgdGhlIHdyYXBwaW5nXG4gICAgICAgICAgICAgICAgICAvLyBGYXRhbEVycm9yIHN0YWNrL21lc3NhZ2Ugc3RpbGwgc3VyZmFjZSB0aGUgZmFpbHVyZS5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyYXBwZWRFcnJvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KClcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgdHJhbnNpdGlvbmVkIHRvIGEgdGVybWluYWwgc3RhdGUg4oCUIGR1cGxpY2F0ZVxuICAgICAgICAgICAgICAgICAgLy8gZGVsaXZlcnkgb3IgY29uY3VycmVudCBjb21wbGV0aW9uLiBEcm9wIHNpbGVudGx5LlxuICAgICAgICAgICAgICAgICAgc3RlcFJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogZXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBTdGF0dXMoJ2ZhaWxlZCcpLFxuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlFeGhhdXN0ZWQodHJ1ZSksXG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIC8vIFJlLWludm9rZSB0aGUgd29ya2Zsb3cgdG8gaGFuZGxlIHRoZSBmYWlsZWQgc3RlcFxuICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCByZXNvbHZlZE5hbWVzcGFjZSksXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIC0tLSBJbmZyYXN0cnVjdHVyZTogcHJlcGFyZSBzdGVwIGlucHV0IC0tLVxuICAgICAgICAgICAgLy8gTmV0d29yay9zZXJ2ZXIgZXJyb3JzIHByb3BhZ2F0ZSB0byB0aGUgcXVldWUgaGFuZGxlciBmb3IgcmV0cnkuXG4gICAgICAgICAgICAvLyBXb3JrZmxvd1J1bnRpbWVFcnJvciAoZGF0YSBpbnRlZ3JpdHkgaXNzdWVzKSBhcmUgZmF0YWwg4oCUIHJldHJ5aW5nXG4gICAgICAgICAgICAvLyB3b24ndCBmaXggdGhlbSwgc28gd2UgcmUtcXVldWUgdGhlIHdvcmtmbG93IHRvIHN1cmZhY2UgdGhlIGVycm9yLlxuICAgICAgICAgICAgLy8gc3RlcF9zdGFydGVkIGFscmVhZHkgdmFsaWRhdGVkIHRoZSBzdGVwIGlzIGluIHZhbGlkIHN0YXRlIChwZW5kaW5nL3J1bm5pbmcpXG4gICAgICAgICAgICAvLyBhbmQgcmV0dXJuZWQgdGhlIHVwZGF0ZWQgc3RlcCBlbnRpdHkgd2l0aCBpbmNyZW1lbnRlZCBhdHRlbXB0XG5cbiAgICAgICAgICAgIC8vIHN0ZXAuYXR0ZW1wdCBpcyBub3cgdGhlIGN1cnJlbnQgYXR0ZW1wdCBudW1iZXIgKGFmdGVyIGluY3JlbWVudClcbiAgICAgICAgICAgIGNvbnN0IGF0dGVtcHQgPSBzdGVwLmF0dGVtcHQ7XG5cbiAgICAgICAgICAgIGlmICghc3RlcC5zdGFydGVkQXQpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYFN0ZXAgXCIke3N0ZXBJZH1cIiBoYXMgbm8gXCJzdGFydGVkQXRcIiB0aW1lc3RhbXBgO1xuICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5lcnJvcignRmF0YWwgcnVudGltZSBlcnJvciBkdXJpbmcgc3RlcCBzZXR1cCcsIHtcbiAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogc3RlcElkLFxuICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogYXdhaXQgZGVoeWRyYXRlU3RlcEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IEZhdGFsRXJyb3IoZXJyb3JNZXNzYWdlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KClcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChmYWlsRXJyKSB7XG4gICAgICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZmFpbEVycikpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZmFpbEVycjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAvLyBSZS1xdWV1ZSB0aGUgd29ya2Zsb3cgc28gaXQgY2FuIHByb2Nlc3MgdGhlIHN0ZXAgZmFpbHVyZVxuICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lLCByZXNvbHZlZE5hbWVzcGFjZSksXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDYXB0dXJlIHN0YXJ0ZWRBdCBmb3IgdXNlIGluIGFzeW5jIGNhbGxiYWNrIChUeXBlU2NyaXB0IG5hcnJvd2luZyBkb2Vzbid0IHBlcnNpc3QpXG4gICAgICAgICAgICBjb25zdCBzdGVwU3RhcnRlZEF0ID0gc3RlcC5zdGFydGVkQXQ7XG5cbiAgICAgICAgICAgIC8vIFJlc29sdmUgdGhlIGVuY3J5cHRpb24ga2V5IG5vdyB0aGF0IHdlJ3JlIGNvbW1pdHRlZCB0byBydW5uaW5nXG4gICAgICAgICAgICAvLyB1c2VyIGNvZGU6IGlucHV0IGh5ZHJhdGlvbiBuZWVkcyBpdCwgYW5kIGBjb250ZXh0U3RvcmFnZWAgKGFuZFxuICAgICAgICAgICAgLy8gYW55IHVzZXItY29kZSBwYXRocyB0aGF0IHJ1biBpbnNpZGUgaXQpIGNhcHR1cmUgdGhlIHJlc29sdmVkXG4gICAgICAgICAgICAvLyB2YWx1ZS4gVHJpZ2dlcnMgdGhlIHVuZGVybHlpbmcgd29ybGQgLyBLTVMgZmV0Y2ggb25jZSwgd2l0aFxuICAgICAgICAgICAgLy8gc3Vic2VxdWVudCBkZWh5ZHJhdGUgcGF0aHMgcmV1c2luZyB0aGUgbWVtb2l6ZWQgcmVzdWx0LlxuICAgICAgICAgICAgY29uc3QgZW5jcnlwdGlvbktleSA9IGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKTtcblxuICAgICAgICAgICAgLy8gSHlkcmF0ZSB0aGUgc3RlcCBpbnB1dCBhcmd1bWVudHMsIGNsb3N1cmUgdmFyaWFibGVzLCBhbmQgdGhpc1ZhbFxuICAgICAgICAgICAgLy8gTk9URTogVGhpcyBjYXB0dXJlcyBvbmx5IHRoZSBzeW5jaHJvbm91cyBwb3J0aW9uIG9mIGh5ZHJhdGlvbi4gQW55IGFzeW5jXG4gICAgICAgICAgICAvLyBvcGVyYXRpb25zIChlLmcuLCBzdHJlYW0gbG9hZGluZykgYXJlIGFkZGVkIHRvIGBvcHNgIGFuZCBleGVjdXRlZCBsYXRlclxuICAgICAgICAgICAgLy8gdmlhIFByb21pc2UuYWxsKG9wcykgLSB0aGVpciB0aW1pbmcgaXMgbm90IGluY2x1ZGVkIGluIHRoaXMgbWVhc3VyZW1lbnQuXG4gICAgICAgICAgICBjb25zdCBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuICAgICAgICAgICAgY29uc3QgaHlkcmF0ZWRJbnB1dCA9IGF3YWl0IHRyYWNlKFxuICAgICAgICAgICAgICAnc3RlcC5oeWRyYXRlJyxcbiAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgIGFzeW5jIChoeWRyYXRlU3BhbikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICAgICAgICBzdGVwLmlucHV0LFxuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICAgICAgICBvcHMsXG4gICAgICAgICAgICAgICAgICBnbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICBwcm9jZXNzLmVudi5WRVJDRUxfREVQTE9ZTUVOVF9JRFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29uc3QgZHVyYXRpb25NcyA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XG4gICAgICAgICAgICAgICAgaHlkcmF0ZVNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBBcmd1bWVudHNDb3VudChyZXN1bHQuYXJncy5sZW5ndGgpLFxuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlF1ZXVlRGVzZXJpYWxpemVUaW1lTXMoZHVyYXRpb25NcyksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgY29uc3QgYXJncyA9IGh5ZHJhdGVkSW5wdXQuYXJncztcbiAgICAgICAgICAgIGNvbnN0IHRoaXNWYWwgPSBoeWRyYXRlZElucHV0LnRoaXNWYWwgPz8gbnVsbDtcblxuICAgICAgICAgICAgLy8gLS0tIFVzZXIgY29kZSBleGVjdXRpb24gLS0tXG4gICAgICAgICAgICAvLyBPbmx5IGVycm9ycyBmcm9tIHN0ZXBGbi5hcHBseSgpICh1c2VyIHN0ZXAgY29kZSkgc2hvdWxkIHByb2R1Y2VcbiAgICAgICAgICAgIC8vIHN0ZXBfZmFpbGVkL3N0ZXBfcmV0cnlpbmcuIEluZnJhc3RydWN0dXJlIGVycm9ycyAobmV0d29yaywgc2VydmVyKVxuICAgICAgICAgICAgLy8gbXVzdCBwcm9wYWdhdGUgdG8gdGhlIHF1ZXVlIGhhbmRsZXIgZm9yIGF1dG9tYXRpYyByZXRyeS5cbiAgICAgICAgICAgIGxldCB1c2VyQ29kZUVycm9yOiB1bmtub3duO1xuICAgICAgICAgICAgbGV0IHVzZXJDb2RlRmFpbGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIGNvbnN0IGV4ZWN1dGlvblN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZXN1bHQgPSBhd2FpdCB0cmFjZSgnc3RlcC5leGVjdXRlJywge30sIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgY29udGV4dFN0b3JhZ2UucnVuKFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBzdGVwTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcFN0YXJ0ZWRBdDogbmV3IERhdGUoK3N0ZXBTdGFydGVkQXQpLFxuICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93TWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1N0YXJ0ZWRBdDogbmV3IERhdGUoK3dvcmtmbG93U3RhcnRlZEF0KSxcbiAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiB0aGVyZSBzaG91bGQgYmUgYSBnZXRVcmwgbWV0aG9kIG9uIHRoZSB3b3JsZCBpbnRlcmZhY2UgaXRzZWxmLiBUaGlzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gc29sdXRpb24gb25seSB3b3JrcyBmb3IgdmVyY2VsICsgbG9jYWwgd29ybGRzLlxuICAgICAgICAgICAgICAgICAgICAgIHVybDogaXNWZXJjZWxcbiAgICAgICAgICAgICAgICAgICAgICAgID8gYGh0dHBzOi8vJHtwcm9jZXNzLmVudi5WRVJDRUxfVVJMfWBcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0ID8/IDMwMDB9YCxcbiAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlczogeyBlbmNyeXB0aW9uOiAhIWVuY3J5cHRpb25LZXkgfSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dEZXBsb3ltZW50SWQ6IHByb2Nlc3MuZW52LlZFUkNFTF9ERVBMT1lNRU5UX0lELFxuICAgICAgICAgICAgICAgICAgICBvcHMsXG4gICAgICAgICAgICAgICAgICAgIGNsb3N1cmVWYXJzOiBoeWRyYXRlZElucHV0LmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICgpID0+IHN0ZXBGbi5hcHBseSh0aGlzVmFsLCBhcmdzKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIHVzZXJDb2RlRXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgIHVzZXJDb2RlRmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGV4ZWN1dGlvblRpbWVNcyA9IERhdGUubm93KCkgLSBleGVjdXRpb25TdGFydFRpbWU7XG5cbiAgICAgICAgICAgIGNhbmNlbEFib3J0UmVhZGVycyguLi5hcmdzLCB0aGlzVmFsLCBoeWRyYXRlZElucHV0LmNsb3N1cmVWYXJzKTtcblxuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5RdWV1ZUV4ZWN1dGlvblRpbWVNcyhleGVjdXRpb25UaW1lTXMpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIC0tLSBEZWh5ZHJhdGUgKHNlcmlhbGl6ZSkgdGhlIHN0ZXAncyByZXR1cm4gdmFsdWUgLS0tXG4gICAgICAgICAgICAvLyBBIG5vbi1zZXJpYWxpemFibGUgcmV0dXJuIHZhbHVlIGlzIGEgdXNlci1jb2RlIGJ1Zywgbm90IGFuXG4gICAgICAgICAgICAvLyBpbmZyYXN0cnVjdHVyZSBmYWlsdXJlLiBSb3V0ZSBpdCB0aHJvdWdoIHRoZSBzYW1lIHN0ZXAtZmFpbHVyZVxuICAgICAgICAgICAgLy8gcGF0aCBhcyBhIHRocm93biBlcnJvciBzbyBTZXJpYWxpemF0aW9uRXJyb3IgKHdoaWNoIGlzIG1hcmtlZFxuICAgICAgICAgICAgLy8gYGZhdGFsOiB0cnVlYCkgc2hvcnQtY2lyY3VpdHMgdGhlIHJldHJ5IGxvb3AgaW5zdGVhZCBvZlxuICAgICAgICAgICAgLy8gYnViYmxpbmcgYXMgYW4gSFRUUCA1MDAgYW5kIGJ1cm5pbmcgdGhyb3VnaCBhbGwgNCBxdWV1ZVxuICAgICAgICAgICAgLy8gZGVsaXZlcmllcyBvbiBhIGd1YXJhbnRlZWQtdG8tZmFpbCBtZXNzYWdlLlxuICAgICAgICAgICAgaWYgKCF1c2VyQ29kZUZhaWxlZCkge1xuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IHRyYWNlKFxuICAgICAgICAgICAgICAgICAgJ3N0ZXAuZGVoeWRyYXRlJyxcbiAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICAgYXN5bmMgKGRlaHlkcmF0ZVNwYW4pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVoeWRyYXRlZCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZShcbiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICAgIG9wc1xuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkdXJhdGlvbk1zID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcbiAgICAgICAgICAgICAgICAgICAgZGVoeWRyYXRlU3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlF1ZXVlU2VyaWFsaXplVGltZU1zKGR1cmF0aW9uTXMpLFxuICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmVzdWx0VHlwZSh0eXBlb2YgZGVoeWRyYXRlZCksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVoeWRyYXRlZDtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB1c2VyQ29kZUVycm9yID0gZXJyO1xuICAgICAgICAgICAgICAgIHVzZXJDb2RlRmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyAtLS0gSGFuZGxlIHVzZXIgY29kZSBlcnJvcnMgLS0tXG4gICAgICAgICAgICBpZiAodXNlckNvZGVGYWlsZWQpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyID0gdXNlckNvZGVFcnJvcjtcblxuICAgICAgICAgICAgICAvLyBJbmZyYXN0cnVjdHVyZSBlcnJvcnMgdGhhdCBzb21laG93IHN1cmZhY2VkIHRocm91Z2ggdXNlciBjb2RlXG4gICAgICAgICAgICAgIC8vIHNob3VsZCBwcm9wYWdhdGUgdG8gdGhlIHF1ZXVlIGhhbmRsZXIgZm9yIHJldHJ5LCBub3QgY29uc3VtZVxuICAgICAgICAgICAgICAvLyBzdGVwIGF0dGVtcHRzLlxuICAgICAgICAgICAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAvLyBXb3JrZmxvdyBoYXMgYWxyZWFkeSBjb21wbGV0ZWQsIHNvIG5vLW9wXG4gICAgICAgICAgICAgICAgc3RlcExvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgc3RlcCcsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKFdvcmtmbG93V29ybGRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVyci5zdGF0dXMgIT09IHVuZGVmaW5lZCAmJiBlcnIuc3RhdHVzID49IDUwMCkge1xuICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIC8vIEFib3J0IGZhaWx1cmVzIGNhbiBjcm9zcyBWTS9zZXJpYWxpemF0aW9uIHJlYWxtcywgd2hlcmVcbiAgICAgICAgICAgICAgLy8gYGluc3RhbmNlb2YgRXJyb3JgIGlzIG5vdCByZWxpYWJsZS5cbiAgICAgICAgICAgICAgY29uc3QgZWZmZWN0aXZlRXJyID0gcHJvbW90ZUFib3J0RXJyb3JUb0ZhdGFsKGVycik7XG4gICAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRFcnJvciA9IGF3YWl0IG5vcm1hbGl6ZVVua25vd25FcnJvcihlZmZlY3RpdmVFcnIpO1xuICAgICAgICAgICAgICBjb25zdCBub3JtYWxpemVkU3RhY2sgPVxuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRFcnJvci5zdGFjayB8fCBnZXRFcnJvclN0YWNrKGVmZmVjdGl2ZUVycikgfHwgJyc7XG5cbiAgICAgICAgICAgICAgLy8gUmVjb3JkIGV4Y2VwdGlvbiBmb3IgT1RFTCBlcnJvciB0cmFja2luZ1xuICAgICAgICAgICAgICBpZiAoZWZmZWN0aXZlRXJyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgICAgICBzcGFuPy5yZWNvcmRFeGNlcHRpb24/LihlZmZlY3RpdmVFcnIpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIGVycm9yIGNhdGVnb3J5IGFuZCByZXRyeWFiaWxpdHlcbiAgICAgICAgICAgICAgY29uc3QgaXNGYXRhbCA9IEZhdGFsRXJyb3IuaXMoZWZmZWN0aXZlRXJyKTtcbiAgICAgICAgICAgICAgY29uc3QgaXNSZXRyeWFibGUgPSBSZXRyeWFibGVFcnJvci5pcyhlZmZlY3RpdmVFcnIpO1xuICAgICAgICAgICAgICBjb25zdCBlcnJvckNhdGVnb3J5ID0gaXNGYXRhbFxuICAgICAgICAgICAgICAgID8gJ2ZhdGFsJ1xuICAgICAgICAgICAgICAgIDogaXNSZXRyeWFibGVcbiAgICAgICAgICAgICAgICAgID8gJ3JldHJ5YWJsZSdcbiAgICAgICAgICAgICAgICAgIDogJ3RyYW5zaWVudCc7XG5cbiAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBFcnJvck5hbWUoZ2V0RXJyb3JOYW1lKGVmZmVjdGl2ZUVycikpLFxuICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRXJyb3JNZXNzYWdlKG5vcm1hbGl6ZWRFcnJvci5tZXNzYWdlKSxcbiAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JUeXBlKGdldEVycm9yTmFtZShlZmZlY3RpdmVFcnIpKSxcbiAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JDYXRlZ29yeShlcnJvckNhdGVnb3J5KSxcbiAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuRXJyb3JSZXRyeWFibGUoIWlzRmF0YWwpLFxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBpZiAoaXNGYXRhbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gZGVzY3JpYmVFcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyaWVuZGx5U3RlcCA9IGZvcm1hdFN0ZXBOYW1lKHN0ZXBOYW1lKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmcmFtaW5nID1cbiAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uLmF0dHJpYnV0aW9uID09PSAnc2RrJ1xuICAgICAgICAgICAgICAgICAgICA/IGBTdGVwICR7ZnJpZW5kbHlTdGVwfSBmYWlsZWQgd2l0aCBhIEZhdGFsRXJyb3IgZnJvbSB0aGUgU0RLIHJ1bnRpbWUg4oCUIGJ1YmJsaW5nIHVwIHRvIHBhcmVudCB3b3JrZmxvd2BcbiAgICAgICAgICAgICAgICAgICAgOiBgU3RlcCAke2ZyaWVuZGx5U3RlcH0gdGhyZXcgYSBGYXRhbEVycm9yIOKAlCBidWJibGluZyB1cCB0byBwYXJlbnQgd29ya2Zsb3dgO1xuICAgICAgICAgICAgICAgIC8vIE1pcnJvciB0aGUgd29ya2Zsb3ctbGV2ZWwgbG9nIGZvcm1hdHRpbmc6IHB1dCB0aGUgZnJhbWluZyArXG4gICAgICAgICAgICAgICAgLy8gc3RhY2sgaW50byB0aGUgbWVzc2FnZSBzbyBjb25zb2xlLmVycm9yIHJlbmRlcnMgdGhlIHN0YWNrXG4gICAgICAgICAgICAgICAgLy8gaW5saW5lLCBhbmQga2VlcCB0aGUgbWV0YWRhdGEgb2JqZWN0IHNtYWxsIHdpdGggb25seSB0aGVcbiAgICAgICAgICAgICAgICAvLyBzdHJ1Y3R1cmVkIGZpZWxkcyB0aGF0IGxvZyBkcmFpbnMgd2FudCB0byBpbmRleC5cbiAgICAgICAgICAgICAgICAvLyBObyBgaGludGAgZmllbGQgaGVyZSDigJQgYWN0aW9uYWJsZSBoaW50IHRleHQgbGl2ZXMgb24gdGhlXG4gICAgICAgICAgICAgICAgLy8gZXJyb3IgbWVzc2FnZSBpdHNlbGYgKHNvIGl0IHN1cnZpdmVzIHNlcmlhbGl6YXRpb24g4oaSXG4gICAgICAgICAgICAgICAgLy8gZXZlbnQgbG9nIOKGkiBvYnNlcnZhYmlsaXR5IHJlaHlkcmF0ZSksIGFuZCBhZGRpbmcgaXRcbiAgICAgICAgICAgICAgICAvLyBhZ2FpbiBoZXJlIGp1c3QgZHVwbGljYXRlcyBpdCBvbiBzdGRlcnIuXG4gICAgICAgICAgICAgICAgc3RlcExvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICAgIGAke2ZyYW1pbmd9XFxuJHtub3JtYWxpemVkU3RhY2sgfHwgbm9ybWFsaXplZEVycm9yLm1lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JBdHRyaWJ1dGlvbjogZGVzY3JpcHRpb24uYXR0cmlidXRpb24sXG4gICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogbm9ybWFsaXplZEVycm9yLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogbm9ybWFsaXplZEVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAvLyBGYWlsIHRoZSBzdGVwIHZpYSBldmVudCAoZXZlbnQtc291cmNlZCBhcmNoaXRlY3R1cmUpLlxuICAgICAgICAgICAgICAgIC8vIFBlcnNpc3QgdGhlIHByb21vdGVkIEZhdGFsRXJyb3IgZm9yIGFib3J0cyBzbyB0aGUgcGFyZW50XG4gICAgICAgICAgICAgICAgLy8gd29ya2Zsb3cgY2FuIGRpc3Rpbmd1aXNoIGNhbmNlbGxhdGlvbiBmcm9tIHJldHJ5IGV4aGF1c3Rpb24uXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZWZmZWN0aXZlRXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5XG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoc3RlcEZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgaW4gdGVybWluYWwgc3RhdGUg4oCUIGlkZW1wb3RlbnQuXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IHN0ZXBGYWlsRXJyLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB0aHJvdyBzdGVwRmFpbEVycjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdmYWlsZWQnKSxcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwRmF0YWxFcnJvcih0cnVlKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXhSZXRyaWVzID1cbiAgICAgICAgICAgICAgICAgIHN0ZXBGbi5tYXhSZXRyaWVzID8/IERFRkFVTFRfU1RFUF9NQVhfUkVUUklFUztcbiAgICAgICAgICAgICAgICAvLyBzdGVwLmF0dGVtcHQgd2FzIGluY3JlbWVudGVkIGJ5IHN0ZXBfc3RhcnRlZCwgdXNlIGl0IGhlcmVcbiAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50QXR0ZW1wdCA9IHN0ZXAuYXR0ZW1wdDtcblxuICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBBdHRlbXB0KGN1cnJlbnRBdHRlbXB0KSxcbiAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwTWF4UmV0cmllcyhtYXhSZXRyaWVzKSxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIE5vdGU6IG1heFJldHJpZXMgaXMgdGhlIG51bWJlciBvZiBSRVRSSUVTIGFmdGVyIHRoZSBmaXJzdCBhdHRlbXB0LCBzbyB0b3RhbCBhdHRlbXB0cyA9IG1heFJldHJpZXMgKyAxXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRBdHRlbXB0ID49IG1heFJldHJpZXMgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAvLyBNYXggcmV0cmllcyByZWFjaGVkXG4gICAgICAgICAgICAgICAgICBjb25zdCByZXRyeUNvdW50ID0gc3RlcC5hdHRlbXB0IC0gMTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gZGVzY3JpYmVFcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgZnJpZW5kbHlTdGVwID0gZm9ybWF0U3RlcE5hbWUoc3RlcE5hbWUpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgZnJhbWluZyA9XG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uLmF0dHJpYnV0aW9uID09PSAnc2RrJ1xuICAgICAgICAgICAgICAgICAgICAgID8gYFN0ZXAgJHtmcmllbmRseVN0ZXB9IGhpdCBtYXggcmV0cmllcyBvbiBhbiBTREsgcnVudGltZSBlcnJvciDigJQgYnViYmxpbmcgdG8gcGFyZW50IHdvcmtmbG93YFxuICAgICAgICAgICAgICAgICAgICAgIDogYFN0ZXAgJHtmcmllbmRseVN0ZXB9IGhpdCBtYXggcmV0cmllcyDigJQgYnViYmxpbmcgZXJyb3IgdGhyb3duIGJ5IHlvdXIgc3RlcCB0byB0aGUgcGFyZW50IHdvcmtmbG93YDtcbiAgICAgICAgICAgICAgICAgIHN0ZXBMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGAke2ZyYW1pbmd9XFxuJHtub3JtYWxpemVkU3RhY2sgfHwgbm9ybWFsaXplZEVycm9yLm1lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZCxcbiAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBhdHRlbXB0OiBzdGVwLmF0dGVtcHQsXG4gICAgICAgICAgICAgICAgICAgICAgcmV0cnlDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvckF0dHJpYnV0aW9uOiBkZXNjcmlwdGlvbi5hdHRyaWJ1dGlvbixcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IG5vcm1hbGl6ZWRFcnJvci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogbm9ybWFsaXplZEVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAvLyBEb24ndCBpbmNsdWRlIHRoZSBtYWNoaW5lIHN0ZXAgbmFtZSBpbiB0aGUgcGVyc2lzdGVkXG4gICAgICAgICAgICAgICAgICAvLyBlcnJvciBtZXNzYWdlIOKAlCBvYnNlcnZhYmlsaXR5IGFscmVhZHkgc2hvd3Mgd2hpY2ggc3RlcFxuICAgICAgICAgICAgICAgICAgLy8gcHJvZHVjZWQgdGhlIGV2ZW50LCBhbmQgYHN0ZXBOYW1lOiAnc3RlcC8vLi8uLi4vZm9vJ2BcbiAgICAgICAgICAgICAgICAgIC8vIGluIHRoZSB0aXRsZSBpcyBqdXN0IG5vaXNlLiBUaGUgQ0xJIGxvZ2dlciByZW5kZXJzXG4gICAgICAgICAgICAgICAgICAvLyBgU3RlcCBmb28gKC4vLi4uKSBoaXQgbWF4IHJldHJpZXNgIHNlcGFyYXRlbHkuXG4gICAgICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgU3RlcCBmYWlsZWQgYWZ0ZXIgJHttYXhSZXRyaWVzfSAke3BsdXJhbGl6ZSgncmV0cnknLCAncmV0cmllcycsIG1heFJldHJpZXMpfTogJHtub3JtYWxpemVkRXJyb3IubWVzc2FnZX1gO1xuICAgICAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgc3RlcCB2aWEgZXZlbnQgKGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlKS5cbiAgICAgICAgICAgICAgICAgIC8vIFdyYXAgdGhlIG9yaWdpbmFsIGVycm9yIHdpdGggYSBGYXRhbEVycm9yIHRoYXQgcHJlc2VydmVzXG4gICAgICAgICAgICAgICAgICAvLyB0aGUgd3JhcHBlZCBtZXNzYWdlIHBsdXMgdGhlIG9yaWdpbmFsIHRocm93biB2YWx1ZSBhc1xuICAgICAgICAgICAgICAgICAgLy8gYGNhdXNlYCBzbyBpdCdzIHJlY292ZXJhYmxlIGFmdGVyIGh5ZHJhdGlvbi5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHdyYXBwZWRFcnJvciA9IG5ldyBGYXRhbEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAod3JhcHBlZEVycm9yIGFzIEVycm9yKS5jYXVzZSA9IGVycjtcbiAgICAgICAgICAgICAgICAgIGlmIChub3JtYWxpemVkU3RhY2spIHdyYXBwZWRFcnJvci5zdGFjayA9IG5vcm1hbGl6ZWRTdGFjaztcbiAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2ZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JhcHBlZEVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleVxuICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKHN0ZXBGYWlsRXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKHN0ZXBGYWlsRXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAgIC8vIFN0ZXAgYWxyZWFkeSBpbiB0ZXJtaW5hbCBzdGF0ZSDigJQgaWRlbXBvdGVudC5cbiAgICAgICAgICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBzdGVwRmFpbEVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHN0ZXBGYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgc3RlcEZhaWxFcnI7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwUmV0cnlFeGhhdXN0ZWQodHJ1ZSksXG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgLy8gTm90IGF0IG1heCByZXRyaWVzIHlldCAtIGxvZyBhcyBhIHJldHJ5YWJsZSBlcnJvclxuICAgICAgICAgICAgICAgICAgaWYgKFJldHJ5YWJsZUVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RlcExvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICdFbmNvdW50ZXJlZCBSZXRyeWFibGVFcnJvciwgc3RlcCB3aWxsIGJlIHJldHJpZWQnLFxuICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQ6IGN1cnJlbnRBdHRlbXB0LFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBlcnIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrOiBub3JtYWxpemVkU3RhY2ssXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3RlcExvZ2dlci5pbmZvKCdFbmNvdW50ZXJlZCBFcnJvciwgc3RlcCB3aWxsIGJlIHJldHJpZWQnLCB7XG4gICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcElkLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQ6IGN1cnJlbnRBdHRlbXB0LFxuICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZTogbm9ybWFsaXplZEVycm9yLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBub3JtYWxpemVkRXJyb3IubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrOiBub3JtYWxpemVkU3RhY2ssXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgLy8gU2V0IHN0ZXAgdG8gcGVuZGluZyBmb3IgcmV0cnkgdmlhIGV2ZW50IChldmVudC1zb3VyY2VkIGFyY2hpdGVjdHVyZSlcbiAgICAgICAgICAgICAgICAgIC8vIHN0ZXBfcmV0cnlpbmcgcmVjb3JkcyB0aGUgZXJyb3IgYW5kIHNldHMgc3RhdHVzIHRvIHBlbmRpbmcuXG4gICAgICAgICAgICAgICAgICAvLyBTZXJpYWxpemUgdGhlIG9yaWdpbmFsIHRocm93biB2YWx1ZSBzbyBpdHMgZnVsbCB0eXBlIGlkZW50aXR5XG4gICAgICAgICAgICAgICAgICAvLyBhbmQgY3VzdG9tIHByb3BlcnRpZXMgcm91bmQtdHJpcCB0aHJvdWdoIHRoZSBldmVudCBsb2cuXG4gICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9yZXRyeWluZycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleVxuICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4oUmV0cnlhYmxlRXJyb3IuaXMoZXJyKSAmJiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0cnlBZnRlcjogZXJyLnJldHJ5QWZ0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKHN0ZXBSZXRyeUVycikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhzdGVwUmV0cnlFcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gU3RlcCBhbHJlYWR5IGluIHRlcm1pbmFsIHN0YXRlIOKAlCBpZGVtcG90ZW50LlxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAnVHJpZWQgcmV0cnlpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBzdGVwUmV0cnlFcnIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBzdGVwUmV0cnlFcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBzdGVwUmV0cnlFcnI7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbWVvdXRTZWNvbmRzID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIFJldHJ5YWJsZUVycm9yLmlzKGVycilcbiAgICAgICAgICAgICAgICAgICAgICA/IE1hdGguY2VpbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKCtlcnIucmV0cnlBZnRlci5nZXRUaW1lKCkgLSBEYXRlLm5vdygpKSAvIDEwMDBcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICA6IDFcbiAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJldHJ5VGltZW91dFNlY29uZHModGltZW91dFNlY29uZHMpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuU3RlcFJldHJ5V2lsbFJldHJ5KHRydWUpLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIC8vIEFkZCBzcGFuIGV2ZW50IGZvciByZXRyeSBzY2hlZHVsaW5nXG4gICAgICAgICAgICAgICAgICBzcGFuPy5hZGRFdmVudD8uKCdyZXRyeS5zY2hlZHVsZWQnLCB7XG4gICAgICAgICAgICAgICAgICAgICdyZXRyeS50aW1lb3V0X3NlY29uZHMnOiB0aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgICAgICAgICAgICAgJ3JldHJ5LmF0dGVtcHQnOiBjdXJyZW50QXR0ZW1wdCxcbiAgICAgICAgICAgICAgICAgICAgJ3JldHJ5Lm1heF9yZXRyaWVzJzogbWF4UmV0cmllcyxcbiAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAvLyBJdCdzIGEgcmV0cnlhYmxlIGVycm9yIC0gc28gaGF2ZSB0aGUgcXVldWUga2VlcCB0aGUgbWVzc2FnZSB2aXNpYmxlXG4gICAgICAgICAgICAgICAgICAvLyBzbyB0aGF0IGl0IGdldHMgcmV0cmllZC5cbiAgICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgLy8gUmUtaW52b2tlIHRoZSB3b3JrZmxvdyB0byBoYW5kbGUgdGhlIGZhaWxlZC9yZXRyeWluZyBzdGVwXG4gICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd05hbWUsIHJlc29sdmVkTmFtZXNwYWNlKSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBydW5JZDogd29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCksXG4gICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gLS0tIEluZnJhc3RydWN0dXJlOiBjb21wbGV0ZSB0aGUgc3RlcCAtLS1cbiAgICAgICAgICAgIC8vIEVycm9ycyBoZXJlIChuZXR3b3JrIGZhaWx1cmVzLCBzZXJ2ZXIgZXJyb3JzKSBwcm9wYWdhdGUgdG8gdGhlXG4gICAgICAgICAgICAvLyBxdWV1ZSBoYW5kbGVyIGZvciBhdXRvbWF0aWMgcmV0cnkuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gTk9URTogTm9uZSBvZiB0aGUgY29kZSBmcm9tIHRoaXMgcG9pbnQgaXMgZ3VhcmFudGVlZCB0byBydW4uXG4gICAgICAgICAgICAvLyBTaW5jZSB0aGUgc3RlcCBtaWdodCBmYWlsIG9yIGNhdXNlIGEgZnVuY3Rpb24gdGltZW91dCBhbmQgdGhlXG4gICAgICAgICAgICAvLyBwcm9jZXNzIG1pZ2h0IGJlIFNJR0tJTEwnZCwgdGhlIHdvcmtmbG93IHJ1bnRpbWUgbXVzdCBiZVxuICAgICAgICAgICAgLy8gcmVzaWxpZW50IHRvIHRoZSBiZWxvdyBjb2RlIG5vdCBleGVjdXRpbmcgb24gYSBmYWlsZWQgc3RlcC5cbiAgICAgICAgICAgIC8vIChEZWh5ZHJhdGlvbiBhbHJlYWR5IGhhcHBlbmVkIGFib3ZlIGFuZCBpcyBhY2NvdW50ZWQgZm9yIGluIHRoZVxuICAgICAgICAgICAgLy8gdXNlckNvZGVGYWlsZWQgcGF0aC4pXG4gICAgICAgICAgICAvLyBUaGVzZSBzdHJlYW0gb3BzIGFyZSBmbHVzaGVkIGluIHRoZSBiYWNrZ3JvdW5kOyB0aGUgcHJvbWlzZVxuICAgICAgICAgICAgLy8gaGFuZGVkIHRvIHdhaXRVbnRpbCBtdXN0IG5ldmVyIHJlamVjdCAoYW4gdW5jb25zdW1lZCB3YWl0VW50aWxcbiAgICAgICAgICAgIC8vIHJlamVjdGlvbiBjcmFzaGVzIHRoZSBwcm9jZXNzIGFzIHVuaGFuZGxlZFJlamVjdGlvbiksIHNvXG4gICAgICAgICAgICAvLyB1bmV4cGVjdGVkIGZhaWx1cmVzIGFyZSBsb2dnZWQgaW5zdGVhZC5cbiAgICAgICAgICAgIHNhZmVXYWl0VW50aWwoUHJvbWlzZS5hbGwob3BzKSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICBzdGVwUnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAgICdCYWNrZ3JvdW5kIGZsdXNoIG9mIHN0ZXAgc3RyZWFtIG9wcyBmYWlsZWQnLFxuICAgICAgICAgICAgICAgIHsgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gUnVuIHN0ZXBfY29tcGxldGVkIGFuZCB0cmFjZSBzZXJpYWxpemF0aW9uIGNvbmN1cnJlbnRseTtcbiAgICAgICAgICAgIC8vIHRoZSB0cmFjZSBjYXJyaWVyIGlzIHVzZWQgaW4gdGhlIGZpbmFsIHF1ZXVlTWVzc2FnZSBjYWxsIGJlbG93XG4gICAgICAgICAgICBsZXQgc3RlcENvbXBsZXRlZDQwOSA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgWywgdHJhY2VDYXJyaWVyXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgd29ybGQuZXZlbnRzXG4gICAgICAgICAgICAgICAgLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY29tcGxldGVkJyxcbiAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBzdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdDogcmVzdWx0IGFzIFVpbnQ4QXJyYXksXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAuY2F0Y2goKGVycjogdW5rbm93bikgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTdGVwIGFscmVhZHkgaW4gdGVybWluYWwgc3RhdGUg4oCUIGlkZW1wb3RlbnQuXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBSdW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGNvbXBsZXRpbmcgc3RlcCwgYnV0IHN0ZXAgaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWU6IGVyci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIHN0ZXBDb21wbGV0ZWQ0MDkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgIGlmIChzdGVwQ29tcGxldGVkNDA5KSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5TdGVwU3RhdHVzKCdjb21wbGV0ZWQnKSxcbiAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLlN0ZXBSZXN1bHRUeXBlKHR5cGVvZiByZXN1bHQpLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFF1ZXVlIHRoZSB3b3JrZmxvdyBjb250aW51YXRpb24gd2l0aCB0aGUgY29uY3VycmVudGx5LXJlc29sdmVkIHRyYWNlIGNhcnJpZXJcbiAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSwgcmVzb2x2ZWROYW1lc3BhY2UpLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgcnVuSWQ6IHdvcmtmbG93UnVuSWQsXG4gICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5jb25zdCBzdGVwSGFuZGxlciA9IGNyZWF0ZVN0ZXBIYW5kbGVyKCk7XG5cbi8qKlxuICogQSBzaW5nbGUgcm91dGUgdGhhdCBoYW5kbGVzIGFueSBzdGVwIGV4ZWN1dGlvbiByZXF1ZXN0IGFuZCByb3V0ZXMgdG8gdGhlXG4gKiBhcHByb3ByaWF0ZSBzdGVwIGZ1bmN0aW9uLiBXZSBtYXkgZXZlbnR1YWxseSB3YW50IHRvIGNyZWF0ZSBkaWZmZXJlbnQgYnVuZGxlc1xuICogZm9yIGVhY2ggc3RlcCwgdGhpcyBpcyB0ZW1wb3JhcnkuXG4gKi9cbmxldCBjYWNoZWRTdGVwSGFuZGxlcjogKChyZXE6IFJlcXVlc3QpID0+IFByb21pc2U8UmVzcG9uc2U+KSB8IHVuZGVmaW5lZDtcbmV4cG9ydCBjb25zdCBzdGVwRW50cnlwb2ludDogKHJlcTogUmVxdWVzdCkgPT4gUHJvbWlzZTxSZXNwb25zZT4gPVxuICAvKiBAX19QVVJFX18gKi8gd2l0aEhlYWx0aENoZWNrKGFzeW5jIChyZXEpID0+IHtcbiAgICBpZiAoIWNhY2hlZFN0ZXBIYW5kbGVyKSB7XG4gICAgICBjYWNoZWRTdGVwSGFuZGxlciA9IHN0ZXBIYW5kbGVyKGF3YWl0IGdldFdvcmxkSGFuZGxlcnMoKSk7XG4gICAgfVxuICAgIHJldHVybiBjYWNoZWRTdGVwSGFuZGxlcihyZXEpO1xuICB9KTtcbiJdfQ==
|