@workflow/core 5.0.0-beta.2 → 5.0.0-beta.20

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