@workflow/core 5.0.0-beta.42 → 5.0.0-beta.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capabilities.d.ts +4 -4
- package/dist/capabilities.js +5 -5
- package/dist/capture-stack.d.ts +1 -1
- package/dist/capture-stack.js +2 -2
- package/dist/class-serialization.d.ts +8 -8
- package/dist/class-serialization.js +9 -9
- package/dist/classify-error.js +5 -5
- package/dist/context-violation-error.d.ts +5 -5
- package/dist/context-violation-error.d.ts.map +1 -1
- package/dist/context-violation-error.js +5 -5
- package/dist/create-hook.d.ts +10 -6
- package/dist/create-hook.d.ts.map +1 -1
- package/dist/create-hook.js +1 -1
- package/dist/define-hook.js +2 -2
- package/dist/describe-error.d.ts +7 -7
- package/dist/describe-error.js +8 -8
- package/dist/encryption.d.ts +5 -5
- package/dist/encryption.js +7 -7
- package/dist/events-consumer.d.ts +19 -7
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +33 -12
- package/dist/flushable-stream.d.ts +4 -4
- package/dist/flushable-stream.js +12 -12
- package/dist/global.d.ts +1 -1
- package/dist/global.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/log-format.d.ts +2 -2
- package/dist/log-format.js +5 -5
- package/dist/logger.js +4 -4
- package/dist/private.d.ts +39 -64
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +294 -48
- package/dist/replay-payload-cache.d.ts +1 -1
- package/dist/replay-payload-cache.js +4 -4
- package/dist/runtime/compute-instance.d.ts +4 -3
- package/dist/runtime/compute-instance.d.ts.map +1 -1
- package/dist/runtime/compute-instance.js +5 -4
- package/dist/runtime/constants.d.ts +46 -19
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +76 -38
- package/dist/runtime/count-step-started-events.d.ts +7 -7
- package/dist/runtime/count-step-started-events.js +4 -4
- package/dist/runtime/deployment-guard.d.ts +7 -7
- package/dist/runtime/deployment-guard.js +8 -8
- package/dist/runtime/get-port-lazy.d.ts +2 -2
- package/dist/runtime/get-port-lazy.d.ts.map +1 -1
- package/dist/runtime/get-port-lazy.js +37 -30
- package/dist/runtime/get-world-lazy.d.ts +2 -2
- package/dist/runtime/get-world-lazy.js +3 -3
- package/dist/runtime/helpers.d.ts +18 -18
- package/dist/runtime/helpers.js +27 -27
- package/dist/runtime/quickjs-entrypoint.d.ts +23 -10
- package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -1
- package/dist/runtime/quickjs-entrypoint.js +200 -81
- package/dist/runtime/quickjs-runtime.d.ts +31 -15
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
- package/dist/runtime/quickjs-runtime.js +126 -77
- package/dist/runtime/quickjs-serde.d.ts +10 -10
- package/dist/runtime/quickjs-serde.js +20 -20
- package/dist/runtime/replay-budget.d.ts +4 -4
- package/dist/runtime/replay-budget.js +5 -5
- package/dist/runtime/replay-recovery-reporter.d.ts +1 -1
- package/dist/runtime/replay-recovery-reporter.js +2 -2
- package/dist/runtime/resume-hook.d.ts +2 -2
- package/dist/runtime/resume-hook.js +27 -27
- package/dist/runtime/resume-latency.d.ts +25 -25
- package/dist/runtime/resume-latency.d.ts.map +1 -1
- package/dist/runtime/resume-latency.js +4 -4
- package/dist/runtime/run-id-time.d.ts +2 -2
- package/dist/runtime/run-id-time.js +5 -5
- package/dist/runtime/run.d.ts +21 -4
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +154 -35
- package/dist/runtime/runs.d.ts +4 -4
- package/dist/runtime/runs.js +2 -2
- package/dist/runtime/start.d.ts +3 -3
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +27 -23
- package/dist/runtime/step-executor.d.ts +59 -11
- package/dist/runtime/step-executor.d.ts.map +1 -1
- package/dist/runtime/step-executor.js +116 -42
- package/dist/runtime/step-latency.d.ts +20 -14
- package/dist/runtime/step-latency.d.ts.map +1 -1
- package/dist/runtime/step-latency.js +13 -11
- package/dist/runtime/step-ownership.d.ts +6 -6
- package/dist/runtime/step-ownership.js +8 -8
- package/dist/runtime/step-single-flight.d.ts +1 -1
- package/dist/runtime/step-single-flight.d.ts.map +1 -1
- package/dist/runtime/step-single-flight.js +17 -11
- package/dist/runtime/suspension-handler.d.ts +99 -7
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +678 -57
- package/dist/runtime/unserializable-step.d.ts +34 -0
- package/dist/runtime/unserializable-step.d.ts.map +1 -0
- package/dist/runtime/unserializable-step.js +52 -0
- package/dist/runtime/vm-mode.d.ts +1 -1
- package/dist/runtime/vm-mode.js +2 -2
- package/dist/runtime/wait-continuation.d.ts +31 -9
- package/dist/runtime/wait-continuation.d.ts.map +1 -1
- package/dist/runtime/wait-continuation.js +44 -13
- package/dist/runtime/wait-until.d.ts +1 -1
- package/dist/runtime/wait-until.js +2 -2
- package/dist/runtime/world-compatibility.d.ts +20 -9
- package/dist/runtime/world-compatibility.d.ts.map +1 -1
- package/dist/runtime/world-compatibility.js +24 -13
- package/dist/runtime/world-init.d.ts +5 -5
- package/dist/runtime/world-init.js +6 -6
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +13 -3
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +417 -213
- package/dist/sealed-box.d.ts +7 -7
- package/dist/sealed-box.js +15 -15
- package/dist/serialization/client.js +2 -2
- package/dist/serialization/codec-devalue-vm.d.ts +1 -1
- package/dist/serialization/codec-devalue-vm.js +4 -4
- package/dist/serialization/codec-devalue.d.ts +1 -1
- package/dist/serialization/codec-devalue.js +2 -2
- package/dist/serialization/codec.d.ts +4 -4
- package/dist/serialization/codec.js +2 -2
- package/dist/serialization/compression.d.ts +12 -11
- package/dist/serialization/compression.d.ts.map +1 -1
- package/dist/serialization/compression.js +16 -15
- package/dist/serialization/encryption.d.ts +7 -7
- package/dist/serialization/encryption.d.ts.map +1 -1
- package/dist/serialization/encryption.js +8 -8
- package/dist/serialization/errors.js +2 -2
- package/dist/serialization/format.d.ts +6 -6
- package/dist/serialization/format.js +7 -7
- package/dist/serialization/hardened.d.ts +18 -18
- package/dist/serialization/hardened.d.ts.map +1 -1
- package/dist/serialization/hardened.js +41 -32
- package/dist/serialization/index.d.ts +1 -1
- package/dist/serialization/index.js +2 -2
- package/dist/serialization/reducers/class-vm.d.ts +1 -1
- package/dist/serialization/reducers/class-vm.js +2 -2
- package/dist/serialization/reducers/class.js +2 -2
- package/dist/serialization/reducers/common-vm.js +12 -12
- package/dist/serialization/reducers/common.js +12 -12
- package/dist/serialization/reducers/step-function-vm.d.ts +1 -1
- package/dist/serialization/reducers/step-function-vm.js +2 -2
- package/dist/serialization/reducers/step-function.js +2 -2
- package/dist/serialization/step.js +2 -2
- package/dist/serialization/types.d.ts +5 -5
- package/dist/serialization/types.js +2 -2
- package/dist/serialization/workflow-vm.d.ts +1 -1
- package/dist/serialization/workflow-vm.d.ts.map +1 -1
- package/dist/serialization/workflow-vm.js +13 -10
- package/dist/serialization-format.d.ts +11 -11
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +29 -23
- package/dist/serialization.d.ts +20 -12
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +141 -99
- package/dist/set-attributes.js +2 -2
- package/dist/source-map.d.ts +1 -1
- package/dist/source-map.d.ts.map +1 -1
- package/dist/source-map.js +18 -12
- package/dist/step/context-storage.d.ts +5 -5
- package/dist/step/context-storage.js +1 -1
- package/dist/step/writable-stream.d.ts +3 -3
- package/dist/step/writable-stream.js +7 -7
- package/dist/step.js +12 -12
- package/dist/symbols.d.ts +2 -2
- package/dist/symbols.js +3 -3
- package/dist/telemetry/semantic-conventions.d.ts +21 -13
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +21 -15
- package/dist/telemetry.d.ts +9 -3
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +40 -10
- package/dist/test-support/orchestrator-context.d.ts.map +1 -1
- package/dist/test-support/orchestrator-context.js +12 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.js +4 -4
- package/dist/vm/script-cache.d.ts.map +1 -1
- package/dist/vm/script-cache.js +23 -17
- package/dist/vm/uint8array-base64.js +1 -1
- package/dist/workflow/abort-controller.d.ts +1 -1
- package/dist/workflow/abort-controller.js +12 -12
- package/dist/workflow/create-hook.js +3 -3
- package/dist/workflow/get-workflow-metadata.js +2 -2
- package/dist/workflow/hook.js +18 -18
- package/dist/workflow/set-attributes.d.ts +1 -1
- package/dist/workflow/set-attributes.js +2 -2
- package/dist/workflow/sleep.js +2 -2
- package/dist/workflow/world-init-stub.d.ts +1 -1
- package/dist/workflow/world-init-stub.js +2 -2
- package/dist/workflow.d.ts +2 -2
- package/dist/workflow.js +36 -14
- package/docs/api-reference/create-hook.mdx +15 -15
- package/docs/api-reference/create-webhook.mdx +15 -15
- package/docs/api-reference/define-hook.mdx +10 -10
- package/docs/api-reference/fatal-error.mdx +2 -2
- package/docs/api-reference/fetch.mdx +7 -7
- package/docs/api-reference/get-step-metadata.mdx +2 -2
- package/docs/api-reference/get-workflow-metadata.mdx +3 -3
- package/docs/api-reference/get-writable.mdx +7 -7
- package/docs/api-reference/index.mdx +1 -1
- package/docs/api-reference/retryable-error.mdx +1 -1
- package/docs/api-reference/set-attributes.mdx +2 -2
- package/docs/api-reference/sleep.mdx +3 -3
- package/docs/foundations/cancellation.mdx +31 -31
- package/docs/foundations/errors-and-retries.mdx +42 -11
- package/docs/foundations/hooks.mdx +37 -37
- package/docs/foundations/idempotency.mdx +9 -9
- package/docs/foundations/serialization.mdx +21 -22
- package/docs/foundations/starting-workflows.mdx +36 -37
- package/docs/foundations/streaming.mdx +68 -39
- package/docs/foundations/versioning.mdx +3 -3
- package/docs/foundations/workflows-and-steps.mdx +9 -9
- package/docs/how-it-works/cancellation.mdx +62 -62
- package/docs/how-it-works/code-transform.mdx +66 -54
- package/docs/how-it-works/encryption.mdx +25 -21
- package/docs/how-it-works/event-sourcing.mdx +84 -28
- package/docs/how-it-works/framework-integrations.mdx +12 -12
- package/docs/how-it-works/understanding-directives.mdx +21 -21
- package/package.json +7 -7
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { EntityConflictError, FatalError, HookNotFoundError, PreconditionFailedError, RunExpiredError, WorkflowWorldError, } from '@workflow/errors';
|
|
2
|
-
import { AttributeValidationError, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
|
|
1
|
+
import { EntityConflictError, FatalError, HookNotFoundError, PreconditionFailedError, RunExpiredError, SerializationError, WorkflowWorldError, } from '@workflow/errors';
|
|
2
|
+
import { AttributeValidationError, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_COMPRESSION, SPEC_VERSION_SUPPORTS_SLOT_IDENTITY, } from '@workflow/world';
|
|
3
3
|
import { isRetryableWorldError } from '../classify-error.js';
|
|
4
4
|
import { importKey } from '../encryption.js';
|
|
5
5
|
import { runtimeLogger } from '../logger.js';
|
|
6
|
-
import { dehydrateStepArguments } from '../serialization.js';
|
|
6
|
+
import { dehydrateStepArguments, dehydrateStepError, } from '../serialization.js';
|
|
7
7
|
import * as Attribute from '../telemetry/semantic-conventions.js';
|
|
8
8
|
import { getAbortStreamIdFromToken } from '../util.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { COMPUTE_INSTANCE_ID } from './compute-instance.js';
|
|
10
|
+
import { getMaxInlineSteps, isBatchTransitionsEnabled, isResilientStepDispatchEnabled, MAX_BATCH_FANOUT_EVENTS, MAX_RESILIENT_STEP_INPUT_BYTES, } from './constants.js';
|
|
11
|
+
import { absorbSkippedSlotReport, maxEventSlot, queueMessage, slotSnapshotParams, stepDispatchIdempotencyKey, } from './helpers.js';
|
|
11
12
|
import { ReplayRecoveryReporter } from './replay-recovery-reporter.js';
|
|
13
|
+
import { unserializableStepInputPlaceholder } from './unserializable-step.js';
|
|
12
14
|
async function createHookEvent({ runId, hookEvent, queueItem, requestId, createEvent, }) {
|
|
13
15
|
try {
|
|
14
16
|
const result = await createEvent(hookEvent, {
|
|
@@ -59,14 +61,14 @@ async function createHookEvent({ runId, hookEvent, queueItem, requestId, createE
|
|
|
59
61
|
}
|
|
60
62
|
/**
|
|
61
63
|
* Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
|
|
62
|
-
* Creates events for all operations but does NOT queue step messages
|
|
64
|
+
* Creates events for all operations but does NOT queue step messages; returns the pending
|
|
63
65
|
* steps so the caller can decide which to execute inline vs queue to background.
|
|
64
66
|
*
|
|
65
67
|
* Processing order:
|
|
66
68
|
* 1. Hooks are processed first to prevent race conditions with webhook receivers
|
|
67
69
|
* 2. Step events and wait events are created in parallel
|
|
68
70
|
*/
|
|
69
|
-
export async function handleSuspension({ suspension, world, run, span, requestId, eventLog, runReadyBarrier, replayRecoveryReporter, stepDispatch, }) {
|
|
71
|
+
export async function handleSuspension({ suspension, world, run, span, requestId, eventLog, runReadyBarrier, replayRecoveryReporter, stepDispatch, ownerMessageId, allowDeferredBatchWork, }) {
|
|
70
72
|
const runId = run.runId;
|
|
71
73
|
// Turbo mode: hold every world write below until the backgrounded
|
|
72
74
|
// `run_started` has *settled*, so we never write a step/hook/wait event for a
|
|
@@ -82,7 +84,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
82
84
|
await runReadyBarrier;
|
|
83
85
|
}
|
|
84
86
|
catch {
|
|
85
|
-
// intentional: ordering barrier only
|
|
87
|
+
// intentional: ordering barrier only, see above.
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
};
|
|
@@ -94,8 +96,8 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
94
96
|
* in flight. That matters for a 412: the caller reacts by reloading the event
|
|
95
97
|
* log and restarting the replay, so a sibling create that lands after the
|
|
96
98
|
* rejection escaped commits an event whose correlation id came from the
|
|
97
|
-
* abandoned replay's seeded sequence
|
|
98
|
-
* produces
|
|
99
|
+
* abandoned replay's seeded sequence (an event the fresh replay never
|
|
100
|
+
* produces), and it races the restart's reload while doing so. Settling first
|
|
99
101
|
* makes this phase's write set final before the caller acts on the failure.
|
|
100
102
|
* It mirrors the runtime's inline step claim, which settles the in-flight
|
|
101
103
|
* step executions before escalating a 412.
|
|
@@ -122,7 +124,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
122
124
|
// Adds the optimistic-concurrency guard when the caller supplied a loaded
|
|
123
125
|
// event log; without one it creates directly (callers with no replay
|
|
124
126
|
// snapshot, e.g. tests). A stale (412) rejection propagates to the caller,
|
|
125
|
-
// which restarts the replay from a corrected log
|
|
127
|
+
// which restarts the replay from a corrected log. It is not retried here,
|
|
126
128
|
// because the event's correlation id was minted by *this* replay's seeded
|
|
127
129
|
// sequence, so re-committing it against a corrected log would persist an
|
|
128
130
|
// event no correct replay produces.
|
|
@@ -138,8 +140,8 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
138
140
|
});
|
|
139
141
|
// Bump-and-report: the write landed above the slot it asked for, so the
|
|
140
142
|
// report holds the events it was decided without. Absorbing here rather
|
|
141
|
-
// than at each call site means the rest of this phase's writes
|
|
142
|
-
// the same array to build their own snapshot
|
|
143
|
+
// than at each call site means the rest of this phase's writes (which read
|
|
144
|
+
// the same array to build their own snapshot) ask for a slot above them,
|
|
143
145
|
// and the replay that resumes from this log sees them without a reload.
|
|
144
146
|
const report = absorbSkippedSlotReport(log.events, result);
|
|
145
147
|
reportedEvents += report.added;
|
|
@@ -170,15 +172,15 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
170
172
|
// Group hook items that need work by token, preserving queue-insertion
|
|
171
173
|
// (workflow code) order within each token. Operations on one token must
|
|
172
174
|
// apply in code order: a dispose() of an earlier hook releases the token
|
|
173
|
-
// before a later same-token hook's creation is validated
|
|
175
|
+
// before a later same-token hook's creation is validated (otherwise the
|
|
174
176
|
// new hook records a spurious hook_conflict against the run's own
|
|
175
|
-
// disposed hook
|
|
177
|
+
// disposed hook), while a hook created and disposed within the same
|
|
176
178
|
// suspension is still created before it is disposed. Different tokens
|
|
177
179
|
// have no claim interaction, so token groups are processed in parallel.
|
|
178
180
|
const hookItemsByToken = new Map();
|
|
179
181
|
for (const item of allHookItems) {
|
|
180
182
|
if (item.hasCreatedEvent && !item.disposed) {
|
|
181
|
-
continue; // already committed and still live
|
|
183
|
+
continue; // already committed and still live: nothing to do
|
|
182
184
|
}
|
|
183
185
|
const group = hookItemsByToken.get(item.token);
|
|
184
186
|
if (group) {
|
|
@@ -207,7 +209,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
207
209
|
}
|
|
208
210
|
catch (err) {
|
|
209
211
|
if (EntityConflictError.is(err)) {
|
|
210
|
-
// Hook was already disposed by a concurrent invocation
|
|
212
|
+
// Hook was already disposed by a concurrent invocation, safe to skip
|
|
211
213
|
runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
|
|
212
214
|
workflowRunId: runId,
|
|
213
215
|
correlationId: queueItem.correlationId,
|
|
@@ -235,7 +237,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
235
237
|
}
|
|
236
238
|
}
|
|
237
239
|
// Process hooks first to prevent race conditions with webhook receivers.
|
|
238
|
-
// Track any hook conflicts that occur
|
|
240
|
+
// Track any hook conflicts that occur: these are returned to the caller
|
|
239
241
|
// so the V2 handler can re-invoke immediately.
|
|
240
242
|
let hasHookConflict = false;
|
|
241
243
|
let hasAwaitedHookCreation = false;
|
|
@@ -283,7 +285,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
283
285
|
}));
|
|
284
286
|
hookCreationMs = Date.now() - hookPhaseStart;
|
|
285
287
|
}
|
|
286
|
-
// Process abort requests
|
|
288
|
+
// Process abort requests: resume the hook with abort payload and write stream packet
|
|
287
289
|
const hooksNeedingAbort = allHookItems.filter((item) => item.abortRequested && !item.disposed);
|
|
288
290
|
if (hooksNeedingAbort.length > 0) {
|
|
289
291
|
await ensureRunReady();
|
|
@@ -314,7 +316,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
314
316
|
await world.streams.close(runId, streamName);
|
|
315
317
|
}
|
|
316
318
|
catch {
|
|
317
|
-
// Best-effort stream write
|
|
319
|
+
// Best-effort stream write: hook event provides the durable fallback
|
|
318
320
|
runtimeLogger.debug('Failed to write abort stream packet, hook event will provide fallback', {
|
|
319
321
|
workflowRunId: runId,
|
|
320
322
|
correlationId: queueItem.correlationId,
|
|
@@ -336,7 +338,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
336
338
|
}));
|
|
337
339
|
}
|
|
338
340
|
// Create step events for steps that don't have them yet.
|
|
339
|
-
// Unlike V1, we do NOT queue step messages from here
|
|
341
|
+
// Unlike V1, we do NOT queue step messages from here: the caller
|
|
340
342
|
// decides which steps to execute inline vs. queue to background.
|
|
341
343
|
// Wait events are also created in parallel below.
|
|
342
344
|
const stepsNeedingCreation = new Set(stepItems
|
|
@@ -344,13 +346,116 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
344
346
|
.map((queueItem) => queueItem.correlationId));
|
|
345
347
|
// Correlation IDs for which THIS suspension call actually wrote the
|
|
346
348
|
// step_created event. Populated by the ops below after a successful
|
|
347
|
-
// events.create
|
|
349
|
+
// events.create, used by the caller to claim ownership and avoid
|
|
348
350
|
// racing with concurrent handlers on step execution.
|
|
349
351
|
const createdStepCorrelationIds = new Set();
|
|
352
|
+
// Correlation IDs of steps finalized as failed because their arguments
|
|
353
|
+
// refused to serialize: see finalizeUnserializableStep below.
|
|
354
|
+
const failedStepCorrelationIds = new Set();
|
|
355
|
+
/**
|
|
356
|
+
* A step whose arguments fail to serialize is deterministic: every replay
|
|
357
|
+
* re-derives the same unserializable value, so redelivering the
|
|
358
|
+
* orchestrator message can never succeed. Instead of rejecting the whole
|
|
359
|
+
* suspension (which fails the run from the outside, where no user code can
|
|
360
|
+
* observe it), treat it exactly like a step-body failure: write
|
|
361
|
+
* `step_created` with a placeholder input (every World requires the step
|
|
362
|
+
* entity to exist before a terminal step event, and the real input is
|
|
363
|
+
* precisely what refused to serialize) followed by `step_failed` carrying
|
|
364
|
+
* the SerializationError. The next replay rejects the step's promise with
|
|
365
|
+
* it, so a try/catch around the step call observes the error; uncaught, it
|
|
366
|
+
* propagates out of the workflow body and fails the run as a USER_ERROR,
|
|
367
|
+
* without burning queue redeliveries either way.
|
|
368
|
+
*/
|
|
369
|
+
const finalizeUnserializableStep = async (queueItem, error) => {
|
|
370
|
+
runtimeLogger.warn('Step arguments failed to serialize; failing the step so the ' +
|
|
371
|
+
'workflow can observe the error', {
|
|
372
|
+
workflowRunId: runId,
|
|
373
|
+
correlationId: queueItem.correlationId,
|
|
374
|
+
stepName: queueItem.stepName,
|
|
375
|
+
error: error.message,
|
|
376
|
+
});
|
|
377
|
+
await ensureRunReady();
|
|
378
|
+
// Marker placeholder (not empty args): byte-identical-to-zero-args would
|
|
379
|
+
// make `workflow inspect steps` show "no arguments" for the one step
|
|
380
|
+
// whose entire problem was its arguments.
|
|
381
|
+
const placeholderInput = (await dehydrateStepArguments(unserializableStepInputPlaceholder(), runId, encryptionKey, suspension.globalThis, false, compression));
|
|
382
|
+
try {
|
|
383
|
+
await createGuarded({
|
|
384
|
+
eventType: 'step_created',
|
|
385
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
386
|
+
correlationId: queueItem.correlationId,
|
|
387
|
+
eventData: {
|
|
388
|
+
stepName: queueItem.stepName,
|
|
389
|
+
workflowName: run.workflowName,
|
|
390
|
+
input: placeholderInput,
|
|
391
|
+
},
|
|
392
|
+
}, { requestId });
|
|
393
|
+
}
|
|
394
|
+
catch (createErr) {
|
|
395
|
+
if (EntityConflictError.is(createErr)) {
|
|
396
|
+
// A concurrent handler already created the step: the failure is
|
|
397
|
+
// deterministic, so it is racing toward the same step_failed below.
|
|
398
|
+
runtimeLogger.info('Step already exists, continuing', {
|
|
399
|
+
workflowRunId: runId,
|
|
400
|
+
correlationId: queueItem.correlationId,
|
|
401
|
+
message: createErr.message,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
else if (RunExpiredError.is(createErr)) {
|
|
405
|
+
// Run already finished: nothing to observe the failure.
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
throw createErr;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
try {
|
|
413
|
+
await createGuarded({
|
|
414
|
+
eventType: 'step_failed',
|
|
415
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
416
|
+
correlationId: queueItem.correlationId,
|
|
417
|
+
eventData: {
|
|
418
|
+
stepName: queueItem.stepName,
|
|
419
|
+
// The error itself is a plain WorkflowError (name, message with
|
|
420
|
+
// framed hint, cause chain), serializable even though the step
|
|
421
|
+
// input was not. Error detection is realm-independent
|
|
422
|
+
// (types.isNativeError), so the host-created error serializes
|
|
423
|
+
// the same under either global; the VM global is passed for
|
|
424
|
+
// consistency with every other dehydration in this file and so
|
|
425
|
+
// any VM-realm values guest code threw into the cause chain
|
|
426
|
+
// (getters/proxies executed during the failed dehydration) are
|
|
427
|
+
// detected by the realm-sensitive reducers.
|
|
428
|
+
error: await dehydrateStepError(error, runId, encryptionKey, [], suspension.globalThis, compression),
|
|
429
|
+
},
|
|
430
|
+
}, { requestId });
|
|
431
|
+
}
|
|
432
|
+
catch (failErr) {
|
|
433
|
+
if (EntityConflictError.is(failErr) || RunExpiredError.is(failErr)) {
|
|
434
|
+
// Step already terminal (a concurrent handler wrote the same
|
|
435
|
+
// deterministic failure) or the run already finished.
|
|
436
|
+
runtimeLogger.info('Tried failing step, but step or run has already finished.', {
|
|
437
|
+
workflowRunId: runId,
|
|
438
|
+
correlationId: queueItem.correlationId,
|
|
439
|
+
message: failErr.message,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
throw failErr;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
failedStepCorrelationIds.add(queueItem.correlationId);
|
|
447
|
+
// Release the inline slot bookkeeping: the step never runs, so it must
|
|
448
|
+
// not appear in the rebuilt `lazyInlineSteps`. (Its slot in the first-N
|
|
449
|
+
// selection and in `inlinePairFoldEligible`'s arithmetic was consumed
|
|
450
|
+
// before dehydration could reveal the failure, inherent to selecting
|
|
451
|
+
// before serializing, and bounded to one wasted slot on a pass that
|
|
452
|
+
// ends in a forced replay anyway.)
|
|
453
|
+
lazyInlineCorrelationIds.delete(queueItem.correlationId);
|
|
454
|
+
};
|
|
350
455
|
// Serialization always runs through the one ordinary path below, so the
|
|
351
456
|
// durable bytes cannot depend on retention. What retention needs to know is
|
|
352
457
|
// whether that serialization *executed* workflow code (getters, proxy
|
|
353
|
-
// traps, custom serializers)
|
|
458
|
+
// traps, custom serializers): side effects a cold replay would not
|
|
354
459
|
// repeat, since a replay skips dehydration for already-recorded steps.
|
|
355
460
|
// The hardened serializer records exactly that into this sink (see
|
|
356
461
|
// ../serialization/hardened.ts); when any input in the batch records an
|
|
@@ -364,9 +469,9 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
364
469
|
// (saving a round-trip per step). We never defer when a `hook.getConflict()`
|
|
365
470
|
// awaiter is present, because in that case the caller executes nothing inline
|
|
366
471
|
// (it re-invokes immediately to resolve the awaiter), so deferring would
|
|
367
|
-
// leave the steps uncreated and unqueued. We pick the first N uncreated
|
|
368
|
-
//
|
|
369
|
-
// input here so executeStep can ship it as the step_started payload.
|
|
472
|
+
// leave the steps uncreated and unqueued. We pick the first N uncreated
|
|
473
|
+
// steps (matching the caller's inline-candidate selection) and dehydrate
|
|
474
|
+
// their input here so executeStep can ship it as the step_started payload.
|
|
370
475
|
const lazyInlineCorrelationIds = new Set(hasAwaitedHookCreation === false
|
|
371
476
|
? stepItems
|
|
372
477
|
.filter((item) => stepsNeedingCreation.has(item.correlationId))
|
|
@@ -386,13 +491,13 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
386
491
|
// Resilient step dispatch eligibility, shared by every step op below (the
|
|
387
492
|
// per-step input-size check is applied inside the op). All must hold:
|
|
388
493
|
//
|
|
389
|
-
// - The caller provided a dispatch target (`stepDispatch`)
|
|
494
|
+
// - The caller provided a dispatch target (`stepDispatch`): terminal
|
|
390
495
|
// drains and other create-only callers never queue.
|
|
391
496
|
// - The feature is enabled (`WORKFLOW_RESILIENT_STEP_DISPATCH` opt-in).
|
|
392
497
|
// It is off by default because the publish races the create's verdict,
|
|
393
498
|
// and a create can come back refused: as a duplicate the replay should
|
|
394
|
-
// stop pursuing, or
|
|
395
|
-
// than report what it missed
|
|
499
|
+
// stop pursuing, or (on a World that would rather refuse a stale write
|
|
500
|
+
// than report what it missed) as a 412. Either way the queue message
|
|
396
501
|
// carrying the payload is already out, and the consumer can materialize a
|
|
397
502
|
// step whose create was refused. Nothing orders that verdict before the
|
|
398
503
|
// consumer's redelivery re-ensure, so no backend-side revocation
|
|
@@ -405,6 +510,51 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
405
510
|
const resilientDispatchEligible = stepDispatch !== undefined &&
|
|
406
511
|
isResilientStepDispatchEnabled() &&
|
|
407
512
|
(run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT;
|
|
513
|
+
// Batched fan-out: fold this suspension's step_created + wait_created
|
|
514
|
+
// writes into one `events.createBatch` call (one durable write, per-event
|
|
515
|
+
// outcomes) instead of one write per event. Engages only for a CLEAN
|
|
516
|
+
// fan-out (no attribute writes, no hook writes, no resilient dispatch
|
|
517
|
+
// whose creates are each paired with a queue publish) on a World that
|
|
518
|
+
// implements the optional method and a run whose events are slot-numbered.
|
|
519
|
+
// Everything outside the gate keeps the single-event path byte-for-byte.
|
|
520
|
+
const batchFanoutEligible = isBatchTransitionsEnabled() &&
|
|
521
|
+
typeof world.events.createBatch === 'function' &&
|
|
522
|
+
(run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_SLOT_IDENTITY &&
|
|
523
|
+
!resilientDispatchEligible &&
|
|
524
|
+
allHookItems.length === 0 &&
|
|
525
|
+
attributeItems.length === 0;
|
|
526
|
+
/**
|
|
527
|
+
* The fold's collection, in scheduling order (steps in stepItems order,
|
|
528
|
+
* then waits). Step entries are enqueued by their prep promises (input
|
|
529
|
+
* dehydration runs concurrently, so entries are ordered by `order`, not by
|
|
530
|
+
* completion); the single flush op below awaits every prep, sorts, and
|
|
531
|
+
* commits the whole set through `createBatch`.
|
|
532
|
+
*/
|
|
533
|
+
const batchQueue = [];
|
|
534
|
+
const batchPreps = [];
|
|
535
|
+
// Pre-claimed inline pairs: fold each lazy-inline step's deferred
|
|
536
|
+
// `step_created` (carrying its input) AND its `step_started` claim (bare,
|
|
537
|
+
// ownership-stamped) into the batch, so the whole fan-out (the inline
|
|
538
|
+
// steps' claims included) commits in the one durable write and the caller
|
|
539
|
+
// starts the bodies straight off that commit instead of posting one claim
|
|
540
|
+
// per inline step. The lone-inline case (nothing else to batch with) is
|
|
541
|
+
// excluded: a pair-only batch costs the same round trip as the single lazy
|
|
542
|
+
// claim while giving up the optimistic claim/body overlap and the
|
|
543
|
+
// bump-and-report that `createGuarded` provides, so it stays on the lazy
|
|
544
|
+
// path. Requires the caller's `ownerMessageId`: the started row must
|
|
545
|
+
// stamp ownership exactly like the lazy claim it replaces (and a caller
|
|
546
|
+
// that does not inline-execute never provides one).
|
|
547
|
+
const uncreatedWaitCount = waitItems.filter((item) => !item.hasCreatedEvent).length;
|
|
548
|
+
const inlinePairFoldEligible = batchFanoutEligible &&
|
|
549
|
+
ownerMessageId !== undefined &&
|
|
550
|
+
lazyInlineCorrelationIds.size > 0 &&
|
|
551
|
+
(lazyInlineCorrelationIds.size >= 2 ||
|
|
552
|
+
stepsNeedingCreation.size -
|
|
553
|
+
lazyInlineCorrelationIds.size +
|
|
554
|
+
uncreatedWaitCount >=
|
|
555
|
+
1);
|
|
556
|
+
const inlineClaims = new Map();
|
|
557
|
+
let batchCommittedSlotCeiling;
|
|
408
558
|
// The trace carrier for resilient step dispatches, resolved at most once per
|
|
409
559
|
// suspension (the per-step ops run concurrently and share it).
|
|
410
560
|
let stepDispatchTraceCarrier;
|
|
@@ -415,24 +565,61 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
415
565
|
};
|
|
416
566
|
// Producer-side resilient recovery count for the suspension span attribute.
|
|
417
567
|
let resilientDispatchRecovered = 0;
|
|
418
|
-
// Steps: create step_created events (no queuing
|
|
419
|
-
// to caller
|
|
568
|
+
// Steps: create step_created events (no queuing, V2 returns pending steps
|
|
569
|
+
// to caller, EXCEPT on the resilient dispatch path, which parallelizes the
|
|
420
570
|
// create with the step's queue publish and reports it in
|
|
421
571
|
// `queuedStepCorrelationIds`).
|
|
572
|
+
let batchOrderCounter = 0;
|
|
422
573
|
for (const queueItem of stepItems) {
|
|
423
574
|
if (stepsNeedingCreation.has(queueItem.correlationId)) {
|
|
424
|
-
|
|
575
|
+
// Deterministic position in the batched fold (assigned in stepItems
|
|
576
|
+
// order, before the concurrent dehydration runs). A pair-folded inline
|
|
577
|
+
// step occupies two consecutive positions (created row then started
|
|
578
|
+
// row), which the flush keeps adjacent and never splits across chunks,
|
|
579
|
+
// so a World can fold them into one born-running create.
|
|
580
|
+
const pairFolded = inlinePairFoldEligible &&
|
|
581
|
+
lazyInlineCorrelationIds.has(queueItem.correlationId);
|
|
582
|
+
const stepOrder = batchOrderCounter;
|
|
583
|
+
batchOrderCounter += pairFolded ? 2 : 1;
|
|
584
|
+
const stepOp = (async () => {
|
|
425
585
|
// Per-step sink, merged below: the dehydrate wrapper emits span
|
|
426
586
|
// attributes from the sink it is handed, so sharing one across
|
|
427
587
|
// steps would re-emit (and misattribute) earlier steps' entries.
|
|
428
588
|
const stepGuestCode = { executions: [] };
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
589
|
+
let dehydratedInput;
|
|
590
|
+
try {
|
|
591
|
+
dehydratedInput = await dehydrateStepArguments({
|
|
592
|
+
args: queueItem.args,
|
|
593
|
+
closureVars: queueItem.closureVars,
|
|
594
|
+
thisVal: queueItem.thisVal,
|
|
595
|
+
}, runId, encryptionKey, suspension.globalThis, false, compression, stepGuestCode);
|
|
596
|
+
}
|
|
597
|
+
catch (err) {
|
|
598
|
+
// The sink records executions as they happen, so guest code that
|
|
599
|
+
// ran before the failure still counts against retention.
|
|
600
|
+
guestCodeStats.executions.push(...stepGuestCode.executions);
|
|
601
|
+
if (!SerializationError.is(err)) {
|
|
602
|
+
// e.g. RuntimeDecryptionError: an SDK fault, not a user value
|
|
603
|
+
// problem. Keep its identity (RUNTIME_ERROR) and current
|
|
604
|
+
// fail-the-suspension behavior.
|
|
605
|
+
throw err;
|
|
606
|
+
}
|
|
607
|
+
if (!stepDispatch) {
|
|
608
|
+
// No dispatch target means no replay will observe a
|
|
609
|
+
// finalization: this is the terminal drain (or a create-only
|
|
610
|
+
// test caller). The run is already completing/failing, so
|
|
611
|
+
// writing step_created + step_failed here would leave e.g. a
|
|
612
|
+
// COMPLETED run carrying a failed step nothing can ever
|
|
613
|
+
// observe, reading as a bug from the dashboard. Rethrow
|
|
614
|
+
// instead; the drain's own catch swallows it, preserving its
|
|
615
|
+
// pre-existing behavior (no rows for the unawaited step).
|
|
616
|
+
throw err;
|
|
617
|
+
}
|
|
618
|
+
await finalizeUnserializableStep(queueItem, err);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
434
621
|
guestCodeStats.executions.push(...stepGuestCode.executions);
|
|
435
|
-
// Deferred (lazy) inline step: skip the step_created write
|
|
622
|
+
// Deferred (lazy) inline step: skip the step_created write; the
|
|
436
623
|
// caller's inline executeStep will send a lazy step_started carrying
|
|
437
624
|
// this input, and the world creates the step (entity + synthetic
|
|
438
625
|
// step_created event) atomically. We do NOT add it to
|
|
@@ -444,6 +631,44 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
444
631
|
stepName: queueItem.stepName,
|
|
445
632
|
dehydratedInput: dehydratedInput,
|
|
446
633
|
});
|
|
634
|
+
if (pairFolded) {
|
|
635
|
+
// Enqueue the pair the deferral would otherwise leave to the
|
|
636
|
+
// caller's lazy `step_started`: the created row carries the
|
|
637
|
+
// input (payloads ride creates in a batch), the started row is
|
|
638
|
+
// bare and stamps this invocation's ownership, the same claim
|
|
639
|
+
// shape the lazy start would have sent, settled by the batch.
|
|
640
|
+
batchQueue.push({
|
|
641
|
+
order: stepOrder,
|
|
642
|
+
kind: 'inline-created',
|
|
643
|
+
correlationId: queueItem.correlationId,
|
|
644
|
+
event: {
|
|
645
|
+
eventType: 'step_created',
|
|
646
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
647
|
+
correlationId: queueItem.correlationId,
|
|
648
|
+
eventData: {
|
|
649
|
+
stepName: queueItem.stepName,
|
|
650
|
+
workflowName: run.workflowName,
|
|
651
|
+
input: dehydratedInput,
|
|
652
|
+
},
|
|
653
|
+
},
|
|
654
|
+
});
|
|
655
|
+
batchQueue.push({
|
|
656
|
+
order: stepOrder + 1,
|
|
657
|
+
kind: 'inline-started',
|
|
658
|
+
correlationId: queueItem.correlationId,
|
|
659
|
+
event: {
|
|
660
|
+
eventType: 'step_started',
|
|
661
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
662
|
+
correlationId: queueItem.correlationId,
|
|
663
|
+
eventData: {
|
|
664
|
+
stepName: queueItem.stepName,
|
|
665
|
+
// Checked by inlinePairFoldEligible; spread keeps the
|
|
666
|
+
// narrow-through-closure problem away from the type.
|
|
667
|
+
...(ownerMessageId !== undefined ? { ownerMessageId } : {}),
|
|
668
|
+
},
|
|
669
|
+
},
|
|
670
|
+
});
|
|
671
|
+
}
|
|
447
672
|
return;
|
|
448
673
|
}
|
|
449
674
|
const stepEvent = {
|
|
@@ -457,7 +682,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
457
682
|
},
|
|
458
683
|
};
|
|
459
684
|
// Resilient step dispatch: fire the step_created write and the
|
|
460
|
-
// step-execution queue publish in parallel
|
|
685
|
+
// step-execution queue publish in parallel: the message carries the
|
|
461
686
|
// same serialized input (`stepInput`) so the consumer can
|
|
462
687
|
// idempotently re-ensure the event if the direct write failed
|
|
463
688
|
// transiently. Mirrors the resilient start (`runInput`) and
|
|
@@ -481,10 +706,10 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
481
706
|
stepInput: { input: dehydratedInput },
|
|
482
707
|
},
|
|
483
708
|
// Same key as the caller's dispatch pass and any concurrent
|
|
484
|
-
// handler's
|
|
709
|
+
// handler's, so redundant publishes for this step dedupe. The
|
|
485
710
|
// key is step-identity-scoped so a revoked message for a
|
|
486
711
|
// reassigned correlation id cannot absorb the corrected
|
|
487
|
-
// schedule's dispatch
|
|
712
|
+
// schedule's dispatch: see stepDispatchIdempotencyKey.
|
|
488
713
|
{
|
|
489
714
|
idempotencyKey: stepDispatchIdempotencyKey(queueItem.correlationId, queueItem.stepName),
|
|
490
715
|
}),
|
|
@@ -493,7 +718,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
493
718
|
// the message the step would rely on the create alone, and if the
|
|
494
719
|
// create ALSO failed there would be no durable record at all.
|
|
495
720
|
// Propagating redelivers the orchestrator message, which
|
|
496
|
-
// re-creates the (idempotent) step_created and re-dispatches
|
|
721
|
+
// re-creates the (idempotent) step_created and re-dispatches,
|
|
497
722
|
// the same recovery as the sequential path.
|
|
498
723
|
if (queueResult.status === 'rejected') {
|
|
499
724
|
throw queueResult.reason;
|
|
@@ -502,7 +727,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
502
727
|
if (createResult.status === 'rejected') {
|
|
503
728
|
const err = createResult.reason;
|
|
504
729
|
if (EntityConflictError.is(err)) {
|
|
505
|
-
// Concurrent handler wrote it first
|
|
730
|
+
// Concurrent handler wrote it first, same as the sequential
|
|
506
731
|
// path. The step message is already out; a duplicate publish
|
|
507
732
|
// by that handler dedupes on the shared idempotency key.
|
|
508
733
|
runtimeLogger.info('Step already exists, continuing', {
|
|
@@ -513,8 +738,8 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
513
738
|
}
|
|
514
739
|
else if (isRetryableWorldError(err)) {
|
|
515
740
|
// Resilient: the write failed transiently (429 / 5xx /
|
|
516
|
-
// transport) but the step message
|
|
517
|
-
// serialized input
|
|
741
|
+
// transport) but the step message (carrying the same
|
|
742
|
+
// serialized input) was published, so the consumer
|
|
518
743
|
// idempotently re-ensures the step_created before executing.
|
|
519
744
|
resilientDispatchRecovered++;
|
|
520
745
|
runtimeLogger.warn('Step creation event write failed, but the step was ' +
|
|
@@ -535,6 +760,19 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
535
760
|
}
|
|
536
761
|
return;
|
|
537
762
|
}
|
|
763
|
+
if (batchFanoutEligible) {
|
|
764
|
+
// Fold into the batch instead of writing here. The enclosing
|
|
765
|
+
// promise joins `batchPreps` (see the loop below), so the flush
|
|
766
|
+
// op cannot run before this step's input finished dehydrating.
|
|
767
|
+
batchQueue.push({
|
|
768
|
+
order: stepOrder,
|
|
769
|
+
kind: 'step',
|
|
770
|
+
correlationId: queueItem.correlationId,
|
|
771
|
+
stepName: queueItem.stepName,
|
|
772
|
+
event: stepEvent,
|
|
773
|
+
});
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
538
776
|
try {
|
|
539
777
|
await ensureRunReady();
|
|
540
778
|
await createGuarded(stepEvent, { requestId });
|
|
@@ -552,21 +790,41 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
552
790
|
throw err;
|
|
553
791
|
}
|
|
554
792
|
}
|
|
555
|
-
})()
|
|
793
|
+
})();
|
|
794
|
+
ops.push(stepOp);
|
|
795
|
+
if (batchFanoutEligible) {
|
|
796
|
+
// The flush op waits for every prep before committing; a prep that
|
|
797
|
+
// rejected already surfaces through `ops`, so the flush's own wait
|
|
798
|
+
// swallows it and commits whatever was successfully enqueued,
|
|
799
|
+
// preserving today's per-op independence.
|
|
800
|
+
batchPreps.push(stepOp.catch(() => { }));
|
|
801
|
+
}
|
|
556
802
|
}
|
|
557
803
|
}
|
|
558
804
|
// Create wait events (same as V1)
|
|
559
805
|
for (const queueItem of waitItems) {
|
|
560
806
|
if (!queueItem.hasCreatedEvent) {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
807
|
+
const waitEvent = {
|
|
808
|
+
eventType: 'wait_created',
|
|
809
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
810
|
+
correlationId: queueItem.correlationId,
|
|
811
|
+
eventData: {
|
|
812
|
+
resumeAt: queueItem.resumeAt,
|
|
813
|
+
},
|
|
814
|
+
};
|
|
815
|
+
if (batchFanoutEligible) {
|
|
816
|
+
// Waits need no dehydration, so they enqueue synchronously, after
|
|
817
|
+
// every step's order slot, preserving steps-then-waits scheduling
|
|
818
|
+
// order in the log.
|
|
819
|
+
batchQueue.push({
|
|
820
|
+
order: batchOrderCounter++,
|
|
821
|
+
kind: 'wait',
|
|
565
822
|
correlationId: queueItem.correlationId,
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
823
|
+
event: waitEvent,
|
|
824
|
+
});
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
ops.push((async () => {
|
|
570
828
|
try {
|
|
571
829
|
await ensureRunReady();
|
|
572
830
|
await createGuarded(waitEvent, { requestId });
|
|
@@ -586,6 +844,362 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
586
844
|
})());
|
|
587
845
|
}
|
|
588
846
|
}
|
|
847
|
+
// The batched fold's flush: the clean fan-out commits through
|
|
848
|
+
// `createBatch` in chunks of MAX_BATCH_FANOUT_EVENTS, all chunks IN
|
|
849
|
+
// FLIGHT CONCURRENTLY. Slot assignment is the server's, so parallel
|
|
850
|
+
// chunks race for slot ranges exactly like the pre-fold path's parallel
|
|
851
|
+
// single writes did; entity conditions, not commit order, carry
|
|
852
|
+
// correctness (sibling fan-out events have no cross-order the replay
|
|
853
|
+
// depends on; it matches by correlation id). Each event reports the
|
|
854
|
+
// outcome its own single create would have had: a 409 is the same
|
|
855
|
+
// already-exists tolerance as the single path, anything else fails the
|
|
856
|
+
// delivery the way a single-path rejection would.
|
|
857
|
+
//
|
|
858
|
+
// Latency shape: only the chunk carrying the pre-claimed inline pairs
|
|
859
|
+
// gates the handler's return (the caller starts bodies off its claims).
|
|
860
|
+
// Every other chunk's commit (and every chunk's step-message publishes,
|
|
861
|
+
// which fire the moment ITS creates are durable) rides
|
|
862
|
+
// `deferredBatchWork` when the caller opted in, joined before ack. A slow
|
|
863
|
+
// sibling chunk therefore delays neither the inline bodies nor another
|
|
864
|
+
// chunk's queue messages, while publish-after-create still holds per
|
|
865
|
+
// step: a step's message is only ever sent after the chunk carrying its
|
|
866
|
+
// create has committed.
|
|
867
|
+
let deferredBatchWork;
|
|
868
|
+
if (batchFanoutEligible) {
|
|
869
|
+
ops.push((async () => {
|
|
870
|
+
// Preps that rejected already surface through their own `ops`
|
|
871
|
+
// entries; the fold commits whatever was successfully enqueued,
|
|
872
|
+
// preserving today's per-op independence.
|
|
873
|
+
await Promise.all(batchPreps);
|
|
874
|
+
if (batchQueue.length === 0) {
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
const entries = [...batchQueue].sort((a, b) => a.order - b.order);
|
|
878
|
+
await ensureRunReady();
|
|
879
|
+
// A batch of ONE gains nothing over the single write (same round
|
|
880
|
+
// trip) and loses the slot-snapshot params + bump-and-report that
|
|
881
|
+
// createGuarded provides, so a lone eager event takes the ordinary
|
|
882
|
+
// single path, with the same conflict tolerance and ownership
|
|
883
|
+
// bookkeeping it would have had without the fold.
|
|
884
|
+
if (entries.length === 1) {
|
|
885
|
+
const [entry] = entries;
|
|
886
|
+
try {
|
|
887
|
+
await createGuarded(entry.event, { requestId });
|
|
888
|
+
if (entry.kind === 'step') {
|
|
889
|
+
createdStepCorrelationIds.add(entry.correlationId);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
catch (err) {
|
|
893
|
+
if (EntityConflictError.is(err)) {
|
|
894
|
+
runtimeLogger.info(entry.kind === 'step'
|
|
895
|
+
? 'Step already exists, continuing'
|
|
896
|
+
: 'Wait already exists, continuing', {
|
|
897
|
+
workflowRunId: runId,
|
|
898
|
+
correlationId: entry.correlationId,
|
|
899
|
+
message: err.message,
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
else {
|
|
903
|
+
throw err;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
// Seed for the foreign-interleaving diagnostic below. With chunks
|
|
909
|
+
// committing in parallel there is no per-chunk "expected next slot";
|
|
910
|
+
// the whole fold's committed span is compared against the seed
|
|
911
|
+
// once every chunk has settled: committed slots are dense per the
|
|
912
|
+
// World's invariant, so any excess of (max committed slot − seed +
|
|
913
|
+
// 1) over the fold's own committed count is events OTHER writers
|
|
914
|
+
// landed in between.
|
|
915
|
+
const expectedFirstSlot = eventLog
|
|
916
|
+
? (maxEventSlot(eventLog.events) ?? 0) + 1
|
|
917
|
+
: undefined;
|
|
918
|
+
// Pair-aware chunking: a pre-claimed pair's two rows must land in
|
|
919
|
+
// the same createBatch call (adjacent, so a World can fold them
|
|
920
|
+
// into one born-running create) and never straddle a chunk
|
|
921
|
+
// boundary, which would turn the started row into a standalone
|
|
922
|
+
// claim racing its own create's commit.
|
|
923
|
+
const chunks = [];
|
|
924
|
+
{
|
|
925
|
+
let current = [];
|
|
926
|
+
for (let index = 0; index < entries.length; index++) {
|
|
927
|
+
const entry = entries[index];
|
|
928
|
+
const next = entries[index + 1];
|
|
929
|
+
const pairLead = entry.kind === 'inline-created' &&
|
|
930
|
+
next?.kind === 'inline-started' &&
|
|
931
|
+
next.correlationId === entry.correlationId;
|
|
932
|
+
const take = pairLead ? 2 : 1;
|
|
933
|
+
if (current.length > 0 &&
|
|
934
|
+
current.length + take > MAX_BATCH_FANOUT_EVENTS) {
|
|
935
|
+
chunks.push(current);
|
|
936
|
+
current = [];
|
|
937
|
+
}
|
|
938
|
+
current.push(entry);
|
|
939
|
+
if (pairLead) {
|
|
940
|
+
current.push(next);
|
|
941
|
+
index++;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
if (current.length > 0)
|
|
945
|
+
chunks.push(current);
|
|
946
|
+
}
|
|
947
|
+
// Steps whose queue messages THIS FLUSH will publish (the eager
|
|
948
|
+
// creates), recorded before any chunk settles so the caller's
|
|
949
|
+
// dispatch pass (which runs off the handler's return) skips them.
|
|
950
|
+
// The sends are guaranteed-or-failed by the trailing work the
|
|
951
|
+
// caller joins before acking, so "will be published by this flush"
|
|
952
|
+
// and "already published" are equivalent from the caller's side.
|
|
953
|
+
const publishEagerSteps = stepDispatch !== undefined;
|
|
954
|
+
if (publishEagerSteps) {
|
|
955
|
+
for (const entry of entries) {
|
|
956
|
+
if (entry.kind === 'step') {
|
|
957
|
+
queuedStepCorrelationIds.add(entry.correlationId);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
// Tallies for the foreign-interleaving diagnostic, folded across
|
|
962
|
+
// the concurrent chunks and read once all of them settled.
|
|
963
|
+
let committedCount = 0;
|
|
964
|
+
let maxCommittedSlot;
|
|
965
|
+
const commitChunk = async (chunk) => {
|
|
966
|
+
// Anchors for the pre-claimed steps' telemetry: the POST instant
|
|
967
|
+
// is the claim's "start POST sent" (RSFS's end), the return is the
|
|
968
|
+
// claim's completion (TTR's T6), the same two instants the lazy
|
|
969
|
+
// claim's own POST would have produced.
|
|
970
|
+
const batchPostSentAtMs = Date.now();
|
|
971
|
+
// biome-ignore lint/style/noNonNullAssertion: batchFanoutEligible implies presence
|
|
972
|
+
const { results } = await world.events.createBatch(runId, chunk.map((entry) => ({
|
|
973
|
+
event: entry.event,
|
|
974
|
+
// The started row is the step's executing claim, so it carries
|
|
975
|
+
// the compute-instance attribution the single claim sends via
|
|
976
|
+
// CreateEventParams.
|
|
977
|
+
...(entry.kind === 'inline-started'
|
|
978
|
+
? { computeInstanceId: COMPUTE_INSTANCE_ID }
|
|
979
|
+
: {}),
|
|
980
|
+
})),
|
|
981
|
+
// Per-write request attribution, same as the single path's
|
|
982
|
+
// createGuarded(…, { requestId }).
|
|
983
|
+
{ requestId });
|
|
984
|
+
const claimCompletedAtMs = Date.now();
|
|
985
|
+
for (const [index, item] of results.entries()) {
|
|
986
|
+
const entry = chunk[index];
|
|
987
|
+
if (item.error === undefined) {
|
|
988
|
+
if (entry.kind === 'step') {
|
|
989
|
+
createdStepCorrelationIds.add(entry.correlationId);
|
|
990
|
+
}
|
|
991
|
+
else if (entry.kind === 'inline-started') {
|
|
992
|
+
// The pair committed: this invocation owns the step and the
|
|
993
|
+
// caller runs the body with no claim of its own. The
|
|
994
|
+
// readback entity is authoritative where present; a World
|
|
995
|
+
// that omitted it gets the same locally synthesized running
|
|
996
|
+
// attempt-1 the optimistic path executes against. Either
|
|
997
|
+
// way the input is re-attached locally: batch responses
|
|
998
|
+
// return refs lazily, and the body's hydration wants the
|
|
999
|
+
// exact bytes the pair's created row carried. (The created
|
|
1000
|
+
// row's success is deliberately NOT membership in
|
|
1001
|
+
// createdStepCorrelationIds: for inline steps ownership is
|
|
1002
|
+
// the started row's verdict, and the caller's dispatch pass
|
|
1003
|
+
// skips inline correlation ids regardless.)
|
|
1004
|
+
const dehydrated = lazyInlineByCorrelationId.get(entry.correlationId);
|
|
1005
|
+
if (dehydrated === undefined) {
|
|
1006
|
+
// Unreachable: the same prep op that enqueued the pair set
|
|
1007
|
+
// this entry, and the flush awaited every prep above.
|
|
1008
|
+
//
|
|
1009
|
+
// Not free if it ever fires, though: the pair is already
|
|
1010
|
+
// durable here, so this throws with the step claimed and
|
|
1011
|
+
// its body never run. The delivery fails, and redelivery
|
|
1012
|
+
// recovers it through owned-recovery (the step carries this
|
|
1013
|
+
// message's ownership stamp) rather than the request just
|
|
1014
|
+
// failing cleanly.
|
|
1015
|
+
throw new WorkflowWorldError(`no dehydrated input for pre-claimed step ${entry.correlationId}`, { status: 500 });
|
|
1016
|
+
}
|
|
1017
|
+
const now = new Date();
|
|
1018
|
+
const startedStep = item.step?.startedAt
|
|
1019
|
+
? { ...item.step, startedAt: item.step.startedAt }
|
|
1020
|
+
: {
|
|
1021
|
+
runId,
|
|
1022
|
+
stepId: entry.correlationId,
|
|
1023
|
+
stepName: dehydrated.stepName,
|
|
1024
|
+
status: 'running',
|
|
1025
|
+
attempt: 1,
|
|
1026
|
+
createdAt: now,
|
|
1027
|
+
updatedAt: now,
|
|
1028
|
+
startedAt: now,
|
|
1029
|
+
};
|
|
1030
|
+
inlineClaims.set(entry.correlationId, {
|
|
1031
|
+
owned: true,
|
|
1032
|
+
step: {
|
|
1033
|
+
...startedStep,
|
|
1034
|
+
input: dehydrated.dehydratedInput,
|
|
1035
|
+
},
|
|
1036
|
+
batchPostSentAtMs,
|
|
1037
|
+
claimCompletedAtMs,
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
continue;
|
|
1041
|
+
}
|
|
1042
|
+
if (item.status === 409) {
|
|
1043
|
+
if (entry.kind === 'inline-created' ||
|
|
1044
|
+
entry.kind === 'inline-started') {
|
|
1045
|
+
// The pair lost its atomic create-claim: a concurrent writer
|
|
1046
|
+
// already owns this step (an earlier delivery's create, or a
|
|
1047
|
+
// racing handler's claim). Recorded as a lost claim: the
|
|
1048
|
+
// caller's executeStep returns `skipped` without running the
|
|
1049
|
+
// body, the same outcome as losing the lazy claim. A World
|
|
1050
|
+
// that folds the pair reports the 409 on both rows (set
|
|
1051
|
+
// twice, harmless); one that evaluates rows independently
|
|
1052
|
+
// has the started row (processed second) decide, which is
|
|
1053
|
+
// exactly the single path's semantics (create lost + claim
|
|
1054
|
+
// won still runs the body; create won + claim lost skips).
|
|
1055
|
+
inlineClaims.set(entry.correlationId, { owned: false });
|
|
1056
|
+
runtimeLogger.info('Inline step pre-claim lost, continuing', {
|
|
1057
|
+
workflowRunId: runId,
|
|
1058
|
+
correlationId: entry.correlationId,
|
|
1059
|
+
message: item.message,
|
|
1060
|
+
});
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1063
|
+
// Same tolerance as the single path's EntityConflictError: a
|
|
1064
|
+
// concurrent or earlier delivery already created it.
|
|
1065
|
+
runtimeLogger.info(entry.kind === 'step'
|
|
1066
|
+
? 'Step already exists, continuing'
|
|
1067
|
+
: 'Wait already exists, continuing', {
|
|
1068
|
+
workflowRunId: runId,
|
|
1069
|
+
correlationId: entry.correlationId,
|
|
1070
|
+
message: item.message,
|
|
1071
|
+
});
|
|
1072
|
+
continue;
|
|
1073
|
+
}
|
|
1074
|
+
throw new WorkflowWorldError(`batched ${entry.event.eventType} for ${entry.correlationId} ` +
|
|
1075
|
+
`failed: ${item.error}: ${item.message}`, { status: item.status });
|
|
1076
|
+
}
|
|
1077
|
+
// Highest slot this chunk committed: the ceiling the caller folds
|
|
1078
|
+
// into the inline executions' slot snapshot (see
|
|
1079
|
+
// SuspensionHandlerResult.batchCommittedSlotCeiling) and one input
|
|
1080
|
+
// of the interleaving diagnostic.
|
|
1081
|
+
const chunkMaxSlot = maxEventSlot(results.flatMap((item) => item.error === undefined && item.event ? [item.event] : []));
|
|
1082
|
+
if (chunkMaxSlot !== undefined &&
|
|
1083
|
+
(batchCommittedSlotCeiling === undefined ||
|
|
1084
|
+
chunkMaxSlot > batchCommittedSlotCeiling)) {
|
|
1085
|
+
batchCommittedSlotCeiling = chunkMaxSlot;
|
|
1086
|
+
}
|
|
1087
|
+
committedCount += results.filter((item) => item.error === undefined).length;
|
|
1088
|
+
if (chunkMaxSlot !== undefined &&
|
|
1089
|
+
(maxCommittedSlot === undefined || chunkMaxSlot > maxCommittedSlot)) {
|
|
1090
|
+
maxCommittedSlot = chunkMaxSlot;
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
// Publish the chunk's eager steps' queue messages the moment ITS
|
|
1094
|
+
// creates are durable, the per-chunk half of publish-after-create.
|
|
1095
|
+
// Same message shape and step-identity-scoped idempotency key as the
|
|
1096
|
+
// caller's dispatch pass, so anything double-published dedupes.
|
|
1097
|
+
const publishChunkSteps = async (chunk) => {
|
|
1098
|
+
if (!publishEagerSteps)
|
|
1099
|
+
return;
|
|
1100
|
+
const stepEntries = chunk.filter((entry) => entry.kind === 'step');
|
|
1101
|
+
if (stepEntries.length === 0)
|
|
1102
|
+
return;
|
|
1103
|
+
const traceCarrier = await getStepDispatchTraceCarrier();
|
|
1104
|
+
await Promise.all(stepEntries.map((entry) => queueMessage(world,
|
|
1105
|
+
// biome-ignore lint/style/noNonNullAssertion: publishEagerSteps implies presence
|
|
1106
|
+
stepDispatch.queueName, {
|
|
1107
|
+
runId,
|
|
1108
|
+
stepId: entry.correlationId,
|
|
1109
|
+
// biome-ignore lint/style/noNonNullAssertion: set on every 'step' entry at enqueue
|
|
1110
|
+
stepName: entry.stepName,
|
|
1111
|
+
traceCarrier,
|
|
1112
|
+
requestedAt: new Date(),
|
|
1113
|
+
}, {
|
|
1114
|
+
idempotencyKey: stepDispatchIdempotencyKey(entry.correlationId,
|
|
1115
|
+
// biome-ignore lint/style/noNonNullAssertion: set on every 'step' entry at enqueue
|
|
1116
|
+
entry.stepName),
|
|
1117
|
+
})));
|
|
1118
|
+
};
|
|
1119
|
+
// Launch every chunk's POST now; chain each chunk's publishes on its
|
|
1120
|
+
// OWN commit. A chunk whose commit rejected keeps its messages
|
|
1121
|
+
// unsent (the rejection fails the delivery; redelivery re-creates
|
|
1122
|
+
// and re-dispatches, deduped by the idempotency keys).
|
|
1123
|
+
const commits = chunks.map((chunk) => commitChunk(chunk));
|
|
1124
|
+
const publishes = chunks.map(async (chunk, index) => {
|
|
1125
|
+
await commits[index];
|
|
1126
|
+
await publishChunkSteps(chunk);
|
|
1127
|
+
});
|
|
1128
|
+
const trailing = (async () => {
|
|
1129
|
+
// Let every sibling settle before surfacing the first failure: a
|
|
1130
|
+
// chunk that committed must still get its publishes out even when
|
|
1131
|
+
// another chunk failed, and the caller acks only after this
|
|
1132
|
+
// resolves.
|
|
1133
|
+
const settled = await Promise.allSettled([...commits, ...publishes]);
|
|
1134
|
+
// Foreign-interleaving visibility: the batch endpoint has no
|
|
1135
|
+
// bump-and-report, so events other writers landed between the
|
|
1136
|
+
// snapshot and these commits pushed the fold to higher slots
|
|
1137
|
+
// WITHOUT handing us the skipped events. Same accepted exposure
|
|
1138
|
+
// as a dropped truncated report on the single path: the local
|
|
1139
|
+
// log stays a strict prefix and the next reload observes them.
|
|
1140
|
+
// Logged so a bump is diagnosable rather than silent.
|
|
1141
|
+
if (expectedFirstSlot !== undefined &&
|
|
1142
|
+
maxCommittedSlot !== undefined) {
|
|
1143
|
+
const interleaved = maxCommittedSlot - expectedFirstSlot + 1 - committedCount;
|
|
1144
|
+
if (interleaved > 0) {
|
|
1145
|
+
runtimeLogger.debug('Batched fan-out committed above snapshot', {
|
|
1146
|
+
workflowRunId: runId,
|
|
1147
|
+
expectedFirstSlot,
|
|
1148
|
+
maxCommittedSlot,
|
|
1149
|
+
committedCount,
|
|
1150
|
+
interleaved,
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
const failure = settled.find((outcome) => outcome.status === 'rejected');
|
|
1155
|
+
if (failure)
|
|
1156
|
+
throw failure.reason;
|
|
1157
|
+
})();
|
|
1158
|
+
// EVERY chunk carrying pairs gates the return, not just the first:
|
|
1159
|
+
// a pair whose commit the caller has not seen yields no
|
|
1160
|
+
// `inlineClaims` entry, so the caller falls back to a lazy
|
|
1161
|
+
// `step_started` that would race this same fold's still-in-flight
|
|
1162
|
+
// pair for the same step. Today pairs always land in one chunk
|
|
1163
|
+
// (they sort first, and two rows per inline step fit inside one
|
|
1164
|
+
// chunk, pinned by constants.test.ts), so this is at most one
|
|
1165
|
+
// commit; the filter is what keeps the property true if either cap
|
|
1166
|
+
// moves.
|
|
1167
|
+
const pairCommits = chunks.flatMap((chunk, index) => chunk.some((entry) => entry.kind === 'inline-started')
|
|
1168
|
+
? [commits[index]]
|
|
1169
|
+
: []);
|
|
1170
|
+
if (allowDeferredBatchWork) {
|
|
1171
|
+
// The trailing work is the caller's to join before ack. Attach a
|
|
1172
|
+
// handler now so a rejection that races that join (or a foreground
|
|
1173
|
+
// failure that prevents the caller from ever reaching it) is never
|
|
1174
|
+
// an unhandledRejection; awaiting the promise still observes it.
|
|
1175
|
+
trailing.catch(() => { });
|
|
1176
|
+
deferredBatchWork = trailing;
|
|
1177
|
+
// Only the pair chunks gate the return: their claims are what the
|
|
1178
|
+
// caller starts the inline bodies from. With no pairs there is
|
|
1179
|
+
// nothing the caller's post-return work reads from the commits,
|
|
1180
|
+
// so nothing gates.
|
|
1181
|
+
if (pairCommits.length > 0) {
|
|
1182
|
+
try {
|
|
1183
|
+
await Promise.all(pairCommits);
|
|
1184
|
+
}
|
|
1185
|
+
catch (err) {
|
|
1186
|
+
// A pair chunk failed, so this phase's write set is NOT the
|
|
1187
|
+
// caller's to join any more: `deferredBatchWork` never
|
|
1188
|
+
// reaches it once handleSuspension throws. Settle the rest
|
|
1189
|
+
// before the rejection escapes, for the reason `settlePhase`
|
|
1190
|
+
// gives: a sibling create landing after the throw commits an
|
|
1191
|
+
// event from the abandoned replay's seeded sequence and races
|
|
1192
|
+
// the caller's restart reload while doing so.
|
|
1193
|
+
await trailing.catch(() => { });
|
|
1194
|
+
throw err;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
else {
|
|
1199
|
+
await trailing;
|
|
1200
|
+
}
|
|
1201
|
+
})());
|
|
1202
|
+
}
|
|
589
1203
|
for (const queueItem of attributeItems) {
|
|
590
1204
|
ops.push((async () => {
|
|
591
1205
|
try {
|
|
@@ -593,7 +1207,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
593
1207
|
// Guarded like every other suspension write: an attr_set is a
|
|
594
1208
|
// replay-derived event with a correlation id from this replay's
|
|
595
1209
|
// seeded sequence, so it must not land on a log the replay never
|
|
596
|
-
// saw. Rejecting it is cheap
|
|
1210
|
+
// saw. Rejecting it is cheap: a run with attribute events already
|
|
597
1211
|
// forces an in-process replay, so the restart costs the replay it
|
|
598
1212
|
// was going to do anyway.
|
|
599
1213
|
await createGuarded({
|
|
@@ -618,7 +1232,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
618
1232
|
});
|
|
619
1233
|
}
|
|
620
1234
|
else if (isWorldValidationFailure(err)) {
|
|
621
|
-
// Deterministic validation rejection from the World
|
|
1235
|
+
// Deterministic validation rejection from the World, e.g. the
|
|
622
1236
|
// cumulative per-run attribute cap, which only the World can
|
|
623
1237
|
// check against the run's existing attributes. Redelivering the
|
|
624
1238
|
// orchestrator message replays the workflow into the exact same
|
|
@@ -682,6 +1296,9 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
682
1296
|
...Attribute.WorkflowStepsCreated(stepItems.length),
|
|
683
1297
|
...Attribute.WorkflowHooksCreated(hooksNeedingCreation.length),
|
|
684
1298
|
...Attribute.WorkflowWaitsCreated(waitItems.length),
|
|
1299
|
+
...(failedStepCorrelationIds.size > 0
|
|
1300
|
+
? Attribute.WorkflowStepsFailedSerialization(failedStepCorrelationIds.size)
|
|
1301
|
+
: {}),
|
|
685
1302
|
...(resilientDispatchRecovered > 0
|
|
686
1303
|
? Attribute.StepResilientDispatchRecovered(resilientDispatchRecovered)
|
|
687
1304
|
: {}),
|
|
@@ -689,8 +1306,12 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
689
1306
|
return {
|
|
690
1307
|
pendingSteps: stepItems,
|
|
691
1308
|
createdStepCorrelationIds,
|
|
1309
|
+
failedStepCorrelationIds,
|
|
692
1310
|
queuedStepCorrelationIds,
|
|
693
1311
|
lazyInlineSteps,
|
|
1312
|
+
inlineClaims,
|
|
1313
|
+
batchCommittedSlotCeiling,
|
|
1314
|
+
deferredBatchWork,
|
|
694
1315
|
// On hook conflict the caller re-invokes immediately and never reads
|
|
695
1316
|
// the wait timeout, so don't report one.
|
|
696
1317
|
waitTimeout: hasHookConflict ? undefined : soonestWait,
|
|
@@ -720,4 +1341,4 @@ function isWorldValidationFailure(err) {
|
|
|
720
1341
|
}
|
|
721
1342
|
return WorkflowWorldError.is(err) && err.status === 400;
|
|
722
1343
|
}
|
|
723
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGlCQUFpQixFQUNqQix1QkFBdUIsRUFDdkIsZUFBZSxFQUNmLGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCx3QkFBd0IsRUFLeEIsb0JBQW9CLEVBQ3BCLDBDQUEwQyxFQUMxQyxpQ0FBaUMsR0FLbEMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM3RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFRN0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU3QyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM3RCxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN2RCxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLDhCQUE4QixFQUM5Qiw4QkFBOEIsR0FDL0IsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQ0wsdUJBQXVCLEVBR3ZCLFlBQVksRUFDWixrQkFBa0IsRUFDbEIsMEJBQTBCLEdBQzNCLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBOEl2RSxLQUFLLFVBQVUsZUFBZSxDQUFDLEVBQzdCLEtBQUssRUFDTCxTQUFTLEVBQ1QsU0FBUyxFQUNULFNBQVMsRUFDVCxXQUFXLEdBVVo7SUFJQyxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFN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Q0osQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBUyx3QkFBd0IsQ0FBQyxHQUFZO0lBQzVDLElBQUksR0FBRyxZQUFZLHdCQUF3QjtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3pELElBQUksR0FBRyxZQUFZLEtBQUssSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLDBCQUEwQixFQUFFLENBQUM7UUFDcEUsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsT0FBTyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUM7QUFDMUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU3BhbiB9IGZyb20gJ0BvcGVudGVsZW1ldHJ5L2FwaSc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBGYXRhbEVycm9yLFxuICBIb29rTm90Rm91bmRFcnJvcixcbiAgUHJlY29uZGl0aW9uRmFpbGVkRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbiAgV29ya2Zsb3dXb3JsZEVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7XG4gIEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcixcbiAgdHlwZSBDcmVhdGVFdmVudFBhcmFtcyxcbiAgdHlwZSBDcmVhdGVFdmVudFJlcXVlc3QsXG4gIHR5cGUgRXZlbnRSZXN1bHQsXG4gIHR5cGUgU2VyaWFsaXplZERhdGEsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ0JPUl9RVUVVRV9UUkFOU1BPUlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTixcbiAgdHlwZSBUcmFjZUNhcnJpZXIsXG4gIHR5cGUgVmFsaWRRdWV1ZU5hbWUsXG4gIHR5cGUgV29ya2Zsb3dSdW4sXG4gIHR5cGUgV29ybGQsXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBpc1JldHJ5YWJsZVdvcmxkRXJyb3IgfSBmcm9tICcuLi9jbGFzc2lmeS1lcnJvci5qcyc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgQXR0cmlidXRlSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBXYWl0SW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV29ya2Zsb3dTdXNwZW5zaW9uLFxufSBmcm9tICcuLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgdHlwZSB7IEd1ZXN0Q29kZVN0YXRzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi9oYXJkZW5lZC5qcyc7XG5pbXBvcnQgeyBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IGdldEFib3J0U3RyZWFtSWRGcm9tVG9rZW4gfSBmcm9tICcuLi91dGlsLmpzJztcbmltcG9ydCB7XG4gIGdldE1heElubGluZVN0ZXBzLFxuICBpc1Jlc2lsaWVudFN0ZXBEaXNwYXRjaEVuYWJsZWQsXG4gIE1BWF9SRVNJTElFTlRfU1RFUF9JTlBVVF9CWVRFUyxcbn0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHtcbiAgYWJzb3JiU2tpcHBlZFNsb3RSZXBvcnQsXG4gIHR5cGUgRXZlbnRDcmVhdG9yLFxuICB0eXBlIExvYWRlZEV2ZW50TG9nLFxuICBxdWV1ZU1lc3NhZ2UsXG4gIHNsb3RTbmFwc2hvdFBhcmFtcyxcbiAgc3RlcERpc3BhdGNoSWRlbXBvdGVuY3lLZXksXG59IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyIH0gZnJvbSAnLi9yZXBsYXktcmVjb3ZlcnktcmVwb3J0ZXIuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zIHtcbiAgc3VzcGVuc2lvbjogV29ya2Zsb3dTdXNwZW5zaW9uO1xuICB3b3JsZDogV29ybGQ7XG4gIHJ1bjogV29ya2Zsb3dSdW47XG4gIHNwYW4/OiBTcGFuO1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcnVudGltZSdzIGxvYWRlZCBldmVudCBsb2cuIEV2ZXJ5IGV2ZW50IGNyZWF0aW9uIHRoaXMgc3VzcGVuc2lvbiBtYWtlc1xuICAgKiBuYW1lcyB0aGUgcG9zaXRpb24gaXQgd2FzIGRlcml2ZWQgZnJvbSwgc28gYSBiYWNrZW5kIHRoYXQgaGFzIHJlY29yZGVkXG4gICAqIGV2ZW50cyB0aGUgcmVwbGF5IGRpZCBub3Qgc2VlIGNhbiByZXBvcnQgdGhlbSBiYWNrIG9uIHRoZSB3cml0ZSDigJQgb3IsIGlmXG4gICAqIGl0IHdvdWxkIHJhdGhlciByZWZ1c2UgdGhhbiByZXBvcnQsIHJlamVjdCBpdCB3aXRoIGEgNDEyLiBBIHJlamVjdGlvbiBpc1xuICAgKiBub3QgcmV0cmllZCBoZXJlOiB0aGUgZXZlbnQncyBjb3JyZWxhdGlvbiBpZCB3YXMgbWludGVkIGJ5ICp0aGlzKiByZXBsYXknc1xuICAgKiBzZWVkZWQgc2VxdWVuY2UsIHNvIHJlLWNvbW1pdHRpbmcgaXQgYWdhaW5zdCBhIGNvcnJlY3RlZCBsb2cgd291bGQgcGVyc2lzdFxuICAgKiBhbiBldmVudCBubyBjb3JyZWN0IHJlcGxheSBwcm9kdWNlcy4gVGhlIGNhbGxlciByZXN0YXJ0cyB0aGUgcmVwbGF5XG4gICAqIGluc3RlYWQuXG4gICAqL1xuICBldmVudExvZz86IExvYWRlZEV2ZW50TG9nO1xuICAvKipcbiAgICogVHVyYm8gbW9kZSBvbmx5OiBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBvbmNlIHRoZSBiYWNrZ3JvdW5kZWRcbiAgICogYHJ1bl9zdGFydGVkYCBoYXMgbGFuZGVkICh0aGUgcnVuIGV4aXN0cykuIFdoZW4gcHJlc2VudCwgZXZlcnkgd29ybGQgd3JpdGVcbiAgICogdGhpcyBzdXNwZW5zaW9uIHBlcmZvcm1zIChgaG9va19jcmVhdGVkYCwgYHdhaXRfY3JlYXRlZGAsIGVhZ2VyIG92ZXJmbG93XG4gICAqIGBzdGVwX2NyZWF0ZWRgLCDigKYpIGlzIGdhdGVkIG9uIGl0IHNvIHRoZSB3cml0ZSBuZXZlciByYWNlcyBhaGVhZCBvZiB0aGVcbiAgICogcnVuJ3MgY3JlYXRpb24uIFRoZSBwdXJlIGlubGluZSBob3QgcGF0aCBkZWZlcnMgYWxsIG9mIGl0cyBzdGVwcyBhbmQgd3JpdGVzXG4gICAqIG5vdGhpbmcgaGVyZSwgc28gaXQgbmV2ZXIgYXdhaXRzIHRoaXMgYmFycmllci4gYHVuZGVmaW5lZGAgb3V0c2lkZSB0dXJibyxcbiAgICogd2hlcmUgYHJ1bl9zdGFydGVkYCB3YXMgYWxyZWFkeSBhd2FpdGVkIHVwIGZyb250LlxuICAgKi9cbiAgcnVuUmVhZHlCYXJyaWVyPzogUHJvbWlzZTx1bmtub3duPjtcbiAgLyoqIE9uZS1zaG90IHRlbGVtZXRyeSByZXBvcnRlciwgYWN0aXZhdGVkIG9ubHkgYWZ0ZXIgcmVwbGF5IGhhcyByZWNvdmVyZWQuICovXG4gIHJlcGxheVJlY292ZXJ5UmVwb3J0ZXI/OiBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyO1xuICAvKipcbiAgICogUmVzaWxpZW50IHN0ZXAgZGlzcGF0Y2g6IHdoZW4gcHJvdmlkZWQgKGFuZCB0aGUgcGVyLXN0ZXAgZWxpZ2liaWxpdHkgZ2F0ZXNcbiAgICogcGFzcyDigJQgc2VlIHRoZSBzdGVwIG9wcyBiZWxvdyksIGVhY2ggbmV3bHkgY3JlYXRlZCBub24taW5saW5lIHN0ZXAnc1xuICAgKiBgc3RlcF9jcmVhdGVkYCB3cml0ZSBpcyBwYXJhbGxlbGl6ZWQgd2l0aCBpdHMgc3RlcC1leGVjdXRpb24gcXVldWVcbiAgICogcHVibGlzaCwgYW5kIHRoZSBxdWV1ZSBtZXNzYWdlIGNhcnJpZXMgdGhlIHNlcmlhbGl6ZWQgc3RlcCBpbnB1dFxuICAgKiAoYHN0ZXBJbnB1dGApIHNvIHRoZSBjb25zdW1lciBjYW4gaWRlbXBvdGVudGx5IHJlLWVuc3VyZSB0aGUgZXZlbnQgaWYgdGhlXG4gICAqIGRpcmVjdCB3cml0ZSBmYWlsZWQgdHJhbnNpZW50bHkuIFN0ZXBzIHF1ZXVlZCB0aGlzIHdheSBhcmUgcmVwb3J0ZWQgaW5cbiAgICoge0BsaW5rIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0LnF1ZXVlZFN0ZXBDb3JyZWxhdGlvbklkc30gc28gdGhlIGNhbGxlclxuICAgKiBza2lwcyB0aGVtIGluIGl0cyBvd24gZGlzcGF0Y2ggcGFzcy4gT21pdHRlZCBieSBjYWxsZXJzIHRoYXQgbXVzdCBub3RcbiAgICogcXVldWUgKHRlcm1pbmFsIGRyYWluLCB0ZXN0cykg4oCUIGNyZWF0ZXMgdGhlbiBiZWhhdmUgZXhhY3RseSBhcyBiZWZvcmUuXG4gICAqL1xuICBzdGVwRGlzcGF0Y2g/OiB7XG4gICAgLyoqIFRoZSB1bmlmaWVkIHdvcmtmbG93IHF1ZXVlIHRoaXMgcnVuJ3Mgc3RlcCBtZXNzYWdlcyBhcmUgcHVibGlzaGVkIHRvLiAqL1xuICAgIHF1ZXVlTmFtZTogVmFsaWRRdWV1ZU5hbWU7XG4gICAgLyoqXG4gICAgICogTGF6aWx5IHJlc29sdmVzIHRoZSB0cmFjZSBjYXJyaWVyIHRvIHN0YW1wIG9uIHRoZSBzdGVwIG1lc3NhZ2VzLlxuICAgICAqIENhbGxlZCBhdCBtb3N0IG9uY2UgcGVyIHN1c3BlbnNpb24gKG1lbW9pemVkIGhlcmUpLlxuICAgICAqL1xuICAgIGdldFRyYWNlQ2FycmllcjogKCkgPT4gUHJvbWlzZTxUcmFjZUNhcnJpZXI+O1xuICB9O1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBoYW5kbGluZyBhIHN1c3BlbnNpb24uIFJldHVybnMgcGVuZGluZyBzdGVwIGl0ZW1zIHNvIHRoZSBjYWxsZXJcbiAqIGNhbiBkZWNpZGUgd2hpY2ggdG8gZXhlY3V0ZSBpbmxpbmUgdnMgcXVldWUgdG8gYmFja2dyb3VuZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdCB7XG4gIC8qKiBQZW5kaW5nIHN0ZXAgaXRlbXMgd2l0aCBldmVudHMgY3JlYXRlZCBidXQgTk9UIHF1ZXVlZCAqL1xuICBwZW5kaW5nU3RlcHM6IFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtW107XG4gIC8qKlxuICAgKiBDb3JyZWxhdGlvbiBJRHMgZm9yIHdoaWNoIHRoaXMgc3VzcGVuc2lvbiBjYWxsIGFjdHVhbGx5IHdyb3RlIHRoZVxuICAgKiBzdGVwX2NyZWF0ZWQgZXZlbnQgKGFzIG9wcG9zZWQgdG8gY2F0Y2hpbmcgRW50aXR5Q29uZmxpY3RFcnJvciBiZWNhdXNlXG4gICAqIGEgY29uY3VycmVudCBoYW5kbGVyIHdyb3RlIGl0IGZpcnN0KS4gT25seSB0aGUgaGFuZGxlciB0aGF0IHdyb3RlIHRoZVxuICAgKiBzdGVwX2NyZWF0ZWQgZXZlbnQgc2hvdWxkIHF1ZXVlIC8gaW5saW5lLWV4ZWN1dGUgdGhlIHN0ZXAg4oCUIHRoaXNcbiAgICogZ3VhcmFudGVlcyBhIHNpbmdsZSBvd25lciBwZXIgc3RlcCwgZXZlbiB3aGVuIG11bHRpcGxlIGhhbmRsZXJzIHJhY2VcbiAgICogaW50byB0aGUgc2FtZSBiYXRjaCBib3VuZGFyeS5cbiAgICovXG4gIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHM6IFNldDxzdHJpbmc+O1xuICAvKipcbiAgICogQ29ycmVsYXRpb24gSURzIG9mIHN0ZXBzIHRoaXMgc3VzcGVuc2lvbiBjYWxsIGFscmVhZHkgcHVibGlzaGVkXG4gICAqIHN0ZXAtZXhlY3V0aW9uIHF1ZXVlIG1lc3NhZ2VzIGZvciwgdmlhIHJlc2lsaWVudCBzdGVwIGRpc3BhdGNoICh0aGVcbiAgICogYHN0ZXBfY3JlYXRlZGAgd3JpdGUgcGFyYWxsZWxpemVkIHdpdGggYSBgc3RlcElucHV0YC1jYXJyeWluZyBxdWV1ZVxuICAgKiBwdWJsaXNoKS4gVGhlIGNhbGxlciBNVVNUIE5PVCBkaXNwYXRjaCB0aGVzZSBhZ2FpbiDigJQgdGhlIG1lc3NhZ2UgaXNcbiAgICogYWxyZWFkeSBvdXQgKGEgZHVwbGljYXRlIHdvdWxkIGJlIGRlZHVwZWQgYnkgaXRzIGlkZW1wb3RlbmN5IGtleSwgYnV0XG4gICAqIGNvc3RzIGEgd2FzdGVkIHJvdW5kLXRyaXApLiBFbXB0eSB3aGVuIHtAbGluayBTdXNwZW5zaW9uSGFuZGxlclBhcmFtcy5zdGVwRGlzcGF0Y2h9XG4gICAqIHdhcyBub3QgcHJvdmlkZWQgb3Igbm8gc3RlcCB3YXMgZWxpZ2libGUuXG4gICAqL1xuICBxdWV1ZWRTdGVwQ29ycmVsYXRpb25JZHM6IFNldDxzdHJpbmc+O1xuICAvKipcbiAgICogSG93IG1hbnkgZXZlbnRzIHRoaXMgcGhhc2UncyB3cml0ZXMgcmVwb3J0ZWQgYmFjayBhcyBvY2N1cHlpbmcgc2xvdHMgdGhleVxuICAgKiBza2lwcGVkIG92ZXIsIGFscmVhZHkgbWVyZ2VkIGludG8gdGhlIGNhbGxlcidzIGBldmVudExvZy5ldmVudHNgLiBOb256ZXJvXG4gICAqIG1lYW5zIHRoZSBhcnJheSB3YXMgcmVvcmRlcmVkIHRvIHJlc3RvcmUgc2xvdCBvcmRlciwgc28gYW55IGluZGV4IHRoZVxuICAgKiBjYWxsZXIgY2FjaGVkIGludG8gaXQgKHBheWxvYWQgcHJld2FybSBzY2FuIHBvc2l0aW9uKSBpcyBzdGFsZS5cbiAgICovXG4gIHJlcG9ydGVkRXZlbnRDb3VudDogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIHN0ZXBzIHdob3NlIGBzdGVwX2NyZWF0ZWRgIHdyaXRlcyB3ZXJlIGludGVudGlvbmFsbHkgZGVmZXJyZWQgc28gdGhlXG4gICAqIGNhbGxlciBjYW4gcnVuIHRoZW0gaW5saW5lIHZpYSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGV2ZW50cyAod2hpY2ggY3JlYXRlXG4gICAqIHRoZSBzdGVwIG9uIHRoZSBmbHkpLCBzYXZpbmcgb25lIHdvcmxkIHJvdW5kLXRyaXAgcGVyIGlubGluZSBzdGVwLiBVcCB0b1xuICAgKiBgZ2V0TWF4SW5saW5lU3RlcHMoKWAgc3RlcHMgYXJlIGRlZmVycmVkOyB0aGUgY2FsbGVyIHJ1bnMgdGhlbSBpbmxpbmUgaW5cbiAgICogcGFyYWxsZWwgYW5kIHF1ZXVlcyB0aGUgcmVzdC4gRW1wdHkgd2hlbiBubyBzdGVwIHdhcyBkZWZlcnJlZCAobm90aGluZ1xuICAgKiBwZW5kaW5nLCBvciBhIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXIgaXMgcHJlc2VudCBzbyBub3RoaW5nIGlzXG4gICAqIGV4ZWN1dGVkIGlubGluZSkuIFRoZSBjYWxsZXIgcGFzc2VzIGVhY2ggYGRlaHlkcmF0ZWRJbnB1dGAgc3RyYWlnaHQgdG9cbiAgICogYGV4ZWN1dGVTdGVwYCwgd2hpY2ggc2VuZHMgaXQgYXMgdGhlIGBzdGVwX3N0YXJ0ZWRgIHBheWxvYWQuIFRoZSBhdG9taWNcbiAgICogY3JlYXRlLWNsYWltIGluc2lkZSBlYWNoIGBzdGVwX3N0YXJ0ZWRgIGlzIHRoZSBleGFjdGx5LW9uZS1vd25lciBnYXRlIHRoYXRcbiAgICogdGhlIHN0YW5kYWxvbmUgYHN0ZXBfY3JlYXRlZGAgcHJvdmlkZWQgYmVmb3JlOiB0aGUgbG9zZXIgb2YgdGhlIHJhY2UgZ2V0c1xuICAgKiBgRW50aXR5Q29uZmxpY3RFcnJvcmAg4oaSIGBza2lwcGVkYCBhbmQgZG9lcyBub3QgcnVuIHRoZSBib2R5LlxuICAgKi9cbiAgbGF6eUlubGluZVN0ZXBzOiBBcnJheTx7XG4gICAgY29ycmVsYXRpb25JZDogc3RyaW5nO1xuICAgIHN0ZXBOYW1lOiBzdHJpbmc7XG4gICAgZGVoeWRyYXRlZElucHV0OiBTZXJpYWxpemVkRGF0YTtcbiAgfT47XG4gIC8qKlxuICAgKiBUaGUgc29vbmVzdCBwZW5kaW5nIHdhaXQsIGlmIGFueTogc2Vjb25kcyB1bnRpbCBpdCBlbGFwc2VzIGFuZCB0aGVcbiAgICogY29ycmVsYXRpb25JZCBvZiB0aGUgd2FpdCB0aGF0IHByb2R1Y2VkIHRoYXQgdGltZW91dC4gVGhlXG4gICAqIGNvcnJlbGF0aW9uSWQgc2VlZHMgdGhlIGlkZW1wb3RlbmN5IGtleSBmb3IgdGhlIHdhaXQtY29udGludWF0aW9uXG4gICAqIHF1ZXVlIG1lc3NhZ2Ugc28gdGhhdCByZXBlYXRlZCBzdXNwZW5zaW9uIHBhc3NlcyBvdmVyIHRoZSBzYW1lXG4gICAqIHBlbmRpbmcgd2FpdCBjb2xsYXBzZSBpbnRvIGEgc2luZ2xlIGRlbGF5ZWQgY29udGludWF0aW9uLlxuICAgKi9cbiAgd2FpdFRpbWVvdXQ/OiB7IHNlY29uZHM6IG51bWJlcjsgY29ycmVsYXRpb25JZDogc3RyaW5nIH07XG4gIC8qKiBXaGV0aGVyIGEgaG9vayBjb25mbGljdCB3YXMgZGV0ZWN0ZWQgKHNob3VsZCByZS1pbnZva2UgaW1tZWRpYXRlbHkpICovXG4gIGhhc0hvb2tDb25mbGljdDogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgYSBgaG9vay5nZXRDb25mbGljdCgpYCBhd2FpdGVyIG5lZWRzIHRoZSB3b3JrZmxvdyB0byBjb250aW51ZSBpbW1lZGlhdGVseSAqL1xuICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBib29sZWFuO1xuICAvKiogV2hldGhlciBuYXRpdmUgd29ya2Zsb3cgYXR0cmlidXRlIGV2ZW50cyB3ZXJlIHdyaXR0ZW4gZm9yIHJlcGxheS4gKi9cbiAgaGFzQXR0cmlidXRlRXZlbnRzOiBib29sZWFuO1xuICAvKipcbiAgICogV2hldGhlciB0aGlzIHN1c3BlbnNpb24gY3JlYXRlZCBhbnkgaG9vayAoYGhvb2tfY3JlYXRlZGApIGV2ZW50cy4gVW5saWtlXG4gICAqIGBoYXNIb29rQ29uZmxpY3RgIC8gYGhhc0F3YWl0ZWRIb29rQ3JlYXRpb25gLCB0aGlzIGlzIHRydWUgZXZlbiBmb3IgYSBwbGFpblxuICAgKiBmaXJlLWFuZC1mb3JnZXQgaG9vayB3aXRoIG5vIGNvbmZsaWN0IGFuZCBubyBhd2FpdGVyLiBUdXJibyBtb2RlIHVzZXMgaXQgdG9cbiAgICogZGV0ZWN0IFwiYSBob29rIHdhcyBjcmVhdGVkIHRoaXMgc3VzcGVuc2lvblwiIGFuZCBzdG9wIGZvcmNpbmcgb3B0aW1pc3RpY1xuICAgKiBpbmxpbmUgc3RhcnQgKGEgaG9vayBpbnRyb2R1Y2VzIGxhdGVyIHJlc3VtZSBpbnZvY2F0aW9ucyB0aGF0IGNvdWxkIHJhY2UpLlxuICAgKi9cbiAgaGFzSG9va0V2ZW50czogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFdhbGwtY2xvY2sgbXMgc3BlbnQgY29tbWl0dGluZyB0aGlzIHN1c3BlbnNpb24ncyBgaG9va19jcmVhdGVkYCBldmVudHNcbiAgICogKDAgd2hlbiBpdCBjcmVhdGVkIG5vbmUpLiBUaGUgY2FsbGVyIGFjY3VtdWxhdGVzIHRoaXMgYWNyb3NzIGl0ZXJhdGlvbnNcbiAgICogYW5kIHN1YnRyYWN0cyBpdCBmcm9tIHRoZSBUVEZTIGxhdGVuY3kgbWVhc3VyZW1lbnQsIHNvIHRpbWUgc3BlbnRcbiAgICogZHVyYWJseSBjcmVhdGluZyB0aGUgdXNlcidzIGhvb2tzIGRvZXNuJ3QgY291bnQgYXMgcnVudGltZSBvdmVyaGVhZC5cbiAgICovXG4gIGhvb2tDcmVhdGlvbk1zOiBudW1iZXI7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHNlcmlhbGl6aW5nIHRoaXMgc3VzcGVuc2lvbidzIG5ldyBzdGVwIGlucHV0cyB3YXMgcGFzc2l2ZSAoZGlkXG4gICAqIG5vdCBleGVjdXRlIHdvcmtmbG93LW93bmVkIGNvZGUgc3VjaCBhcyBnZXR0ZXJzLCBwcm94eSB0cmFwcywgb3IgY3VzdG9tXG4gICAqIHNlcmlhbGl6ZXJzKS4gYGZhbHNlYCBtZWFucyB0aGUgcmV0YWluZWQgVk0gbWF5IGhhdmUgZGl2ZXJnZWQgZnJvbSB3aGF0XG4gICAqIGEgY29sZCByZXBsYXkgd291bGQgY29tcHV0ZSwgc28gdGhlIGNhbGxlciBtdXN0IGRlbW90ZSB0byByZXBsYXkuXG4gICAqL1xuICByZXRhaW5lZFN0ZXBJbnB1dHNTYWZlOiBib29sZWFuO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVIb29rRXZlbnQoe1xuICBydW5JZCxcbiAgaG9va0V2ZW50LFxuICBxdWV1ZUl0ZW0sXG4gIHJlcXVlc3RJZCxcbiAgY3JlYXRlRXZlbnQsXG59OiB7XG4gIHJ1bklkOiBzdHJpbmc7XG4gIGhvb2tFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0O1xuICBxdWV1ZUl0ZW06IEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtO1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG4gIGNyZWF0ZUV2ZW50OiAoXG4gICAgZGF0YTogQ3JlYXRlRXZlbnRSZXF1ZXN0LFxuICAgIHBhcmFtcz86IENyZWF0ZUV2ZW50UGFyYW1zXG4gICkgPT4gUHJvbWlzZTxFdmVudFJlc3VsdD47XG59KTogUHJvbWlzZTx7XG4gIGhhc0hvb2tDb25mbGljdDogYm9vbGVhbjtcbiAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogYm9vbGVhbjtcbn0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjcmVhdGVFdmVudChob29rRXZlbnQsIHtcbiAgICAgIHJlcXVlc3RJZCxcbiAgICB9KTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB3b3JsZCByZXR1cm5lZCBhIGhvb2tfY29uZmxpY3QgZXZlbnQgaW5zdGVhZCBvZiBob29rX2NyZWF0ZWQuXG4gICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3QuXG4gICAgaWYgKHJlc3VsdC5ldmVudD8uZXZlbnRUeXBlID09PSAnaG9va19jb25mbGljdCcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhhc0hvb2tDb25mbGljdDogdHJ1ZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFzSG9va0NvbmZsaWN0OiBmYWxzZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vaycsIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBmYWxzZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnIpKSB7XG4gICAgICBjb25zdCBmYXRhbCA9IG5ldyBGYXRhbEVycm9yKFxuICAgICAgICBgY3JlYXRlSG9vayBmYWlsZWQgV29ybGQgdmFsaWRhdGlvbjogJHtcbiAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycilcbiAgICAgICAgfWBcbiAgICAgICk7XG4gICAgICBmYXRhbC5jYXVzZSA9IGVycjtcbiAgICAgIHRocm93IGZhdGFsO1xuICAgIH1cblxuICAgIHRocm93IGVycjtcbiAgfVxufVxuXG4vKipcbiAqIEhhbmRsZXMgYSB3b3JrZmxvdyBzdXNwZW5zaW9uIGJ5IHByb2Nlc3NpbmcgYWxsIHBlbmRpbmcgb3BlcmF0aW9ucyAoaG9va3MsIHN0ZXBzLCB3YWl0cykuXG4gKiBDcmVhdGVzIGV2ZW50cyBmb3IgYWxsIG9wZXJhdGlvbnMgYnV0IGRvZXMgTk9UIHF1ZXVlIHN0ZXAgbWVzc2FnZXMg4oCUIHJldHVybnMgdGhlIHBlbmRpbmdcbiAqIHN0ZXBzIHNvIHRoZSBjYWxsZXIgY2FuIGRlY2lkZSB3aGljaCB0byBleGVjdXRlIGlubGluZSB2cyBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICpcbiAqIFByb2Nlc3Npbmcgb3JkZXI6XG4gKiAxLiBIb29rcyBhcmUgcHJvY2Vzc2VkIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnNcbiAqIDIuIFN0ZXAgZXZlbnRzIGFuZCB3YWl0IGV2ZW50cyBhcmUgY3JlYXRlZCBpbiBwYXJhbGxlbFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlU3VzcGVuc2lvbih7XG4gIHN1c3BlbnNpb24sXG4gIHdvcmxkLFxuICBydW4sXG4gIHNwYW4sXG4gIHJlcXVlc3RJZCxcbiAgZXZlbnRMb2csXG4gIHJ1blJlYWR5QmFycmllcixcbiAgcmVwbGF5UmVjb3ZlcnlSZXBvcnRlcixcbiAgc3RlcERpc3BhdGNoLFxufTogU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMpOiBQcm9taXNlPFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0PiB7XG4gIGNvbnN0IHJ1bklkID0gcnVuLnJ1bklkO1xuXG4gIC8vIFR1cmJvIG1vZGU6IGhvbGQgZXZlcnkgd29ybGQgd3JpdGUgYmVsb3cgdW50aWwgdGhlIGJhY2tncm91bmRlZFxuICAvLyBgcnVuX3N0YXJ0ZWRgIGhhcyAqc2V0dGxlZCosIHNvIHdlIG5ldmVyIHdyaXRlIGEgc3RlcC9ob29rL3dhaXQgZXZlbnQgZm9yIGFcbiAgLy8gcnVuIHRoYXQgZG9lcyBub3QgZXhpc3QgeWV0LiBBIG5vLW9wIG91dHNpZGUgdHVyYm8gKGJhcnJpZXIgdW5kZWZpbmVkKSBhbmRcbiAgLy8gb24gdGhlIHB1cmUgaW5saW5lIGhvdCBwYXRoLCB3aGljaCBkZWZlcnMgYWxsIHN0ZXBzIGFuZCB3cml0ZXMgbm90aGluZy5cbiAgLy8gQXdhaXRpbmcgdGhlIHNhbWUgKHVzdWFsbHkgYWxyZWFkeS1zZXR0bGVkKSBwcm9taXNlIG1vcmUgdGhhbiBvbmNlIGlzIGNoZWFwLlxuICAvLyBBIGJhcnJpZXIgcmVqZWN0aW9uIGlzIHN3YWxsb3dlZCBmb3Igb3JkZXJpbmcgb25seTogaWYgYHJ1bl9zdGFydGVkYCB0cnVseVxuICAvLyBmYWlsZWQgdGhlIHJ1biBkb2VzIG5vdCBleGlzdCwgc28gdGhlIHN1YnNlcXVlbnQgd3JpdGUgc3VyZmFjZXMgdGhlIHJlYWxcbiAgLy8gZXJyb3IgKHJ1biBub3QgZm91bmQgLyBnb25lKSBhbmQgdGhlIG1lc3NhZ2UgcmVkZWxpdmVycy5cbiAgY29uc3QgZW5zdXJlUnVuUmVhZHkgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgaWYgKHJ1blJlYWR5QmFycmllcikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgcnVuUmVhZHlCYXJyaWVyO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIGludGVudGlvbmFsOiBvcmRlcmluZyBiYXJyaWVyIG9ubHkg4oCUIHNlZSBhYm92ZS5cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEF3YWl0IGV2ZXJ5IG9wZXJhdGlvbiBpbiBhIHN1c3BlbnNpb24gcGhhc2UgYmVmb3JlIGxldHRpbmcgYSBmYWlsdXJlXG4gICAqIGVzY2FwZSwgcHJlZmVycmluZyBhIHN0YWxlLXNuYXBzaG90ICg0MTIpIHJlamVjdGlvbiB3aGVuIG9uZSBvY2N1cnJlZC5cbiAgICpcbiAgICogYFByb21pc2UuYWxsYCByZWplY3RzIGFzIHNvb24gYXMgb25lIG9wZXJhdGlvbiBkb2VzIGFuZCBsZWF2ZXMgaXRzIHNpYmxpbmdzXG4gICAqIGluIGZsaWdodC4gVGhhdCBtYXR0ZXJzIGZvciBhIDQxMjogdGhlIGNhbGxlciByZWFjdHMgYnkgcmVsb2FkaW5nIHRoZSBldmVudFxuICAgKiBsb2cgYW5kIHJlc3RhcnRpbmcgdGhlIHJlcGxheSwgc28gYSBzaWJsaW5nIGNyZWF0ZSB0aGF0IGxhbmRzIGFmdGVyIHRoZVxuICAgKiByZWplY3Rpb24gZXNjYXBlZCBjb21taXRzIGFuIGV2ZW50IHdob3NlIGNvcnJlbGF0aW9uIGlkIGNhbWUgZnJvbSB0aGVcbiAgICogYWJhbmRvbmVkIHJlcGxheSdzIHNlZWRlZCBzZXF1ZW5jZSDigJQgYW4gZXZlbnQgdGhlIGZyZXNoIHJlcGxheSBuZXZlclxuICAgKiBwcm9kdWNlcyDigJQgYW5kIGl0IHJhY2VzIHRoZSByZXN0YXJ0J3MgcmVsb2FkIHdoaWxlIGRvaW5nIHNvLiBTZXR0bGluZyBmaXJzdFxuICAgKiBtYWtlcyB0aGlzIHBoYXNlJ3Mgd3JpdGUgc2V0IGZpbmFsIGJlZm9yZSB0aGUgY2FsbGVyIGFjdHMgb24gdGhlIGZhaWx1cmUuXG4gICAqIEl0IG1pcnJvcnMgdGhlIHJ1bnRpbWUncyBpbmxpbmUgc3RlcCBjbGFpbSwgd2hpY2ggc2V0dGxlcyB0aGUgaW4tZmxpZ2h0XG4gICAqIHN0ZXAgZXhlY3V0aW9ucyBiZWZvcmUgZXNjYWxhdGluZyBhIDQxMi5cbiAgICpcbiAgICogQSA0MTIgaXMgcHJlZmVycmVkIG92ZXIgYW55IG90aGVyIHJlamVjdGlvbiBpbiB0aGUgc2FtZSBwaGFzZSBiZWNhdXNlIGl0XG4gICAqIGhhcyBhIGRlZmluZWQsIGNoZWFwIHJlY292ZXJ5IChyZXBsYXkgZnJvbSBhIGNvcnJlY3RlZCBsb2cpIHdoaWxlIHRoZVxuICAgKiBvdGhlcnMgZG8gbm90LiBBIGRldGVybWluaXN0aWMgZmFpbHVyZSBzdWNoIGFzIGFuIGF0dHJpYnV0ZS12YWxpZGF0aW9uXG4gICAqIGBGYXRhbEVycm9yYCByZWN1cnMgb24gdGhlIHJlc3RhcnQgYW5kIGZhaWxzIHRoZSBydW4gdGhlbiwgYXQgdGhlIGNvc3Qgb2ZcbiAgICogb25lIGV4dHJhIHJlcGxheS5cbiAgICovXG4gIGNvbnN0IHNldHRsZVBoYXNlID0gYXN5bmMgKG9wczogUHJvbWlzZTx1bmtub3duPltdKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgY29uc3QgcmVhc29ucyA9IChhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQob3BzKSlcbiAgICAgIC5maWx0ZXIoKHIpOiByIGlzIFByb21pc2VSZWplY3RlZFJlc3VsdCA9PiByLnN0YXR1cyA9PT0gJ3JlamVjdGVkJylcbiAgICAgIC5tYXAoKHIpID0+IHIucmVhc29uKTtcbiAgICBpZiAocmVhc29ucy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aHJvdyByZWFzb25zLmZpbmQoKHIpID0+IFByZWNvbmRpdGlvbkZhaWxlZEVycm9yLmlzKHIpKSA/PyByZWFzb25zWzBdO1xuICB9O1xuXG4gIC8vIEV2ZXJ5IHN1c3BlbnNpb24gd3JpdGUgY2FycmllcyByZXBsYXktcmVjb3ZlcnkgdGVsZW1ldHJ5IG9uIHRoZSBmaXJzdCBvbmVcbiAgLy8gdGhhdCBjb21taXRzIGFmdGVyIHJlcGxheSByZWNvdmVyZWQuIEFsbCBzdXNwZW5zaW9uIGV2ZW50cyBhcmVcbiAgLy8gbm9uLXJ1bl9jcmVhdGVkIGV2ZW50cyBvbiB0aGlzIHJ1bidzIGBydW5JZGAuXG4gIGNvbnN0IHJlcG9ydGVyID0gcmVwbGF5UmVjb3ZlcnlSZXBvcnRlciA/PyBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyLmluZXJ0KCk7XG4gIGNvbnN0IGNyZWF0ZUV2ZW50ID0gKGRhdGE6IENyZWF0ZUV2ZW50UmVxdWVzdCwgcGFyYW1zPzogQ3JlYXRlRXZlbnRQYXJhbXMpID0+XG4gICAgcmVwb3J0ZXIud2l0aEV2ZW50Q3JlYXRlKHBhcmFtcywgKHApID0+XG4gICAgICB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBkYXRhLCBwKVxuICAgICk7XG4gIC8vIEFkZHMgdGhlIG9wdGltaXN0aWMtY29uY3VycmVuY3kgZ3VhcmQgd2hlbiB0aGUgY2FsbGVyIHN1cHBsaWVkIGEgbG9hZGVkXG4gIC8vIGV2ZW50IGxvZzsgd2l0aG91dCBvbmUgaXQgY3JlYXRlcyBkaXJlY3RseSAoY2FsbGVycyB3aXRoIG5vIHJlcGxheVxuICAvLyBzbmFwc2hvdCwgZS5nLiB0ZXN0cykuIEEgc3RhbGUgKDQxMikgcmVqZWN0aW9uIHByb3BhZ2F0ZXMgdG8gdGhlIGNhbGxlcixcbiAgLy8gd2hpY2ggcmVzdGFydHMgdGhlIHJlcGxheSBmcm9tIGEgY29ycmVjdGVkIGxvZyDigJQgaXQgaXMgbm90IHJldHJpZWQgaGVyZSxcbiAgLy8gYmVjYXVzZSB0aGUgZXZlbnQncyBjb3JyZWxhdGlvbiBpZCB3YXMgbWludGVkIGJ5ICp0aGlzKiByZXBsYXkncyBzZWVkZWRcbiAgLy8gc2VxdWVuY2UsIHNvIHJlLWNvbW1pdHRpbmcgaXQgYWdhaW5zdCBhIGNvcnJlY3RlZCBsb2cgd291bGQgcGVyc2lzdCBhblxuICAvLyBldmVudCBubyBjb3JyZWN0IHJlcGxheSBwcm9kdWNlcy5cbiAgbGV0IHJlcG9ydGVkRXZlbnRzID0gMDtcbiAgY29uc3QgY3JlYXRlR3VhcmRlZDogRXZlbnRDcmVhdG9yID0gYXN5bmMgKGRhdGEsIHBhcmFtcykgPT4ge1xuICAgIGlmICghZXZlbnRMb2cpIHtcbiAgICAgIHJldHVybiBjcmVhdGVFdmVudChkYXRhLCBwYXJhbXMpO1xuICAgIH1cbiAgICBjb25zdCBsb2cgPSBldmVudExvZztcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjcmVhdGVFdmVudChkYXRhLCB7XG4gICAgICAuLi5wYXJhbXMsXG4gICAgICAuLi5zbG90U25hcHNob3RQYXJhbXMobG9nLmV2ZW50cyksXG4gICAgfSk7XG4gICAgLy8gQnVtcC1hbmQtcmVwb3J0OiB0aGUgd3JpdGUgbGFuZGVkIGFib3ZlIHRoZSBzbG90IGl0IGFza2VkIGZvciwgc28gdGhlXG4gICAgLy8gcmVwb3J0IGhvbGRzIHRoZSBldmVudHMgaXQgd2FzIGRlY2lkZWQgd2l0aG91dC4gQWJzb3JiaW5nIGhlcmUgcmF0aGVyXG4gICAgLy8gdGhhbiBhdCBlYWNoIGNhbGwgc2l0ZSBtZWFucyB0aGUgcmVzdCBvZiB0aGlzIHBoYXNlJ3Mgd3JpdGVzIOKAlCB3aGljaCByZWFkXG4gICAgLy8gdGhlIHNhbWUgYXJyYXkgdG8gYnVpbGQgdGhlaXIgb3duIHNuYXBzaG90IOKAlCBhc2sgZm9yIGEgc2xvdCBhYm92ZSB0aGVtLFxuICAgIC8vIGFuZCB0aGUgcmVwbGF5IHRoYXQgcmVzdW1lcyBmcm9tIHRoaXMgbG9nIHNlZXMgdGhlbSB3aXRob3V0IGEgcmVsb2FkLlxuICAgIGNvbnN0IHJlcG9ydCA9IGFic29yYlNraXBwZWRTbG90UmVwb3J0KGxvZy5ldmVudHMsIHJlc3VsdCk7XG4gICAgcmVwb3J0ZWRFdmVudHMgKz0gcmVwb3J0LmFkZGVkO1xuICAgIGlmIChyZXBvcnQudHJ1bmNhdGVkKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdEcm9wcGVkIGEgdHJ1bmNhdGVkIHNraXBwZWQtc2xvdCByZXBvcnQnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBldmVudFR5cGU6IGRhdGEuZXZlbnRUeXBlLFxuICAgICAgICBldmVudElkOiByZXN1bHQuZXZlbnQ/LmV2ZW50SWQsXG4gICAgICAgIG9mZmVyZWQ6IHJlcG9ydC5vZmZlcmVkLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChyZXBvcnQuYWRkZWQgPiAwKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdTdXNwZW5zaW9uIHdyaXRlIHNraXBwZWQgb2NjdXBpZWQgc2xvdHMnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBldmVudFR5cGU6IGRhdGEuZXZlbnRUeXBlLFxuICAgICAgICBldmVudElkOiByZXN1bHQuZXZlbnQ/LmV2ZW50SWQsXG4gICAgICAgIHJlcG9ydGVkOiByZXBvcnQuYWRkZWQsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcbiAgLy8gU2VwYXJhdGUgcXVldWUgaXRlbXMgYnkgdHlwZVxuICBjb25zdCBzdGVwSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgU3RlcEludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnc3RlcCdcbiAgKTtcbiAgY29uc3QgYWxsSG9va0l0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ2hvb2snXG4gICk7XG4gIGNvbnN0IHdhaXRJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBXYWl0SW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICd3YWl0J1xuICApO1xuICBjb25zdCBhdHRyaWJ1dGVJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBBdHRyaWJ1dGVJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ2F0dHJpYnV0ZSdcbiAgKTtcblxuICBjb25zdCBob29rc05lZWRpbmdDcmVhdGlvbiA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+ICFpdGVtLmhhc0NyZWF0ZWRFdmVudFxuICApO1xuXG4gIC8vIEdyb3VwIGhvb2sgaXRlbXMgdGhhdCBuZWVkIHdvcmsgYnkgdG9rZW4sIHByZXNlcnZpbmcgcXVldWUtaW5zZXJ0aW9uXG4gIC8vICh3b3JrZmxvdyBjb2RlKSBvcmRlciB3aXRoaW4gZWFjaCB0b2tlbi4gT3BlcmF0aW9ucyBvbiBvbmUgdG9rZW4gbXVzdFxuICAvLyBhcHBseSBpbiBjb2RlIG9yZGVyOiBhIGRpc3Bvc2UoKSBvZiBhbiBlYXJsaWVyIGhvb2sgcmVsZWFzZXMgdGhlIHRva2VuXG4gIC8vIGJlZm9yZSBhIGxhdGVyIHNhbWUtdG9rZW4gaG9vaydzIGNyZWF0aW9uIGlzIHZhbGlkYXRlZCDigJQgb3RoZXJ3aXNlIHRoZVxuICAvLyBuZXcgaG9vayByZWNvcmRzIGEgc3B1cmlvdXMgaG9va19jb25mbGljdCBhZ2FpbnN0IHRoZSBydW4ncyBvd25cbiAgLy8gZGlzcG9zZWQgaG9vayDigJQgd2hpbGUgYSBob29rIGNyZWF0ZWQgYW5kIGRpc3Bvc2VkIHdpdGhpbiB0aGUgc2FtZVxuICAvLyBzdXNwZW5zaW9uIGlzIHN0aWxsIGNyZWF0ZWQgYmVmb3JlIGl0IGlzIGRpc3Bvc2VkLiBEaWZmZXJlbnQgdG9rZW5zXG4gIC8vIGhhdmUgbm8gY2xhaW0gaW50ZXJhY3Rpb24sIHNvIHRva2VuIGdyb3VwcyBhcmUgcHJvY2Vzc2VkIGluIHBhcmFsbGVsLlxuICBjb25zdCBob29rSXRlbXNCeVRva2VuID0gbmV3IE1hcDxzdHJpbmcsIEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtW10+KCk7XG4gIGZvciAoY29uc3QgaXRlbSBvZiBhbGxIb29rSXRlbXMpIHtcbiAgICBpZiAoaXRlbS5oYXNDcmVhdGVkRXZlbnQgJiYgIWl0ZW0uZGlzcG9zZWQpIHtcbiAgICAgIGNvbnRpbnVlOyAvLyBhbHJlYWR5IGNvbW1pdHRlZCBhbmQgc3RpbGwgbGl2ZSDigJQgbm90aGluZyB0byBkb1xuICAgIH1cbiAgICBjb25zdCBncm91cCA9IGhvb2tJdGVtc0J5VG9rZW4uZ2V0KGl0ZW0udG9rZW4pO1xuICAgIGlmIChncm91cCkge1xuICAgICAgZ3JvdXAucHVzaChpdGVtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaG9va0l0ZW1zQnlUb2tlbi5zZXQoaXRlbS50b2tlbiwgW2l0ZW1dKTtcbiAgICB9XG4gIH1cblxuICAvLyBSZXNvbHZlIGVuY3J5cHRpb24ga2V5IGZvciB0aGlzIHJ1blxuICBjb25zdCByYXdLZXkgPSBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4ocnVuKTtcbiAgY29uc3QgZW5jcnlwdGlvbktleSA9IHJhd0tleSA/IGF3YWl0IGltcG9ydEtleShyYXdLZXkpIDogdW5kZWZpbmVkO1xuXG4gIC8vIEdhdGUgcGF5bG9hZCBjb21wcmVzc2lvbiBvbiB0aGUgcnVuJ3Mgc3BlY1ZlcnNpb24uXG4gIGNvbnN0IGNvbXByZXNzaW9uID1cbiAgICAocnVuLnNwZWNWZXJzaW9uID8/IDApID49IFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTjtcblxuICBhc3luYyBmdW5jdGlvbiBkaXNwb3NlSG9vayhcbiAgICBxdWV1ZUl0ZW06IEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGhvb2tEaXNwb3NlZEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICBldmVudFR5cGU6ICdob29rX2Rpc3Bvc2VkJyBhcyBjb25zdCxcbiAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICB9LFxuICAgIH07XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoaG9va0Rpc3Bvc2VkRXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAvLyBIb29rIHdhcyBhbHJlYWR5IGRpc3Bvc2VkIGJ5IGEgY29uY3VycmVudCBpbnZvY2F0aW9uIOKAlCBzYWZlIHRvIHNraXBcbiAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICdIb29rIGFscmVhZHkgZGlzcG9zZWQsIHNraXBwaW5nIGR1cGxpY2F0ZSBkaXNwb3NhbCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2sgZGlzcG9zYWwnLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKEhvb2tOb3RGb3VuZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgLy8gSG9vayBtYXkgaGF2ZSBhbHJlYWR5IGJlZW4gZGlzcG9zZWQgb3IgbmV2ZXIgY3JlYXRlZFxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgbm90IGZvdW5kIGZvciBkaXNwb3NhbCwgY29udGludWluZycsIHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gUHJvY2VzcyBob29rcyBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzLlxuICAvLyBUcmFjayBhbnkgaG9vayBjb25mbGljdHMgdGhhdCBvY2N1ciDigJQgdGhlc2UgYXJlIHJldHVybmVkIHRvIHRoZSBjYWxsZXJcbiAgLy8gc28gdGhlIFYyIGhhbmRsZXIgY2FuIHJlLWludm9rZSBpbW1lZGlhdGVseS5cbiAgbGV0IGhhc0hvb2tDb25mbGljdCA9IGZhbHNlO1xuICBsZXQgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbiA9IGZhbHNlO1xuICBsZXQgaG9va0NyZWF0aW9uTXMgPSAwO1xuXG4gIGlmIChob29rSXRlbXNCeVRva2VuLnNpemUgPiAwKSB7XG4gICAgY29uc3QgaG9va1BoYXNlU3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgYXdhaXQgc2V0dGxlUGhhc2UoXG4gICAgICBbLi4uaG9va0l0ZW1zQnlUb2tlbi52YWx1ZXMoKV0ubWFwKGFzeW5jIChpdGVtcykgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBpdGVtcykge1xuICAgICAgICAgIGxldCBjcmVhdGlvbkNvbmZsaWN0ZWQgPSBmYWxzZTtcblxuICAgICAgICAgIGlmICghcXVldWVJdGVtLmhhc0NyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgY29uc3QgaG9va01ldGFkYXRhOiBTZXJpYWxpemVkRGF0YSB8IHVuZGVmaW5lZCA9XG4gICAgICAgICAgICAgIHR5cGVvZiBxdWV1ZUl0ZW0ubWV0YWRhdGEgPT09ICd1bmRlZmluZWQnXG4gICAgICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICA6ICgoYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgICAgICAgICAgcXVldWVJdGVtLm1ldGFkYXRhLFxuICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvbi5nbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICAgICAgICAgICkpIGFzIFNlcmlhbGl6ZWREYXRhKTtcbiAgICAgICAgICAgIGNvbnN0IGhvb2tFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgICBldmVudFR5cGU6ICdob29rX2NyZWF0ZWQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgICAgICAgICAgIHRva2VuUmV0ZW50aW9uVW50aWw6IHF1ZXVlSXRlbS50b2tlblJldGVudGlvblVudGlsLFxuICAgICAgICAgICAgICAgIG1ldGFkYXRhOiBob29rTWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgaXNXZWJob29rOiBxdWV1ZUl0ZW0uaXNXZWJob29rID8/IGZhbHNlLFxuICAgICAgICAgICAgICAgIC4uLihxdWV1ZUl0ZW0uaXNTeXN0ZW0gJiYgeyBpc1N5c3RlbTogdHJ1ZSB9KSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjcmVhdGVIb29rRXZlbnQoe1xuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgaG9va0V2ZW50LFxuICAgICAgICAgICAgICBxdWV1ZUl0ZW0sXG4gICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgY3JlYXRlRXZlbnQ6IGNyZWF0ZUd1YXJkZWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGhhc0hvb2tDb25mbGljdCB8fD0gcmVzdWx0Lmhhc0hvb2tDb25mbGljdDtcbiAgICAgICAgICAgIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb24gfHw9IHJlc3VsdC5oYXNBd2FpdGVkSG9va0NyZWF0aW9uO1xuICAgICAgICAgICAgY3JlYXRpb25Db25mbGljdGVkID0gcmVzdWx0Lmhhc0hvb2tDb25mbGljdDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBEaXNwb3NlIGFmdGVyIGNyZWF0aW9uIGZvciBob29rcyBib3JuIGFuZCBkaXNwb3NlZCB3aXRoaW4gdGhpc1xuICAgICAgICAgIC8vIGJhdGNoLiBBIGhvb2sgd2hvc2UgY3JlYXRpb24gY29uZmxpY3RlZCB3YXMgbmV2ZXIgY3JlYXRlZCwgc29cbiAgICAgICAgICAvLyB0aGVyZSBpcyBub3RoaW5nIHRvIGRpc3Bvc2UuXG4gICAgICAgICAgaWYgKHF1ZXVlSXRlbS5kaXNwb3NlZCAmJiAhY3JlYXRpb25Db25mbGljdGVkKSB7XG4gICAgICAgICAgICBhd2FpdCBkaXNwb3NlSG9vayhxdWV1ZUl0ZW0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICAgIGhvb2tDcmVhdGlvbk1zID0gRGF0ZS5ub3coKSAtIGhvb2tQaGFzZVN0YXJ0O1xuICB9XG5cbiAgLy8gUHJvY2VzcyBhYm9ydCByZXF1ZXN0cyDigJQgcmVzdW1lIHRoZSBob29rIHdpdGggYWJvcnQgcGF5bG9hZCBhbmQgd3JpdGUgc3RyZWFtIHBhY2tldFxuICBjb25zdCBob29rc05lZWRpbmdBYm9ydCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+IGl0ZW0uYWJvcnRSZXF1ZXN0ZWQgJiYgIWl0ZW0uZGlzcG9zZWRcbiAgKTtcblxuICBpZiAoaG9va3NOZWVkaW5nQWJvcnQubGVuZ3RoID4gMCkge1xuICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgYXdhaXQgc2V0dGxlUGhhc2UoXG4gICAgICBob29rc05lZWRpbmdBYm9ydC5tYXAoYXN5bmMgKHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIERlaHlkcmF0ZSB0aGUgYWJvcnQgcGF5bG9hZCBmb3Igc3RvcmFnZVxuICAgICAgICAgIGNvbnN0IGFib3J0UGF5bG9hZCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICB7IGFib3J0ZWQ6IHRydWUsIHJlYXNvbjogcXVldWVJdGVtLmFib3J0UmVhc29uIH0sXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIENyZWF0ZSBob29rX3JlY2VpdmVkIGV2ZW50IHdpdGggYWJvcnQgcGF5bG9hZFxuICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoe1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgICAgICAgICBwYXlsb2FkOiBhYm9ydFBheWxvYWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gV3JpdGUgc3RyZWFtIGNhbmNlbGxhdGlvbiBwYWNrZXQgZm9yIHJlYWwtdGltZSBzdGVwIHByb3BhZ2F0aW9uLlxuICAgICAgICAgIC8vIFJldXNlIHRoZSBzYW1lIGRlaHlkcmF0ZWQgcGF5bG9hZCBhcyB0aGUgaG9vayBldmVudCBzbyB0aGUgcmVhc29uXG4gICAgICAgICAgLy8gcm91bmQtdHJpcHMgdGhyb3VnaCBgZGVoeWRyYXRlU3RlcEFyZ3VtZW50c2AgLyBgaHlkcmF0ZVN0ZXBBcmd1bWVudHNgXG4gICAgICAgICAgLy8gKGhhbmRsZXMgRE9NRXhjZXB0aW9uLCBjdXN0b20gZXJyb3JzLCBlbmNyeXB0aW9uLCBldGMuKSBpbnN0ZWFkIG9mXG4gICAgICAgICAgLy8gYmFyZSBKU09OLnN0cmluZ2lmeSB3aGljaCBsb3NlcyB0eXBlIGluZm9ybWF0aW9uIGFuZCBkcm9wcyB1bmRlZmluZWQuXG4gICAgICAgICAgLy8gc3RyZWFtTmFtZSBpcyBzZXQgb24gdGhlIHF1ZXVlIGl0ZW0gYXQgY29udHJvbGxlciBjb25zdHJ1Y3Rpb24gdGltZVxuICAgICAgICAgIC8vIChzZWUgd29ya2Zsb3cvYWJvcnQtY29udHJvbGxlci50cykuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU5hbWUgPSBnZXRBYm9ydFN0cmVhbUlkRnJvbVRva2VuKHF1ZXVlSXRlbS50b2tlbik7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLndyaXRlKFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgc3RyZWFtTmFtZSxcbiAgICAgICAgICAgICAgYWJvcnRQYXlsb2FkIGFzIFVpbnQ4QXJyYXlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLmNsb3NlKHJ1bklkLCBzdHJlYW1OYW1lKTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIEJlc3QtZWZmb3J0IHN0cmVhbSB3cml0ZSDigJQgaG9vayBldmVudCBwcm92aWRlcyB0aGUgZHVyYWJsZSBmYWxsYmFja1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgJ0ZhaWxlZCB0byB3cml0ZSBhYm9ydCBzdHJlYW0gcGFja2V0LCBob29rIGV2ZW50IHdpbGwgcHJvdmlkZSBmYWxsYmFjaycsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHwgUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgYWJvcnQnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBzdGVwIGV2ZW50cyBmb3Igc3RlcHMgdGhhdCBkb24ndCBoYXZlIHRoZW0geWV0LlxuICAvLyBVbmxpa2UgVjEsIHdlIGRvIE5PVCBxdWV1ZSBzdGVwIG1lc3NhZ2VzIGZyb20gaGVyZSDigJQgdGhlIGNhbGxlclxuICAvLyBkZWNpZGVzIHdoaWNoIHN0ZXBzIHRvIGV4ZWN1dGUgaW5saW5lIHZzLiBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICAvLyBXYWl0IGV2ZW50cyBhcmUgYWxzbyBjcmVhdGVkIGluIHBhcmFsbGVsIGJlbG93LlxuICBjb25zdCBzdGVwc05lZWRpbmdDcmVhdGlvbiA9IG5ldyBTZXQoXG4gICAgc3RlcEl0ZW1zXG4gICAgICAuZmlsdGVyKChxdWV1ZUl0ZW0pID0+ICFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KVxuICAgICAgLm1hcCgocXVldWVJdGVtKSA9PiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZClcbiAgKTtcblxuICAvLyBDb3JyZWxhdGlvbiBJRHMgZm9yIHdoaWNoIFRISVMgc3VzcGVuc2lvbiBjYWxsIGFjdHVhbGx5IHdyb3RlIHRoZVxuICAvLyBzdGVwX2NyZWF0ZWQgZXZlbnQuIFBvcHVsYXRlZCBieSB0aGUgb3BzIGJlbG93IGFmdGVyIGEgc3VjY2Vzc2Z1bFxuICAvLyBldmVudHMuY3JlYXRlIOKAlCB1c2VkIGJ5IHRoZSBjYWxsZXIgdG8gY2xhaW0gb3duZXJzaGlwIGFuZCBhdm9pZFxuICAvLyByYWNpbmcgd2l0aCBjb25jdXJyZW50IGhhbmRsZXJzIG9uIHN0ZXAgZXhlY3V0aW9uLlxuICBjb25zdCBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgLy8gU2VyaWFsaXphdGlvbiBhbHdheXMgcnVucyB0aHJvdWdoIHRoZSBvbmUgb3JkaW5hcnkgcGF0aCBiZWxvdywgc28gdGhlXG4gIC8vIGR1cmFibGUgYnl0ZXMgY2Fubm90IGRlcGVuZCBvbiByZXRlbnRpb24uIFdoYXQgcmV0ZW50aW9uIG5lZWRzIHRvIGtub3cgaXNcbiAgLy8gd2hldGhlciB0aGF0IHNlcmlhbGl6YXRpb24gKmV4ZWN1dGVkKiB3b3JrZmxvdyBjb2RlIChnZXR0ZXJzLCBwcm94eVxuICAvLyB0cmFwcywgY3VzdG9tIHNlcmlhbGl6ZXJzKSDigJQgc2lkZSBlZmZlY3RzIGEgY29sZCByZXBsYXkgd291bGQgbm90XG4gIC8vIHJlcGVhdCwgc2luY2UgYSByZXBsYXkgc2tpcHMgZGVoeWRyYXRpb24gZm9yIGFscmVhZHktcmVjb3JkZWQgc3RlcHMuXG4gIC8vIFRoZSBoYXJkZW5lZCBzZXJpYWxpemVyIHJlY29yZHMgZXhhY3RseSB0aGF0IGludG8gdGhpcyBzaW5rIChzZWVcbiAgLy8gLi4vc2VyaWFsaXphdGlvbi9oYXJkZW5lZC50cyk7IHdoZW4gYW55IGlucHV0IGluIHRoZSBiYXRjaCByZWNvcmRzIGFuXG4gIC8vIGV4ZWN1dGlvbiwgdGhlIGNhbGxlciBkZW1vdGVzIHRoZSBzZXNzaW9uIHNvIHRoZSBzaWRlIGVmZmVjdHMgbGFuZCBpbiBhXG4gIC8vIFZNIHRoYXQgaXMgYWJvdXQgdG8gYmUgZGlzY2FyZGVkLCBleGFjdGx5IGxpa2UgdGhlIHByZS1yZXRlbnRpb25cbiAgLy8gcnVudGltZS5cbiAgY29uc3QgZ3Vlc3RDb2RlU3RhdHM6IEd1ZXN0Q29kZVN0YXRzID0geyBleGVjdXRpb25zOiBbXSB9O1xuXG4gIC8vIExhenkgaW5saW5lIHN0YXJ0OiBkZWZlciB0aGUgc3RlcF9jcmVhdGVkIHdyaXRlIGZvciB1cCB0b1xuICAvLyBgZ2V0TWF4SW5saW5lU3RlcHMoKWAgc3RlcHMgdGhlIGNhbGxlciB3aWxsIHJ1biBpbmxpbmUgKGluIHBhcmFsbGVsKS4gRWFjaFxuICAvLyBzdGVwIGlzIGNyZWF0ZWQgb24gdGhlIGZseSBieSB0aGUgbGF6eSBgc3RlcF9zdGFydGVkYCBleGVjdXRlU3RlcCBzZW5kc1xuICAvLyAoc2F2aW5nIGEgcm91bmQtdHJpcCBwZXIgc3RlcCkuIFdlIG5ldmVyIGRlZmVyIHdoZW4gYSBgaG9vay5nZXRDb25mbGljdCgpYFxuICAvLyBhd2FpdGVyIGlzIHByZXNlbnQsIGJlY2F1c2UgaW4gdGhhdCBjYXNlIHRoZSBjYWxsZXIgZXhlY3V0ZXMgbm90aGluZyBpbmxpbmVcbiAgLy8gKGl0IHJlLWludm9rZXMgaW1tZWRpYXRlbHkgdG8gcmVzb2x2ZSB0aGUgYXdhaXRlciksIHNvIGRlZmVycmluZyB3b3VsZFxuICAvLyBsZWF2ZSB0aGUgc3RlcHMgdW5jcmVhdGVkIGFuZCB1bnF1ZXVlZC4gV2UgcGljayB0aGUgZmlyc3QgTiB1bmNyZWF0ZWQgc3RlcHNcbiAgLy8g4oCUIG1hdGNoaW5nIHRoZSBjYWxsZXIncyBpbmxpbmUtY2FuZGlkYXRlIHNlbGVjdGlvbiDigJQgYW5kIGRlaHlkcmF0ZSB0aGVpclxuICAvLyBpbnB1dCBoZXJlIHNvIGV4ZWN1dGVTdGVwIGNhbiBzaGlwIGl0IGFzIHRoZSBzdGVwX3N0YXJ0ZWQgcGF5bG9hZC5cbiAgY29uc3QgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzID0gbmV3IFNldDxzdHJpbmc+KFxuICAgIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb24gPT09IGZhbHNlXG4gICAgICA/IHN0ZXBJdGVtc1xuICAgICAgICAgIC5maWx0ZXIoKGl0ZW0pID0+IHN0ZXBzTmVlZGluZ0NyZWF0aW9uLmhhcyhpdGVtLmNvcnJlbGF0aW9uSWQpKVxuICAgICAgICAgIC5zbGljZSgwLCBnZXRNYXhJbmxpbmVTdGVwcygpKVxuICAgICAgICAgIC5tYXAoKGl0ZW0pID0+IGl0ZW0uY29ycmVsYXRpb25JZClcbiAgICAgIDogW11cbiAgKTtcbiAgLy8gQ29sbGVjdGVkIGJ5IGNvcnJlbGF0aW9uSWQgYmVjYXVzZSB0aGUgcGVyLXN0ZXAgb3BzIGJlbG93IHJ1biBjb25jdXJyZW50bHlcbiAgLy8gYW5kIHNldHRsZSBvdXQgb2Ygb3JkZXIuIFdlIHJlYnVpbGQgdGhlIGFycmF5IGluIGRldGVybWluaXN0aWNcbiAgLy8gYGxhenlJbmxpbmVDb3JyZWxhdGlvbklkc2Agb3JkZXIgKHRoZSBvcmRlcmVkIHNsaWNlIGFib3ZlKSBhZnRlciB0aGUgb3BzXG4gIC8vIHNldHRsZSwgc28gdGhlIGlubGluZSBiYXRjaCBvcmRlciBpcyBzdGFibGUgcmVnYXJkbGVzcyBvZiBkZWh5ZHJhdGlvbiB0aW1pbmcuXG4gIGNvbnN0IGxhenlJbmxpbmVCeUNvcnJlbGF0aW9uSWQgPSBuZXcgTWFwPFxuICAgIHN0cmluZyxcbiAgICBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdFsnbGF6eUlubGluZVN0ZXBzJ11bbnVtYmVyXVxuICA+KCk7XG5cbiAgY29uc3Qgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcblxuICAvLyBDb3JyZWxhdGlvbiBJRHMgb2Ygc3RlcHMgd2hvc2Ugc3RlcC1leGVjdXRpb24gcXVldWUgbWVzc2FnZSB3YXMgYWxyZWFkeVxuICAvLyBwdWJsaXNoZWQgYnkgdGhlIHJlc2lsaWVudC1kaXNwYXRjaCBvcHMgYmVsb3cgKGFsb25nc2lkZSB0aGUgc3RlcF9jcmVhdGVkXG4gIC8vIHdyaXRlKS4gUmVwb3J0ZWQgdG8gdGhlIGNhbGxlciBzbyBpdHMgZGlzcGF0Y2ggcGFzcyBza2lwcyB0aGVtLlxuICBjb25zdCBxdWV1ZWRTdGVwQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAvLyBSZXNpbGllbnQgc3RlcCBkaXNwYXRjaCBlbGlnaWJpbGl0eSwgc2hhcmVkIGJ5IGV2ZXJ5IHN0ZXAgb3AgYmVsb3cgKHRoZVxuICAvLyBwZXItc3RlcCBpbnB1dC1zaXplIGNoZWNrIGlzIGFwcGxpZWQgaW5zaWRlIHRoZSBvcCkuIEFsbCBtdXN0IGhvbGQ6XG4gIC8vXG4gIC8vICAtIFRoZSBjYWxsZXIgcHJvdmlkZWQgYSBkaXNwYXRjaCB0YXJnZXQgKGBzdGVwRGlzcGF0Y2hgKSDigJQgdGVybWluYWxcbiAgLy8gICAgZHJhaW5zIGFuZCBvdGhlciBjcmVhdGUtb25seSBjYWxsZXJzIG5ldmVyIHF1ZXVlLlxuICAvLyAgLSBUaGUgZmVhdHVyZSBpcyBlbmFibGVkIChgV09SS0ZMT1dfUkVTSUxJRU5UX1NURVBfRElTUEFUQ0hgIG9wdC1pbikuXG4gIC8vICAgIEl0IGlzIG9mZiBieSBkZWZhdWx0IGJlY2F1c2UgdGhlIHB1Ymxpc2ggcmFjZXMgdGhlIGNyZWF0ZSdzIHZlcmRpY3QsXG4gIC8vICAgIGFuZCBhIGNyZWF0ZSBjYW4gY29tZSBiYWNrIHJlZnVzZWQ6IGFzIGEgZHVwbGljYXRlIHRoZSByZXBsYXkgc2hvdWxkXG4gIC8vICAgIHN0b3AgcHVyc3VpbmcsIG9yIOKAlCBvbiBhIFdvcmxkIHRoYXQgd291bGQgcmF0aGVyIHJlZnVzZSBhIHN0YWxlIHdyaXRlXG4gIC8vICAgIHRoYW4gcmVwb3J0IHdoYXQgaXQgbWlzc2VkIOKAlCBhcyBhIDQxMi4gRWl0aGVyIHdheSB0aGUgcXVldWUgbWVzc2FnZVxuICAvLyAgICBjYXJyeWluZyB0aGUgcGF5bG9hZCBpcyBhbHJlYWR5IG91dCwgYW5kIHRoZSBjb25zdW1lciBjYW4gbWF0ZXJpYWxpemUgYVxuICAvLyAgICBzdGVwIHdob3NlIGNyZWF0ZSB3YXMgcmVmdXNlZC4gTm90aGluZyBvcmRlcnMgdGhhdCB2ZXJkaWN0IGJlZm9yZSB0aGVcbiAgLy8gICAgY29uc3VtZXIncyByZWRlbGl2ZXJ5IHJlLWVuc3VyZSwgc28gbm8gYmFja2VuZC1zaWRlIHJldm9jYXRpb25cbiAgLy8gICAgYm9va2tlZXBpbmcgY2FuIGNsb3NlIHRoZSB3aW5kb3c6IGEgYmVzdC1lZmZvcnQgbWFya2VyIHRoYXQgZmFpbHMgb3BlblxuICAvLyAgICBjYW5ub3QgY2FycnkgYSBjb3JyZWN0bmVzcyBwcm9wZXJ0eS4gVGhlIHNlcXVlbnRpYWwgcGF0aCBpcyB0aGUgb25seVxuICAvLyAgICB0aGluZyB0aGF0IGdpdmVzIHRoZSBtZXNzYWdlIGEgaGFwcGVucy1hZnRlciBlZGdlIG92ZXIgdGhlIHZlcmRpY3QuXG4gIC8vICAtIFRoZSBydW4ncyBxdWV1ZSB0cmFuc3BvcnQgcHJlc2VydmVzIGJpbmFyeSBwYXlsb2FkcyAoQ0JPUixcbiAgLy8gICAgc3BlY1ZlcnNpb24gPj0gMyk6IGBzdGVwSW5wdXQuaW5wdXRgIGlzIHRoZSBzZXJpYWxpemVkIChwb3NzaWJseVxuICAvLyAgICBlbmNyeXB0ZWQpIGlucHV0IGJ5dGVzLCB3aGljaCB0aGUgSlNPTiB0cmFuc3BvcnQgd291bGQgbWFuZ2xlLlxuICBjb25zdCByZXNpbGllbnREaXNwYXRjaEVsaWdpYmxlID1cbiAgICBzdGVwRGlzcGF0Y2ggIT09IHVuZGVmaW5lZCAmJlxuICAgIGlzUmVzaWxpZW50U3RlcERpc3BhdGNoRW5hYmxlZCgpICYmXG4gICAgKHJ1bi5zcGVjVmVyc2lvbiA/PyAwKSA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ0JPUl9RVUVVRV9UUkFOU1BPUlQ7XG5cbiAgLy8gVGhlIHRyYWNlIGNhcnJpZXIgZm9yIHJlc2lsaWVudCBzdGVwIGRpc3BhdGNoZXMsIHJlc29sdmVkIGF0IG1vc3Qgb25jZSBwZXJcbiAgLy8gc3VzcGVuc2lvbiAodGhlIHBlci1zdGVwIG9wcyBydW4gY29uY3VycmVudGx5IGFuZCBzaGFyZSBpdCkuXG4gIGxldCBzdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXI6IFByb21pc2U8VHJhY2VDYXJyaWVyPiB8IHVuZGVmaW5lZDtcbiAgY29uc3QgZ2V0U3RlcERpc3BhdGNoVHJhY2VDYXJyaWVyID0gKCk6IFByb21pc2U8VHJhY2VDYXJyaWVyPiA9PiB7XG4gICAgc3RlcERpc3BhdGNoVHJhY2VDYXJyaWVyID8/PVxuICAgICAgc3RlcERpc3BhdGNoPy5nZXRUcmFjZUNhcnJpZXIoKSA/PyBQcm9taXNlLnJlc29sdmUoe30pO1xuICAgIHJldHVybiBzdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXI7XG4gIH07XG5cbiAgLy8gUHJvZHVjZXItc2lkZSByZXNpbGllbnQgcmVjb3ZlcnkgY291bnQgZm9yIHRoZSBzdXNwZW5zaW9uIHNwYW4gYXR0cmlidXRlLlxuICBsZXQgcmVzaWxpZW50RGlzcGF0Y2hSZWNvdmVyZWQgPSAwO1xuXG4gIC8vIFN0ZXBzOiBjcmVhdGUgc3RlcF9jcmVhdGVkIGV2ZW50cyAobm8gcXVldWluZyDigJQgVjIgcmV0dXJucyBwZW5kaW5nIHN0ZXBzXG4gIC8vIHRvIGNhbGxlciDigJQgRVhDRVBUIG9uIHRoZSByZXNpbGllbnQgZGlzcGF0Y2ggcGF0aCwgd2hpY2ggcGFyYWxsZWxpemVzIHRoZVxuICAvLyBjcmVhdGUgd2l0aCB0aGUgc3RlcCdzIHF1ZXVlIHB1Ymxpc2ggYW5kIHJlcG9ydHMgaXQgaW5cbiAgLy8gYHF1ZXVlZFN0ZXBDb3JyZWxhdGlvbklkc2ApLlxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBzdGVwSXRlbXMpIHtcbiAgICBpZiAoc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgb3BzLnB1c2goXG4gICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgLy8gUGVyLXN0ZXAgc2luaywgbWVyZ2VkIGJlbG93OiB0aGUgZGVoeWRyYXRlIHdyYXBwZXIgZW1pdHMgc3BhblxuICAgICAgICAgIC8vIGF0dHJpYnV0ZXMgZnJvbSB0aGUgc2luayBpdCBpcyBoYW5kZWQsIHNvIHNoYXJpbmcgb25lIGFjcm9zc1xuICAgICAgICAgIC8vIHN0ZXBzIHdvdWxkIHJlLWVtaXQgKGFuZCBtaXNhdHRyaWJ1dGUpIGVhcmxpZXIgc3RlcHMnIGVudHJpZXMuXG4gICAgICAgICAgY29uc3Qgc3RlcEd1ZXN0Q29kZTogR3Vlc3RDb2RlU3RhdHMgPSB7IGV4ZWN1dGlvbnM6IFtdIH07XG4gICAgICAgICAgY29uc3QgZGVoeWRyYXRlZElucHV0ID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYXJnczogcXVldWVJdGVtLmFyZ3MsXG4gICAgICAgICAgICAgIGNsb3N1cmVWYXJzOiBxdWV1ZUl0ZW0uY2xvc3VyZVZhcnMsXG4gICAgICAgICAgICAgIHRoaXNWYWw6IHF1ZXVlSXRlbS50aGlzVmFsLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgY29tcHJlc3Npb24sXG4gICAgICAgICAgICBzdGVwR3Vlc3RDb2RlXG4gICAgICAgICAgKTtcbiAgICAgICAgICBndWVzdENvZGVTdGF0cy5leGVjdXRpb25zLnB1c2goLi4uc3RlcEd1ZXN0Q29kZS5leGVjdXRpb25zKTtcbiAgICAgICAgICAvLyBEZWZlcnJlZCAobGF6eSkgaW5saW5lIHN0ZXA6IHNraXAgdGhlIHN0ZXBfY3JlYXRlZCB3cml0ZSDigJQgdGhlXG4gICAgICAgICAgLy8gY2FsbGVyJ3MgaW5saW5lIGV4ZWN1dGVTdGVwIHdpbGwgc2VuZCBhIGxhenkgc3RlcF9zdGFydGVkIGNhcnJ5aW5nXG4gICAgICAgICAgLy8gdGhpcyBpbnB1dCwgYW5kIHRoZSB3b3JsZCBjcmVhdGVzIHRoZSBzdGVwIChlbnRpdHkgKyBzeW50aGV0aWNcbiAgICAgICAgICAvLyBzdGVwX2NyZWF0ZWQgZXZlbnQpIGF0b21pY2FsbHkuIFdlIGRvIE5PVCBhZGQgaXQgdG9cbiAgICAgICAgICAvLyBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzOyBvd25lcnNoaXAgaXMgZGVjaWRlZCBieSB0aGF0IGxhenlcbiAgICAgICAgICAvLyBzdGVwX3N0YXJ0ZWQncyBhdG9taWMgY3JlYXRlLWNsYWltIGluc3RlYWQuXG4gICAgICAgICAgaWYgKGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcy5oYXMocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpKSB7XG4gICAgICAgICAgICBsYXp5SW5saW5lQnlDb3JyZWxhdGlvbklkLnNldChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCwge1xuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgZGVoeWRyYXRlZElucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3Qgc3RlcEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2NyZWF0ZWQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBydW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICBpbnB1dDogZGVoeWRyYXRlZElucHV0IGFzIFNlcmlhbGl6ZWREYXRhLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgLy8gUmVzaWxpZW50IHN0ZXAgZGlzcGF0Y2g6IGZpcmUgdGhlIHN0ZXBfY3JlYXRlZCB3cml0ZSBhbmQgdGhlXG4gICAgICAgICAgLy8gc3RlcC1leGVjdXRpb24gcXVldWUgcHVibGlzaCBpbiBwYXJhbGxlbCDigJQgdGhlIG1lc3NhZ2UgY2FycmllcyB0aGVcbiAgICAgICAgICAvLyBzYW1lIHNlcmlhbGl6ZWQgaW5wdXQgKGBzdGVwSW5wdXRgKSBzbyB0aGUgY29uc3VtZXIgY2FuXG4gICAgICAgICAgLy8gaWRlbXBvdGVudGx5IHJlLWVuc3VyZSB0aGUgZXZlbnQgaWYgdGhlIGRpcmVjdCB3cml0ZSBmYWlsZWRcbiAgICAgICAgICAvLyB0cmFuc2llbnRseS4gTWlycm9ycyB0aGUgcmVzaWxpZW50IHN0YXJ0IChgcnVuSW5wdXRgKSBhbmRcbiAgICAgICAgICAvLyByZXNpbGllbnQgaG9vayByZXN1bWUgKGBob29rSW5wdXRgKSBwYXR0ZXJucy4gT25seSBmb3IgaW5wdXRzIHRoZVxuICAgICAgICAgIC8vIHF1ZXVlIG1lc3NhZ2UgY2FuIHNhZmVseSBjYXJyeSAoYmluYXJ5LCB1bmRlciB0aGUgVlFTIHNpemUgY2FwKS5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICByZXNpbGllbnREaXNwYXRjaEVsaWdpYmxlICYmXG4gICAgICAgICAgICBkZWh5ZHJhdGVkSW5wdXQgaW5zdGFuY2VvZiBVaW50OEFycmF5ICYmXG4gICAgICAgICAgICBkZWh5ZHJhdGVkSW5wdXQuYnl0ZUxlbmd0aCA8PSBNQVhfUkVTSUxJRU5UX1NURVBfSU5QVVRfQllURVNcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgICAgICBjb25zdCB0cmFjZUNhcnJpZXIgPSBhd2FpdCBnZXRTdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXIoKTtcbiAgICAgICAgICAgIGNvbnN0IFtjcmVhdGVSZXN1bHQsIHF1ZXVlUmVzdWx0XSA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbXG4gICAgICAgICAgICAgIGNyZWF0ZUd1YXJkZWQoc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KSxcbiAgICAgICAgICAgICAgcXVldWVNZXNzYWdlKFxuICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N0eWxlL25vTm9uTnVsbEFzc2VydGlvbjogaW1wbGllZCBieSByZXNpbGllbnREaXNwYXRjaEVsaWdpYmxlXG4gICAgICAgICAgICAgICAgc3RlcERpc3BhdGNoIS5xdWV1ZU5hbWUsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICBzdGVwSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgICAgc3RlcElucHV0OiB7IGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIC8vIFNhbWUga2V5IGFzIHRoZSBjYWxsZXIncyBkaXNwYXRjaCBwYXNzIGFuZCBhbnkgY29uY3VycmVudFxuICAgICAgICAgICAgICAgIC8vIGhhbmRsZXIncyDigJQgcmVkdW5kYW50IHB1Ymxpc2hlcyBmb3IgdGhpcyBzdGVwIGRlZHVwZS4gVGhlXG4gICAgICAgICAgICAgICAgLy8ga2V5IGlzIHN0ZXAtaWRlbnRpdHktc2NvcGVkIHNvIGEgcmV2b2tlZCBtZXNzYWdlIGZvciBhXG4gICAgICAgICAgICAgICAgLy8gcmVhc3NpZ25lZCBjb3JyZWxhdGlvbiBpZCBjYW5ub3QgYWJzb3JiIHRoZSBjb3JyZWN0ZWRcbiAgICAgICAgICAgICAgICAvLyBzY2hlZHVsZSdzIGRpc3BhdGNoIOKAlCBzZWUgc3RlcERpc3BhdGNoSWRlbXBvdGVuY3lLZXkuXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgaWRlbXBvdGVuY3lLZXk6IHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5KFxuICAgICAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcXVldWVJdGVtLnN0ZXBOYW1lXG4gICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgLy8gUXVldWUgZmFpbHVyZSBpcyBhbHdheXMgZmF0YWwgZm9yIHRoaXMgc3VzcGVuc2lvbiBwYXNzOiB3aXRob3V0XG4gICAgICAgICAgICAvLyB0aGUgbWVzc2FnZSB0aGUgc3RlcCB3b3VsZCByZWx5IG9uIHRoZSBjcmVhdGUgYWxvbmUsIGFuZCBpZiB0aGVcbiAgICAgICAgICAgIC8vIGNyZWF0ZSBBTFNPIGZhaWxlZCB0aGVyZSB3b3VsZCBiZSBubyBkdXJhYmxlIHJlY29yZCBhdCBhbGwuXG4gICAgICAgICAgICAvLyBQcm9wYWdhdGluZyByZWRlbGl2ZXJzIHRoZSBvcmNoZXN0cmF0b3IgbWVzc2FnZSwgd2hpY2hcbiAgICAgICAgICAgIC8vIHJlLWNyZWF0ZXMgdGhlIChpZGVtcG90ZW50KSBzdGVwX2NyZWF0ZWQgYW5kIHJlLWRpc3BhdGNoZXMg4oCUXG4gICAgICAgICAgICAvLyB0aGUgc2FtZSByZWNvdmVyeSBhcyB0aGUgc2VxdWVudGlhbCBwYXRoLlxuICAgICAgICAgICAgaWYgKHF1ZXVlUmVzdWx0LnN0YXR1cyA9PT0gJ3JlamVjdGVkJykge1xuICAgICAgICAgICAgICB0aHJvdyBxdWV1ZVJlc3VsdC5yZWFzb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBxdWV1ZWRTdGVwQ29ycmVsYXRpb25JZHMuYWRkKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICAgIGlmIChjcmVhdGVSZXN1bHQuc3RhdHVzID09PSAncmVqZWN0ZWQnKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVyciA9IGNyZWF0ZVJlc3VsdC5yZWFzb247XG4gICAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAvLyBDb25jdXJyZW50IGhhbmRsZXIgd3JvdGUgaXQgZmlyc3Qg4oCUIHNhbWUgYXMgdGhlIHNlcXVlbnRpYWxcbiAgICAgICAgICAgICAgICAvLyBwYXRoLiBUaGUgc3RlcCBtZXNzYWdlIGlzIGFscmVhZHkgb3V0OyBhIGR1cGxpY2F0ZSBwdWJsaXNoXG4gICAgICAgICAgICAgICAgLy8gYnkgdGhhdCBoYW5kbGVyIGRlZHVwZXMgb24gdGhlIHNoYXJlZCBpZGVtcG90ZW5jeSBrZXkuXG4gICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdTdGVwIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzUmV0cnlhYmxlV29ybGRFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzaWxpZW50OiB0aGUgd3JpdGUgZmFpbGVkIHRyYW5zaWVudGx5ICg0MjkgLyA1eHggL1xuICAgICAgICAgICAgICAgIC8vIHRyYW5zcG9ydCkgYnV0IHRoZSBzdGVwIG1lc3NhZ2Ug4oCUIGNhcnJ5aW5nIHRoZSBzYW1lXG4gICAgICAgICAgICAgICAgLy8gc2VyaWFsaXplZCBpbnB1dCDigJQgd2FzIHB1Ymxpc2hlZCwgc28gdGhlIGNvbnN1bWVyXG4gICAgICAgICAgICAgICAgLy8gaWRlbXBvdGVudGx5IHJlLWVuc3VyZXMgdGhlIHN0ZXBfY3JlYXRlZCBiZWZvcmUgZXhlY3V0aW5nLlxuICAgICAgICAgICAgICAgIHJlc2lsaWVudERpc3BhdGNoUmVjb3ZlcmVkKys7XG4gICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAgICAgJ1N0ZXAgY3JlYXRpb24gZXZlbnQgd3JpdGUgZmFpbGVkLCBidXQgdGhlIHN0ZXAgd2FzICcgK1xuICAgICAgICAgICAgICAgICAgICAnZGlzcGF0Y2hlZCB2aWEgdGhlIHF1ZXVlLiBUaGUgc3RlcF9jcmVhdGVkIGV2ZW50IHdpbGwgJyArXG4gICAgICAgICAgICAgICAgICAgICdiZSBlbnN1cmVkIGJ5IHRoZSBxdWV1ZSBjb25zdW1lci4nLFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMuYWRkKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMuYWRkKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdTdGVwIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pKClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIHdhaXQgZXZlbnRzIChzYW1lIGFzIFYxKVxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiB3YWl0SXRlbXMpIHtcbiAgICBpZiAoIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdhaXRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHJlc3VtZUF0OiBxdWV1ZUl0ZW0ucmVzdW1lQXQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKHdhaXRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnV2FpdCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIGF0dHJpYnV0ZUl0ZW1zKSB7XG4gICAgb3BzLnB1c2goXG4gICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgICAgLy8gR3VhcmRlZCBsaWtlIGV2ZXJ5IG90aGVyIHN1c3BlbnNpb24gd3JpdGU6IGFuIGF0dHJfc2V0IGlzIGFcbiAgICAgICAgICAvLyByZXBsYXktZGVyaXZlZCBldmVudCB3aXRoIGEgY29ycmVsYXRpb24gaWQgZnJvbSB0aGlzIHJlcGxheSdzXG4gICAgICAgICAgLy8gc2VlZGVkIHNlcXVlbmNlLCBzbyBpdCBtdXN0IG5vdCBsYW5kIG9uIGEgbG9nIHRoZSByZXBsYXkgbmV2ZXJcbiAgICAgICAgICAvLyBzYXcuIFJlamVjdGluZyBpdCBpcyBjaGVhcCDigJQgYSBydW4gd2l0aCBhdHRyaWJ1dGUgZXZlbnRzIGFscmVhZHlcbiAgICAgICAgICAvLyBmb3JjZXMgYW4gaW4tcHJvY2VzcyByZXBsYXksIHNvIHRoZSByZXN0YXJ0IGNvc3RzIHRoZSByZXBsYXkgaXRcbiAgICAgICAgICAvLyB3YXMgZ29pbmcgdG8gZG8gYW55d2F5LlxuICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2F0dHJfc2V0JyxcbiAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgY2hhbmdlczogcXVldWVJdGVtLmNoYW5nZXMsXG4gICAgICAgICAgICAgICAgd3JpdGVyOiB7IHR5cGU6ICd3b3JrZmxvdycgfSxcbiAgICAgICAgICAgICAgICAuLi4ocXVldWVJdGVtLmFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgICA/IHsgYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXM6IHRydWUgfVxuICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1dvcmtmbG93IGF0dHJpYnV0ZSBldmVudCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnIpKSB7XG4gICAgICAgICAgICAvLyBEZXRlcm1pbmlzdGljIHZhbGlkYXRpb24gcmVqZWN0aW9uIGZyb20gdGhlIFdvcmxkIOKAlCBlLmcuIHRoZVxuICAgICAgICAgICAgLy8gY3VtdWxhdGl2ZSBwZXItcnVuIGF0dHJpYnV0ZSBjYXAsIHdoaWNoIG9ubHkgdGhlIFdvcmxkIGNhblxuICAgICAgICAgICAgLy8gY2hlY2sgYWdhaW5zdCB0aGUgcnVuJ3MgZXhpc3RpbmcgYXR0cmlidXRlcy4gUmVkZWxpdmVyaW5nIHRoZVxuICAgICAgICAgICAgLy8gb3JjaGVzdHJhdG9yIG1lc3NhZ2UgcmVwbGF5cyB0aGUgd29ya2Zsb3cgaW50byB0aGUgZXhhY3Qgc2FtZVxuICAgICAgICAgICAgLy8gd3JpdGUgYW5kIHRoZSBleGFjdCBzYW1lIHJlamVjdGlvbiwgc28gcmV0cnlpbmcgY2FuIG5ldmVyXG4gICAgICAgICAgICAvLyBzdWNjZWVkLiBTdXJmYWNlIGl0IGFzIGEgRmF0YWxFcnJvciBzbyB0aGUgY2FsbGVyIGZhaWxzIHRoZVxuICAgICAgICAgICAgLy8gcnVuIHdpdGggYSBjbGVhciBlcnJvciBpbnN0ZWFkIG9mIHdlZGdpbmcgaXQgaW4gcmVkZWxpdmVyeS5cbiAgICAgICAgICAgIGNvbnN0IGZhdGFsID0gbmV3IEZhdGFsRXJyb3IoXG4gICAgICAgICAgICAgIGBzZXRBdHRyaWJ1dGVzIGZhaWxlZCBXb3JsZCB2YWxpZGF0aW9uOiAke1xuICAgICAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKVxuICAgICAgICAgICAgICB9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGZhdGFsLmNhdXNlID0gZXJyO1xuICAgICAgICAgICAgdGhyb3cgZmF0YWw7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pKClcbiAgICApO1xuICB9XG5cbiAgLy8gQXdhaXQgdGhlIHN0ZXBfY3JlYXRlZCAvIHdhaXRfY3JlYXRlZCBldmVudCBjcmVhdGVzIGJlZm9yZSByZXR1cm5pbmcuXG4gIC8vIFRoZSBjYWxsZXIgKHdvcmtmbG93RW50cnlwb2ludCkgb25seSBlbnF1ZXVlcyB0aGUgc3RlcC1kaXNwYXRjaCBxdWV1ZVxuICAvLyBtZXNzYWdlcyBBRlRFUiBoYW5kbGVTdXNwZW5zaW9uIHJlc29sdmVzLCBhbmQgdGhlIHF1ZXVlIGhhbmRsZXIgYWNrc1xuICAvLyB0aGUgb3JjaGVzdHJhdG9yIG1lc3NhZ2Ugb25seSBhZnRlciB0aGUgY2FsbGVyIHJlc29sdmVzLiBTbyB0aGUgc3RlcF9jcmVhdGVkXG4gIC8vIGV2ZW50cyBtdXN0IGJlIGR1cmFibGUgaGVyZSwgYW5kIHRoZSBkaXNwYXRjaCBzZW5kcyBtdXN0IGNvbXBsZXRlIGluIHRoZSBjYWxsZXIsXG4gIC8vIGFsbCBiZWZvcmUgYWNrLiBJZiB0aGUgcHJvY2VzcyBjcmFzaGVzIGJlZm9yZSB0aGlzIHJlc29sdmVzLCB0aGUgb3JjaGVzdHJhdG9yXG4gIC8vIG1lc3NhZ2UgaXMgbm90IGFja2VkIGFuZCBWUVMgcmVkZWxpdmVycywgcmUtY3JlYXRlcyB0aGUgKGlkZW1wb3RlbnQpXG4gIC8vIHN0ZXBfY3JlYXRlZCBhbmQgcmUtZGlzcGF0Y2hlcywgYW5kIHJlY292ZXJzIHRoZSBydW4gaW5zdGVhZCBvZiBvcnBoYW5pbmcgaXQuXG4gIGF3YWl0IHNldHRsZVBoYXNlKG9wcyk7XG5cbiAgLy8gVGhlIHN0ZXAtaW5wdXQgZGVoeWRyYXRpb25zIGFib3ZlIGhhdmUgc2V0dGxlZCwgc28gdGhlIHNpbmsgaXMgZmluYWwuXG4gIGNvbnN0IHJldGFpbmVkU3RlcElucHV0c1NhZmUgPSBndWVzdENvZGVTdGF0cy5leGVjdXRpb25zLmxlbmd0aCA9PT0gMDtcbiAgaWYgKCFyZXRhaW5lZFN0ZXBJbnB1dHNTYWZlKSB7XG4gICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICdTZXJpYWxpemluZyBzdGVwIGlucHV0cyBleGVjdXRlZCB3b3JrZmxvdyBjb2RlOyBmYWxsaW5nIGJhY2sgdG8gcmVwbGF5IGluc3RlYWQgb2YgcmV0YWluaW5nIHRoZSBWTScsXG4gICAgICB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBleGVjdXRpb25zOiBndWVzdENvZGVTdGF0cy5leGVjdXRpb25zXG4gICAgICAgICAgLnNsaWNlKDAsIDUpXG4gICAgICAgICAgLm1hcCgoZSkgPT4gKGUuZGV0YWlsID8gYCR7ZS5raW5kfSgke2UuZGV0YWlsfSlgIDogZS5raW5kKSksXG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIC8vIFJlYnVpbGQgdGhlIGlubGluZSBiYXRjaCBpbiBkZXRlcm1pbmlzdGljIG9yZGVyLiBgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzYFxuICAvLyBpcyBhIFNldCBzZWVkZWQgZnJvbSB0aGUgb3JkZXJlZCBmaXJzdC1OIHNsaWNlLCBzbyBpdGVyYXRpbmcgaXQgcHJlc2VydmVzXG4gIC8vIHN0ZXBJdGVtcyBvcmRlcjsgZXZlcnkgaWQgaW4gaXQgd2FzIHNldCBieSB0aGUgbGF6eSBicmFuY2ggYWJvdmUuXG4gIGNvbnN0IGxhenlJbmxpbmVTdGVwczogU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHRbJ2xhenlJbmxpbmVTdGVwcyddID0gW107XG4gIGZvciAoY29uc3QgY29ycmVsYXRpb25JZCBvZiBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMpIHtcbiAgICBjb25zdCBsYXp5U3RlcCA9IGxhenlJbmxpbmVCeUNvcnJlbGF0aW9uSWQuZ2V0KGNvcnJlbGF0aW9uSWQpO1xuICAgIGlmIChsYXp5U3RlcCkgbGF6eUlubGluZVN0ZXBzLnB1c2gobGF6eVN0ZXApO1xuICB9XG5cbiAgLy8gRmluZCB0aGUgc29vbmVzdCBwZW5kaW5nIHdhaXQgKG1pbmltdW0gdGltZW91dClcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgbGV0IHNvb25lc3RXYWl0OiB7IHNlY29uZHM6IG51bWJlcjsgY29ycmVsYXRpb25JZDogc3RyaW5nIH0gfCB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIHdhaXRJdGVtcykge1xuICAgIGNvbnN0IHJlc3VtZUF0TXMgPSBxdWV1ZUl0ZW0ucmVzdW1lQXQuZ2V0VGltZSgpO1xuICAgIGNvbnN0IGRlbGF5TXMgPSBNYXRoLm1heCgxMDAwLCByZXN1bWVBdE1zIC0gbm93KTtcbiAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGguY2VpbChkZWxheU1zIC8gMTAwMCk7XG4gICAgaWYgKCFzb29uZXN0V2FpdCB8fCB0aW1lb3V0U2Vjb25kcyA8IHNvb25lc3RXYWl0LnNlY29uZHMpIHtcbiAgICAgIHNvb25lc3RXYWl0ID0ge1xuICAgICAgICBzZWNvbmRzOiB0aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cygnd29ya2Zsb3dfc3VzcGVuZGVkJyksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93U3RlcHNDcmVhdGVkKHN0ZXBJdGVtcy5sZW5ndGgpLFxuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0hvb2tzQ3JlYXRlZChob29rc05lZWRpbmdDcmVhdGlvbi5sZW5ndGgpLFxuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1dhaXRzQ3JlYXRlZCh3YWl0SXRlbXMubGVuZ3RoKSxcbiAgICAuLi4ocmVzaWxpZW50RGlzcGF0Y2hSZWNvdmVyZWQgPiAwXG4gICAgICA/IEF0dHJpYnV0ZS5TdGVwUmVzaWxpZW50RGlzcGF0Y2hSZWNvdmVyZWQocmVzaWxpZW50RGlzcGF0Y2hSZWNvdmVyZWQpXG4gICAgICA6IHt9KSxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBwZW5kaW5nU3RlcHM6IHN0ZXBJdGVtcyxcbiAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLFxuICAgIHF1ZXVlZFN0ZXBDb3JyZWxhdGlvbklkcyxcbiAgICBsYXp5SW5saW5lU3RlcHMsXG4gICAgLy8gT24gaG9vayBjb25mbGljdCB0aGUgY2FsbGVyIHJlLWludm9rZXMgaW1tZWRpYXRlbHkgYW5kIG5ldmVyIHJlYWRzXG4gICAgLy8gdGhlIHdhaXQgdGltZW91dCwgc28gZG9uJ3QgcmVwb3J0IG9uZS5cbiAgICB3YWl0VGltZW91dDogaGFzSG9va0NvbmZsaWN0ID8gdW5kZWZpbmVkIDogc29vbmVzdFdhaXQsXG4gICAgaGFzSG9va0NvbmZsaWN0LFxuICAgIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb24sXG4gICAgaGFzQXR0cmlidXRlRXZlbnRzOiBhdHRyaWJ1dGVJdGVtcy5sZW5ndGggPiAwLFxuICAgIGhhc0hvb2tFdmVudHM6IGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCA+IDAsXG4gICAgaG9va0NyZWF0aW9uTXMsXG4gICAgcmV0YWluZWRTdGVwSW5wdXRzU2FmZSxcbiAgICByZXBvcnRlZEV2ZW50Q291bnQ6IHJlcG9ydGVkRXZlbnRzLFxuICB9O1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYW4gYGV2ZW50cy5jcmVhdGVgIHJlamVjdGlvbiBpcyBkZXRlcm1pbmlzdGljIFdvcmxkIHZhbGlkYXRpb25cbiAqIHJhdGhlciB0aGFuIGEgdHJhbnNpZW50L3N0b3JhZ2UgZXJyb3IuIExvY2FsIFdvcmxkc1xuICogKHdvcmxkLWxvY2FsLCB3b3JsZC1wb3N0Z3JlcykgdGhyb3cgYEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcmAgZGlyZWN0bHk7XG4gKiByZW1vdGUgV29ybGRzIHN1cmZhY2UgdGhlIGVxdWl2YWxlbnQgc2VydmVyLXNpZGUgcmVqZWN0aW9uIGFzIGFcbiAqIGBXb3JrZmxvd1dvcmxkRXJyb3JgIHdpdGggSFRUUCBzdGF0dXMgNDAwLiBUaGUgbmFtZSBjaGVjayBjb3ZlcnNcbiAqIGBBdHRyaWJ1dGVWYWxpZGF0aW9uRXJyb3JgIGluc3RhbmNlcyBmcm9tIGEgZGlmZmVyZW50IGNvcHkgb2ZcbiAqIGBAd29ya2Zsb3cvd29ybGRgIHRoYW4gdGhlIG9uZSB0aGlzIHBhY2thZ2UgcmVzb2x2ZWQuXG4gKi9cbmZ1bmN0aW9uIGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnI6IHVua25vd24pOiBib29sZWFuIHtcbiAgaWYgKGVyciBpbnN0YW5jZW9mIEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcikgcmV0dXJuIHRydWU7XG4gIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnIubmFtZSA9PT0gJ0F0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcicpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gV29ya2Zsb3dXb3JsZEVycm9yLmlzKGVycikgJiYgZXJyLnN0YXR1cyA9PT0gNDAwO1xufVxuIl19
|
|
1344
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGlCQUFpQixFQUNqQix1QkFBdUIsRUFDdkIsZUFBZSxFQUNmLGtCQUFrQixFQUNsQixrQkFBa0IsR0FDbkIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQ0wsd0JBQXdCLEVBS3hCLG9CQUFvQixFQUNwQiwwQ0FBMEMsRUFDMUMsaUNBQWlDLEVBQ2pDLG1DQUFtQyxHQU1wQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQVE3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRTdDLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsa0JBQWtCLEdBQ25CLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDdkQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUQsT0FBTyxFQUNMLGlCQUFpQixFQUNqQix5QkFBeUIsRUFDekIsOEJBQThCLEVBQzlCLHVCQUF1QixFQUN2Qiw4QkFBOEIsR0FDL0IsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQ0wsdUJBQXVCLEVBR3ZCLFlBQVksRUFDWixZQUFZLEVBQ1osa0JBQWtCLEVBQ2xCLDBCQUEwQixHQUMzQixNQUFNLGNBQWMsQ0FBQztBQUN0QixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztB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Q3RCLGtCQUFrQixFQUFFLGNBQWM7S0FDbkMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQVMsd0JBQXdCLENBQUMsR0FBWTtJQUM1QyxJQUFJLEdBQUcsWUFBWSx3QkFBd0I7UUFBRSxPQUFPLElBQUksQ0FBQztJQUN6RCxJQUFJLEdBQUcsWUFBWSxLQUFLLElBQUksR0FBRyxDQUFDLElBQUksS0FBSywwQkFBMEIsRUFBRSxDQUFDO1FBQ3BFLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU8sa0JBQWtCLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssR0FBRyxDQUFDO0FBQzFELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFNwYW4gfSBmcm9tICdAb3BlbnRlbGVtZXRyeS9hcGknO1xuaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgRmF0YWxFcnJvcixcbiAgSG9va05vdEZvdW5kRXJyb3IsXG4gIFByZWNvbmRpdGlvbkZhaWxlZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFNlcmlhbGl6YXRpb25FcnJvcixcbiAgV29ya2Zsb3dXb3JsZEVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7XG4gIEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcixcbiAgdHlwZSBDcmVhdGVFdmVudFBhcmFtcyxcbiAgdHlwZSBDcmVhdGVFdmVudFJlcXVlc3QsXG4gIHR5cGUgRXZlbnRSZXN1bHQsXG4gIHR5cGUgU2VyaWFsaXplZERhdGEsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ0JPUl9RVUVVRV9UUkFOU1BPUlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTixcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX1NMT1RfSURFTlRJVFksXG4gIHR5cGUgU3RhcnRlZFN0ZXAsXG4gIHR5cGUgVHJhY2VDYXJyaWVyLFxuICB0eXBlIFZhbGlkUXVldWVOYW1lLFxuICB0eXBlIFdvcmtmbG93UnVuLFxuICB0eXBlIFdvcmxkLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgaXNSZXRyeWFibGVXb3JsZEVycm9yIH0gZnJvbSAnLi4vY2xhc3NpZnktZXJyb3IuanMnO1xuaW1wb3J0IHsgaW1wb3J0S2V5IH0gZnJvbSAnLi4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQgdHlwZSB7XG4gIEF0dHJpYnV0ZUludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV2FpdEludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFdvcmtmbG93U3VzcGVuc2lvbixcbn0gZnJvbSAnLi4vZ2xvYmFsLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBHdWVzdENvZGVTdGF0cyB9IGZyb20gJy4uL3NlcmlhbGl6YXRpb24vaGFyZGVuZWQuanMnO1xuaW1wb3J0IHtcbiAgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyxcbiAgZGVoeWRyYXRlU3RlcEVycm9yLFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgZ2V0QWJvcnRTdHJlYW1JZEZyb21Ub2tlbiB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0IHsgQ09NUFVURV9JTlNUQU5DRV9JRCB9IGZyb20gJy4vY29tcHV0ZS1pbnN0YW5jZS5qcyc7XG5pbXBvcnQge1xuICBnZXRNYXhJbmxpbmVTdGVwcyxcbiAgaXNCYXRjaFRyYW5zaXRpb25zRW5hYmxlZCxcbiAgaXNSZXNpbGllbnRTdGVwRGlzcGF0Y2hFbmFibGVkLFxuICBNQVhfQkFUQ0hfRkFOT1VUX0VWRU5UUyxcbiAgTUFYX1JFU0lMSUVOVF9TVEVQX0lOUFVUX0JZVEVTLFxufSBmcm9tICcuL2NvbnN0YW50cy5qcyc7XG5pbXBvcnQge1xuICBhYnNvcmJTa2lwcGVkU2xvdFJlcG9ydCxcbiAgdHlwZSBFdmVudENyZWF0b3IsXG4gIHR5cGUgTG9hZGVkRXZlbnRMb2csXG4gIG1heEV2ZW50U2xvdCxcbiAgcXVldWVNZXNzYWdlLFxuICBzbG90U25hcHNob3RQYXJhbXMsXG4gIHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5LFxufSBmcm9tICcuL2hlbHBlcnMuanMnO1xuaW1wb3J0IHsgUmVwbGF5UmVjb3ZlcnlSZXBvcnRlciB9IGZyb20gJy4vcmVwbGF5LXJlY292ZXJ5LXJlcG9ydGVyLmpzJztcbmltcG9ydCB0eXBlIHsgUHJlY2xhaW1lZElubGluZVN0YXJ0IH0gZnJvbSAnLi9zdGVwLWV4ZWN1dG9yLmpzJztcbmltcG9ydCB7IHVuc2VyaWFsaXphYmxlU3RlcElucHV0UGxhY2Vob2xkZXIgfSBmcm9tICcuL3Vuc2VyaWFsaXphYmxlLXN0ZXAuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zIHtcbiAgc3VzcGVuc2lvbjogV29ya2Zsb3dTdXNwZW5zaW9uO1xuICB3b3JsZDogV29ybGQ7XG4gIHJ1bjogV29ya2Zsb3dSdW47XG4gIHNwYW4/OiBTcGFuO1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcnVudGltZSdzIGxvYWRlZCBldmVudCBsb2cuIEV2ZXJ5IGV2ZW50IGNyZWF0aW9uIHRoaXMgc3VzcGVuc2lvbiBtYWtlc1xuICAgKiBuYW1lcyB0aGUgcG9zaXRpb24gaXQgd2FzIGRlcml2ZWQgZnJvbSwgc28gYSBiYWNrZW5kIHRoYXQgaGFzIHJlY29yZGVkXG4gICAqIGV2ZW50cyB0aGUgcmVwbGF5IGRpZCBub3Qgc2VlIGNhbiByZXBvcnQgdGhlbSBiYWNrIG9uIHRoZSB3cml0ZSwgb3IsIGlmXG4gICAqIGl0IHdvdWxkIHJhdGhlciByZWZ1c2UgdGhhbiByZXBvcnQsIHJlamVjdCBpdCB3aXRoIGEgNDEyLiBBIHJlamVjdGlvbiBpc1xuICAgKiBub3QgcmV0cmllZCBoZXJlOiB0aGUgZXZlbnQncyBjb3JyZWxhdGlvbiBpZCB3YXMgbWludGVkIGJ5ICp0aGlzKiByZXBsYXknc1xuICAgKiBzZWVkZWQgc2VxdWVuY2UsIHNvIHJlLWNvbW1pdHRpbmcgaXQgYWdhaW5zdCBhIGNvcnJlY3RlZCBsb2cgd291bGQgcGVyc2lzdFxuICAgKiBhbiBldmVudCBubyBjb3JyZWN0IHJlcGxheSBwcm9kdWNlcy4gVGhlIGNhbGxlciByZXN0YXJ0cyB0aGUgcmVwbGF5XG4gICAqIGluc3RlYWQuXG4gICAqL1xuICBldmVudExvZz86IExvYWRlZEV2ZW50TG9nO1xuICAvKipcbiAgICogVHVyYm8gbW9kZSBvbmx5OiBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBvbmNlIHRoZSBiYWNrZ3JvdW5kZWRcbiAgICogYHJ1bl9zdGFydGVkYCBoYXMgbGFuZGVkICh0aGUgcnVuIGV4aXN0cykuIFdoZW4gcHJlc2VudCwgZXZlcnkgd29ybGQgd3JpdGVcbiAgICogdGhpcyBzdXNwZW5zaW9uIHBlcmZvcm1zIChgaG9va19jcmVhdGVkYCwgYHdhaXRfY3JlYXRlZGAsIGVhZ2VyIG92ZXJmbG93XG4gICAqIGBzdGVwX2NyZWF0ZWRgLCDigKYpIGlzIGdhdGVkIG9uIGl0IHNvIHRoZSB3cml0ZSBuZXZlciByYWNlcyBhaGVhZCBvZiB0aGVcbiAgICogcnVuJ3MgY3JlYXRpb24uIFRoZSBwdXJlIGlubGluZSBob3QgcGF0aCBkZWZlcnMgYWxsIG9mIGl0cyBzdGVwcyBhbmQgd3JpdGVzXG4gICAqIG5vdGhpbmcgaGVyZSwgc28gaXQgbmV2ZXIgYXdhaXRzIHRoaXMgYmFycmllci4gYHVuZGVmaW5lZGAgb3V0c2lkZSB0dXJibyxcbiAgICogd2hlcmUgYHJ1bl9zdGFydGVkYCB3YXMgYWxyZWFkeSBhd2FpdGVkIHVwIGZyb250LlxuICAgKi9cbiAgcnVuUmVhZHlCYXJyaWVyPzogUHJvbWlzZTx1bmtub3duPjtcbiAgLyoqIE9uZS1zaG90IHRlbGVtZXRyeSByZXBvcnRlciwgYWN0aXZhdGVkIG9ubHkgYWZ0ZXIgcmVwbGF5IGhhcyByZWNvdmVyZWQuICovXG4gIHJlcGxheVJlY292ZXJ5UmVwb3J0ZXI/OiBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyO1xuICAvKipcbiAgICogUmVzaWxpZW50IHN0ZXAgZGlzcGF0Y2g6IHdoZW4gcHJvdmlkZWQgKGFuZCB0aGUgcGVyLXN0ZXAgZWxpZ2liaWxpdHkgZ2F0ZXNcbiAgICogcGFzcywgc2VlIHRoZSBzdGVwIG9wcyBiZWxvdyksIGVhY2ggbmV3bHkgY3JlYXRlZCBub24taW5saW5lIHN0ZXAnc1xuICAgKiBgc3RlcF9jcmVhdGVkYCB3cml0ZSBpcyBwYXJhbGxlbGl6ZWQgd2l0aCBpdHMgc3RlcC1leGVjdXRpb24gcXVldWVcbiAgICogcHVibGlzaCwgYW5kIHRoZSBxdWV1ZSBtZXNzYWdlIGNhcnJpZXMgdGhlIHNlcmlhbGl6ZWQgc3RlcCBpbnB1dFxuICAgKiAoYHN0ZXBJbnB1dGApIHNvIHRoZSBjb25zdW1lciBjYW4gaWRlbXBvdGVudGx5IHJlLWVuc3VyZSB0aGUgZXZlbnQgaWYgdGhlXG4gICAqIGRpcmVjdCB3cml0ZSBmYWlsZWQgdHJhbnNpZW50bHkuIFN0ZXBzIHF1ZXVlZCB0aGlzIHdheSBhcmUgcmVwb3J0ZWQgaW5cbiAgICoge0BsaW5rIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0LnF1ZXVlZFN0ZXBDb3JyZWxhdGlvbklkc30gc28gdGhlIGNhbGxlclxuICAgKiBza2lwcyB0aGVtIGluIGl0cyBvd24gZGlzcGF0Y2ggcGFzcy4gT21pdHRlZCBieSBjYWxsZXJzIHRoYXQgbXVzdCBub3RcbiAgICogcXVldWUgKHRlcm1pbmFsIGRyYWluLCB0ZXN0cyk7IGNyZWF0ZXMgdGhlbiBiZWhhdmUgZXhhY3RseSBhcyBiZWZvcmUuXG4gICAqL1xuICBzdGVwRGlzcGF0Y2g/OiB7XG4gICAgLyoqIFRoZSB1bmlmaWVkIHdvcmtmbG93IHF1ZXVlIHRoaXMgcnVuJ3Mgc3RlcCBtZXNzYWdlcyBhcmUgcHVibGlzaGVkIHRvLiAqL1xuICAgIHF1ZXVlTmFtZTogVmFsaWRRdWV1ZU5hbWU7XG4gICAgLyoqXG4gICAgICogTGF6aWx5IHJlc29sdmVzIHRoZSB0cmFjZSBjYXJyaWVyIHRvIHN0YW1wIG9uIHRoZSBzdGVwIG1lc3NhZ2VzLlxuICAgICAqIENhbGxlZCBhdCBtb3N0IG9uY2UgcGVyIHN1c3BlbnNpb24gKG1lbW9pemVkIGhlcmUpLlxuICAgICAqL1xuICAgIGdldFRyYWNlQ2FycmllcjogKCkgPT4gUHJvbWlzZTxUcmFjZUNhcnJpZXI+O1xuICB9O1xuICAvKipcbiAgICogSW5saW5lIHN0ZXAgb3duZXJzaGlwOiB0aGUgcXVldWUgbWVzc2FnZSBJRCBvZiB0aGUgaW52b2NhdGlvbiB0aGlzXG4gICAqIHN1c3BlbnNpb24gcnVucyBpbiAodGhlIHF1ZXVlIGhhbmRsZXIncyBtZXRhKS4gV2hlbiBwcmVzZW50IEFORCB0aGVcbiAgICogYmF0Y2hlZCBmYW4tb3V0IGVuZ2FnZXMsIHRoZSBsYXp5LWlubGluZSBzdGVwcycgZGVmZXJyZWQgd3JpdGVzIGFyZVxuICAgKiBmb2xkZWQgaW50byB0aGUgYmF0Y2ggYXMgYHN0ZXBfY3JlYXRlZGAgKyBgc3RlcF9zdGFydGVkYCBwYWlycyAodGhlXG4gICAqIHN0YXJ0ZWQgcm93IHN0YW1wZWQgd2l0aCB0aGlzIElELCBleGFjdGx5IGxpa2UgdGhlIGxhenkgY2xhaW0gaXRcbiAgICogcmVwbGFjZXMpLCBwcmUtY2xhaW1pbmcgdGhlIHN0ZXBzIHRoZSBjYWxsZXIgaXMgYWJvdXQgdG8gcnVuIGlubGluZS4gU2VlXG4gICAqIHtAbGluayBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdC5pbmxpbmVDbGFpbXN9LiBDYWxsZXJzIHRoYXQgbmV2ZXJcbiAgICogaW5saW5lLWV4ZWN1dGUgKHRlcm1pbmFsIGRyYWluKSBvbWl0IGl0LCBrZWVwaW5nIHRoZWlyIGxhenkgc3RlcHMgb24gdGhlXG4gICAqIHBsYWluIGRlZmVycmVkIHBhdGguXG4gICAqL1xuICBvd25lck1lc3NhZ2VJZD86IHN0cmluZztcbiAgLyoqXG4gICAqIExldHMgdGhlIGJhdGNoZWQgZmFuLW91dCByZXR1cm4gYmVmb3JlIGV2ZXJ5IGNodW5rIGhhcyBjb21taXR0ZWQ6IG9ubHlcbiAgICogdGhlIGNodW5rIGNhcnJ5aW5nIHRoZSBwcmUtY2xhaW1lZCBpbmxpbmUgcGFpcnMgZ2F0ZXMgdGhlIGhhbmRsZXInc1xuICAgKiByZXR1cm4gKGl0cyBjbGFpbXMgYXJlIHdoYXQgdGhlIGNhbGxlciBzdGFydHMgYm9kaWVzIGZyb20pLCB3aGlsZSB0aGVcbiAgICogdHJhaWxpbmcgY2h1bmtzJyBjb21taXRzIChhbmQgZXZlcnkgY2h1bmsncyBpbi1mbHVzaCBzdGVwLW1lc3NhZ2VcbiAgICogcHVibGlzaGVzKSByaWRlIHtAbGluayBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdC5kZWZlcnJlZEJhdGNoV29ya30uIEFcbiAgICogY2FsbGVyIHRoYXQgb3B0cyBpbiBNVVNUIGF3YWl0IHRoYXQgcHJvbWlzZSBiZWZvcmUgYWNraW5nIGl0cyBkZWxpdmVyeTpcbiAgICogdGhlIGR1cmFiaWxpdHkgY29udHJhY3QgKFwiZXZlcnkgY3JlYXRlIGR1cmFibGUgYmVmb3JlIGFja1wiKSBtb3ZlcyBmcm9tXG4gICAqIHRoZSBoYW5kbGVyJ3MgcmV0dXJuIHRvIHRoYXQgam9pbiwgYW5kIG5vdGhpbmcgZWxzZSByZS1kcml2ZXMgYSBsb3N0XG4gICAqIHRyYWlsaW5nIGNodW5rLiBDYWxsZXJzIHRoYXQgZG9uJ3Qgb3B0IGluICh0ZXJtaW5hbCBkcmFpbiwgZGVmYXVsdClcbiAgICoga2VlcCB0aGUgZXZlcnl0aGluZy1kdXJhYmxlLWF0LXJldHVybiBiZWhhdmlvci5cbiAgICovXG4gIGFsbG93RGVmZXJyZWRCYXRjaFdvcms/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBoYW5kbGluZyBhIHN1c3BlbnNpb24uIFJldHVybnMgcGVuZGluZyBzdGVwIGl0ZW1zIHNvIHRoZSBjYWxsZXJcbiAqIGNhbiBkZWNpZGUgd2hpY2ggdG8gZXhlY3V0ZSBpbmxpbmUgdnMgcXVldWUgdG8gYmFja2dyb3VuZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdCB7XG4gIC8qKiBQZW5kaW5nIHN0ZXAgaXRlbXMgd2l0aCBldmVudHMgY3JlYXRlZCBidXQgTk9UIHF1ZXVlZCAqL1xuICBwZW5kaW5nU3RlcHM6IFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtW107XG4gIC8qKlxuICAgKiBDb3JyZWxhdGlvbiBJRHMgZm9yIHdoaWNoIHRoaXMgc3VzcGVuc2lvbiBjYWxsIGFjdHVhbGx5IHdyb3RlIHRoZVxuICAgKiBzdGVwX2NyZWF0ZWQgZXZlbnQgKGFzIG9wcG9zZWQgdG8gY2F0Y2hpbmcgRW50aXR5Q29uZmxpY3RFcnJvciBiZWNhdXNlXG4gICAqIGEgY29uY3VycmVudCBoYW5kbGVyIHdyb3RlIGl0IGZpcnN0KS4gT25seSB0aGUgaGFuZGxlciB0aGF0IHdyb3RlIHRoZVxuICAgKiBzdGVwX2NyZWF0ZWQgZXZlbnQgc2hvdWxkIHF1ZXVlIC8gaW5saW5lLWV4ZWN1dGUgdGhlIHN0ZXA7IHRoaXNcbiAgICogZ3VhcmFudGVlcyBhIHNpbmdsZSBvd25lciBwZXIgc3RlcCwgZXZlbiB3aGVuIG11bHRpcGxlIGhhbmRsZXJzIHJhY2VcbiAgICogaW50byB0aGUgc2FtZSBiYXRjaCBib3VuZGFyeS5cbiAgICovXG4gIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHM6IFNldDxzdHJpbmc+O1xuICAvKipcbiAgICogQ29ycmVsYXRpb24gSURzIG9mIHN0ZXBzIHdob3NlIGFyZ3VtZW50cyBmYWlsZWQgdG8gc2VyaWFsaXplLiBFYWNoIHdhc1xuICAgKiBmaW5hbGl6ZWQgaGVyZSBhcyBgc3RlcF9jcmVhdGVkYCAod2l0aCBhIHBsYWNlaG9sZGVyIGlucHV0OyB0aGUgcmVhbFxuICAgKiBpbnB1dCBpcyBwcmVjaXNlbHkgd2hhdCByZWZ1c2VkIHRvIHNlcmlhbGl6ZSkgZm9sbG93ZWQgYnkgYHN0ZXBfZmFpbGVkYFxuICAgKiBjYXJyeWluZyB0aGUgU2VyaWFsaXphdGlvbkVycm9yLCBzbyB0aGUgbmV4dCByZXBsYXkgcmVqZWN0cyB0aGUgc3RlcCdzXG4gICAqIHByb21pc2UgYW5kIGEgdHJ5L2NhdGNoIGFyb3VuZCB0aGUgc3RlcCBjYWxsIG9ic2VydmVzIHRoZSBlcnJvcixcbiAgICogZXhhY3RseSBsaWtlIGEgc3RlcC1ib2R5IGZhaWx1cmUuIE5vIHN0ZXAtZXhlY3V0aW9uIG1lc3NhZ2UgaXNcbiAgICogZGlzcGF0Y2hlZCBmb3IgdGhlc2UsIHNvIHRoZSBjYWxsZXIgTVVTVCBmb3JjZSBhbiBpbi1wcm9jZXNzIHJlcGxheTpcbiAgICogd2hlbiB0aGUgZmFpbGVkIHN0ZXAgd2FzIHRoZSBvbmx5IHBlbmRpbmcgd29yaywgbm90aGluZyBlbHNlIHdpbGwgZXZlclxuICAgKiByZS1pbnZva2UgdGhlIHJ1biB0byBvYnNlcnZlIHRoZSB0ZXJtaW5hbCBldmVudC5cbiAgICovXG4gIGZhaWxlZFN0ZXBDb3JyZWxhdGlvbklkczogU2V0PHN0cmluZz47XG4gIC8qKlxuICAgKiBDb3JyZWxhdGlvbiBJRHMgb2Ygc3RlcHMgdGhpcyBzdXNwZW5zaW9uIGNhbGwgYWxyZWFkeSBwdWJsaXNoZWRcbiAgICogc3RlcC1leGVjdXRpb24gcXVldWUgbWVzc2FnZXMgZm9yLCB2aWEgcmVzaWxpZW50IHN0ZXAgZGlzcGF0Y2ggKHRoZVxuICAgKiBgc3RlcF9jcmVhdGVkYCB3cml0ZSBwYXJhbGxlbGl6ZWQgd2l0aCBhIGBzdGVwSW5wdXRgLWNhcnJ5aW5nIHF1ZXVlXG4gICAqIHB1Ymxpc2gpLiBUaGUgY2FsbGVyIE1VU1QgTk9UIGRpc3BhdGNoIHRoZXNlIGFnYWluOiB0aGUgbWVzc2FnZSBpc1xuICAgKiBhbHJlYWR5IG91dCAoYSBkdXBsaWNhdGUgd291bGQgYmUgZGVkdXBlZCBieSBpdHMgaWRlbXBvdGVuY3kga2V5LCBidXRcbiAgICogY29zdHMgYSB3YXN0ZWQgcm91bmQtdHJpcCkuIEVtcHR5IHdoZW4ge0BsaW5rIFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zLnN0ZXBEaXNwYXRjaH1cbiAgICogd2FzIG5vdCBwcm92aWRlZCBvciBubyBzdGVwIHdhcyBlbGlnaWJsZS5cbiAgICovXG4gIHF1ZXVlZFN0ZXBDb3JyZWxhdGlvbklkczogU2V0PHN0cmluZz47XG4gIC8qKlxuICAgKiBIb3cgbWFueSBldmVudHMgdGhpcyBwaGFzZSdzIHdyaXRlcyByZXBvcnRlZCBiYWNrIGFzIG9jY3VweWluZyBzbG90cyB0aGV5XG4gICAqIHNraXBwZWQgb3ZlciwgYWxyZWFkeSBtZXJnZWQgaW50byB0aGUgY2FsbGVyJ3MgYGV2ZW50TG9nLmV2ZW50c2AuIE5vbnplcm9cbiAgICogbWVhbnMgdGhlIGFycmF5IHdhcyByZW9yZGVyZWQgdG8gcmVzdG9yZSBzbG90IG9yZGVyLCBzbyBhbnkgaW5kZXggdGhlXG4gICAqIGNhbGxlciBjYWNoZWQgaW50byBpdCAocGF5bG9hZCBwcmV3YXJtIHNjYW4gcG9zaXRpb24pIGlzIHN0YWxlLlxuICAgKi9cbiAgcmVwb3J0ZWRFdmVudENvdW50OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgc3RlcHMgd2hvc2UgYHN0ZXBfY3JlYXRlZGAgd3JpdGVzIHdlcmUgaW50ZW50aW9uYWxseSBkZWZlcnJlZCBzbyB0aGVcbiAgICogY2FsbGVyIGNhbiBydW4gdGhlbSBpbmxpbmUgdmlhIGxhenkgYHN0ZXBfc3RhcnRlZGAgZXZlbnRzICh3aGljaCBjcmVhdGVcbiAgICogdGhlIHN0ZXAgb24gdGhlIGZseSksIHNhdmluZyBvbmUgd29ybGQgcm91bmQtdHJpcCBwZXIgaW5saW5lIHN0ZXAuIFVwIHRvXG4gICAqIGBnZXRNYXhJbmxpbmVTdGVwcygpYCBzdGVwcyBhcmUgZGVmZXJyZWQ7IHRoZSBjYWxsZXIgcnVucyB0aGVtIGlubGluZSBpblxuICAgKiBwYXJhbGxlbCBhbmQgcXVldWVzIHRoZSByZXN0LiBFbXB0eSB3aGVuIG5vIHN0ZXAgd2FzIGRlZmVycmVkIChub3RoaW5nXG4gICAqIHBlbmRpbmcsIG9yIGEgYGhvb2suZ2V0Q29uZmxpY3QoKWAgYXdhaXRlciBpcyBwcmVzZW50IHNvIG5vdGhpbmcgaXNcbiAgICogZXhlY3V0ZWQgaW5saW5lKS4gVGhlIGNhbGxlciBwYXNzZXMgZWFjaCBgZGVoeWRyYXRlZElucHV0YCBzdHJhaWdodCB0b1xuICAgKiBgZXhlY3V0ZVN0ZXBgLCB3aGljaCBzZW5kcyBpdCBhcyB0aGUgYHN0ZXBfc3RhcnRlZGAgcGF5bG9hZC4gVGhlIGF0b21pY1xuICAgKiBjcmVhdGUtY2xhaW0gaW5zaWRlIGVhY2ggYHN0ZXBfc3RhcnRlZGAgaXMgdGhlIGV4YWN0bHktb25lLW93bmVyIGdhdGUgdGhhdFxuICAgKiB0aGUgc3RhbmRhbG9uZSBgc3RlcF9jcmVhdGVkYCBwcm92aWRlZCBiZWZvcmU6IHRoZSBsb3NlciBvZiB0aGUgcmFjZSBnZXRzXG4gICAqIGBFbnRpdHlDb25mbGljdEVycm9yYCDihpIgYHNraXBwZWRgIGFuZCBkb2VzIG5vdCBydW4gdGhlIGJvZHkuXG4gICAqL1xuICBsYXp5SW5saW5lU3RlcHM6IEFycmF5PHtcbiAgICBjb3JyZWxhdGlvbklkOiBzdHJpbmc7XG4gICAgc3RlcE5hbWU6IHN0cmluZztcbiAgICBkZWh5ZHJhdGVkSW5wdXQ6IFNlcmlhbGl6ZWREYXRhO1xuICB9PjtcbiAgLyoqXG4gICAqIFByZS1jbGFpbWVkIGlubGluZSBzdGFydHMsIGJ5IGNvcnJlbGF0aW9uIGlkOiB0aGUgcGVyLXN0ZXAgdmVyZGljdHMgb2ZcbiAgICogdGhlIGBzdGVwX2NyZWF0ZWRgICsgYHN0ZXBfc3RhcnRlZGAgcGFpcnMgdGhlIGJhdGNoZWQgZmFuLW91dCBjb21taXR0ZWRcbiAgICogZm9yIHRoZSBsYXp5LWlubGluZSBzdGVwcy4gQSBzdGVwIHdpdGggYW4gZW50cnkgaGVyZSBpcyBwYXNzZWQgdG9cbiAgICogYGV4ZWN1dGVTdGVwYCBhcyBgcHJlY2xhaW1lZFN0YXJ0YCBJTlNURUFEIG9mIGBsYXp5U3RlcElucHV0YDogaXRzXG4gICAqIGlucHV0IGFscmVhZHkgcm9kZSB0aGUgcGFpciwgYW5kIHRoZSBjbGFpbSBpcyBzZXR0bGVkOiBgb3duZWQ6IHRydWVgXG4gICAqIGNhcnJpZXMgdGhlIHN0YXJ0ZWQgYXR0ZW1wdC0xIGVudGl0eSAoaW5wdXQgcmUtYXR0YWNoZWQpIHNvIHRoZSBib2R5XG4gICAqIHJ1bnMgc3RyYWlnaHQgb2ZmIHRoZSBiYXRjaCBjb21taXQgd2l0aCBubyBzdGFydCB3cml0ZSBvZiBpdHMgb3duO1xuICAgKiBgb3duZWQ6IGZhbHNlYCBsb3N0IHRoZSBwYWlyJ3MgYXRvbWljIGNyZWF0ZS1jbGFpbSB0byBhIGNvbmN1cnJlbnRcbiAgICogd3JpdGVyLCBhbmQgZXhlY3V0ZVN0ZXAgcmV0dXJucyBgc2tpcHBlZGAgd2l0aG91dCBydW5uaW5nIHRoZSBib2R5LFxuICAgKiB0aGUgc2FtZSBvdXRjb21lIGFzIGxvc2luZyB0aGUgbGF6eSBjbGFpbS4gRW1wdHkgd2hlbmV2ZXIgdGhlIGZvbGQgZGlkXG4gICAqIG5vdCBlbmdhZ2UgKGJhdGNoaW5nIG9mZiwgbm8gYG93bmVyTWVzc2FnZUlkYCwgb3IgdGhlIGxvbmUtaW5saW5lIGNhc2UsXG4gICAqIHdoaWNoIGtlZXBzIHRoZSBvcHRpbWlzdGljIGxhenkgcGF0aCBhbmQgaXRzIGNsYWltL2JvZHkgb3ZlcmxhcCkuXG4gICAqXG4gICAqIENyYXNoIHdpbmRvdzogdGhlIHBhaXIgY29tbWl0cyBiZWZvcmUgdGhlIGNhbGxlciBydW5zIHRoZSBib2R5LCBzbyBhXG4gICAqIGNyYXNoIGJldHdlZW4gdGhlbSBsZWF2ZXMgYSBzdGFydGVkIHN0ZXAgc3RhbXBlZCB3aXRoIHRoaXMgbWVzc2FnZSdzXG4gICAqIElELiBSZWRlbGl2ZXJ5IG9mIHRoZSBzYW1lIG1lc3NhZ2UgcmUtZXhlY3V0ZXMgaXQgdmlhIHRoZSBvd25lZC1yZWNvdmVyeVxuICAgKiBwYXRoLCB0aGUgZXhhY3QgbWFjaGluZXJ5IHRoZSBsYXp5IGNsYWltJ3MgY3Jhc2ggd2luZG93IGFscmVhZHkgdXNlcy5cbiAgICovXG4gIGlubGluZUNsYWltczogTWFwPHN0cmluZywgUHJlY2xhaW1lZElubGluZVN0YXJ0PjtcbiAgLyoqXG4gICAqIFRoZSBoaWdoZXN0IHNsb3QgdGhlIGJhdGNoZWQgZmFuLW91dCBjb21taXR0ZWQsIHdoZW4gaXQgcmFuLiBUaGUgYmF0Y2gnc1xuICAgKiBvd24gZXZlbnRzIGFyZSBub3QgaW4gdGhlIGNhbGxlcidzIGxvYWRlZCBsb2cgKHRoZSBuZXh0IHJlbG9hZCBwaWNrc1xuICAgKiB0aGVtIHVwKSwgc28gdGhlIGNhbGxlciBmb2xkcyB0aGlzIGNlaWxpbmcgaW50byB0aGUgc2xvdCBzbmFwc2hvdCBpdFxuICAgKiBoYW5kcyB0aGUgaW5saW5lIGV4ZWN1dGlvbnM7IG90aGVyd2lzZSBldmVyeSBpbmxpbmUgdGVybWluYWwgd3JpdGVcbiAgICogd291bGQgbmFtZSBhIHByZS1iYXRjaCBwb3NpdGlvbiBhbmQgYmUgYW5zd2VyZWQgd2l0aCBhIHNraXBwZWQtc2xvdFxuICAgKiByZXBvcnQgZWNob2luZyB0aGUgZXZlbnRzIHRoaXMgc3VzcGVuc2lvbiBqdXN0IHdyb3RlLiBVbmRlclxuICAgKiB7QGxpbmsgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMuYWxsb3dEZWZlcnJlZEJhdGNoV29ya30gdGhpcyBjb3ZlcnMgdGhlXG4gICAqIGNodW5rcyB0aGF0IGhhZCBjb21taXR0ZWQgYnkgdGhlIGhhbmRsZXIncyByZXR1cm4gKGFsd2F5cyB0aGUgcGFpclxuICAgKiBjaHVuayk7IGEgdHJhaWxpbmcgY2h1bmsgdGhhdCBjb21taXRzIGxhdGVyIGlzIGVjaG9lZCBiYWNrIG9uIHRoZVxuICAgKiB0ZXJtaW5hbCB3cml0ZXMgbGlrZSBhbnkgZm9yZWlnbiBldmVudDogcmVwb3J0cyB0aGUgZXhlY3V0b3IgcmVhZHMgZm9yXG4gICAqIHBvc2l0aW9uIGFuZCBkaXNjYXJkcy5cbiAgICpcbiAgICogU28gdGhlIGVjaG8gaXMgb25seSBmdWxseSBzdXBwcmVzc2VkIGZvciBhIFNJTkdMRS1jaHVuayBmb2xkLiBPbiBhXG4gICAqIG11bHRpLWNodW5rIGZhbi1vdXQgdGhlIGJvZGllcyBzdGFydCBvZmYgdGhlIHBhaXIgY2h1bmsgd2hpbGUgdHJhaWxpbmdcbiAgICogY2h1bmtzIGFyZSBzdGlsbCBpbiBmbGlnaHQsIGFuZCBhbiBpbmxpbmUgdGVybWluYWwgd3JpdGUgaXNzdWVkIGluIHRoYXRcbiAgICogd2luZG93IHN0aWxsIG5hbWVzIGEgcG9zaXRpb24gYmVsb3cgdGhlbSBhbmQgc3RpbGwgZHJhd3MgYSByZXBvcnQgZm9yXG4gICAqIHRoZWlyIGV2ZW50cy4gQm91bmRlZCAodHJhaWxpbmcgY2h1bmtzIG9ubHksIGxhcmdlIGZhbi1vdXRzIG9ubHkpIGFuZFxuICAgKiBzZWxmLWNvcnJlY3Rpbmcgb24gdGhlIG5leHQgcmVsb2FkLCBhbmQgcmVjb3JkZWQgc28gYSByZXBvcnQgc2VlbiB0aGVyZVxuICAgKiByZWFkcyBhcyBleHBlY3RlZCByYXRoZXIgdGhhbiBhcyBhIGJ1Zy5cbiAgICovXG4gIGJhdGNoQ29tbWl0dGVkU2xvdENlaWxpbmc/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgYmF0Y2hlZCBmYW4tb3V0J3MgZGVmZXJyZWQgd29yaywgcHJlc2VudCBvbmx5IHdoZW4gdGhlIGNhbGxlciBvcHRlZFxuICAgKiBpbiB2aWEge0BsaW5rIFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zLmFsbG93RGVmZXJyZWRCYXRjaFdvcmt9IGFuZFxuICAgKiB0cmFpbGluZyB3b3JrIGV4aXN0czogdGhlIGNvbW1pdHMgb2YgZXZlcnkgY2h1bmsgZXhjZXB0IHRoZSBwYWlyIGNodW5rLFxuICAgKiBwbHVzIGV2ZXJ5IGNodW5rJ3Mgc3RlcC1tZXNzYWdlIHB1Ymxpc2hlcyAoZWFjaCBjaGFpbmVkIG9uIElUUyBPV05cbiAgICogY2h1bmsncyBjb21taXQsIHNvIHB1Ymxpc2gtYWZ0ZXItY3JlYXRlIGhvbGRzIHBlciBzdGVwKS4gVGhlIGNhbGxlclxuICAgKiBNVVNUIGF3YWl0IGl0IGJlZm9yZSBhY2tpbmc6IGEgcmVqZWN0aW9uIGhlcmUgaXMgYSBmYWlsZWQgc3VzcGVuc2lvblxuICAgKiB3cml0ZSBhbmQgZmFpbHMgdGhlIGRlbGl2ZXJ5IGV4YWN0bHkgYXMgaXQgd291bGQgaGF2ZSBhdCB0aGUgaGFuZGxlcidzXG4gICAqIHJldHVybi4gU3RlcHMgd2hvc2UgbWVzc2FnZXMgdGhpcyB3b3JrIHB1Ymxpc2hlcyBhcmUgYWxyZWFkeSBpblxuICAgKiB7QGxpbmsgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzfSBhdCByZXR1cm4gdGltZS5cbiAgICovXG4gIGRlZmVycmVkQmF0Y2hXb3JrPzogUHJvbWlzZTx2b2lkPjtcbiAgLyoqXG4gICAqIFRoZSBzb29uZXN0IHBlbmRpbmcgd2FpdCwgaWYgYW55OiBzZWNvbmRzIHVudGlsIGl0IGVsYXBzZXMgYW5kIHRoZVxuICAgKiBjb3JyZWxhdGlvbklkIG9mIHRoZSB3YWl0IHRoYXQgcHJvZHVjZWQgdGhhdCB0aW1lb3V0LiBUaGVcbiAgICogY29ycmVsYXRpb25JZCBzZWVkcyB0aGUgaWRlbXBvdGVuY3kga2V5IGZvciB0aGUgd2FpdC1jb250aW51YXRpb25cbiAgICogcXVldWUgbWVzc2FnZSBzbyB0aGF0IHJlcGVhdGVkIHN1c3BlbnNpb24gcGFzc2VzIG92ZXIgdGhlIHNhbWVcbiAgICogcGVuZGluZyB3YWl0IGNvbGxhcHNlIGludG8gYSBzaW5nbGUgZGVsYXllZCBjb250aW51YXRpb24uXG4gICAqL1xuICB3YWl0VGltZW91dD86IHsgc2Vjb25kczogbnVtYmVyOyBjb3JyZWxhdGlvbklkOiBzdHJpbmcgfTtcbiAgLyoqIFdoZXRoZXIgYSBob29rIGNvbmZsaWN0IHdhcyBkZXRlY3RlZCAoc2hvdWxkIHJlLWludm9rZSBpbW1lZGlhdGVseSkgKi9cbiAgaGFzSG9va0NvbmZsaWN0OiBib29sZWFuO1xuICAvKiogV2hldGhlciBhIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXIgbmVlZHMgdGhlIHdvcmtmbG93IHRvIGNvbnRpbnVlIGltbWVkaWF0ZWx5ICovXG4gIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIG5hdGl2ZSB3b3JrZmxvdyBhdHRyaWJ1dGUgZXZlbnRzIHdlcmUgd3JpdHRlbiBmb3IgcmVwbGF5LiAqL1xuICBoYXNBdHRyaWJ1dGVFdmVudHM6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgc3VzcGVuc2lvbiBjcmVhdGVkIGFueSBob29rIChgaG9va19jcmVhdGVkYCkgZXZlbnRzLiBVbmxpa2VcbiAgICogYGhhc0hvb2tDb25mbGljdGAgLyBgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbmAsIHRoaXMgaXMgdHJ1ZSBldmVuIGZvciBhIHBsYWluXG4gICAqIGZpcmUtYW5kLWZvcmdldCBob29rIHdpdGggbm8gY29uZmxpY3QgYW5kIG5vIGF3YWl0ZXIuIFR1cmJvIG1vZGUgdXNlcyBpdCB0b1xuICAgKiBkZXRlY3QgXCJhIGhvb2sgd2FzIGNyZWF0ZWQgdGhpcyBzdXNwZW5zaW9uXCIgYW5kIHN0b3AgZm9yY2luZyBvcHRpbWlzdGljXG4gICAqIGlubGluZSBzdGFydCAoYSBob29rIGludHJvZHVjZXMgbGF0ZXIgcmVzdW1lIGludm9jYXRpb25zIHRoYXQgY291bGQgcmFjZSkuXG4gICAqL1xuICBoYXNIb29rRXZlbnRzOiBib29sZWFuO1xuICAvKipcbiAgICogV2FsbC1jbG9jayBtcyBzcGVudCBjb21taXR0aW5nIHRoaXMgc3VzcGVuc2lvbidzIGBob29rX2NyZWF0ZWRgIGV2ZW50c1xuICAgKiAoMCB3aGVuIGl0IGNyZWF0ZWQgbm9uZSkuIFRoZSBjYWxsZXIgYWNjdW11bGF0ZXMgdGhpcyBhY3Jvc3MgaXRlcmF0aW9uc1xuICAgKiBhbmQgc3VidHJhY3RzIGl0IGZyb20gdGhlIFRURlMgbGF0ZW5jeSBtZWFzdXJlbWVudCwgc28gdGltZSBzcGVudFxuICAgKiBkdXJhYmx5IGNyZWF0aW5nIHRoZSB1c2VyJ3MgaG9va3MgZG9lc24ndCBjb3VudCBhcyBydW50aW1lIG92ZXJoZWFkLlxuICAgKi9cbiAgaG9va0NyZWF0aW9uTXM6IG51bWJlcjtcbiAgLyoqXG4gICAqIFdoZXRoZXIgc2VyaWFsaXppbmcgdGhpcyBzdXNwZW5zaW9uJ3MgbmV3IHN0ZXAgaW5wdXRzIHdhcyBwYXNzaXZlIChkaWRcbiAgICogbm90IGV4ZWN1dGUgd29ya2Zsb3ctb3duZWQgY29kZSBzdWNoIGFzIGdldHRlcnMsIHByb3h5IHRyYXBzLCBvciBjdXN0b21cbiAgICogc2VyaWFsaXplcnMpLiBgZmFsc2VgIG1lYW5zIHRoZSByZXRhaW5lZCBWTSBtYXkgaGF2ZSBkaXZlcmdlZCBmcm9tIHdoYXRcbiAgICogYSBjb2xkIHJlcGxheSB3b3VsZCBjb21wdXRlLCBzbyB0aGUgY2FsbGVyIG11c3QgZGVtb3RlIHRvIHJlcGxheS5cbiAgICovXG4gIHJldGFpbmVkU3RlcElucHV0c1NhZmU6IGJvb2xlYW47XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUhvb2tFdmVudCh7XG4gIHJ1bklkLFxuICBob29rRXZlbnQsXG4gIHF1ZXVlSXRlbSxcbiAgcmVxdWVzdElkLFxuICBjcmVhdGVFdmVudCxcbn06IHtcbiAgcnVuSWQ6IHN0cmluZztcbiAgaG9va0V2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3Q7XG4gIHF1ZXVlSXRlbTogSG9va0ludm9jYXRpb25RdWV1ZUl0ZW07XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbiAgY3JlYXRlRXZlbnQ6IChcbiAgICBkYXRhOiBDcmVhdGVFdmVudFJlcXVlc3QsXG4gICAgcGFyYW1zPzogQ3JlYXRlRXZlbnRQYXJhbXNcbiAgKSA9PiBQcm9taXNlPEV2ZW50UmVzdWx0Pjtcbn0pOiBQcm9taXNlPHtcbiAgaGFzSG9va0NvbmZsaWN0OiBib29sZWFuO1xuICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBib29sZWFuO1xufT4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUV2ZW50KGhvb2tFdmVudCwge1xuICAgICAgcmVxdWVzdElkLFxuICAgIH0pO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHdvcmxkIHJldHVybmVkIGEgaG9va19jb25mbGljdCBldmVudCBpbnN0ZWFkIG9mIGhvb2tfY3JlYXRlZC5cbiAgICAvLyBUaGUgaG9va19jb25mbGljdCBldmVudCBpcyBzdG9yZWQgaW4gdGhlIGV2ZW50IGxvZyBhbmQgd2lsbCBiZSByZXBsYXllZFxuICAgIC8vIG9uIHRoZSBuZXh0IHdvcmtmbG93IGludm9jYXRpb24sIGNhdXNpbmcgdGhlIGhvb2sncyBwcm9taXNlIHRvIHJlamVjdC5cbiAgICBpZiAocmVzdWx0LmV2ZW50Py5ldmVudFR5cGUgPT09ICdob29rX2NvbmZsaWN0Jykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFzSG9va0NvbmZsaWN0OiB0cnVlLFxuICAgICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBmYWxzZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGhhc0hvb2tDb25mbGljdDogZmFsc2UsXG4gICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBxdWV1ZUl0ZW0uaGFzQ29uZmxpY3RBd2FpdGVyID09PSB0cnVlLFxuICAgIH07XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnSG9vayBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBxdWV1ZUl0ZW0uaGFzQ29uZmxpY3RBd2FpdGVyID09PSB0cnVlLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBob29rJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhhc0hvb2tDb25mbGljdDogZmFsc2UsXG4gICAgICAgIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IGZhbHNlLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoaXNXb3JsZFZhbGlkYXRpb25GYWlsdXJlKGVycikpIHtcbiAgICAgIGNvbnN0IGZhdGFsID0gbmV3IEZhdGFsRXJyb3IoXG4gICAgICAgIGBjcmVhdGVIb29rIGZhaWxlZCBXb3JsZCB2YWxpZGF0aW9uOiAke1xuICAgICAgICAgIGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKVxuICAgICAgICB9YFxuICAgICAgKTtcbiAgICAgIGZhdGFsLmNhdXNlID0gZXJyO1xuICAgICAgdGhyb3cgZmF0YWw7XG4gICAgfVxuXG4gICAgdGhyb3cgZXJyO1xuICB9XG59XG5cbi8qKlxuICogSGFuZGxlcyBhIHdvcmtmbG93IHN1c3BlbnNpb24gYnkgcHJvY2Vzc2luZyBhbGwgcGVuZGluZyBvcGVyYXRpb25zIChob29rcywgc3RlcHMsIHdhaXRzKS5cbiAqIENyZWF0ZXMgZXZlbnRzIGZvciBhbGwgb3BlcmF0aW9ucyBidXQgZG9lcyBOT1QgcXVldWUgc3RlcCBtZXNzYWdlczsgcmV0dXJucyB0aGUgcGVuZGluZ1xuICogc3RlcHMgc28gdGhlIGNhbGxlciBjYW4gZGVjaWRlIHdoaWNoIHRvIGV4ZWN1dGUgaW5saW5lIHZzIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gKlxuICogUHJvY2Vzc2luZyBvcmRlcjpcbiAqIDEuIEhvb2tzIGFyZSBwcm9jZXNzZWQgZmlyc3QgdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnMgd2l0aCB3ZWJob29rIHJlY2VpdmVyc1xuICogMi4gU3RlcCBldmVudHMgYW5kIHdhaXQgZXZlbnRzIGFyZSBjcmVhdGVkIGluIHBhcmFsbGVsXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVTdXNwZW5zaW9uKHtcbiAgc3VzcGVuc2lvbixcbiAgd29ybGQsXG4gIHJ1bixcbiAgc3BhbixcbiAgcmVxdWVzdElkLFxuICBldmVudExvZyxcbiAgcnVuUmVhZHlCYXJyaWVyLFxuICByZXBsYXlSZWNvdmVyeVJlcG9ydGVyLFxuICBzdGVwRGlzcGF0Y2gsXG4gIG93bmVyTWVzc2FnZUlkLFxuICBhbGxvd0RlZmVycmVkQmF0Y2hXb3JrLFxufTogU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMpOiBQcm9taXNlPFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0PiB7XG4gIGNvbnN0IHJ1bklkID0gcnVuLnJ1bklkO1xuXG4gIC8vIFR1cmJvIG1vZGU6IGhvbGQgZXZlcnkgd29ybGQgd3JpdGUgYmVsb3cgdW50aWwgdGhlIGJhY2tncm91bmRlZFxuICAvLyBgcnVuX3N0YXJ0ZWRgIGhhcyAqc2V0dGxlZCosIHNvIHdlIG5ldmVyIHdyaXRlIGEgc3RlcC9ob29rL3dhaXQgZXZlbnQgZm9yIGFcbiAgLy8gcnVuIHRoYXQgZG9lcyBub3QgZXhpc3QgeWV0LiBBIG5vLW9wIG91dHNpZGUgdHVyYm8gKGJhcnJpZXIgdW5kZWZpbmVkKSBhbmRcbiAgLy8gb24gdGhlIHB1cmUgaW5saW5lIGhvdCBwYXRoLCB3aGljaCBkZWZlcnMgYWxsIHN0ZXBzIGFuZCB3cml0ZXMgbm90aGluZy5cbiAgLy8gQXdhaXRpbmcgdGhlIHNhbWUgKHVzdWFsbHkgYWxyZWFkeS1zZXR0bGVkKSBwcm9taXNlIG1vcmUgdGhhbiBvbmNlIGlzIGNoZWFwLlxuICAvLyBBIGJhcnJpZXIgcmVqZWN0aW9uIGlzIHN3YWxsb3dlZCBmb3Igb3JkZXJpbmcgb25seTogaWYgYHJ1bl9zdGFydGVkYCB0cnVseVxuICAvLyBmYWlsZWQgdGhlIHJ1biBkb2VzIG5vdCBleGlzdCwgc28gdGhlIHN1YnNlcXVlbnQgd3JpdGUgc3VyZmFjZXMgdGhlIHJlYWxcbiAgLy8gZXJyb3IgKHJ1biBub3QgZm91bmQgLyBnb25lKSBhbmQgdGhlIG1lc3NhZ2UgcmVkZWxpdmVycy5cbiAgY29uc3QgZW5zdXJlUnVuUmVhZHkgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgaWYgKHJ1blJlYWR5QmFycmllcikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgcnVuUmVhZHlCYXJyaWVyO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIGludGVudGlvbmFsOiBvcmRlcmluZyBiYXJyaWVyIG9ubHksIHNlZSBhYm92ZS5cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEF3YWl0IGV2ZXJ5IG9wZXJhdGlvbiBpbiBhIHN1c3BlbnNpb24gcGhhc2UgYmVmb3JlIGxldHRpbmcgYSBmYWlsdXJlXG4gICAqIGVzY2FwZSwgcHJlZmVycmluZyBhIHN0YWxlLXNuYXBzaG90ICg0MTIpIHJlamVjdGlvbiB3aGVuIG9uZSBvY2N1cnJlZC5cbiAgICpcbiAgICogYFByb21pc2UuYWxsYCByZWplY3RzIGFzIHNvb24gYXMgb25lIG9wZXJhdGlvbiBkb2VzIGFuZCBsZWF2ZXMgaXRzIHNpYmxpbmdzXG4gICAqIGluIGZsaWdodC4gVGhhdCBtYXR0ZXJzIGZvciBhIDQxMjogdGhlIGNhbGxlciByZWFjdHMgYnkgcmVsb2FkaW5nIHRoZSBldmVudFxuICAgKiBsb2cgYW5kIHJlc3RhcnRpbmcgdGhlIHJlcGxheSwgc28gYSBzaWJsaW5nIGNyZWF0ZSB0aGF0IGxhbmRzIGFmdGVyIHRoZVxuICAgKiByZWplY3Rpb24gZXNjYXBlZCBjb21taXRzIGFuIGV2ZW50IHdob3NlIGNvcnJlbGF0aW9uIGlkIGNhbWUgZnJvbSB0aGVcbiAgICogYWJhbmRvbmVkIHJlcGxheSdzIHNlZWRlZCBzZXF1ZW5jZSAoYW4gZXZlbnQgdGhlIGZyZXNoIHJlcGxheSBuZXZlclxuICAgKiBwcm9kdWNlcyksIGFuZCBpdCByYWNlcyB0aGUgcmVzdGFydCdzIHJlbG9hZCB3aGlsZSBkb2luZyBzby4gU2V0dGxpbmcgZmlyc3RcbiAgICogbWFrZXMgdGhpcyBwaGFzZSdzIHdyaXRlIHNldCBmaW5hbCBiZWZvcmUgdGhlIGNhbGxlciBhY3RzIG9uIHRoZSBmYWlsdXJlLlxuICAgKiBJdCBtaXJyb3JzIHRoZSBydW50aW1lJ3MgaW5saW5lIHN0ZXAgY2xhaW0sIHdoaWNoIHNldHRsZXMgdGhlIGluLWZsaWdodFxuICAgKiBzdGVwIGV4ZWN1dGlvbnMgYmVmb3JlIGVzY2FsYXRpbmcgYSA0MTIuXG4gICAqXG4gICAqIEEgNDEyIGlzIHByZWZlcnJlZCBvdmVyIGFueSBvdGhlciByZWplY3Rpb24gaW4gdGhlIHNhbWUgcGhhc2UgYmVjYXVzZSBpdFxuICAgKiBoYXMgYSBkZWZpbmVkLCBjaGVhcCByZWNvdmVyeSAocmVwbGF5IGZyb20gYSBjb3JyZWN0ZWQgbG9nKSB3aGlsZSB0aGVcbiAgICogb3RoZXJzIGRvIG5vdC4gQSBkZXRlcm1pbmlzdGljIGZhaWx1cmUgc3VjaCBhcyBhbiBhdHRyaWJ1dGUtdmFsaWRhdGlvblxuICAgKiBgRmF0YWxFcnJvcmAgcmVjdXJzIG9uIHRoZSByZXN0YXJ0IGFuZCBmYWlscyB0aGUgcnVuIHRoZW4sIGF0IHRoZSBjb3N0IG9mXG4gICAqIG9uZSBleHRyYSByZXBsYXkuXG4gICAqL1xuICBjb25zdCBzZXR0bGVQaGFzZSA9IGFzeW5jIChvcHM6IFByb21pc2U8dW5rbm93bj5bXSk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGNvbnN0IHJlYXNvbnMgPSAoYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKG9wcykpXG4gICAgICAuZmlsdGVyKChyKTogciBpcyBQcm9taXNlUmVqZWN0ZWRSZXN1bHQgPT4gci5zdGF0dXMgPT09ICdyZWplY3RlZCcpXG4gICAgICAubWFwKChyKSA9PiByLnJlYXNvbik7XG4gICAgaWYgKHJlYXNvbnMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgdGhyb3cgcmVhc29ucy5maW5kKChyKSA9PiBQcmVjb25kaXRpb25GYWlsZWRFcnJvci5pcyhyKSkgPz8gcmVhc29uc1swXTtcbiAgfTtcblxuICAvLyBFdmVyeSBzdXNwZW5zaW9uIHdyaXRlIGNhcnJpZXMgcmVwbGF5LXJlY292ZXJ5IHRlbGVtZXRyeSBvbiB0aGUgZmlyc3Qgb25lXG4gIC8vIHRoYXQgY29tbWl0cyBhZnRlciByZXBsYXkgcmVjb3ZlcmVkLiBBbGwgc3VzcGVuc2lvbiBldmVudHMgYXJlXG4gIC8vIG5vbi1ydW5fY3JlYXRlZCBldmVudHMgb24gdGhpcyBydW4ncyBgcnVuSWRgLlxuICBjb25zdCByZXBvcnRlciA9IHJlcGxheVJlY292ZXJ5UmVwb3J0ZXIgPz8gUmVwbGF5UmVjb3ZlcnlSZXBvcnRlci5pbmVydCgpO1xuICBjb25zdCBjcmVhdGVFdmVudCA9IChkYXRhOiBDcmVhdGVFdmVudFJlcXVlc3QsIHBhcmFtcz86IENyZWF0ZUV2ZW50UGFyYW1zKSA9PlxuICAgIHJlcG9ydGVyLndpdGhFdmVudENyZWF0ZShwYXJhbXMsIChwKSA9PlxuICAgICAgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwgZGF0YSwgcClcbiAgICApO1xuICAvLyBBZGRzIHRoZSBvcHRpbWlzdGljLWNvbmN1cnJlbmN5IGd1YXJkIHdoZW4gdGhlIGNhbGxlciBzdXBwbGllZCBhIGxvYWRlZFxuICAvLyBldmVudCBsb2c7IHdpdGhvdXQgb25lIGl0IGNyZWF0ZXMgZGlyZWN0bHkgKGNhbGxlcnMgd2l0aCBubyByZXBsYXlcbiAgLy8gc25hcHNob3QsIGUuZy4gdGVzdHMpLiBBIHN0YWxlICg0MTIpIHJlamVjdGlvbiBwcm9wYWdhdGVzIHRvIHRoZSBjYWxsZXIsXG4gIC8vIHdoaWNoIHJlc3RhcnRzIHRoZSByZXBsYXkgZnJvbSBhIGNvcnJlY3RlZCBsb2cuIEl0IGlzIG5vdCByZXRyaWVkIGhlcmUsXG4gIC8vIGJlY2F1c2UgdGhlIGV2ZW50J3MgY29ycmVsYXRpb24gaWQgd2FzIG1pbnRlZCBieSAqdGhpcyogcmVwbGF5J3Mgc2VlZGVkXG4gIC8vIHNlcXVlbmNlLCBzbyByZS1jb21taXR0aW5nIGl0IGFnYWluc3QgYSBjb3JyZWN0ZWQgbG9nIHdvdWxkIHBlcnNpc3QgYW5cbiAgLy8gZXZlbnQgbm8gY29ycmVjdCByZXBsYXkgcHJvZHVjZXMuXG4gIGxldCByZXBvcnRlZEV2ZW50cyA9IDA7XG4gIGNvbnN0IGNyZWF0ZUd1YXJkZWQ6IEV2ZW50Q3JlYXRvciA9IGFzeW5jIChkYXRhLCBwYXJhbXMpID0+IHtcbiAgICBpZiAoIWV2ZW50TG9nKSB7XG4gICAgICByZXR1cm4gY3JlYXRlRXZlbnQoZGF0YSwgcGFyYW1zKTtcbiAgICB9XG4gICAgY29uc3QgbG9nID0gZXZlbnRMb2c7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlRXZlbnQoZGF0YSwge1xuICAgICAgLi4ucGFyYW1zLFxuICAgICAgLi4uc2xvdFNuYXBzaG90UGFyYW1zKGxvZy5ldmVudHMpLFxuICAgIH0pO1xuICAgIC8vIEJ1bXAtYW5kLXJlcG9ydDogdGhlIHdyaXRlIGxhbmRlZCBhYm92ZSB0aGUgc2xvdCBpdCBhc2tlZCBmb3IsIHNvIHRoZVxuICAgIC8vIHJlcG9ydCBob2xkcyB0aGUgZXZlbnRzIGl0IHdhcyBkZWNpZGVkIHdpdGhvdXQuIEFic29yYmluZyBoZXJlIHJhdGhlclxuICAgIC8vIHRoYW4gYXQgZWFjaCBjYWxsIHNpdGUgbWVhbnMgdGhlIHJlc3Qgb2YgdGhpcyBwaGFzZSdzIHdyaXRlcyAod2hpY2ggcmVhZFxuICAgIC8vIHRoZSBzYW1lIGFycmF5IHRvIGJ1aWxkIHRoZWlyIG93biBzbmFwc2hvdCkgYXNrIGZvciBhIHNsb3QgYWJvdmUgdGhlbSxcbiAgICAvLyBhbmQgdGhlIHJlcGxheSB0aGF0IHJlc3VtZXMgZnJvbSB0aGlzIGxvZyBzZWVzIHRoZW0gd2l0aG91dCBhIHJlbG9hZC5cbiAgICBjb25zdCByZXBvcnQgPSBhYnNvcmJTa2lwcGVkU2xvdFJlcG9ydChsb2cuZXZlbnRzLCByZXN1bHQpO1xuICAgIHJlcG9ydGVkRXZlbnRzICs9IHJlcG9ydC5hZGRlZDtcbiAgICBpZiAocmVwb3J0LnRydW5jYXRlZCkge1xuICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnRHJvcHBlZCBhIHRydW5jYXRlZCBza2lwcGVkLXNsb3QgcmVwb3J0Jywge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgZXZlbnRUeXBlOiBkYXRhLmV2ZW50VHlwZSxcbiAgICAgICAgZXZlbnRJZDogcmVzdWx0LmV2ZW50Py5ldmVudElkLFxuICAgICAgICBvZmZlcmVkOiByZXBvcnQub2ZmZXJlZCxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAocmVwb3J0LmFkZGVkID4gMCkge1xuICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnU3VzcGVuc2lvbiB3cml0ZSBza2lwcGVkIG9jY3VwaWVkIHNsb3RzJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgZXZlbnRUeXBlOiBkYXRhLmV2ZW50VHlwZSxcbiAgICAgICAgZXZlbnRJZDogcmVzdWx0LmV2ZW50Py5ldmVudElkLFxuICAgICAgICByZXBvcnRlZDogcmVwb3J0LmFkZGVkLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG4gIC8vIFNlcGFyYXRlIHF1ZXVlIGl0ZW1zIGJ5IHR5cGVcbiAgY29uc3Qgc3RlcEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3N0ZXAnXG4gICk7XG4gIGNvbnN0IGFsbEhvb2tJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBIb29rSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdob29rJ1xuICApO1xuICBjb25zdCB3YWl0SXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgV2FpdEludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnd2FpdCdcbiAgKTtcbiAgY29uc3QgYXR0cmlidXRlSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgQXR0cmlidXRlSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdhdHRyaWJ1dGUnXG4gICk7XG5cbiAgY29uc3QgaG9va3NOZWVkaW5nQ3JlYXRpb24gPSBhbGxIb29rSXRlbXMuZmlsdGVyKFxuICAgIChpdGVtKSA9PiAhaXRlbS5oYXNDcmVhdGVkRXZlbnRcbiAgKTtcblxuICAvLyBHcm91cCBob29rIGl0ZW1zIHRoYXQgbmVlZCB3b3JrIGJ5IHRva2VuLCBwcmVzZXJ2aW5nIHF1ZXVlLWluc2VydGlvblxuICAvLyAod29ya2Zsb3cgY29kZSkgb3JkZXIgd2l0aGluIGVhY2ggdG9rZW4uIE9wZXJhdGlvbnMgb24gb25lIHRva2VuIG11c3RcbiAgLy8gYXBwbHkgaW4gY29kZSBvcmRlcjogYSBkaXNwb3NlKCkgb2YgYW4gZWFybGllciBob29rIHJlbGVhc2VzIHRoZSB0b2tlblxuICAvLyBiZWZvcmUgYSBsYXRlciBzYW1lLXRva2VuIGhvb2sncyBjcmVhdGlvbiBpcyB2YWxpZGF0ZWQgKG90aGVyd2lzZSB0aGVcbiAgLy8gbmV3IGhvb2sgcmVjb3JkcyBhIHNwdXJpb3VzIGhvb2tfY29uZmxpY3QgYWdhaW5zdCB0aGUgcnVuJ3Mgb3duXG4gIC8vIGRpc3Bvc2VkIGhvb2spLCB3aGlsZSBhIGhvb2sgY3JlYXRlZCBhbmQgZGlzcG9zZWQgd2l0aGluIHRoZSBzYW1lXG4gIC8vIHN1c3BlbnNpb24gaXMgc3RpbGwgY3JlYXRlZCBiZWZvcmUgaXQgaXMgZGlzcG9zZWQuIERpZmZlcmVudCB0b2tlbnNcbiAgLy8gaGF2ZSBubyBjbGFpbSBpbnRlcmFjdGlvbiwgc28gdG9rZW4gZ3JvdXBzIGFyZSBwcm9jZXNzZWQgaW4gcGFyYWxsZWwuXG4gIGNvbnN0IGhvb2tJdGVtc0J5VG9rZW4gPSBuZXcgTWFwPHN0cmluZywgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW1bXT4oKTtcbiAgZm9yIChjb25zdCBpdGVtIG9mIGFsbEhvb2tJdGVtcykge1xuICAgIGlmIChpdGVtLmhhc0NyZWF0ZWRFdmVudCAmJiAhaXRlbS5kaXNwb3NlZCkge1xuICAgICAgY29udGludWU7IC8vIGFscmVhZHkgY29tbWl0dGVkIGFuZCBzdGlsbCBsaXZlOiBub3RoaW5nIHRvIGRvXG4gICAgfVxuICAgIGNvbnN0IGdyb3VwID0gaG9va0l0ZW1zQnlUb2tlbi5nZXQoaXRlbS50b2tlbik7XG4gICAgaWYgKGdyb3VwKSB7XG4gICAgICBncm91cC5wdXNoKGl0ZW0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBob29rSXRlbXNCeVRva2VuLnNldChpdGVtLnRva2VuLCBbaXRlbV0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuXG4gIGNvbnN0IHJhd0tleSA9IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihydW4pO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgLy8gR2F0ZSBwYXlsb2FkIGNvbXByZXNzaW9uIG9uIHRoZSBydW4ncyBzcGVjVmVyc2lvbi5cbiAgY29uc3QgY29tcHJlc3Npb24gPVxuICAgIChydW4uc3BlY1ZlcnNpb24gPz8gMCkgPj0gU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGRpc3Bvc2VIb29rKFxuICAgIHF1ZXVlSXRlbTogSG9va0ludm9jYXRpb25RdWV1ZUl0ZW1cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaG9va0Rpc3Bvc2VkRXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgIGV2ZW50VHlwZTogJ2hvb2tfZGlzcG9zZWQnIGFzIGNvbnN0LFxuICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICBldmVudERhdGE6IHtcbiAgICAgICAgdG9rZW46IHF1ZXVlSXRlbS50b2tlbixcbiAgICAgIH0sXG4gICAgfTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZChob29rRGlzcG9zZWRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIC8vIEhvb2sgd2FzIGFscmVhZHkgZGlzcG9zZWQgYnkgYSBjb25jdXJyZW50IGludm9jYXRpb24sIHNhZmUgdG8gc2tpcFxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ0hvb2sgYWxyZWFkeSBkaXNwb3NlZCwgc2tpcHBpbmcgZHVwbGljYXRlIGRpc3Bvc2FsJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vayBkaXNwb3NhbCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoSG9va05vdEZvdW5kRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAvLyBIb29rIG1heSBoYXZlIGFscmVhZHkgYmVlbiBkaXNwb3NlZCBvciBuZXZlciBjcmVhdGVkXG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnSG9vayBub3QgZm91bmQgZm9yIGRpc3Bvc2FsLCBjb250aW51aW5nJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBQcm9jZXNzIGhvb2tzIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnMuXG4gIC8vIFRyYWNrIGFueSBob29rIGNvbmZsaWN0cyB0aGF0IG9jY3VyOiB0aGVzZSBhcmUgcmV0dXJuZWQgdG8gdGhlIGNhbGxlclxuICAvLyBzbyB0aGUgVjIgaGFuZGxlciBjYW4gcmUtaW52b2tlIGltbWVkaWF0ZWx5LlxuICBsZXQgaGFzSG9va0NvbmZsaWN0ID0gZmFsc2U7XG4gIGxldCBoYXNBd2FpdGVkSG9va0NyZWF0aW9uID0gZmFsc2U7XG4gIGxldCBob29rQ3JlYXRpb25NcyA9IDA7XG5cbiAgaWYgKGhvb2tJdGVtc0J5VG9rZW4uc2l6ZSA+IDApIHtcbiAgICBjb25zdCBob29rUGhhc2VTdGFydCA9IERhdGUubm93KCk7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBzZXR0bGVQaGFzZShcbiAgICAgIFsuLi5ob29rSXRlbXNCeVRva2VuLnZhbHVlcygpXS5tYXAoYXN5bmMgKGl0ZW1zKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIGl0ZW1zKSB7XG4gICAgICAgICAgbGV0IGNyZWF0aW9uQ29uZmxpY3RlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBob29rTWV0YWRhdGE6IFNlcmlhbGl6ZWREYXRhIHwgdW5kZWZpbmVkID1cbiAgICAgICAgICAgICAgdHlwZW9mIHF1ZXVlSXRlbS5tZXRhZGF0YSA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIDogKChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0ubWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2lvblxuICAgICAgICAgICAgICAgICAgKSkgYXMgU2VyaWFsaXplZERhdGEpO1xuICAgICAgICAgICAgY29uc3QgaG9va0V2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgICAgICAgdG9rZW5SZXRlbnRpb25VbnRpbDogcXVldWVJdGVtLnRva2VuUmV0ZW50aW9uVW50aWwsXG4gICAgICAgICAgICAgICAgbWV0YWRhdGE6IGhvb2tNZXRhZGF0YSxcbiAgICAgICAgICAgICAgICBpc1dlYmhvb2s6IHF1ZXVlSXRlbS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgICAgICAgICAgLi4uKHF1ZXVlSXRlbS5pc1N5c3RlbSAmJiB7IGlzU3lzdGVtOiB0cnVlIH0pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUhvb2tFdmVudCh7XG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBob29rRXZlbnQsXG4gICAgICAgICAgICAgIHF1ZXVlSXRlbSxcbiAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICBjcmVhdGVFdmVudDogY3JlYXRlR3VhcmRlZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaGFzSG9va0NvbmZsaWN0IHx8PSByZXN1bHQuaGFzSG9va0NvbmZsaWN0O1xuICAgICAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbiB8fD0gcmVzdWx0Lmhhc0F3YWl0ZWRIb29rQ3JlYXRpb247XG4gICAgICAgICAgICBjcmVhdGlvbkNvbmZsaWN0ZWQgPSByZXN1bHQuaGFzSG9va0NvbmZsaWN0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIERpc3Bvc2UgYWZ0ZXIgY3JlYXRpb24gZm9yIGhvb2tzIGJvcm4gYW5kIGRpc3Bvc2VkIHdpdGhpbiB0aGlzXG4gICAgICAgICAgLy8gYmF0Y2guIEEgaG9vayB3aG9zZSBjcmVhdGlvbiBjb25mbGljdGVkIHdhcyBuZXZlciBjcmVhdGVkLCBzb1xuICAgICAgICAgIC8vIHRoZXJlIGlzIG5vdGhpbmcgdG8gZGlzcG9zZS5cbiAgICAgICAgICBpZiAocXVldWVJdGVtLmRpc3Bvc2VkICYmICFjcmVhdGlvbkNvbmZsaWN0ZWQpIHtcbiAgICAgICAgICAgIGF3YWl0IGRpc3Bvc2VIb29rKHF1ZXVlSXRlbSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gICAgaG9va0NyZWF0aW9uTXMgPSBEYXRlLm5vdygpIC0gaG9va1BoYXNlU3RhcnQ7XG4gIH1cblxuICAvLyBQcm9jZXNzIGFib3J0IHJlcXVlc3RzOiByZXN1bWUgdGhlIGhvb2sgd2l0aCBhYm9ydCBwYXlsb2FkIGFuZCB3cml0ZSBzdHJlYW0gcGFja2V0XG4gIGNvbnN0IGhvb2tzTmVlZGluZ0Fib3J0ID0gYWxsSG9va0l0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSkgPT4gaXRlbS5hYm9ydFJlcXVlc3RlZCAmJiAhaXRlbS5kaXNwb3NlZFxuICApO1xuXG4gIGlmIChob29rc05lZWRpbmdBYm9ydC5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBzZXR0bGVQaGFzZShcbiAgICAgIGhvb2tzTmVlZGluZ0Fib3J0Lm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gRGVoeWRyYXRlIHRoZSBhYm9ydCBwYXlsb2FkIGZvciBzdG9yYWdlXG4gICAgICAgICAgY29uc3QgYWJvcnRQYXlsb2FkID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgIHsgYWJvcnRlZDogdHJ1ZSwgcmVhc29uOiBxdWV1ZUl0ZW0uYWJvcnRSZWFzb24gfSxcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gQ3JlYXRlIGhvb2tfcmVjZWl2ZWQgZXZlbnQgd2l0aCBhYm9ydCBwYXlsb2FkXG4gICAgICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZCh7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdob29rX3JlY2VpdmVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgICAgIHBheWxvYWQ6IGFib3J0UGF5bG9hZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBXcml0ZSBzdHJlYW0gY2FuY2VsbGF0aW9uIHBhY2tldCBmb3IgcmVhbC10aW1lIHN0ZXAgcHJvcGFnYXRpb24uXG4gICAgICAgICAgLy8gUmV1c2UgdGhlIHNhbWUgZGVoeWRyYXRlZCBwYXlsb2FkIGFzIHRoZSBob29rIGV2ZW50IHNvIHRoZSByZWFzb25cbiAgICAgICAgICAvLyByb3VuZC10cmlwcyB0aHJvdWdoIGBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzYCAvIGBoeWRyYXRlU3RlcEFyZ3VtZW50c2BcbiAgICAgICAgICAvLyAoaGFuZGxlcyBET01FeGNlcHRpb24sIGN1c3RvbSBlcnJvcnMsIGVuY3J5cHRpb24sIGV0Yy4pIGluc3RlYWQgb2ZcbiAgICAgICAgICAvLyBiYXJlIEpTT04uc3RyaW5naWZ5IHdoaWNoIGxvc2VzIHR5cGUgaW5mb3JtYXRpb24gYW5kIGRyb3BzIHVuZGVmaW5lZC5cbiAgICAgICAgICAvLyBzdHJlYW1OYW1lIGlzIHNldCBvbiB0aGUgcXVldWUgaXRlbSBhdCBjb250cm9sbGVyIGNvbnN0cnVjdGlvbiB0aW1lXG4gICAgICAgICAgLy8gKHNlZSB3b3JrZmxvdy9hYm9ydC1jb250cm9sbGVyLnRzKS5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtTmFtZSA9IGdldEFib3J0U3RyZWFtSWRGcm9tVG9rZW4ocXVldWVJdGVtLnRva2VuKTtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMud3JpdGUoXG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBzdHJlYW1OYW1lLFxuICAgICAgICAgICAgICBhYm9ydFBheWxvYWQgYXMgVWludDhBcnJheVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMuY2xvc2UocnVuSWQsIHN0cmVhbU5hbWUpO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLy8gQmVzdC1lZmZvcnQgc3RyZWFtIHdyaXRlOiBob29rIGV2ZW50IHByb3ZpZGVzIHRoZSBkdXJhYmxlIGZhbGxiYWNrXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAnRmFpbGVkIHRvIHdyaXRlIGFib3J0IHN0cmVhbSBwYWNrZXQsIGhvb2sgZXZlbnQgd2lsbCBwcm92aWRlIGZhbGxiYWNrJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBhYm9ydCcsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLy8gQ3JlYXRlIHN0ZXAgZXZlbnRzIGZvciBzdGVwcyB0aGF0IGRvbid0IGhhdmUgdGhlbSB5ZXQuXG4gIC8vIFVubGlrZSBWMSwgd2UgZG8gTk9UIHF1ZXVlIHN0ZXAgbWVzc2FnZXMgZnJvbSBoZXJlOiB0aGUgY2FsbGVyXG4gIC8vIGRlY2lkZXMgd2hpY2ggc3RlcHMgdG8gZXhlY3V0ZSBpbmxpbmUgdnMuIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gIC8vIFdhaXQgZXZlbnRzIGFyZSBhbHNvIGNyZWF0ZWQgaW4gcGFyYWxsZWwgYmVsb3cuXG4gIGNvbnN0IHN0ZXBzTmVlZGluZ0NyZWF0aW9uID0gbmV3IFNldChcbiAgICBzdGVwSXRlbXNcbiAgICAgIC5maWx0ZXIoKHF1ZXVlSXRlbSkgPT4gIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpXG4gICAgICAubWFwKChxdWV1ZUl0ZW0pID0+IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKVxuICApO1xuXG4gIC8vIENvcnJlbGF0aW9uIElEcyBmb3Igd2hpY2ggVEhJUyBzdXNwZW5zaW9uIGNhbGwgYWN0dWFsbHkgd3JvdGUgdGhlXG4gIC8vIHN0ZXBfY3JlYXRlZCBldmVudC4gUG9wdWxhdGVkIGJ5IHRoZSBvcHMgYmVsb3cgYWZ0ZXIgYSBzdWNjZXNzZnVsXG4gIC8vIGV2ZW50cy5jcmVhdGUsIHVzZWQgYnkgdGhlIGNhbGxlciB0byBjbGFpbSBvd25lcnNoaXAgYW5kIGF2b2lkXG4gIC8vIHJhY2luZyB3aXRoIGNvbmN1cnJlbnQgaGFuZGxlcnMgb24gc3RlcCBleGVjdXRpb24uXG4gIGNvbnN0IGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAvLyBDb3JyZWxhdGlvbiBJRHMgb2Ygc3RlcHMgZmluYWxpemVkIGFzIGZhaWxlZCBiZWNhdXNlIHRoZWlyIGFyZ3VtZW50c1xuICAvLyByZWZ1c2VkIHRvIHNlcmlhbGl6ZTogc2VlIGZpbmFsaXplVW5zZXJpYWxpemFibGVTdGVwIGJlbG93LlxuICBjb25zdCBmYWlsZWRTdGVwQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAvKipcbiAgICogQSBzdGVwIHdob3NlIGFyZ3VtZW50cyBmYWlsIHRvIHNlcmlhbGl6ZSBpcyBkZXRlcm1pbmlzdGljOiBldmVyeSByZXBsYXlcbiAgICogcmUtZGVyaXZlcyB0aGUgc2FtZSB1bnNlcmlhbGl6YWJsZSB2YWx1ZSwgc28gcmVkZWxpdmVyaW5nIHRoZVxuICAgKiBvcmNoZXN0cmF0b3IgbWVzc2FnZSBjYW4gbmV2ZXIgc3VjY2VlZC4gSW5zdGVhZCBvZiByZWplY3RpbmcgdGhlIHdob2xlXG4gICAqIHN1c3BlbnNpb24gKHdoaWNoIGZhaWxzIHRoZSBydW4gZnJvbSB0aGUgb3V0c2lkZSwgd2hlcmUgbm8gdXNlciBjb2RlIGNhblxuICAgKiBvYnNlcnZlIGl0KSwgdHJlYXQgaXQgZXhhY3RseSBsaWtlIGEgc3RlcC1ib2R5IGZhaWx1cmU6IHdyaXRlXG4gICAqIGBzdGVwX2NyZWF0ZWRgIHdpdGggYSBwbGFjZWhvbGRlciBpbnB1dCAoZXZlcnkgV29ybGQgcmVxdWlyZXMgdGhlIHN0ZXBcbiAgICogZW50aXR5IHRvIGV4aXN0IGJlZm9yZSBhIHRlcm1pbmFsIHN0ZXAgZXZlbnQsIGFuZCB0aGUgcmVhbCBpbnB1dCBpc1xuICAgKiBwcmVjaXNlbHkgd2hhdCByZWZ1c2VkIHRvIHNlcmlhbGl6ZSkgZm9sbG93ZWQgYnkgYHN0ZXBfZmFpbGVkYCBjYXJyeWluZ1xuICAgKiB0aGUgU2VyaWFsaXphdGlvbkVycm9yLiBUaGUgbmV4dCByZXBsYXkgcmVqZWN0cyB0aGUgc3RlcCdzIHByb21pc2Ugd2l0aFxuICAgKiBpdCwgc28gYSB0cnkvY2F0Y2ggYXJvdW5kIHRoZSBzdGVwIGNhbGwgb2JzZXJ2ZXMgdGhlIGVycm9yOyB1bmNhdWdodCwgaXRcbiAgICogcHJvcGFnYXRlcyBvdXQgb2YgdGhlIHdvcmtmbG93IGJvZHkgYW5kIGZhaWxzIHRoZSBydW4gYXMgYSBVU0VSX0VSUk9SLFxuICAgKiB3aXRob3V0IGJ1cm5pbmcgcXVldWUgcmVkZWxpdmVyaWVzIGVpdGhlciB3YXkuXG4gICAqL1xuICBjb25zdCBmaW5hbGl6ZVVuc2VyaWFsaXphYmxlU3RlcCA9IGFzeW5jIChcbiAgICBxdWV1ZUl0ZW06IFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtLFxuICAgIGVycm9yOiBTZXJpYWxpemF0aW9uRXJyb3JcbiAgKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgJ1N0ZXAgYXJndW1lbnRzIGZhaWxlZCB0byBzZXJpYWxpemU7IGZhaWxpbmcgdGhlIHN0ZXAgc28gdGhlICcgK1xuICAgICAgICAnd29ya2Zsb3cgY2FuIG9ic2VydmUgdGhlIGVycm9yJyxcbiAgICAgIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICBzdGVwTmFtZTogcXVldWVJdGVtLnN0ZXBOYW1lLFxuICAgICAgICBlcnJvcjogZXJyb3IubWVzc2FnZSxcbiAgICAgIH1cbiAgICApO1xuICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgLy8gTWFya2VyIHBsYWNlaG9sZGVyIChub3QgZW1wdHkgYXJncyk6IGJ5dGUtaWRlbnRpY2FsLXRvLXplcm8tYXJncyB3b3VsZFxuICAgIC8vIG1ha2UgYHdvcmtmbG93IGluc3BlY3Qgc3RlcHNgIHNob3cgXCJubyBhcmd1bWVudHNcIiBmb3IgdGhlIG9uZSBzdGVwXG4gICAgLy8gd2hvc2UgZW50aXJlIHByb2JsZW0gd2FzIGl0cyBhcmd1bWVudHMuXG4gICAgY29uc3QgcGxhY2Vob2xkZXJJbnB1dCA9IChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgdW5zZXJpYWxpemFibGVTdGVwSW5wdXRQbGFjZWhvbGRlcigpLFxuICAgICAgcnVuSWQsXG4gICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgc3VzcGVuc2lvbi5nbG9iYWxUaGlzLFxuICAgICAgZmFsc2UsXG4gICAgICBjb21wcmVzc2lvblxuICAgICkpIGFzIFNlcmlhbGl6ZWREYXRhO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKFxuICAgICAgICB7XG4gICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICBzdGVwTmFtZTogcXVldWVJdGVtLnN0ZXBOYW1lLFxuICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBydW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgaW5wdXQ6IHBsYWNlaG9sZGVySW5wdXQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChjcmVhdGVFcnIpIHtcbiAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGNyZWF0ZUVycikpIHtcbiAgICAgICAgLy8gQSBjb25jdXJyZW50IGhhbmRsZXIgYWxyZWFkeSBjcmVhdGVkIHRoZSBzdGVwOiB0aGUgZmFpbHVyZSBpc1xuICAgICAgICAvLyBkZXRlcm1pbmlzdGljLCBzbyBpdCBpcyByYWNpbmcgdG93YXJkIHRoZSBzYW1lIHN0ZXBfZmFpbGVkIGJlbG93LlxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1N0ZXAgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgbWVzc2FnZTogY3JlYXRlRXJyLm1lc3NhZ2UsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoY3JlYXRlRXJyKSkge1xuICAgICAgICAvLyBSdW4gYWxyZWFkeSBmaW5pc2hlZDogbm90aGluZyB0byBvYnNlcnZlIHRoZSBmYWlsdXJlLlxuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBjcmVhdGVFcnI7XG4gICAgICB9XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKFxuICAgICAgICB7XG4gICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnIGFzIGNvbnN0LFxuICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAvLyBUaGUgZXJyb3IgaXRzZWxmIGlzIGEgcGxhaW4gV29ya2Zsb3dFcnJvciAobmFtZSwgbWVzc2FnZSB3aXRoXG4gICAgICAgICAgICAvLyBmcmFtZWQgaGludCwgY2F1c2UgY2hhaW4pLCBzZXJpYWxpemFibGUgZXZlbiB0aG91Z2ggdGhlIHN0ZXBcbiAgICAgICAgICAgIC8vIGlucHV0IHdhcyBub3QuIEVycm9yIGRldGVjdGlvbiBpcyByZWFsbS1pbmRlcGVuZGVudFxuICAgICAgICAgICAgLy8gKHR5cGVzLmlzTmF0aXZlRXJyb3IpLCBzbyB0aGUgaG9zdC1jcmVhdGVkIGVycm9yIHNlcmlhbGl6ZXNcbiAgICAgICAgICAgIC8vIHRoZSBzYW1lIHVuZGVyIGVpdGhlciBnbG9iYWw7IHRoZSBWTSBnbG9iYWwgaXMgcGFzc2VkIGZvclxuICAgICAgICAgICAgLy8gY29uc2lzdGVuY3kgd2l0aCBldmVyeSBvdGhlciBkZWh5ZHJhdGlvbiBpbiB0aGlzIGZpbGUgYW5kIHNvXG4gICAgICAgICAgICAvLyBhbnkgVk0tcmVhbG0gdmFsdWVzIGd1ZXN0IGNvZGUgdGhyZXcgaW50byB0aGUgY2F1c2UgY2hhaW5cbiAgICAgICAgICAgIC8vIChnZXR0ZXJzL3Byb3hpZXMgZXhlY3V0ZWQgZHVyaW5nIHRoZSBmYWlsZWQgZGVoeWRyYXRpb24pIGFyZVxuICAgICAgICAgICAgLy8gZGV0ZWN0ZWQgYnkgdGhlIHJlYWxtLXNlbnNpdGl2ZSByZWR1Y2Vycy5cbiAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICAgICksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChmYWlsRXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhmYWlsRXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZmFpbEVycikpIHtcbiAgICAgICAgLy8gU3RlcCBhbHJlYWR5IHRlcm1pbmFsIChhIGNvbmN1cnJlbnQgaGFuZGxlciB3cm90ZSB0aGUgc2FtZVxuICAgICAgICAvLyBkZXRlcm1pbmlzdGljIGZhaWx1cmUpIG9yIHRoZSBydW4gYWxyZWFkeSBmaW5pc2hlZC5cbiAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICdUcmllZCBmYWlsaW5nIHN0ZXAsIGJ1dCBzdGVwIG9yIHJ1biBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBtZXNzYWdlOiBmYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZmFpbEVycjtcbiAgICAgIH1cbiAgICB9XG4gICAgZmFpbGVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgLy8gUmVsZWFzZSB0aGUgaW5saW5lIHNsb3QgYm9va2tlZXBpbmc6IHRoZSBzdGVwIG5ldmVyIHJ1bnMsIHNvIGl0IG11c3RcbiAgICAvLyBub3QgYXBwZWFyIGluIHRoZSByZWJ1aWx0IGBsYXp5SW5saW5lU3RlcHNgLiAoSXRzIHNsb3QgaW4gdGhlIGZpcnN0LU5cbiAgICAvLyBzZWxlY3Rpb24gYW5kIGluIGBpbmxpbmVQYWlyRm9sZEVsaWdpYmxlYCdzIGFyaXRobWV0aWMgd2FzIGNvbnN1bWVkXG4gICAgLy8gYmVmb3JlIGRlaHlkcmF0aW9uIGNvdWxkIHJldmVhbCB0aGUgZmFpbHVyZSwgaW5oZXJlbnQgdG8gc2VsZWN0aW5nXG4gICAgLy8gYmVmb3JlIHNlcmlhbGl6aW5nLCBhbmQgYm91bmRlZCB0byBvbmUgd2FzdGVkIHNsb3Qgb24gYSBwYXNzIHRoYXRcbiAgICAvLyBlbmRzIGluIGEgZm9yY2VkIHJlcGxheSBhbnl3YXkuKVxuICAgIGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcy5kZWxldGUocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpO1xuICB9O1xuXG4gIC8vIFNlcmlhbGl6YXRpb24gYWx3YXlzIHJ1bnMgdGhyb3VnaCB0aGUgb25lIG9yZGluYXJ5IHBhdGggYmVsb3csIHNvIHRoZVxuICAvLyBkdXJhYmxlIGJ5dGVzIGNhbm5vdCBkZXBlbmQgb24gcmV0ZW50aW9uLiBXaGF0IHJldGVudGlvbiBuZWVkcyB0byBrbm93IGlzXG4gIC8vIHdoZXRoZXIgdGhhdCBzZXJpYWxpemF0aW9uICpleGVjdXRlZCogd29ya2Zsb3cgY29kZSAoZ2V0dGVycywgcHJveHlcbiAgLy8gdHJhcHMsIGN1c3RvbSBzZXJpYWxpemVycyk6IHNpZGUgZWZmZWN0cyBhIGNvbGQgcmVwbGF5IHdvdWxkIG5vdFxuICAvLyByZXBlYXQsIHNpbmNlIGEgcmVwbGF5IHNraXBzIGRlaHlkcmF0aW9uIGZvciBhbHJlYWR5LXJlY29yZGVkIHN0ZXBzLlxuICAvLyBUaGUgaGFyZGVuZWQgc2VyaWFsaXplciByZWNvcmRzIGV4YWN0bHkgdGhhdCBpbnRvIHRoaXMgc2luayAoc2VlXG4gIC8vIC4uL3NlcmlhbGl6YXRpb24vaGFyZGVuZWQudHMpOyB3aGVuIGFueSBpbnB1dCBpbiB0aGUgYmF0Y2ggcmVjb3JkcyBhblxuICAvLyBleGVjdXRpb24sIHRoZSBjYWxsZXIgZGVtb3RlcyB0aGUgc2Vzc2lvbiBzbyB0aGUgc2lkZSBlZmZlY3RzIGxhbmQgaW4gYVxuICAvLyBWTSB0aGF0IGlzIGFib3V0IHRvIGJlIGRpc2NhcmRlZCwgZXhhY3RseSBsaWtlIHRoZSBwcmUtcmV0ZW50aW9uXG4gIC8vIHJ1bnRpbWUuXG4gIGNvbnN0IGd1ZXN0Q29kZVN0YXRzOiBHdWVzdENvZGVTdGF0cyA9IHsgZXhlY3V0aW9uczogW10gfTtcblxuICAvLyBMYXp5IGlubGluZSBzdGFydDogZGVmZXIgdGhlIHN0ZXBfY3JlYXRlZCB3cml0ZSBmb3IgdXAgdG9cbiAgLy8gYGdldE1heElubGluZVN0ZXBzKClgIHN0ZXBzIHRoZSBjYWxsZXIgd2lsbCBydW4gaW5saW5lIChpbiBwYXJhbGxlbCkuIEVhY2hcbiAgLy8gc3RlcCBpcyBjcmVhdGVkIG9uIHRoZSBmbHkgYnkgdGhlIGxhenkgYHN0ZXBfc3RhcnRlZGAgZXhlY3V0ZVN0ZXAgc2VuZHNcbiAgLy8gKHNhdmluZyBhIHJvdW5kLXRyaXAgcGVyIHN0ZXApLiBXZSBuZXZlciBkZWZlciB3aGVuIGEgYGhvb2suZ2V0Q29uZmxpY3QoKWBcbiAgLy8gYXdhaXRlciBpcyBwcmVzZW50LCBiZWNhdXNlIGluIHRoYXQgY2FzZSB0aGUgY2FsbGVyIGV4ZWN1dGVzIG5vdGhpbmcgaW5saW5lXG4gIC8vIChpdCByZS1pbnZva2VzIGltbWVkaWF0ZWx5IHRvIHJlc29sdmUgdGhlIGF3YWl0ZXIpLCBzbyBkZWZlcnJpbmcgd291bGRcbiAgLy8gbGVhdmUgdGhlIHN0ZXBzIHVuY3JlYXRlZCBhbmQgdW5xdWV1ZWQuIFdlIHBpY2sgdGhlIGZpcnN0IE4gdW5jcmVhdGVkXG4gIC8vIHN0ZXBzIChtYXRjaGluZyB0aGUgY2FsbGVyJ3MgaW5saW5lLWNhbmRpZGF0ZSBzZWxlY3Rpb24pIGFuZCBkZWh5ZHJhdGVcbiAgLy8gdGhlaXIgaW5wdXQgaGVyZSBzbyBleGVjdXRlU3RlcCBjYW4gc2hpcCBpdCBhcyB0aGUgc3RlcF9zdGFydGVkIHBheWxvYWQuXG4gIGNvbnN0IGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcyA9IG5ldyBTZXQ8c3RyaW5nPihcbiAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uID09PSBmYWxzZVxuICAgICAgPyBzdGVwSXRlbXNcbiAgICAgICAgICAuZmlsdGVyKChpdGVtKSA9PiBzdGVwc05lZWRpbmdDcmVhdGlvbi5oYXMoaXRlbS5jb3JyZWxhdGlvbklkKSlcbiAgICAgICAgICAuc2xpY2UoMCwgZ2V0TWF4SW5saW5lU3RlcHMoKSlcbiAgICAgICAgICAubWFwKChpdGVtKSA9PiBpdGVtLmNvcnJlbGF0aW9uSWQpXG4gICAgICA6IFtdXG4gICk7XG4gIC8vIENvbGxlY3RlZCBieSBjb3JyZWxhdGlvbklkIGJlY2F1c2UgdGhlIHBlci1zdGVwIG9wcyBiZWxvdyBydW4gY29uY3VycmVudGx5XG4gIC8vIGFuZCBzZXR0bGUgb3V0IG9mIG9yZGVyLiBXZSByZWJ1aWxkIHRoZSBhcnJheSBpbiBkZXRlcm1pbmlzdGljXG4gIC8vIGBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHNgIG9yZGVyICh0aGUgb3JkZXJlZCBzbGljZSBhYm92ZSkgYWZ0ZXIgdGhlIG9wc1xuICAvLyBzZXR0bGUsIHNvIHRoZSBpbmxpbmUgYmF0Y2ggb3JkZXIgaXMgc3RhYmxlIHJlZ2FyZGxlc3Mgb2YgZGVoeWRyYXRpb24gdGltaW5nLlxuICBjb25zdCBsYXp5SW5saW5lQnlDb3JyZWxhdGlvbklkID0gbmV3IE1hcDxcbiAgICBzdHJpbmcsXG4gICAgU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHRbJ2xhenlJbmxpbmVTdGVwcyddW251bWJlcl1cbiAgPigpO1xuXG4gIGNvbnN0IG9wczogUHJvbWlzZTx2b2lkPltdID0gW107XG5cbiAgLy8gQ29ycmVsYXRpb24gSURzIG9mIHN0ZXBzIHdob3NlIHN0ZXAtZXhlY3V0aW9uIHF1ZXVlIG1lc3NhZ2Ugd2FzIGFscmVhZHlcbiAgLy8gcHVibGlzaGVkIGJ5IHRoZSByZXNpbGllbnQtZGlzcGF0Y2ggb3BzIGJlbG93IChhbG9uZ3NpZGUgdGhlIHN0ZXBfY3JlYXRlZFxuICAvLyB3cml0ZSkuIFJlcG9ydGVkIHRvIHRoZSBjYWxsZXIgc28gaXRzIGRpc3BhdGNoIHBhc3Mgc2tpcHMgdGhlbS5cbiAgY29uc3QgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgLy8gUmVzaWxpZW50IHN0ZXAgZGlzcGF0Y2ggZWxpZ2liaWxpdHksIHNoYXJlZCBieSBldmVyeSBzdGVwIG9wIGJlbG93ICh0aGVcbiAgLy8gcGVyLXN0ZXAgaW5wdXQtc2l6ZSBjaGVjayBpcyBhcHBsaWVkIGluc2lkZSB0aGUgb3ApLiBBbGwgbXVzdCBob2xkOlxuICAvL1xuICAvLyAgLSBUaGUgY2FsbGVyIHByb3ZpZGVkIGEgZGlzcGF0Y2ggdGFyZ2V0IChgc3RlcERpc3BhdGNoYCk6IHRlcm1pbmFsXG4gIC8vICAgIGRyYWlucyBhbmQgb3RoZXIgY3JlYXRlLW9ubHkgY2FsbGVycyBuZXZlciBxdWV1ZS5cbiAgLy8gIC0gVGhlIGZlYXR1cmUgaXMgZW5hYmxlZCAoYFdPUktGTE9XX1JFU0lMSUVOVF9TVEVQX0RJU1BBVENIYCBvcHQtaW4pLlxuICAvLyAgICBJdCBpcyBvZmYgYnkgZGVmYXVsdCBiZWNhdXNlIHRoZSBwdWJsaXNoIHJhY2VzIHRoZSBjcmVhdGUncyB2ZXJkaWN0LFxuICAvLyAgICBhbmQgYSBjcmVhdGUgY2FuIGNvbWUgYmFjayByZWZ1c2VkOiBhcyBhIGR1cGxpY2F0ZSB0aGUgcmVwbGF5IHNob3VsZFxuICAvLyAgICBzdG9wIHB1cnN1aW5nLCBvciAob24gYSBXb3JsZCB0aGF0IHdvdWxkIHJhdGhlciByZWZ1c2UgYSBzdGFsZSB3cml0ZVxuICAvLyAgICB0aGFuIHJlcG9ydCB3aGF0IGl0IG1pc3NlZCkgYXMgYSA0MTIuIEVpdGhlciB3YXkgdGhlIHF1ZXVlIG1lc3NhZ2VcbiAgLy8gICAgY2FycnlpbmcgdGhlIHBheWxvYWQgaXMgYWxyZWFkeSBvdXQsIGFuZCB0aGUgY29uc3VtZXIgY2FuIG1hdGVyaWFsaXplIGFcbiAgLy8gICAgc3RlcCB3aG9zZSBjcmVhdGUgd2FzIHJlZnVzZWQuIE5vdGhpbmcgb3JkZXJzIHRoYXQgdmVyZGljdCBiZWZvcmUgdGhlXG4gIC8vICAgIGNvbnN1bWVyJ3MgcmVkZWxpdmVyeSByZS1lbnN1cmUsIHNvIG5vIGJhY2tlbmQtc2lkZSByZXZvY2F0aW9uXG4gIC8vICAgIGJvb2trZWVwaW5nIGNhbiBjbG9zZSB0aGUgd2luZG93OiBhIGJlc3QtZWZmb3J0IG1hcmtlciB0aGF0IGZhaWxzIG9wZW5cbiAgLy8gICAgY2Fubm90IGNhcnJ5IGEgY29ycmVjdG5lc3MgcHJvcGVydHkuIFRoZSBzZXF1ZW50aWFsIHBhdGggaXMgdGhlIG9ubHlcbiAgLy8gICAgdGhpbmcgdGhhdCBnaXZlcyB0aGUgbWVzc2FnZSBhIGhhcHBlbnMtYWZ0ZXIgZWRnZSBvdmVyIHRoZSB2ZXJkaWN0LlxuICAvLyAgLSBUaGUgcnVuJ3MgcXVldWUgdHJhbnNwb3J0IHByZXNlcnZlcyBiaW5hcnkgcGF5bG9hZHMgKENCT1IsXG4gIC8vICAgIHNwZWNWZXJzaW9uID49IDMpOiBgc3RlcElucHV0LmlucHV0YCBpcyB0aGUgc2VyaWFsaXplZCAocG9zc2libHlcbiAgLy8gICAgZW5jcnlwdGVkKSBpbnB1dCBieXRlcywgd2hpY2ggdGhlIEpTT04gdHJhbnNwb3J0IHdvdWxkIG1hbmdsZS5cbiAgY29uc3QgcmVzaWxpZW50RGlzcGF0Y2hFbGlnaWJsZSA9XG4gICAgc3RlcERpc3BhdGNoICE9PSB1bmRlZmluZWQgJiZcbiAgICBpc1Jlc2lsaWVudFN0ZXBEaXNwYXRjaEVuYWJsZWQoKSAmJlxuICAgIChydW4uc3BlY1ZlcnNpb24gPz8gMCkgPj0gU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NCT1JfUVVFVUVfVFJBTlNQT1JUO1xuXG4gIC8vIEJhdGNoZWQgZmFuLW91dDogZm9sZCB0aGlzIHN1c3BlbnNpb24ncyBzdGVwX2NyZWF0ZWQgKyB3YWl0X2NyZWF0ZWRcbiAgLy8gd3JpdGVzIGludG8gb25lIGBldmVudHMuY3JlYXRlQmF0Y2hgIGNhbGwgKG9uZSBkdXJhYmxlIHdyaXRlLCBwZXItZXZlbnRcbiAgLy8gb3V0Y29tZXMpIGluc3RlYWQgb2Ygb25lIHdyaXRlIHBlciBldmVudC4gRW5nYWdlcyBvbmx5IGZvciBhIENMRUFOXG4gIC8vIGZhbi1vdXQgKG5vIGF0dHJpYnV0ZSB3cml0ZXMsIG5vIGhvb2sgd3JpdGVzLCBubyByZXNpbGllbnQgZGlzcGF0Y2hcbiAgLy8gd2hvc2UgY3JlYXRlcyBhcmUgZWFjaCBwYWlyZWQgd2l0aCBhIHF1ZXVlIHB1Ymxpc2gpIG9uIGEgV29ybGQgdGhhdFxuICAvLyBpbXBsZW1lbnRzIHRoZSBvcHRpb25hbCBtZXRob2QgYW5kIGEgcnVuIHdob3NlIGV2ZW50cyBhcmUgc2xvdC1udW1iZXJlZC5cbiAgLy8gRXZlcnl0aGluZyBvdXRzaWRlIHRoZSBnYXRlIGtlZXBzIHRoZSBzaW5nbGUtZXZlbnQgcGF0aCBieXRlLWZvci1ieXRlLlxuICBjb25zdCBiYXRjaEZhbm91dEVsaWdpYmxlID1cbiAgICBpc0JhdGNoVHJhbnNpdGlvbnNFbmFibGVkKCkgJiZcbiAgICB0eXBlb2Ygd29ybGQuZXZlbnRzLmNyZWF0ZUJhdGNoID09PSAnZnVuY3Rpb24nICYmXG4gICAgKHJ1bi5zcGVjVmVyc2lvbiA/PyAwKSA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfU0xPVF9JREVOVElUWSAmJlxuICAgICFyZXNpbGllbnREaXNwYXRjaEVsaWdpYmxlICYmXG4gICAgYWxsSG9va0l0ZW1zLmxlbmd0aCA9PT0gMCAmJlxuICAgIGF0dHJpYnV0ZUl0ZW1zLmxlbmd0aCA9PT0gMDtcbiAgLyoqXG4gICAqIFRoZSBmb2xkJ3MgY29sbGVjdGlvbiwgaW4gc2NoZWR1bGluZyBvcmRlciAoc3RlcHMgaW4gc3RlcEl0ZW1zIG9yZGVyLFxuICAgKiB0aGVuIHdhaXRzKS4gU3RlcCBlbnRyaWVzIGFyZSBlbnF1ZXVlZCBieSB0aGVpciBwcmVwIHByb21pc2VzIChpbnB1dFxuICAgKiBkZWh5ZHJhdGlvbiBydW5zIGNvbmN1cnJlbnRseSwgc28gZW50cmllcyBhcmUgb3JkZXJlZCBieSBgb3JkZXJgLCBub3QgYnlcbiAgICogY29tcGxldGlvbik7IHRoZSBzaW5nbGUgZmx1c2ggb3AgYmVsb3cgYXdhaXRzIGV2ZXJ5IHByZXAsIHNvcnRzLCBhbmRcbiAgICogY29tbWl0cyB0aGUgd2hvbGUgc2V0IHRocm91Z2ggYGNyZWF0ZUJhdGNoYC5cbiAgICovXG4gIGNvbnN0IGJhdGNoUXVldWU6IHtcbiAgICBvcmRlcjogbnVtYmVyO1xuICAgIGtpbmQ6ICdzdGVwJyB8ICd3YWl0JyB8ICdpbmxpbmUtY3JlYXRlZCcgfCAnaW5saW5lLXN0YXJ0ZWQnO1xuICAgIGNvcnJlbGF0aW9uSWQ6IHN0cmluZztcbiAgICAvKiogVGhlIHN0ZXAncyBuYW1lLCBzZXQgb24gc3RlcC1jYXJyeWluZyBraW5kcyAodGhlIGluLWZsdXNoIHB1Ymxpc2hlc1xuICAgICAqICBhbmQgdGhlIGRpc3BhdGNoIGlkZW1wb3RlbmN5IGtleSBuZWVkIGl0KS4gKi9cbiAgICBzdGVwTmFtZT86IHN0cmluZztcbiAgICBldmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0O1xuICB9W10gPSBbXTtcbiAgY29uc3QgYmF0Y2hQcmVwczogUHJvbWlzZTx2b2lkPltdID0gW107XG5cbiAgLy8gUHJlLWNsYWltZWQgaW5saW5lIHBhaXJzOiBmb2xkIGVhY2ggbGF6eS1pbmxpbmUgc3RlcCdzIGRlZmVycmVkXG4gIC8vIGBzdGVwX2NyZWF0ZWRgIChjYXJyeWluZyBpdHMgaW5wdXQpIEFORCBpdHMgYHN0ZXBfc3RhcnRlZGAgY2xhaW0gKGJhcmUsXG4gIC8vIG93bmVyc2hpcC1zdGFtcGVkKSBpbnRvIHRoZSBiYXRjaCwgc28gdGhlIHdob2xlIGZhbi1vdXQgKHRoZSBpbmxpbmVcbiAgLy8gc3RlcHMnIGNsYWltcyBpbmNsdWRlZCkgY29tbWl0cyBpbiB0aGUgb25lIGR1cmFibGUgd3JpdGUgYW5kIHRoZSBjYWxsZXJcbiAgLy8gc3RhcnRzIHRoZSBib2RpZXMgc3RyYWlnaHQgb2ZmIHRoYXQgY29tbWl0IGluc3RlYWQgb2YgcG9zdGluZyBvbmUgY2xhaW1cbiAgLy8gcGVyIGlubGluZSBzdGVwLiBUaGUgbG9uZS1pbmxpbmUgY2FzZSAobm90aGluZyBlbHNlIHRvIGJhdGNoIHdpdGgpIGlzXG4gIC8vIGV4Y2x1ZGVkOiBhIHBhaXItb25seSBiYXRjaCBjb3N0cyB0aGUgc2FtZSByb3VuZCB0cmlwIGFzIHRoZSBzaW5nbGUgbGF6eVxuICAvLyBjbGFpbSB3aGlsZSBnaXZpbmcgdXAgdGhlIG9wdGltaXN0aWMgY2xhaW0vYm9keSBvdmVybGFwIGFuZCB0aGVcbiAgLy8gYnVtcC1hbmQtcmVwb3J0IHRoYXQgYGNyZWF0ZUd1YXJkZWRgIHByb3ZpZGVzLCBzbyBpdCBzdGF5cyBvbiB0aGUgbGF6eVxuICAvLyBwYXRoLiBSZXF1aXJlcyB0aGUgY2FsbGVyJ3MgYG93bmVyTWVzc2FnZUlkYDogdGhlIHN0YXJ0ZWQgcm93IG11c3RcbiAgLy8gc3RhbXAgb3duZXJzaGlwIGV4YWN0bHkgbGlrZSB0aGUgbGF6eSBjbGFpbSBpdCByZXBsYWNlcyAoYW5kIGEgY2FsbGVyXG4gIC8vIHRoYXQgZG9lcyBub3QgaW5saW5lLWV4ZWN1dGUgbmV2ZXIgcHJvdmlkZXMgb25lKS5cbiAgY29uc3QgdW5jcmVhdGVkV2FpdENvdW50ID0gd2FpdEl0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSkgPT4gIWl0ZW0uaGFzQ3JlYXRlZEV2ZW50XG4gICkubGVuZ3RoO1xuICBjb25zdCBpbmxpbmVQYWlyRm9sZEVsaWdpYmxlID1cbiAgICBiYXRjaEZhbm91dEVsaWdpYmxlICYmXG4gICAgb3duZXJNZXNzYWdlSWQgIT09IHVuZGVmaW5lZCAmJlxuICAgIGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcy5zaXplID4gMCAmJlxuICAgIChsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMuc2l6ZSA+PSAyIHx8XG4gICAgICBzdGVwc05lZWRpbmdDcmVhdGlvbi5zaXplIC1cbiAgICAgICAgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzLnNpemUgK1xuICAgICAgICB1bmNyZWF0ZWRXYWl0Q291bnQgPj1cbiAgICAgICAgMSk7XG4gIGNvbnN0IGlubGluZUNsYWltczogU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHRbJ2lubGluZUNsYWltcyddID0gbmV3IE1hcCgpO1xuICBsZXQgYmF0Y2hDb21taXR0ZWRTbG90Q2VpbGluZzogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gIC8vIFRoZSB0cmFjZSBjYXJyaWVyIGZvciByZXNpbGllbnQgc3RlcCBkaXNwYXRjaGVzLCByZXNvbHZlZCBhdCBtb3N0IG9uY2UgcGVyXG4gIC8vIHN1c3BlbnNpb24gKHRoZSBwZXItc3RlcCBvcHMgcnVuIGNvbmN1cnJlbnRseSBhbmQgc2hhcmUgaXQpLlxuICBsZXQgc3RlcERpc3BhdGNoVHJhY2VDYXJyaWVyOiBQcm9taXNlPFRyYWNlQ2Fycmllcj4gfCB1bmRlZmluZWQ7XG4gIGNvbnN0IGdldFN0ZXBEaXNwYXRjaFRyYWNlQ2FycmllciA9ICgpOiBQcm9taXNlPFRyYWNlQ2Fycmllcj4gPT4ge1xuICAgIHN0ZXBEaXNwYXRjaFRyYWNlQ2FycmllciA/Pz1cbiAgICAgIHN0ZXBEaXNwYXRjaD8uZ2V0VHJhY2VDYXJyaWVyKCkgPz8gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgICByZXR1cm4gc3RlcERpc3BhdGNoVHJhY2VDYXJyaWVyO1xuICB9O1xuXG4gIC8vIFByb2R1Y2VyLXNpZGUgcmVzaWxpZW50IHJlY292ZXJ5IGNvdW50IGZvciB0aGUgc3VzcGVuc2lvbiBzcGFuIGF0dHJpYnV0ZS5cbiAgbGV0IHJlc2lsaWVudERpc3BhdGNoUmVjb3ZlcmVkID0gMDtcblxuICAvLyBTdGVwczogY3JlYXRlIHN0ZXBfY3JlYXRlZCBldmVudHMgKG5vIHF1ZXVpbmcsIFYyIHJldHVybnMgcGVuZGluZyBzdGVwc1xuICAvLyB0byBjYWxsZXIsIEVYQ0VQVCBvbiB0aGUgcmVzaWxpZW50IGRpc3BhdGNoIHBhdGgsIHdoaWNoIHBhcmFsbGVsaXplcyB0aGVcbiAgLy8gY3JlYXRlIHdpdGggdGhlIHN0ZXAncyBxdWV1ZSBwdWJsaXNoIGFuZCByZXBvcnRzIGl0IGluXG4gIC8vIGBxdWV1ZWRTdGVwQ29ycmVsYXRpb25JZHNgKS5cbiAgbGV0IGJhdGNoT3JkZXJDb3VudGVyID0gMDtcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygc3RlcEl0ZW1zKSB7XG4gICAgaWYgKHN0ZXBzTmVlZGluZ0NyZWF0aW9uLmhhcyhxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCkpIHtcbiAgICAgIC8vIERldGVybWluaXN0aWMgcG9zaXRpb24gaW4gdGhlIGJhdGNoZWQgZm9sZCAoYXNzaWduZWQgaW4gc3RlcEl0ZW1zXG4gICAgICAvLyBvcmRlciwgYmVmb3JlIHRoZSBjb25jdXJyZW50IGRlaHlkcmF0aW9uIHJ1bnMpLiBBIHBhaXItZm9sZGVkIGlubGluZVxuICAgICAgLy8gc3RlcCBvY2N1cGllcyB0d28gY29uc2VjdXRpdmUgcG9zaXRpb25zIChjcmVhdGVkIHJvdyB0aGVuIHN0YXJ0ZWRcbiAgICAgIC8vIHJvdyksIHdoaWNoIHRoZSBmbHVzaCBrZWVwcyBhZGphY2VudCBhbmQgbmV2ZXIgc3BsaXRzIGFjcm9zcyBjaHVua3MsXG4gICAgICAvLyBzbyBhIFdvcmxkIGNhbiBmb2xkIHRoZW0gaW50byBvbmUgYm9ybi1ydW5uaW5nIGNyZWF0ZS5cbiAgICAgIGNvbnN0IHBhaXJGb2xkZWQgPVxuICAgICAgICBpbmxpbmVQYWlyRm9sZEVsaWdpYmxlICYmXG4gICAgICAgIGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcy5oYXMocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpO1xuICAgICAgY29uc3Qgc3RlcE9yZGVyID0gYmF0Y2hPcmRlckNvdW50ZXI7XG4gICAgICBiYXRjaE9yZGVyQ291bnRlciArPSBwYWlyRm9sZGVkID8gMiA6IDE7XG4gICAgICBjb25zdCBzdGVwT3AgPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAvLyBQZXItc3RlcCBzaW5rLCBtZXJnZWQgYmVsb3c6IHRoZSBkZWh5ZHJhdGUgd3JhcHBlciBlbWl0cyBzcGFuXG4gICAgICAgIC8vIGF0dHJpYnV0ZXMgZnJvbSB0aGUgc2luayBpdCBpcyBoYW5kZWQsIHNvIHNoYXJpbmcgb25lIGFjcm9zc1xuICAgICAgICAvLyBzdGVwcyB3b3VsZCByZS1lbWl0IChhbmQgbWlzYXR0cmlidXRlKSBlYXJsaWVyIHN0ZXBzJyBlbnRyaWVzLlxuICAgICAgICBjb25zdCBzdGVwR3Vlc3RDb2RlOiBHdWVzdENvZGVTdGF0cyA9IHsgZXhlY3V0aW9uczogW10gfTtcbiAgICAgICAgbGV0IGRlaHlkcmF0ZWRJbnB1dDogVWludDhBcnJheSB8IHVua25vd247XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZGVoeWRyYXRlZElucHV0ID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYXJnczogcXVldWVJdGVtLmFyZ3MsXG4gICAgICAgICAgICAgIGNsb3N1cmVWYXJzOiBxdWV1ZUl0ZW0uY2xvc3VyZVZhcnMsXG4gICAgICAgICAgICAgIHRoaXNWYWw6IHF1ZXVlSXRlbS50aGlzVmFsLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgY29tcHJlc3Npb24sXG4gICAgICAgICAgICBzdGVwR3Vlc3RDb2RlXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgLy8gVGhlIHNpbmsgcmVjb3JkcyBleGVjdXRpb25zIGFzIHRoZXkgaGFwcGVuLCBzbyBndWVzdCBjb2RlIHRoYXRcbiAgICAgICAgICAvLyByYW4gYmVmb3JlIHRoZSBmYWlsdXJlIHN0aWxsIGNvdW50cyBhZ2FpbnN0IHJldGVudGlvbi5cbiAgICAgICAgICBndWVzdENvZGVTdGF0cy5leGVjdXRpb25zLnB1c2goLi4uc3RlcEd1ZXN0Q29kZS5leGVjdXRpb25zKTtcbiAgICAgICAgICBpZiAoIVNlcmlhbGl6YXRpb25FcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBlLmcuIFJ1bnRpbWVEZWNyeXB0aW9uRXJyb3I6IGFuIFNESyBmYXVsdCwgbm90IGEgdXNlciB2YWx1ZVxuICAgICAgICAgICAgLy8gcHJvYmxlbS4gS2VlcCBpdHMgaWRlbnRpdHkgKFJVTlRJTUVfRVJST1IpIGFuZCBjdXJyZW50XG4gICAgICAgICAgICAvLyBmYWlsLXRoZS1zdXNwZW5zaW9uIGJlaGF2aW9yLlxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIXN0ZXBEaXNwYXRjaCkge1xuICAgICAgICAgICAgLy8gTm8gZGlzcGF0Y2ggdGFyZ2V0IG1lYW5zIG5vIHJlcGxheSB3aWxsIG9ic2VydmUgYVxuICAgICAgICAgICAgLy8gZmluYWxpemF0aW9uOiB0aGlzIGlzIHRoZSB0ZXJtaW5hbCBkcmFpbiAob3IgYSBjcmVhdGUtb25seVxuICAgICAgICAgICAgLy8gdGVzdCBjYWxsZXIpLiBUaGUgcnVuIGlzIGFscmVhZHkgY29tcGxldGluZy9mYWlsaW5nLCBzb1xuICAgICAgICAgICAgLy8gd3JpdGluZyBzdGVwX2NyZWF0ZWQgKyBzdGVwX2ZhaWxlZCBoZXJlIHdvdWxkIGxlYXZlIGUuZy4gYVxuICAgICAgICAgICAgLy8gQ09NUExFVEVEIHJ1biBjYXJyeWluZyBhIGZhaWxlZCBzdGVwIG5vdGhpbmcgY2FuIGV2ZXJcbiAgICAgICAgICAgIC8vIG9ic2VydmUsIHJlYWRpbmcgYXMgYSBidWcgZnJvbSB0aGUgZGFzaGJvYXJkLiBSZXRocm93XG4gICAgICAgICAgICAvLyBpbnN0ZWFkOyB0aGUgZHJhaW4ncyBvd24gY2F0Y2ggc3dhbGxvd3MgaXQsIHByZXNlcnZpbmcgaXRzXG4gICAgICAgICAgICAvLyBwcmUtZXhpc3RpbmcgYmVoYXZpb3IgKG5vIHJvd3MgZm9yIHRoZSB1bmF3YWl0ZWQgc3RlcCkuXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGF3YWl0IGZpbmFsaXplVW5zZXJpYWxpemFibGVTdGVwKHF1ZXVlSXRlbSwgZXJyKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZ3Vlc3RDb2RlU3RhdHMuZXhlY3V0aW9ucy5wdXNoKC4uLnN0ZXBHdWVzdENvZGUuZXhlY3V0aW9ucyk7XG4gICAgICAgIC8vIERlZmVycmVkIChsYXp5KSBpbmxpbmUgc3RlcDogc2tpcCB0aGUgc3RlcF9jcmVhdGVkIHdyaXRlOyB0aGVcbiAgICAgICAgLy8gY2FsbGVyJ3MgaW5saW5lIGV4ZWN1dGVTdGVwIHdpbGwgc2VuZCBhIGxhenkgc3RlcF9zdGFydGVkIGNhcnJ5aW5nXG4gICAgICAgIC8vIHRoaXMgaW5wdXQsIGFuZCB0aGUgd29ybGQgY3JlYXRlcyB0aGUgc3RlcCAoZW50aXR5ICsgc3ludGhldGljXG4gICAgICAgIC8vIHN0ZXBfY3JlYXRlZCBldmVudCkgYXRvbWljYWxseS4gV2UgZG8gTk9UIGFkZCBpdCB0b1xuICAgICAgICAvLyBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzOyBvd25lcnNoaXAgaXMgZGVjaWRlZCBieSB0aGF0IGxhenlcbiAgICAgICAgLy8gc3RlcF9zdGFydGVkJ3MgYXRvbWljIGNyZWF0ZS1jbGFpbSBpbnN0ZWFkLlxuICAgICAgICBpZiAobGF6eUlubGluZUNvcnJlbGF0aW9uSWRzLmhhcyhxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCkpIHtcbiAgICAgICAgICBsYXp5SW5saW5lQnlDb3JyZWxhdGlvbklkLnNldChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCwge1xuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBzdGVwTmFtZTogcXVldWVJdGVtLnN0ZXBOYW1lLFxuICAgICAgICAgICAgZGVoeWRyYXRlZElucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKHBhaXJGb2xkZWQpIHtcbiAgICAgICAgICAgIC8vIEVucXVldWUgdGhlIHBhaXIgdGhlIGRlZmVycmFsIHdvdWxkIG90aGVyd2lzZSBsZWF2ZSB0byB0aGVcbiAgICAgICAgICAgIC8vIGNhbGxlcidzIGxhenkgYHN0ZXBfc3RhcnRlZGA6IHRoZSBjcmVhdGVkIHJvdyBjYXJyaWVzIHRoZVxuICAgICAgICAgICAgLy8gaW5wdXQgKHBheWxvYWRzIHJpZGUgY3JlYXRlcyBpbiBhIGJhdGNoKSwgdGhlIHN0YXJ0ZWQgcm93IGlzXG4gICAgICAgICAgICAvLyBiYXJlIGFuZCBzdGFtcHMgdGhpcyBpbnZvY2F0aW9uJ3Mgb3duZXJzaGlwLCB0aGUgc2FtZSBjbGFpbVxuICAgICAgICAgICAgLy8gc2hhcGUgdGhlIGxhenkgc3RhcnQgd291bGQgaGF2ZSBzZW50LCBzZXR0bGVkIGJ5IHRoZSBiYXRjaC5cbiAgICAgICAgICAgIGJhdGNoUXVldWUucHVzaCh7XG4gICAgICAgICAgICAgIG9yZGVyOiBzdGVwT3JkZXIsXG4gICAgICAgICAgICAgIGtpbmQ6ICdpbmxpbmUtY3JlYXRlZCcsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudDoge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY3JlYXRlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYmF0Y2hRdWV1ZS5wdXNoKHtcbiAgICAgICAgICAgICAgb3JkZXI6IHN0ZXBPcmRlciArIDEsXG4gICAgICAgICAgICAgIGtpbmQ6ICdpbmxpbmUtc3RhcnRlZCcsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudDoge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfc3RhcnRlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIC8vIENoZWNrZWQgYnkgaW5saW5lUGFpckZvbGRFbGlnaWJsZTsgc3ByZWFkIGtlZXBzIHRoZVxuICAgICAgICAgICAgICAgICAgLy8gbmFycm93LXRocm91Z2gtY2xvc3VyZSBwcm9ibGVtIGF3YXkgZnJvbSB0aGUgdHlwZS5cbiAgICAgICAgICAgICAgICAgIC4uLihvd25lck1lc3NhZ2VJZCAhPT0gdW5kZWZpbmVkID8geyBvd25lck1lc3NhZ2VJZCB9IDoge30pLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0ZXBFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXNpbGllbnQgc3RlcCBkaXNwYXRjaDogZmlyZSB0aGUgc3RlcF9jcmVhdGVkIHdyaXRlIGFuZCB0aGVcbiAgICAgICAgLy8gc3RlcC1leGVjdXRpb24gcXVldWUgcHVibGlzaCBpbiBwYXJhbGxlbDogdGhlIG1lc3NhZ2UgY2FycmllcyB0aGVcbiAgICAgICAgLy8gc2FtZSBzZXJpYWxpemVkIGlucHV0IChgc3RlcElucHV0YCkgc28gdGhlIGNvbnN1bWVyIGNhblxuICAgICAgICAvLyBpZGVtcG90ZW50bHkgcmUtZW5zdXJlIHRoZSBldmVudCBpZiB0aGUgZGlyZWN0IHdyaXRlIGZhaWxlZFxuICAgICAgICAvLyB0cmFuc2llbnRseS4gTWlycm9ycyB0aGUgcmVzaWxpZW50IHN0YXJ0IChgcnVuSW5wdXRgKSBhbmRcbiAgICAgICAgLy8gcmVzaWxpZW50IGhvb2sgcmVzdW1lIChgaG9va0lucHV0YCkgcGF0dGVybnMuIE9ubHkgZm9yIGlucHV0cyB0aGVcbiAgICAgICAgLy8gcXVldWUgbWVzc2FnZSBjYW4gc2FmZWx5IGNhcnJ5IChiaW5hcnksIHVuZGVyIHRoZSBWUVMgc2l6ZSBjYXApLlxuICAgICAgICBpZiAoXG4gICAgICAgICAgcmVzaWxpZW50RGlzcGF0Y2hFbGlnaWJsZSAmJlxuICAgICAgICAgIGRlaHlkcmF0ZWRJbnB1dCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgJiZcbiAgICAgICAgICBkZWh5ZHJhdGVkSW5wdXQuYnl0ZUxlbmd0aCA8PSBNQVhfUkVTSUxJRU5UX1NURVBfSU5QVVRfQllURVNcbiAgICAgICAgKSB7XG4gICAgICAgICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICAgICAgICBjb25zdCB0cmFjZUNhcnJpZXIgPSBhd2FpdCBnZXRTdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXIoKTtcbiAgICAgICAgICBjb25zdCBbY3JlYXRlUmVzdWx0LCBxdWV1ZVJlc3VsdF0gPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoW1xuICAgICAgICAgICAgY3JlYXRlR3VhcmRlZChzdGVwRXZlbnQsIHsgcmVxdWVzdElkIH0pLFxuICAgICAgICAgICAgcXVldWVNZXNzYWdlKFxuICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBpbXBsaWVkIGJ5IHJlc2lsaWVudERpc3BhdGNoRWxpZ2libGVcbiAgICAgICAgICAgICAgc3RlcERpc3BhdGNoIS5xdWV1ZU5hbWUsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICBzdGVwSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgIHN0ZXBJbnB1dDogeyBpbnB1dDogZGVoeWRyYXRlZElucHV0IH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIC8vIFNhbWUga2V5IGFzIHRoZSBjYWxsZXIncyBkaXNwYXRjaCBwYXNzIGFuZCBhbnkgY29uY3VycmVudFxuICAgICAgICAgICAgICAvLyBoYW5kbGVyJ3MsIHNvIHJlZHVuZGFudCBwdWJsaXNoZXMgZm9yIHRoaXMgc3RlcCBkZWR1cGUuIFRoZVxuICAgICAgICAgICAgICAvLyBrZXkgaXMgc3RlcC1pZGVudGl0eS1zY29wZWQgc28gYSByZXZva2VkIG1lc3NhZ2UgZm9yIGFcbiAgICAgICAgICAgICAgLy8gcmVhc3NpZ25lZCBjb3JyZWxhdGlvbiBpZCBjYW5ub3QgYWJzb3JiIHRoZSBjb3JyZWN0ZWRcbiAgICAgICAgICAgICAgLy8gc2NoZWR1bGUncyBkaXNwYXRjaDogc2VlIHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5LlxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgaWRlbXBvdGVuY3lLZXk6IHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5KFxuICAgICAgICAgICAgICAgICAgcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0uc3RlcE5hbWVcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApLFxuICAgICAgICAgIF0pO1xuICAgICAgICAgIC8vIFF1ZXVlIGZhaWx1cmUgaXMgYWx3YXlzIGZhdGFsIGZvciB0aGlzIHN1c3BlbnNpb24gcGFzczogd2l0aG91dFxuICAgICAgICAgIC8vIHRoZSBtZXNzYWdlIHRoZSBzdGVwIHdvdWxkIHJlbHkgb24gdGhlIGNyZWF0ZSBhbG9uZSwgYW5kIGlmIHRoZVxuICAgICAgICAgIC8vIGNyZWF0ZSBBTFNPIGZhaWxlZCB0aGVyZSB3b3VsZCBiZSBubyBkdXJhYmxlIHJlY29yZCBhdCBhbGwuXG4gICAgICAgICAgLy8gUHJvcGFnYXRpbmcgcmVkZWxpdmVycyB0aGUgb3JjaGVzdHJhdG9yIG1lc3NhZ2UsIHdoaWNoXG4gICAgICAgICAgLy8gcmUtY3JlYXRlcyB0aGUgKGlkZW1wb3RlbnQpIHN0ZXBfY3JlYXRlZCBhbmQgcmUtZGlzcGF0Y2hlcyxcbiAgICAgICAgICAvLyB0aGUgc2FtZSByZWNvdmVyeSBhcyB0aGUgc2VxdWVudGlhbCBwYXRoLlxuICAgICAgICAgIGlmIChxdWV1ZVJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgICAgIHRocm93IHF1ZXVlUmVzdWx0LnJlYXNvbjtcbiAgICAgICAgICB9XG4gICAgICAgICAgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgaWYgKGNyZWF0ZVJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgICAgIGNvbnN0IGVyciA9IGNyZWF0ZVJlc3VsdC5yZWFzb247XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIC8vIENvbmN1cnJlbnQgaGFuZGxlciB3cm90ZSBpdCBmaXJzdCwgc2FtZSBhcyB0aGUgc2VxdWVudGlhbFxuICAgICAgICAgICAgICAvLyBwYXRoLiBUaGUgc3RlcCBtZXNzYWdlIGlzIGFscmVhZHkgb3V0OyBhIGR1cGxpY2F0ZSBwdWJsaXNoXG4gICAgICAgICAgICAgIC8vIGJ5IHRoYXQgaGFuZGxlciBkZWR1cGVzIG9uIHRoZSBzaGFyZWQgaWRlbXBvdGVuY3kga2V5LlxuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1N0ZXAgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc1JldHJ5YWJsZVdvcmxkRXJyb3IoZXJyKSkge1xuICAgICAgICAgICAgICAvLyBSZXNpbGllbnQ6IHRoZSB3cml0ZSBmYWlsZWQgdHJhbnNpZW50bHkgKDQyOSAvIDV4eCAvXG4gICAgICAgICAgICAgIC8vIHRyYW5zcG9ydCkgYnV0IHRoZSBzdGVwIG1lc3NhZ2UgKGNhcnJ5aW5nIHRoZSBzYW1lXG4gICAgICAgICAgICAgIC8vIHNlcmlhbGl6ZWQgaW5wdXQpIHdhcyBwdWJsaXNoZWQsIHNvIHRoZSBjb25zdW1lclxuICAgICAgICAgICAgICAvLyBpZGVtcG90ZW50bHkgcmUtZW5zdXJlcyB0aGUgc3RlcF9jcmVhdGVkIGJlZm9yZSBleGVjdXRpbmcuXG4gICAgICAgICAgICAgIHJlc2lsaWVudERpc3BhdGNoUmVjb3ZlcmVkKys7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICAnU3RlcCBjcmVhdGlvbiBldmVudCB3cml0ZSBmYWlsZWQsIGJ1dCB0aGUgc3RlcCB3YXMgJyArXG4gICAgICAgICAgICAgICAgICAnZGlzcGF0Y2hlZCB2aWEgdGhlIHF1ZXVlLiBUaGUgc3RlcF9jcmVhdGVkIGV2ZW50IHdpbGwgJyArXG4gICAgICAgICAgICAgICAgICAnYmUgZW5zdXJlZCBieSB0aGUgcXVldWUgY29uc3VtZXIuJyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChiYXRjaEZhbm91dEVsaWdpYmxlKSB7XG4gICAgICAgICAgLy8gRm9sZCBpbnRvIHRoZSBiYXRjaCBpbnN0ZWFkIG9mIHdyaXRpbmcgaGVyZS4gVGhlIGVuY2xvc2luZ1xuICAgICAgICAgIC8vIHByb21pc2Ugam9pbnMgYGJhdGNoUHJlcHNgIChzZWUgdGhlIGxvb3AgYmVsb3cpLCBzbyB0aGUgZmx1c2hcbiAgICAgICAgICAvLyBvcCBjYW5ub3QgcnVuIGJlZm9yZSB0aGlzIHN0ZXAncyBpbnB1dCBmaW5pc2hlZCBkZWh5ZHJhdGluZy5cbiAgICAgICAgICBiYXRjaFF1ZXVlLnB1c2goe1xuICAgICAgICAgICAgb3JkZXI6IHN0ZXBPcmRlcixcbiAgICAgICAgICAgIGtpbmQ6ICdzdGVwJyxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgIGV2ZW50OiBzdGVwRXZlbnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSgpO1xuICAgICAgb3BzLnB1c2goc3RlcE9wKTtcbiAgICAgIGlmIChiYXRjaEZhbm91dEVsaWdpYmxlKSB7XG4gICAgICAgIC8vIFRoZSBmbHVzaCBvcCB3YWl0cyBmb3IgZXZlcnkgcHJlcCBiZWZvcmUgY29tbWl0dGluZzsgYSBwcmVwIHRoYXRcbiAgICAgICAgLy8gcmVqZWN0ZWQgYWxyZWFkeSBzdXJmYWNlcyB0aHJvdWdoIGBvcHNgLCBzbyB0aGUgZmx1c2gncyBvd24gd2FpdFxuICAgICAgICAvLyBzd2FsbG93cyBpdCBhbmQgY29tbWl0cyB3aGF0ZXZlciB3YXMgc3VjY2Vzc2Z1bGx5IGVucXVldWVkLFxuICAgICAgICAvLyBwcmVzZXJ2aW5nIHRvZGF5J3MgcGVyLW9wIGluZGVwZW5kZW5jZS5cbiAgICAgICAgYmF0Y2hQcmVwcy5wdXNoKHN0ZXBPcC5jYXRjaCgoKSA9PiB7fSkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIENyZWF0ZSB3YWl0IGV2ZW50cyAoc2FtZSBhcyBWMSlcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICBjb25zdCB3YWl0RXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgcmVzdW1lQXQ6IHF1ZXVlSXRlbS5yZXN1bWVBdCxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBpZiAoYmF0Y2hGYW5vdXRFbGlnaWJsZSkge1xuICAgICAgICAvLyBXYWl0cyBuZWVkIG5vIGRlaHlkcmF0aW9uLCBzbyB0aGV5IGVucXVldWUgc3luY2hyb25vdXNseSwgYWZ0ZXJcbiAgICAgICAgLy8gZXZlcnkgc3RlcCdzIG9yZGVyIHNsb3QsIHByZXNlcnZpbmcgc3RlcHMtdGhlbi13YWl0cyBzY2hlZHVsaW5nXG4gICAgICAgIC8vIG9yZGVyIGluIHRoZSBsb2cuXG4gICAgICAgIGJhdGNoUXVldWUucHVzaCh7XG4gICAgICAgICAgb3JkZXI6IGJhdGNoT3JkZXJDb3VudGVyKyssXG4gICAgICAgICAga2luZDogJ3dhaXQnLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIGV2ZW50OiB3YWl0RXZlbnQsXG4gICAgICAgIH0pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZCh3YWl0RXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBUaGUgYmF0Y2hlZCBmb2xkJ3MgZmx1c2g6IHRoZSBjbGVhbiBmYW4tb3V0IGNvbW1pdHMgdGhyb3VnaFxuICAvLyBgY3JlYXRlQmF0Y2hgIGluIGNodW5rcyBvZiBNQVhfQkFUQ0hfRkFOT1VUX0VWRU5UUywgYWxsIGNodW5rcyBJTlxuICAvLyBGTElHSFQgQ09OQ1VSUkVOVExZLiBTbG90IGFzc2lnbm1lbnQgaXMgdGhlIHNlcnZlcidzLCBzbyBwYXJhbGxlbFxuICAvLyBjaHVua3MgcmFjZSBmb3Igc2xvdCByYW5nZXMgZXhhY3RseSBsaWtlIHRoZSBwcmUtZm9sZCBwYXRoJ3MgcGFyYWxsZWxcbiAgLy8gc2luZ2xlIHdyaXRlcyBkaWQ7IGVudGl0eSBjb25kaXRpb25zLCBub3QgY29tbWl0IG9yZGVyLCBjYXJyeVxuICAvLyBjb3JyZWN0bmVzcyAoc2libGluZyBmYW4tb3V0IGV2ZW50cyBoYXZlIG5vIGNyb3NzLW9yZGVyIHRoZSByZXBsYXlcbiAgLy8gZGVwZW5kcyBvbjsgaXQgbWF0Y2hlcyBieSBjb3JyZWxhdGlvbiBpZCkuIEVhY2ggZXZlbnQgcmVwb3J0cyB0aGVcbiAgLy8gb3V0Y29tZSBpdHMgb3duIHNpbmdsZSBjcmVhdGUgd291bGQgaGF2ZSBoYWQ6IGEgNDA5IGlzIHRoZSBzYW1lXG4gIC8vIGFscmVhZHktZXhpc3RzIHRvbGVyYW5jZSBhcyB0aGUgc2luZ2xlIHBhdGgsIGFueXRoaW5nIGVsc2UgZmFpbHMgdGhlXG4gIC8vIGRlbGl2ZXJ5IHRoZSB3YXkgYSBzaW5nbGUtcGF0aCByZWplY3Rpb24gd291bGQuXG4gIC8vXG4gIC8vIExhdGVuY3kgc2hhcGU6IG9ubHkgdGhlIGNodW5rIGNhcnJ5aW5nIHRoZSBwcmUtY2xhaW1lZCBpbmxpbmUgcGFpcnNcbiAgLy8gZ2F0ZXMgdGhlIGhhbmRsZXIncyByZXR1cm4gKHRoZSBjYWxsZXIgc3RhcnRzIGJvZGllcyBvZmYgaXRzIGNsYWltcykuXG4gIC8vIEV2ZXJ5IG90aGVyIGNodW5rJ3MgY29tbWl0IChhbmQgZXZlcnkgY2h1bmsncyBzdGVwLW1lc3NhZ2UgcHVibGlzaGVzLFxuICAvLyB3aGljaCBmaXJlIHRoZSBtb21lbnQgSVRTIGNyZWF0ZXMgYXJlIGR1cmFibGUpIHJpZGVzXG4gIC8vIGBkZWZlcnJlZEJhdGNoV29ya2Agd2hlbiB0aGUgY2FsbGVyIG9wdGVkIGluLCBqb2luZWQgYmVmb3JlIGFjay4gQSBzbG93XG4gIC8vIHNpYmxpbmcgY2h1bmsgdGhlcmVmb3JlIGRlbGF5cyBuZWl0aGVyIHRoZSBpbmxpbmUgYm9kaWVzIG5vciBhbm90aGVyXG4gIC8vIGNodW5rJ3MgcXVldWUgbWVzc2FnZXMsIHdoaWxlIHB1Ymxpc2gtYWZ0ZXItY3JlYXRlIHN0aWxsIGhvbGRzIHBlclxuICAvLyBzdGVwOiBhIHN0ZXAncyBtZXNzYWdlIGlzIG9ubHkgZXZlciBzZW50IGFmdGVyIHRoZSBjaHVuayBjYXJyeWluZyBpdHNcbiAgLy8gY3JlYXRlIGhhcyBjb21taXR0ZWQuXG4gIGxldCBkZWZlcnJlZEJhdGNoV29yazogUHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZDtcbiAgaWYgKGJhdGNoRmFub3V0RWxpZ2libGUpIHtcbiAgICBvcHMucHVzaChcbiAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIFByZXBzIHRoYXQgcmVqZWN0ZWQgYWxyZWFkeSBzdXJmYWNlIHRocm91Z2ggdGhlaXIgb3duIGBvcHNgXG4gICAgICAgIC8vIGVudHJpZXM7IHRoZSBmb2xkIGNvbW1pdHMgd2hhdGV2ZXIgd2FzIHN1Y2Nlc3NmdWxseSBlbnF1ZXVlZCxcbiAgICAgICAgLy8gcHJlc2VydmluZyB0b2RheSdzIHBlci1vcCBpbmRlcGVuZGVuY2UuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKGJhdGNoUHJlcHMpO1xuICAgICAgICBpZiAoYmF0Y2hRdWV1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZW50cmllcyA9IFsuLi5iYXRjaFF1ZXVlXS5zb3J0KChhLCBiKSA9PiBhLm9yZGVyIC0gYi5vcmRlcik7XG4gICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgIC8vIEEgYmF0Y2ggb2YgT05FIGdhaW5zIG5vdGhpbmcgb3ZlciB0aGUgc2luZ2xlIHdyaXRlIChzYW1lIHJvdW5kXG4gICAgICAgIC8vIHRyaXApIGFuZCBsb3NlcyB0aGUgc2xvdC1zbmFwc2hvdCBwYXJhbXMgKyBidW1wLWFuZC1yZXBvcnQgdGhhdFxuICAgICAgICAvLyBjcmVhdGVHdWFyZGVkIHByb3ZpZGVzLCBzbyBhIGxvbmUgZWFnZXIgZXZlbnQgdGFrZXMgdGhlIG9yZGluYXJ5XG4gICAgICAgIC8vIHNpbmdsZSBwYXRoLCB3aXRoIHRoZSBzYW1lIGNvbmZsaWN0IHRvbGVyYW5jZSBhbmQgb3duZXJzaGlwXG4gICAgICAgIC8vIGJvb2trZWVwaW5nIGl0IHdvdWxkIGhhdmUgaGFkIHdpdGhvdXQgdGhlIGZvbGQuXG4gICAgICAgIGlmIChlbnRyaWVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIGNvbnN0IFtlbnRyeV0gPSBlbnRyaWVzO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKGVudHJ5LmV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGlmIChlbnRyeS5raW5kID09PSAnc3RlcCcpIHtcbiAgICAgICAgICAgICAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcy5hZGQoZW50cnkuY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICBlbnRyeS5raW5kID09PSAnc3RlcCdcbiAgICAgICAgICAgICAgICAgID8gJ1N0ZXAgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnXG4gICAgICAgICAgICAgICAgICA6ICdXYWl0IGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGVudHJ5LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBTZWVkIGZvciB0aGUgZm9yZWlnbi1pbnRlcmxlYXZpbmcgZGlhZ25vc3RpYyBiZWxvdy4gV2l0aCBjaHVua3NcbiAgICAgICAgLy8gY29tbWl0dGluZyBpbiBwYXJhbGxlbCB0aGVyZSBpcyBubyBwZXItY2h1bmsgXCJleHBlY3RlZCBuZXh0IHNsb3RcIjtcbiAgICAgICAgLy8gdGhlIHdob2xlIGZvbGQncyBjb21taXR0ZWQgc3BhbiBpcyBjb21wYXJlZCBhZ2FpbnN0IHRoZSBzZWVkXG4gICAgICAgIC8vIG9uY2UgZXZlcnkgY2h1bmsgaGFzIHNldHRsZWQ6IGNvbW1pdHRlZCBzbG90cyBhcmUgZGVuc2UgcGVyIHRoZVxuICAgICAgICAvLyBXb3JsZCdzIGludmFyaWFudCwgc28gYW55IGV4Y2VzcyBvZiAobWF4IGNvbW1pdHRlZCBzbG90IOKIkiBzZWVkICtcbiAgICAgICAgLy8gMSkgb3ZlciB0aGUgZm9sZCdzIG93biBjb21taXR0ZWQgY291bnQgaXMgZXZlbnRzIE9USEVSIHdyaXRlcnNcbiAgICAgICAgLy8gbGFuZGVkIGluIGJldHdlZW4uXG4gICAgICAgIGNvbnN0IGV4cGVjdGVkRmlyc3RTbG90ID0gZXZlbnRMb2dcbiAgICAgICAgICA/IChtYXhFdmVudFNsb3QoZXZlbnRMb2cuZXZlbnRzKSA/PyAwKSArIDFcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgICAgLy8gUGFpci1hd2FyZSBjaHVua2luZzogYSBwcmUtY2xhaW1lZCBwYWlyJ3MgdHdvIHJvd3MgbXVzdCBsYW5kIGluXG4gICAgICAgIC8vIHRoZSBzYW1lIGNyZWF0ZUJhdGNoIGNhbGwgKGFkamFjZW50LCBzbyBhIFdvcmxkIGNhbiBmb2xkIHRoZW1cbiAgICAgICAgLy8gaW50byBvbmUgYm9ybi1ydW5uaW5nIGNyZWF0ZSkgYW5kIG5ldmVyIHN0cmFkZGxlIGEgY2h1bmtcbiAgICAgICAgLy8gYm91bmRhcnksIHdoaWNoIHdvdWxkIHR1cm4gdGhlIHN0YXJ0ZWQgcm93IGludG8gYSBzdGFuZGFsb25lXG4gICAgICAgIC8vIGNsYWltIHJhY2luZyBpdHMgb3duIGNyZWF0ZSdzIGNvbW1pdC5cbiAgICAgICAgY29uc3QgY2h1bmtzOiAodHlwZW9mIGVudHJpZXMpW10gPSBbXTtcbiAgICAgICAge1xuICAgICAgICAgIGxldCBjdXJyZW50OiB0eXBlb2YgZW50cmllcyA9IFtdO1xuICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBlbnRyaWVzLmxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICAgICAgY29uc3QgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICAgICAgICAgIGNvbnN0IG5leHQgPSBlbnRyaWVzW2luZGV4ICsgMV07XG4gICAgICAgICAgICBjb25zdCBwYWlyTGVhZCA9XG4gICAgICAgICAgICAgIGVudHJ5LmtpbmQgPT09ICdpbmxpbmUtY3JlYXRlZCcgJiZcbiAgICAgICAgICAgICAgbmV4dD8ua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJyAmJlxuICAgICAgICAgICAgICBuZXh0LmNvcnJlbGF0aW9uSWQgPT09IGVudHJ5LmNvcnJlbGF0aW9uSWQ7XG4gICAgICAgICAgICBjb25zdCB0YWtlID0gcGFpckxlYWQgPyAyIDogMTtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgY3VycmVudC5sZW5ndGggPiAwICYmXG4gICAgICAgICAgICAgIGN1cnJlbnQubGVuZ3RoICsgdGFrZSA+IE1BWF9CQVRDSF9GQU5PVVRfRVZFTlRTXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY2h1bmtzLnB1c2goY3VycmVudCk7XG4gICAgICAgICAgICAgIGN1cnJlbnQgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnQucHVzaChlbnRyeSk7XG4gICAgICAgICAgICBpZiAocGFpckxlYWQpIHtcbiAgICAgICAgICAgICAgY3VycmVudC5wdXNoKG5leHQpO1xuICAgICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY3VycmVudC5sZW5ndGggPiAwKSBjaHVua3MucHVzaChjdXJyZW50KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBTdGVwcyB3aG9zZSBxdWV1ZSBtZXNzYWdlcyBUSElTIEZMVVNIIHdpbGwgcHVibGlzaCAodGhlIGVhZ2VyXG4gICAgICAgIC8vIGNyZWF0ZXMpLCByZWNvcmRlZCBiZWZvcmUgYW55IGNodW5rIHNldHRsZXMgc28gdGhlIGNhbGxlcidzXG4gICAgICAgIC8vIGRpc3BhdGNoIHBhc3MgKHdoaWNoIHJ1bnMgb2ZmIHRoZSBoYW5kbGVyJ3MgcmV0dXJuKSBza2lwcyB0aGVtLlxuICAgICAgICAvLyBUaGUgc2VuZHMgYXJlIGd1YXJhbnRlZWQtb3ItZmFpbGVkIGJ5IHRoZSB0cmFpbGluZyB3b3JrIHRoZVxuICAgICAgICAvLyBjYWxsZXIgam9pbnMgYmVmb3JlIGFja2luZywgc28gXCJ3aWxsIGJlIHB1Ymxpc2hlZCBieSB0aGlzIGZsdXNoXCJcbiAgICAgICAgLy8gYW5kIFwiYWxyZWFkeSBwdWJsaXNoZWRcIiBhcmUgZXF1aXZhbGVudCBmcm9tIHRoZSBjYWxsZXIncyBzaWRlLlxuICAgICAgICBjb25zdCBwdWJsaXNoRWFnZXJTdGVwcyA9IHN0ZXBEaXNwYXRjaCAhPT0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAocHVibGlzaEVhZ2VyU3RlcHMpIHtcbiAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgICAgICAgIGlmIChlbnRyeS5raW5kID09PSAnc3RlcCcpIHtcbiAgICAgICAgICAgICAgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChlbnRyeS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUYWxsaWVzIGZvciB0aGUgZm9yZWlnbi1pbnRlcmxlYXZpbmcgZGlhZ25vc3RpYywgZm9sZGVkIGFjcm9zc1xuICAgICAgICAvLyB0aGUgY29uY3VycmVudCBjaHVua3MgYW5kIHJlYWQgb25jZSBhbGwgb2YgdGhlbSBzZXR0bGVkLlxuICAgICAgICBsZXQgY29tbWl0dGVkQ291bnQgPSAwO1xuICAgICAgICBsZXQgbWF4Q29tbWl0dGVkU2xvdDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIGNvbnN0IGNvbW1pdENodW5rID0gYXN5bmMgKGNodW5rOiB0eXBlb2YgZW50cmllcyk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgIC8vIEFuY2hvcnMgZm9yIHRoZSBwcmUtY2xhaW1lZCBzdGVwcycgdGVsZW1ldHJ5OiB0aGUgUE9TVCBpbnN0YW50XG4gICAgICAgICAgLy8gaXMgdGhlIGNsYWltJ3MgXCJzdGFydCBQT1NUIHNlbnRcIiAoUlNGUydzIGVuZCksIHRoZSByZXR1cm4gaXMgdGhlXG4gICAgICAgICAgLy8gY2xhaW0ncyBjb21wbGV0aW9uIChUVFIncyBUNiksIHRoZSBzYW1lIHR3byBpbnN0YW50cyB0aGUgbGF6eVxuICAgICAgICAgIC8vIGNsYWltJ3Mgb3duIFBPU1Qgd291bGQgaGF2ZSBwcm9kdWNlZC5cbiAgICAgICAgICBjb25zdCBiYXRjaFBvc3RTZW50QXRNcyA9IERhdGUubm93KCk7XG4gICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBiYXRjaEZhbm91dEVsaWdpYmxlIGltcGxpZXMgcHJlc2VuY2VcbiAgICAgICAgICBjb25zdCB7IHJlc3VsdHMgfSA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGVCYXRjaCEoXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGNodW5rLm1hcCgoZW50cnkpID0+ICh7XG4gICAgICAgICAgICAgIGV2ZW50OiBlbnRyeS5ldmVudCxcbiAgICAgICAgICAgICAgLy8gVGhlIHN0YXJ0ZWQgcm93IGlzIHRoZSBzdGVwJ3MgZXhlY3V0aW5nIGNsYWltLCBzbyBpdCBjYXJyaWVzXG4gICAgICAgICAgICAgIC8vIHRoZSBjb21wdXRlLWluc3RhbmNlIGF0dHJpYnV0aW9uIHRoZSBzaW5nbGUgY2xhaW0gc2VuZHMgdmlhXG4gICAgICAgICAgICAgIC8vIENyZWF0ZUV2ZW50UGFyYW1zLlxuICAgICAgICAgICAgICAuLi4oZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJ1xuICAgICAgICAgICAgICAgID8geyBjb21wdXRlSW5zdGFuY2VJZDogQ09NUFVURV9JTlNUQU5DRV9JRCB9XG4gICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICB9KSksXG4gICAgICAgICAgICAvLyBQZXItd3JpdGUgcmVxdWVzdCBhdHRyaWJ1dGlvbiwgc2FtZSBhcyB0aGUgc2luZ2xlIHBhdGgnc1xuICAgICAgICAgICAgLy8gY3JlYXRlR3VhcmRlZCjigKYsIHsgcmVxdWVzdElkIH0pLlxuICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgY2xhaW1Db21wbGV0ZWRBdE1zID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICBmb3IgKGNvbnN0IFtpbmRleCwgaXRlbV0gb2YgcmVzdWx0cy5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGVudHJ5ID0gY2h1bmtbaW5kZXhdO1xuICAgICAgICAgICAgaWYgKGl0ZW0uZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBpZiAoZW50cnkua2luZCA9PT0gJ3N0ZXAnKSB7XG4gICAgICAgICAgICAgICAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcy5hZGQoZW50cnkuY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJykge1xuICAgICAgICAgICAgICAgIC8vIFRoZSBwYWlyIGNvbW1pdHRlZDogdGhpcyBpbnZvY2F0aW9uIG93bnMgdGhlIHN0ZXAgYW5kIHRoZVxuICAgICAgICAgICAgICAgIC8vIGNhbGxlciBydW5zIHRoZSBib2R5IHdpdGggbm8gY2xhaW0gb2YgaXRzIG93bi4gVGhlXG4gICAgICAgICAgICAgICAgLy8gcmVhZGJhY2sgZW50aXR5IGlzIGF1dGhvcml0YXRpdmUgd2hlcmUgcHJlc2VudDsgYSBXb3JsZFxuICAgICAgICAgICAgICAgIC8vIHRoYXQgb21pdHRlZCBpdCBnZXRzIHRoZSBzYW1lIGxvY2FsbHkgc3ludGhlc2l6ZWQgcnVubmluZ1xuICAgICAgICAgICAgICAgIC8vIGF0dGVtcHQtMSB0aGUgb3B0aW1pc3RpYyBwYXRoIGV4ZWN1dGVzIGFnYWluc3QuIEVpdGhlclxuICAgICAgICAgICAgICAgIC8vIHdheSB0aGUgaW5wdXQgaXMgcmUtYXR0YWNoZWQgbG9jYWxseTogYmF0Y2ggcmVzcG9uc2VzXG4gICAgICAgICAgICAgICAgLy8gcmV0dXJuIHJlZnMgbGF6aWx5LCBhbmQgdGhlIGJvZHkncyBoeWRyYXRpb24gd2FudHMgdGhlXG4gICAgICAgICAgICAgICAgLy8gZXhhY3QgYnl0ZXMgdGhlIHBhaXIncyBjcmVhdGVkIHJvdyBjYXJyaWVkLiAoVGhlIGNyZWF0ZWRcbiAgICAgICAgICAgICAgICAvLyByb3cncyBzdWNjZXNzIGlzIGRlbGliZXJhdGVseSBOT1QgbWVtYmVyc2hpcCBpblxuICAgICAgICAgICAgICAgIC8vIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHM6IGZvciBpbmxpbmUgc3RlcHMgb3duZXJzaGlwIGlzXG4gICAgICAgICAgICAgICAgLy8gdGhlIHN0YXJ0ZWQgcm93J3MgdmVyZGljdCwgYW5kIHRoZSBjYWxsZXIncyBkaXNwYXRjaCBwYXNzXG4gICAgICAgICAgICAgICAgLy8gc2tpcHMgaW5saW5lIGNvcnJlbGF0aW9uIGlkcyByZWdhcmRsZXNzLilcbiAgICAgICAgICAgICAgICBjb25zdCBkZWh5ZHJhdGVkID0gbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZC5nZXQoXG4gICAgICAgICAgICAgICAgICBlbnRyeS5jb3JyZWxhdGlvbklkXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAoZGVoeWRyYXRlZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAvLyBVbnJlYWNoYWJsZTogdGhlIHNhbWUgcHJlcCBvcCB0aGF0IGVucXVldWVkIHRoZSBwYWlyIHNldFxuICAgICAgICAgICAgICAgICAgLy8gdGhpcyBlbnRyeSwgYW5kIHRoZSBmbHVzaCBhd2FpdGVkIGV2ZXJ5IHByZXAgYWJvdmUuXG4gICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgLy8gTm90IGZyZWUgaWYgaXQgZXZlciBmaXJlcywgdGhvdWdoOiB0aGUgcGFpciBpcyBhbHJlYWR5XG4gICAgICAgICAgICAgICAgICAvLyBkdXJhYmxlIGhlcmUsIHNvIHRoaXMgdGhyb3dzIHdpdGggdGhlIHN0ZXAgY2xhaW1lZCBhbmRcbiAgICAgICAgICAgICAgICAgIC8vIGl0cyBib2R5IG5ldmVyIHJ1bi4gVGhlIGRlbGl2ZXJ5IGZhaWxzLCBhbmQgcmVkZWxpdmVyeVxuICAgICAgICAgICAgICAgICAgLy8gcmVjb3ZlcnMgaXQgdGhyb3VnaCBvd25lZC1yZWNvdmVyeSAodGhlIHN0ZXAgY2FycmllcyB0aGlzXG4gICAgICAgICAgICAgICAgICAvLyBtZXNzYWdlJ3Mgb3duZXJzaGlwIHN0YW1wKSByYXRoZXIgdGhhbiB0aGUgcmVxdWVzdCBqdXN0XG4gICAgICAgICAgICAgICAgICAvLyBmYWlsaW5nIGNsZWFubHkuXG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dXb3JsZEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgbm8gZGVoeWRyYXRlZCBpbnB1dCBmb3IgcHJlLWNsYWltZWQgc3RlcCAke2VudHJ5LmNvcnJlbGF0aW9uSWR9YCxcbiAgICAgICAgICAgICAgICAgICAgeyBzdGF0dXM6IDUwMCB9XG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0ZWRTdGVwOiBTdGFydGVkU3RlcCA9IGl0ZW0uc3RlcD8uc3RhcnRlZEF0XG4gICAgICAgICAgICAgICAgICA/IHsgLi4uaXRlbS5zdGVwLCBzdGFydGVkQXQ6IGl0ZW0uc3RlcC5zdGFydGVkQXQgfVxuICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcElkOiBlbnRyeS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBkZWh5ZHJhdGVkLnN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHN0YXR1czogJ3J1bm5pbmcnLFxuICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQ6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgICAgc3RhcnRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaW5saW5lQ2xhaW1zLnNldChlbnRyeS5jb3JyZWxhdGlvbklkLCB7XG4gICAgICAgICAgICAgICAgICBvd25lZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgIHN0ZXA6IHtcbiAgICAgICAgICAgICAgICAgICAgLi4uc3RhcnRlZFN0ZXAsXG4gICAgICAgICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkLmRlaHlkcmF0ZWRJbnB1dCxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBiYXRjaFBvc3RTZW50QXRNcyxcbiAgICAgICAgICAgICAgICAgIGNsYWltQ29tcGxldGVkQXRNcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpdGVtLnN0YXR1cyA9PT0gNDA5KSB7XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBlbnRyeS5raW5kID09PSAnaW5saW5lLWNyZWF0ZWQnIHx8XG4gICAgICAgICAgICAgICAgZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJ1xuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgcGFpciBsb3N0IGl0cyBhdG9taWMgY3JlYXRlLWNsYWltOiBhIGNvbmN1cnJlbnQgd3JpdGVyXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBvd25zIHRoaXMgc3RlcCAoYW4gZWFybGllciBkZWxpdmVyeSdzIGNyZWF0ZSwgb3IgYVxuICAgICAgICAgICAgICAgIC8vIHJhY2luZyBoYW5kbGVyJ3MgY2xhaW0pLiBSZWNvcmRlZCBhcyBhIGxvc3QgY2xhaW06IHRoZVxuICAgICAgICAgICAgICAgIC8vIGNhbGxlcidzIGV4ZWN1dGVTdGVwIHJldHVybnMgYHNraXBwZWRgIHdpdGhvdXQgcnVubmluZyB0aGVcbiAgICAgICAgICAgICAgICAvLyBib2R5LCB0aGUgc2FtZSBvdXRjb21lIGFzIGxvc2luZyB0aGUgbGF6eSBjbGFpbS4gQSBXb3JsZFxuICAgICAgICAgICAgICAgIC8vIHRoYXQgZm9sZHMgdGhlIHBhaXIgcmVwb3J0cyB0aGUgNDA5IG9uIGJvdGggcm93cyAoc2V0XG4gICAgICAgICAgICAgICAgLy8gdHdpY2UsIGhhcm1sZXNzKTsgb25lIHRoYXQgZXZhbHVhdGVzIHJvd3MgaW5kZXBlbmRlbnRseVxuICAgICAgICAgICAgICAgIC8vIGhhcyB0aGUgc3RhcnRlZCByb3cgKHByb2Nlc3NlZCBzZWNvbmQpIGRlY2lkZSwgd2hpY2ggaXNcbiAgICAgICAgICAgICAgICAvLyBleGFjdGx5IHRoZSBzaW5nbGUgcGF0aCdzIHNlbWFudGljcyAoY3JlYXRlIGxvc3QgKyBjbGFpbVxuICAgICAgICAgICAgICAgIC8vIHdvbiBzdGlsbCBydW5zIHRoZSBib2R5OyBjcmVhdGUgd29uICsgY2xhaW0gbG9zdCBza2lwcykuXG4gICAgICAgICAgICAgICAgaW5saW5lQ2xhaW1zLnNldChlbnRyeS5jb3JyZWxhdGlvbklkLCB7IG93bmVkOiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0lubGluZSBzdGVwIHByZS1jbGFpbSBsb3N0LCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBlbnRyeS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgbWVzc2FnZTogaXRlbS5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIFNhbWUgdG9sZXJhbmNlIGFzIHRoZSBzaW5nbGUgcGF0aCdzIEVudGl0eUNvbmZsaWN0RXJyb3I6IGFcbiAgICAgICAgICAgICAgLy8gY29uY3VycmVudCBvciBlYXJsaWVyIGRlbGl2ZXJ5IGFscmVhZHkgY3JlYXRlZCBpdC5cbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgIGVudHJ5LmtpbmQgPT09ICdzdGVwJ1xuICAgICAgICAgICAgICAgICAgPyAnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZydcbiAgICAgICAgICAgICAgICAgIDogJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogZW50cnkuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGl0ZW0ubWVzc2FnZSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93V29ybGRFcnJvcihcbiAgICAgICAgICAgICAgYGJhdGNoZWQgJHtlbnRyeS5ldmVudC5ldmVudFR5cGV9IGZvciAke2VudHJ5LmNvcnJlbGF0aW9uSWR9IGAgK1xuICAgICAgICAgICAgICAgIGBmYWlsZWQ6ICR7aXRlbS5lcnJvcn06ICR7aXRlbS5tZXNzYWdlfWAsXG4gICAgICAgICAgICAgIHsgc3RhdHVzOiBpdGVtLnN0YXR1cyB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBIaWdoZXN0IHNsb3QgdGhpcyBjaHVuayBjb21taXR0ZWQ6IHRoZSBjZWlsaW5nIHRoZSBjYWxsZXIgZm9sZHNcbiAgICAgICAgICAvLyBpbnRvIHRoZSBpbmxpbmUgZXhlY3V0aW9ucycgc2xvdCBzbmFwc2hvdCAoc2VlXG4gICAgICAgICAgLy8gU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQuYmF0Y2hDb21taXR0ZWRTbG90Q2VpbGluZykgYW5kIG9uZSBpbnB1dFxuICAgICAgICAgIC8vIG9mIHRoZSBpbnRlcmxlYXZpbmcgZGlhZ25vc3RpYy5cbiAgICAgICAgICBjb25zdCBjaHVua01heFNsb3QgPSBtYXhFdmVudFNsb3QoXG4gICAgICAgICAgICByZXN1bHRzLmZsYXRNYXAoKGl0ZW0pID0+XG4gICAgICAgICAgICAgIGl0ZW0uZXJyb3IgPT09IHVuZGVmaW5lZCAmJiBpdGVtLmV2ZW50ID8gW2l0ZW0uZXZlbnRdIDogW11cbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGNodW5rTWF4U2xvdCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAoYmF0Y2hDb21taXR0ZWRTbG90Q2VpbGluZyA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICAgIGNodW5rTWF4U2xvdCA+IGJhdGNoQ29tbWl0dGVkU2xvdENlaWxpbmcpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBiYXRjaENvbW1pdHRlZFNsb3RDZWlsaW5nID0gY2h1bmtNYXhTbG90O1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb21taXR0ZWRDb3VudCArPSByZXN1bHRzLmZpbHRlcihcbiAgICAgICAgICAgIChpdGVtKSA9PiBpdGVtLmVycm9yID09PSB1bmRlZmluZWRcbiAgICAgICAgICApLmxlbmd0aDtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBjaHVua01heFNsb3QgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgKG1heENvbW1pdHRlZFNsb3QgPT09IHVuZGVmaW5lZCB8fCBjaHVua01heFNsb3QgPiBtYXhDb21taXR0ZWRTbG90KVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgbWF4Q29tbWl0dGVkU2xvdCA9IGNodW5rTWF4U2xvdDtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUHVibGlzaCB0aGUgY2h1bmsncyBlYWdlciBzdGVwcycgcXVldWUgbWVzc2FnZXMgdGhlIG1vbWVudCBJVFNcbiAgICAgICAgLy8gY3JlYXRlcyBhcmUgZHVyYWJsZSwgdGhlIHBlci1jaHVuayBoYWxmIG9mIHB1Ymxpc2gtYWZ0ZXItY3JlYXRlLlxuICAgICAgICAvLyBTYW1lIG1lc3NhZ2Ugc2hhcGUgYW5kIHN0ZXAtaWRlbnRpdHktc2NvcGVkIGlkZW1wb3RlbmN5IGtleSBhcyB0aGVcbiAgICAgICAgLy8gY2FsbGVyJ3MgZGlzcGF0Y2ggcGFzcywgc28gYW55dGhpbmcgZG91YmxlLXB1Ymxpc2hlZCBkZWR1cGVzLlxuICAgICAgICBjb25zdCBwdWJsaXNoQ2h1bmtTdGVwcyA9IGFzeW5jIChcbiAgICAgICAgICBjaHVuazogdHlwZW9mIGVudHJpZXNcbiAgICAgICAgKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgaWYgKCFwdWJsaXNoRWFnZXJTdGVwcykgcmV0dXJuO1xuICAgICAgICAgIGNvbnN0IHN0ZXBFbnRyaWVzID0gY2h1bmsuZmlsdGVyKChlbnRyeSkgPT4gZW50cnkua2luZCA9PT0gJ3N0ZXAnKTtcbiAgICAgICAgICBpZiAoc3RlcEVudHJpZXMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICAgICAgY29uc3QgdHJhY2VDYXJyaWVyID0gYXdhaXQgZ2V0U3RlcERpc3BhdGNoVHJhY2VDYXJyaWVyKCk7XG4gICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICBzdGVwRW50cmllcy5tYXAoKGVudHJ5KSA9PlxuICAgICAgICAgICAgICBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBwdWJsaXNoRWFnZXJTdGVwcyBpbXBsaWVzIHByZXNlbmNlXG4gICAgICAgICAgICAgICAgc3RlcERpc3BhdGNoIS5xdWV1ZU5hbWUsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICBzdGVwSWQ6IGVudHJ5LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdHlsZS9ub05vbk51bGxBc3NlcnRpb246IHNldCBvbiBldmVyeSAnc3RlcCcgZW50cnkgYXQgZW5xdWV1ZVxuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IGVudHJ5LnN0ZXBOYW1lISxcbiAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgaWRlbXBvdGVuY3lLZXk6IHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5KFxuICAgICAgICAgICAgICAgICAgICBlbnRyeS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdHlsZS9ub05vbk51bGxBc3NlcnRpb246IHNldCBvbiBldmVyeSAnc3RlcCcgZW50cnkgYXQgZW5xdWV1ZVxuICAgICAgICAgICAgICAgICAgICBlbnRyeS5zdGVwTmFtZSFcbiAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICAgKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBMYXVuY2ggZXZlcnkgY2h1bmsncyBQT1NUIG5vdzsgY2hhaW4gZWFjaCBjaHVuaydzIHB1Ymxpc2hlcyBvbiBpdHNcbiAgICAgICAgLy8gT1dOIGNvbW1pdC4gQSBjaHVuayB3aG9zZSBjb21taXQgcmVqZWN0ZWQga2VlcHMgaXRzIG1lc3NhZ2VzXG4gICAgICAgIC8vIHVuc2VudCAodGhlIHJlamVjdGlvbiBmYWlscyB0aGUgZGVsaXZlcnk7IHJlZGVsaXZlcnkgcmUtY3JlYXRlc1xuICAgICAgICAvLyBhbmQgcmUtZGlzcGF0Y2hlcywgZGVkdXBlZCBieSB0aGUgaWRlbXBvdGVuY3kga2V5cykuXG4gICAgICAgIGNvbnN0IGNvbW1pdHMgPSBjaHVua3MubWFwKChjaHVuaykgPT4gY29tbWl0Q2h1bmsoY2h1bmspKTtcbiAgICAgICAgY29uc3QgcHVibGlzaGVzID0gY2h1bmtzLm1hcChhc3luYyAoY2h1bmssIGluZGV4KSA9PiB7XG4gICAgICAgICAgYXdhaXQgY29tbWl0c1tpbmRleF07XG4gICAgICAgICAgYXdhaXQgcHVibGlzaENodW5rU3RlcHMoY2h1bmspO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB0cmFpbGluZyA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgLy8gTGV0IGV2ZXJ5IHNpYmxpbmcgc2V0dGxlIGJlZm9yZSBzdXJmYWNpbmcgdGhlIGZpcnN0IGZhaWx1cmU6IGFcbiAgICAgICAgICAvLyBjaHVuayB0aGF0IGNvbW1pdHRlZCBtdXN0IHN0aWxsIGdldCBpdHMgcHVibGlzaGVzIG91dCBldmVuIHdoZW5cbiAgICAgICAgICAvLyBhbm90aGVyIGNodW5rIGZhaWxlZCwgYW5kIHRoZSBjYWxsZXIgYWNrcyBvbmx5IGFmdGVyIHRoaXNcbiAgICAgICAgICAvLyByZXNvbHZlcy5cbiAgICAgICAgICBjb25zdCBzZXR0bGVkID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFsuLi5jb21taXRzLCAuLi5wdWJsaXNoZXNdKTtcbiAgICAgICAgICAvLyBGb3JlaWduLWludGVybGVhdmluZyB2aXNpYmlsaXR5OiB0aGUgYmF0Y2ggZW5kcG9pbnQgaGFzIG5vXG4gICAgICAgICAgLy8gYnVtcC1hbmQtcmVwb3J0LCBzbyBldmVudHMgb3RoZXIgd3JpdGVycyBsYW5kZWQgYmV0d2VlbiB0aGVcbiAgICAgICAgICAvLyBzbmFwc2hvdCBhbmQgdGhlc2UgY29tbWl0cyBwdXNoZWQgdGhlIGZvbGQgdG8gaGlnaGVyIHNsb3RzXG4gICAgICAgICAgLy8gV0lUSE9VVCBoYW5kaW5nIHVzIHRoZSBza2lwcGVkIGV2ZW50cy4gU2FtZSBhY2NlcHRlZCBleHBvc3VyZVxuICAgICAgICAgIC8vIGFzIGEgZHJvcHBlZCB0cnVuY2F0ZWQgcmVwb3J0IG9uIHRoZSBzaW5nbGUgcGF0aDogdGhlIGxvY2FsXG4gICAgICAgICAgLy8gbG9nIHN0YXlzIGEgc3RyaWN0IHByZWZpeCBhbmQgdGhlIG5leHQgcmVsb2FkIG9ic2VydmVzIHRoZW0uXG4gICAgICAgICAgLy8gTG9nZ2VkIHNvIGEgYnVtcCBpcyBkaWFnbm9zYWJsZSByYXRoZXIgdGhhbiBzaWxlbnQuXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgZXhwZWN0ZWRGaXJzdFNsb3QgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgbWF4Q29tbWl0dGVkU2xvdCAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBpbnRlcmxlYXZlZCA9XG4gICAgICAgICAgICAgIG1heENvbW1pdHRlZFNsb3QgLSBleHBlY3RlZEZpcnN0U2xvdCArIDEgLSBjb21taXR0ZWRDb3VudDtcbiAgICAgICAgICAgIGlmIChpbnRlcmxlYXZlZCA+IDApIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnQmF0Y2hlZCBmYW4tb3V0IGNvbW1pdHRlZCBhYm92ZSBzbmFwc2hvdCcsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBleHBlY3RlZEZpcnN0U2xvdCxcbiAgICAgICAgICAgICAgICBtYXhDb21taXR0ZWRTbG90LFxuICAgICAgICAgICAgICAgIGNvbW1pdHRlZENvdW50LFxuICAgICAgICAgICAgICAgIGludGVybGVhdmVkLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgZmFpbHVyZSA9IHNldHRsZWQuZmluZChcbiAgICAgICAgICAgIChvdXRjb21lKTogb3V0Y29tZSBpcyBQcm9taXNlUmVqZWN0ZWRSZXN1bHQgPT5cbiAgICAgICAgICAgICAgb3V0Y29tZS5zdGF0dXMgPT09ICdyZWplY3RlZCdcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChmYWlsdXJlKSB0aHJvdyBmYWlsdXJlLnJlYXNvbjtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICAvLyBFVkVSWSBjaHVuayBjYXJyeWluZyBwYWlycyBnYXRlcyB0aGUgcmV0dXJuLCBub3QganVzdCB0aGUgZmlyc3Q6XG4gICAgICAgIC8vIGEgcGFpciB3aG9zZSBjb21taXQgdGhlIGNhbGxlciBoYXMgbm90IHNlZW4geWllbGRzIG5vXG4gICAgICAgIC8vIGBpbmxpbmVDbGFpbXNgIGVudHJ5LCBzbyB0aGUgY2FsbGVyIGZhbGxzIGJhY2sgdG8gYSBsYXp5XG4gICAgICAgIC8vIGBzdGVwX3N0YXJ0ZWRgIHRoYXQgd291bGQgcmFjZSB0aGlzIHNhbWUgZm9sZCdzIHN0aWxsLWluLWZsaWdodFxuICAgICAgICAvLyBwYWlyIGZvciB0aGUgc2FtZSBzdGVwLiBUb2RheSBwYWlycyBhbHdheXMgbGFuZCBpbiBvbmUgY2h1bmtcbiAgICAgICAgLy8gKHRoZXkgc29ydCBmaXJzdCwgYW5kIHR3byByb3dzIHBlciBpbmxpbmUgc3RlcCBmaXQgaW5zaWRlIG9uZVxuICAgICAgICAvLyBjaHVuaywgcGlubmVkIGJ5IGNvbnN0YW50cy50ZXN0LnRzKSwgc28gdGhpcyBpcyBhdCBtb3N0IG9uZVxuICAgICAgICAvLyBjb21taXQ7IHRoZSBmaWx0ZXIgaXMgd2hhdCBrZWVwcyB0aGUgcHJvcGVydHkgdHJ1ZSBpZiBlaXRoZXIgY2FwXG4gICAgICAgIC8vIG1vdmVzLlxuICAgICAgICBjb25zdCBwYWlyQ29tbWl0cyA9IGNodW5rcy5mbGF0TWFwKChjaHVuaywgaW5kZXgpID0+XG4gICAgICAgICAgY2h1bmsuc29tZSgoZW50cnkpID0+IGVudHJ5LmtpbmQgPT09ICdpbmxpbmUtc3RhcnRlZCcpXG4gICAgICAgICAgICA/IFtjb21taXRzW2luZGV4XV1cbiAgICAgICAgICAgIDogW11cbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGFsbG93RGVmZXJyZWRCYXRjaFdvcmspIHtcbiAgICAgICAgICAvLyBUaGUgdHJhaWxpbmcgd29yayBpcyB0aGUgY2FsbGVyJ3MgdG8gam9pbiBiZWZvcmUgYWNrLiBBdHRhY2ggYVxuICAgICAgICAgIC8vIGhhbmRsZXIgbm93IHNvIGEgcmVqZWN0aW9uIHRoYXQgcmFjZXMgdGhhdCBqb2luIChvciBhIGZvcmVncm91bmRcbiAgICAgICAgICAvLyBmYWlsdXJlIHRoYXQgcHJldmVudHMgdGhlIGNhbGxlciBmcm9tIGV2ZXIgcmVhY2hpbmcgaXQpIGlzIG5ldmVyXG4gICAgICAgICAgLy8gYW4gdW5oYW5kbGVkUmVqZWN0aW9uOyBhd2FpdGluZyB0aGUgcHJvbWlzZSBzdGlsbCBvYnNlcnZlcyBpdC5cbiAgICAgICAgICB0cmFpbGluZy5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICAgICAgZGVmZXJyZWRCYXRjaFdvcmsgPSB0cmFpbGluZztcbiAgICAgICAgICAvLyBPbmx5IHRoZSBwYWlyIGNodW5rcyBnYXRlIHRoZSByZXR1cm46IHRoZWlyIGNsYWltcyBhcmUgd2hhdCB0aGVcbiAgICAgICAgICAvLyBjYWxsZXIgc3RhcnRzIHRoZSBpbmxpbmUgYm9kaWVzIGZyb20uIFdpdGggbm8gcGFpcnMgdGhlcmUgaXNcbiAgICAgICAgICAvLyBub3RoaW5nIHRoZSBjYWxsZXIncyBwb3N0LXJldHVybiB3b3JrIHJlYWRzIGZyb20gdGhlIGNvbW1pdHMsXG4gICAgICAgICAgLy8gc28gbm90aGluZyBnYXRlcy5cbiAgICAgICAgICBpZiAocGFpckNvbW1pdHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocGFpckNvbW1pdHMpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIC8vIEEgcGFpciBjaHVuayBmYWlsZWQsIHNvIHRoaXMgcGhhc2UncyB3cml0ZSBzZXQgaXMgTk9UIHRoZVxuICAgICAgICAgICAgICAvLyBjYWxsZXIncyB0byBqb2luIGFueSBtb3JlOiBgZGVmZXJyZWRCYXRjaFdvcmtgIG5ldmVyXG4gICAgICAgICAgICAgIC8vIHJlYWNoZXMgaXQgb25jZSBoYW5kbGVTdXNwZW5zaW9uIHRocm93cy4gU2V0dGxlIHRoZSByZXN0XG4gICAgICAgICAgICAgIC8vIGJlZm9yZSB0aGUgcmVqZWN0aW9uIGVzY2FwZXMsIGZvciB0aGUgcmVhc29uIGBzZXR0bGVQaGFzZWBcbiAgICAgICAgICAgICAgLy8gZ2l2ZXM6IGEgc2libGluZyBjcmVhdGUgbGFuZGluZyBhZnRlciB0aGUgdGhyb3cgY29tbWl0cyBhblxuICAgICAgICAgICAgICAvLyBldmVudCBmcm9tIHRoZSBhYmFuZG9uZWQgcmVwbGF5J3Mgc2VlZGVkIHNlcXVlbmNlIGFuZCByYWNlc1xuICAgICAgICAgICAgICAvLyB0aGUgY2FsbGVyJ3MgcmVzdGFydCByZWxvYWQgd2hpbGUgZG9pbmcgc28uXG4gICAgICAgICAgICAgIGF3YWl0IHRyYWlsaW5nLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCB0cmFpbGluZztcbiAgICAgICAgfVxuICAgICAgfSkoKVxuICAgICk7XG4gIH1cblxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBhdHRyaWJ1dGVJdGVtcykge1xuICAgIG9wcy5wdXNoKFxuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgIC8vIEd1YXJkZWQgbGlrZSBldmVyeSBvdGhlciBzdXNwZW5zaW9uIHdyaXRlOiBhbiBhdHRyX3NldCBpcyBhXG4gICAgICAgICAgLy8gcmVwbGF5LWRlcml2ZWQgZXZlbnQgd2l0aCBhIGNvcnJlbGF0aW9uIGlkIGZyb20gdGhpcyByZXBsYXknc1xuICAgICAgICAgIC8vIHNlZWRlZCBzZXF1ZW5jZSwgc28gaXQgbXVzdCBub3QgbGFuZCBvbiBhIGxvZyB0aGUgcmVwbGF5IG5ldmVyXG4gICAgICAgICAgLy8gc2F3LiBSZWplY3RpbmcgaXQgaXMgY2hlYXA6IGEgcnVuIHdpdGggYXR0cmlidXRlIGV2ZW50cyBhbHJlYWR5XG4gICAgICAgICAgLy8gZm9yY2VzIGFuIGluLXByb2Nlc3MgcmVwbGF5LCBzbyB0aGUgcmVzdGFydCBjb3N0cyB0aGUgcmVwbGF5IGl0XG4gICAgICAgICAgLy8gd2FzIGdvaW5nIHRvIGRvIGFueXdheS5cbiAgICAgICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBldmVudFR5cGU6ICdhdHRyX3NldCcsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIGNoYW5nZXM6IHF1ZXVlSXRlbS5jaGFuZ2VzLFxuICAgICAgICAgICAgICAgIHdyaXRlcjogeyB0eXBlOiAnd29ya2Zsb3cnIH0sXG4gICAgICAgICAgICAgICAgLi4uKHF1ZXVlSXRlbS5hbGxvd1Jlc2VydmVkQXR0cmlidXRlc1xuICAgICAgICAgICAgICAgICAgPyB7IGFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzOiB0cnVlIH1cbiAgICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBhdHRyaWJ1dGUgZXZlbnQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChpc1dvcmxkVmFsaWRhdGlvbkZhaWx1cmUoZXJyKSkge1xuICAgICAgICAgICAgLy8gRGV0ZXJtaW5pc3RpYyB2YWxpZGF0aW9uIHJlamVjdGlvbiBmcm9tIHRoZSBXb3JsZCwgZS5nLiB0aGVcbiAgICAgICAgICAgIC8vIGN1bXVsYXRpdmUgcGVyLXJ1biBhdHRyaWJ1dGUgY2FwLCB3aGljaCBvbmx5IHRoZSBXb3JsZCBjYW5cbiAgICAgICAgICAgIC8vIGNoZWNrIGFnYWluc3QgdGhlIHJ1bidzIGV4aXN0aW5nIGF0dHJpYnV0ZXMuIFJlZGVsaXZlcmluZyB0aGVcbiAgICAgICAgICAgIC8vIG9yY2hlc3RyYXRvciBtZXNzYWdlIHJlcGxheXMgdGhlIHdvcmtmbG93IGludG8gdGhlIGV4YWN0IHNhbWVcbiAgICAgICAgICAgIC8vIHdyaXRlIGFuZCB0aGUgZXhhY3Qgc2FtZSByZWplY3Rpb24sIHNvIHJldHJ5aW5nIGNhbiBuZXZlclxuICAgICAgICAgICAgLy8gc3VjY2VlZC4gU3VyZmFjZSBpdCBhcyBhIEZhdGFsRXJyb3Igc28gdGhlIGNhbGxlciBmYWlscyB0aGVcbiAgICAgICAgICAgIC8vIHJ1biB3aXRoIGEgY2xlYXIgZXJyb3IgaW5zdGVhZCBvZiB3ZWRnaW5nIGl0IGluIHJlZGVsaXZlcnkuXG4gICAgICAgICAgICBjb25zdCBmYXRhbCA9IG5ldyBGYXRhbEVycm9yKFxuICAgICAgICAgICAgICBgc2V0QXR0cmlidXRlcyBmYWlsZWQgV29ybGQgdmFsaWRhdGlvbjogJHtcbiAgICAgICAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycilcbiAgICAgICAgICAgICAgfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBmYXRhbC5jYXVzZSA9IGVycjtcbiAgICAgICAgICAgIHRocm93IGZhdGFsO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSgpXG4gICAgKTtcbiAgfVxuXG4gIC8vIEF3YWl0IHRoZSBzdGVwX2NyZWF0ZWQgLyB3YWl0X2NyZWF0ZWQgZXZlbnQgY3JlYXRlcyBiZWZvcmUgcmV0dXJuaW5nLlxuICAvLyBUaGUgY2FsbGVyICh3b3JrZmxvd0VudHJ5cG9pbnQpIG9ubHkgZW5xdWV1ZXMgdGhlIHN0ZXAtZGlzcGF0Y2ggcXVldWVcbiAgLy8gbWVzc2FnZXMgQUZURVIgaGFuZGxlU3VzcGVuc2lvbiByZXNvbHZlcywgYW5kIHRoZSBxdWV1ZSBoYW5kbGVyIGFja3NcbiAgLy8gdGhlIG9yY2hlc3RyYXRvciBtZXNzYWdlIG9ubHkgYWZ0ZXIgdGhlIGNhbGxlciByZXNvbHZlcy4gU28gdGhlIHN0ZXBfY3JlYXRlZFxuICAvLyBldmVudHMgbXVzdCBiZSBkdXJhYmxlIGhlcmUsIGFuZCB0aGUgZGlzcGF0Y2ggc2VuZHMgbXVzdCBjb21wbGV0ZSBpbiB0aGUgY2FsbGVyLFxuICAvLyBhbGwgYmVmb3JlIGFjay4gSWYgdGhlIHByb2Nlc3MgY3Jhc2hlcyBiZWZvcmUgdGhpcyByZXNvbHZlcywgdGhlIG9yY2hlc3RyYXRvclxuICAvLyBtZXNzYWdlIGlzIG5vdCBhY2tlZCBhbmQgVlFTIHJlZGVsaXZlcnMsIHJlLWNyZWF0ZXMgdGhlIChpZGVtcG90ZW50KVxuICAvLyBzdGVwX2NyZWF0ZWQgYW5kIHJlLWRpc3BhdGNoZXMsIGFuZCByZWNvdmVycyB0aGUgcnVuIGluc3RlYWQgb2Ygb3JwaGFuaW5nIGl0LlxuICBhd2FpdCBzZXR0bGVQaGFzZShvcHMpO1xuXG4gIC8vIFRoZSBzdGVwLWlucHV0IGRlaHlkcmF0aW9ucyBhYm92ZSBoYXZlIHNldHRsZWQsIHNvIHRoZSBzaW5rIGlzIGZpbmFsLlxuICBjb25zdCByZXRhaW5lZFN0ZXBJbnB1dHNTYWZlID0gZ3Vlc3RDb2RlU3RhdHMuZXhlY3V0aW9ucy5sZW5ndGggPT09IDA7XG4gIGlmICghcmV0YWluZWRTdGVwSW5wdXRzU2FmZSkge1xuICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoXG4gICAgICAnU2VyaWFsaXppbmcgc3RlcCBpbnB1dHMgZXhlY3V0ZWQgd29ya2Zsb3cgY29kZTsgZmFsbGluZyBiYWNrIHRvIHJlcGxheSBpbnN0ZWFkIG9mIHJldGFpbmluZyB0aGUgVk0nLFxuICAgICAge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgZXhlY3V0aW9uczogZ3Vlc3RDb2RlU3RhdHMuZXhlY3V0aW9uc1xuICAgICAgICAgIC5zbGljZSgwLCA1KVxuICAgICAgICAgIC5tYXAoKGUpID0+IChlLmRldGFpbCA/IGAke2Uua2luZH0oJHtlLmRldGFpbH0pYCA6IGUua2luZCkpLFxuICAgICAgfVxuICAgICk7XG4gIH1cblxuICAvLyBSZWJ1aWxkIHRoZSBpbmxpbmUgYmF0Y2ggaW4gZGV0ZXJtaW5pc3RpYyBvcmRlci4gYGxhenlJbmxpbmVDb3JyZWxhdGlvbklkc2BcbiAgLy8gaXMgYSBTZXQgc2VlZGVkIGZyb20gdGhlIG9yZGVyZWQgZmlyc3QtTiBzbGljZSwgc28gaXRlcmF0aW5nIGl0IHByZXNlcnZlc1xuICAvLyBzdGVwSXRlbXMgb3JkZXI7IGV2ZXJ5IGlkIGluIGl0IHdhcyBzZXQgYnkgdGhlIGxhenkgYnJhbmNoIGFib3ZlLlxuICBjb25zdCBsYXp5SW5saW5lU3RlcHM6IFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0WydsYXp5SW5saW5lU3RlcHMnXSA9IFtdO1xuICBmb3IgKGNvbnN0IGNvcnJlbGF0aW9uSWQgb2YgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzKSB7XG4gICAgY29uc3QgbGF6eVN0ZXAgPSBsYXp5SW5saW5lQnlDb3JyZWxhdGlvbklkLmdldChjb3JyZWxhdGlvbklkKTtcbiAgICBpZiAobGF6eVN0ZXApIGxhenlJbmxpbmVTdGVwcy5wdXNoKGxhenlTdGVwKTtcbiAgfVxuXG4gIC8vIEZpbmQgdGhlIHNvb25lc3QgcGVuZGluZyB3YWl0IChtaW5pbXVtIHRpbWVvdXQpXG4gIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gIGxldCBzb29uZXN0V2FpdDogeyBzZWNvbmRzOiBudW1iZXI7IGNvcnJlbGF0aW9uSWQ6IHN0cmluZyB9IHwgdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiB3YWl0SXRlbXMpIHtcbiAgICBjb25zdCByZXN1bWVBdE1zID0gcXVldWVJdGVtLnJlc3VtZUF0LmdldFRpbWUoKTtcbiAgICBjb25zdCBkZWxheU1zID0gTWF0aC5tYXgoMTAwMCwgcmVzdW1lQXRNcyAtIG5vdyk7XG4gICAgY29uc3QgdGltZW91dFNlY29uZHMgPSBNYXRoLmNlaWwoZGVsYXlNcyAvIDEwMDApO1xuICAgIGlmICghc29vbmVzdFdhaXQgfHwgdGltZW91dFNlY29uZHMgPCBzb29uZXN0V2FpdC5zZWNvbmRzKSB7XG4gICAgICBzb29uZXN0V2FpdCA9IHtcbiAgICAgICAgc2Vjb25kczogdGltZW91dFNlY29uZHMsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5TdGF0dXMoJ3dvcmtmbG93X3N1c3BlbmRlZCcpLFxuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1N0ZXBzQ3JlYXRlZChzdGVwSXRlbXMubGVuZ3RoKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dIb29rc0NyZWF0ZWQoaG9va3NOZWVkaW5nQ3JlYXRpb24ubGVuZ3RoKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dXYWl0c0NyZWF0ZWQod2FpdEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uKGZhaWxlZFN0ZXBDb3JyZWxhdGlvbklkcy5zaXplID4gMFxuICAgICAgPyBBdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0ZhaWxlZFNlcmlhbGl6YXRpb24oXG4gICAgICAgICAgZmFpbGVkU3RlcENvcnJlbGF0aW9uSWRzLnNpemVcbiAgICAgICAgKVxuICAgICAgOiB7fSksXG4gICAgLi4uKHJlc2lsaWVudERpc3BhdGNoUmVjb3ZlcmVkID4gMFxuICAgICAgPyBBdHRyaWJ1dGUuU3RlcFJlc2lsaWVudERpc3BhdGNoUmVjb3ZlcmVkKHJlc2lsaWVudERpc3BhdGNoUmVjb3ZlcmVkKVxuICAgICAgOiB7fSksXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgcGVuZGluZ1N0ZXBzOiBzdGVwSXRlbXMsXG4gICAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcyxcbiAgICBmYWlsZWRTdGVwQ29ycmVsYXRpb25JZHMsXG4gICAgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzLFxuICAgIGxhenlJbmxpbmVTdGVwcyxcbiAgICBpbmxpbmVDbGFpbXMsXG4gICAgYmF0Y2hDb21taXR0ZWRTbG90Q2VpbGluZyxcbiAgICBkZWZlcnJlZEJhdGNoV29yayxcbiAgICAvLyBPbiBob29rIGNvbmZsaWN0IHRoZSBjYWxsZXIgcmUtaW52b2tlcyBpbW1lZGlhdGVseSBhbmQgbmV2ZXIgcmVhZHNcbiAgICAvLyB0aGUgd2FpdCB0aW1lb3V0LCBzbyBkb24ndCByZXBvcnQgb25lLlxuICAgIHdhaXRUaW1lb3V0OiBoYXNIb29rQ29uZmxpY3QgPyB1bmRlZmluZWQgOiBzb29uZXN0V2FpdCxcbiAgICBoYXNIb29rQ29uZmxpY3QsXG4gICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbixcbiAgICBoYXNBdHRyaWJ1dGVFdmVudHM6IGF0dHJpYnV0ZUl0ZW1zLmxlbmd0aCA+IDAsXG4gICAgaGFzSG9va0V2ZW50czogaG9va3NOZWVkaW5nQ3JlYXRpb24ubGVuZ3RoID4gMCxcbiAgICBob29rQ3JlYXRpb25NcyxcbiAgICByZXRhaW5lZFN0ZXBJbnB1dHNTYWZlLFxuICAgIHJlcG9ydGVkRXZlbnRDb3VudDogcmVwb3J0ZWRFdmVudHMsXG4gIH07XG59XG5cbi8qKlxuICogV2hldGhlciBhbiBgZXZlbnRzLmNyZWF0ZWAgcmVqZWN0aW9uIGlzIGRldGVybWluaXN0aWMgV29ybGQgdmFsaWRhdGlvblxuICogcmF0aGVyIHRoYW4gYSB0cmFuc2llbnQvc3RvcmFnZSBlcnJvci4gTG9jYWwgV29ybGRzXG4gKiAod29ybGQtbG9jYWwsIHdvcmxkLXBvc3RncmVzKSB0aHJvdyBgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yYCBkaXJlY3RseTtcbiAqIHJlbW90ZSBXb3JsZHMgc3VyZmFjZSB0aGUgZXF1aXZhbGVudCBzZXJ2ZXItc2lkZSByZWplY3Rpb24gYXMgYVxuICogYFdvcmtmbG93V29ybGRFcnJvcmAgd2l0aCBIVFRQIHN0YXR1cyA0MDAuIFRoZSBuYW1lIGNoZWNrIGNvdmVyc1xuICogYEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcmAgaW5zdGFuY2VzIGZyb20gYSBkaWZmZXJlbnQgY29weSBvZlxuICogYEB3b3JrZmxvdy93b3JsZGAgdGhhbiB0aGUgb25lIHRoaXMgcGFja2FnZSByZXNvbHZlZC5cbiAqL1xuZnVuY3Rpb24gaXNXb3JsZFZhbGlkYXRpb25GYWlsdXJlKGVycjogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoZXJyIGluc3RhbmNlb2YgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yICYmIGVyci5uYW1lID09PSAnQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yJykge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBXb3JrZmxvd1dvcmxkRXJyb3IuaXMoZXJyKSAmJiBlcnIuc3RhdHVzID09PSA0MDA7XG59XG4iXX0=
|