UNPKG

56.2 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Wrapper = exports.WrapperOptionDefaults = exports.createErrorResponse = exports.filename = exports.isGenerator = void 0;
4const childProcess = require("child_process");
5const process = require("process");
6const proctor = require("process-doctor");
7const util_1 = require("util");
8const serialize_1 = require("./serialize");
9const throttle_1 = require("./throttle");
10const error_1 = require("./error");
11const p = (val) => (0, util_1.inspect)(val, { compact: true, breakLength: Infinity });
12const isGenerator = (fn) => fn instanceof function* () { }.constructor ||
13 fn instanceof async function* () { }.constructor;
14exports.isGenerator = isGenerator;
15exports.filename = module.filename;
16function createErrorResponse(err, { call, startTime, logUrl, executionId }) {
17 return {
18 kind: "promise",
19 type: "reject",
20 value: (0, serialize_1.serializeReturnValue)(call.name, err, false),
21 isErrorObject: typeof err === "object" && err instanceof Error,
22 callId: call.callId,
23 remoteExecutionStartTime: startTime,
24 remoteExecutionEndTime: Date.now(),
25 logUrl,
26 executionId
27 };
28}
29exports.createErrorResponse = createErrorResponse;
30exports.WrapperOptionDefaults = {
31 wrapperLog: console.log,
32 childProcess: true,
33 childProcessMemoryLimitMb: 0,
34 childProcessTimeoutMs: 0,
35 childProcessEnvironment: {},
36 childDir: ".",
37 wrapperVerbose: false,
38 validateSerialization: true
39};
40const oomPattern = /Allocation failed - JavaScript heap out of memory/;
41const FAAST_CHILD_ENV = "FAAST_CHILD";
42class Wrapper {
43 constructor(fModule, options = {}) {
44 this.executing = false;
45 this.verbose = false;
46 this.funcs = {};
47 this.logLines = (msg) => {
48 let lines = msg.split("\n");
49 if (lines[lines.length - 1] === "") {
50 lines = lines.slice(0, lines.length - 1);
51 }
52 for (const line of lines) {
53 this.log(`[${this.childPid}]: ${line}`);
54 }
55 };
56 this.options = { ...exports.WrapperOptionDefaults, ...options };
57 this.log = this.options.wrapperLog;
58 this.verbose = this.options.wrapperVerbose;
59 this.funcs = fModule;
60 this.queue = new throttle_1.AsyncIterableQueue();
61 /* istanbul ignore if */
62 if (process.env[FAAST_CHILD_ENV]) {
63 this.options.childProcess = false;
64 this.log(`faast: started child process for module wrapper.`);
65 process.on("message", async (cc) => {
66 const startTime = Date.now();
67 try {
68 await this.execute({ ...cc, startTime }, {
69 onMessage: async (msg) => {
70 this.log(`Received message ${msg.kind}`);
71 process.send({ done: false, value: msg });
72 }
73 });
74 this.log(`Done with this.execute()`);
75 }
76 catch (err) {
77 this.log(err);
78 }
79 finally {
80 process.send({ done: true });
81 }
82 });
83 }
84 else {
85 if (!process.env.FAAST_SILENT) {
86 this.log(`faast: successful cold start.`);
87 }
88 }
89 }
90 lookupFunction(request) {
91 const { name, args } = request;
92 if (!name) {
93 throw new Error("Invalid function call request: no name");
94 }
95 const func = this.funcs[name];
96 if (!func) {
97 throw new Error(`Function named "${name}" not found`);
98 }
99 if (!args) {
100 throw new Error("Invalid arguments to function call");
101 }
102 return func;
103 }
104 stopCpuMonitoring() {
105 this.monitoringTimer && clearInterval(this.monitoringTimer);
106 this.monitoringTimer = undefined;
107 }
108 startCpuMonitoring(pid, callId) {
109 if (this.monitoringTimer) {
110 this.stopCpuMonitoring();
111 }
112 this.monitoringTimer = cpuMonitor(pid, 1000, (err, result) => {
113 if (err) {
114 this.log(`cpu monitor error: ${err}`);
115 }
116 if (result) {
117 this.queue.push({ kind: "cpumetrics", callId, metrics: result });
118 }
119 });
120 }
121 stop() {
122 this.stopCpuMonitoring();
123 if (this.child) {
124 this.log(`Stopping child process.`);
125 this.child.stdout.removeListener("data", this.logLines);
126 this.child.stderr.removeListener("data", this.logLines);
127 this.child.disconnect();
128 this.child.kill();
129 this.child = undefined;
130 this.executing = false;
131 }
132 }
133 async execute(callingContext, { errorCallback, onMessage, measureCpuUsage }) {
134 const processError = (err) => err instanceof Error && errorCallback ? errorCallback(err) : err;
135 try {
136 /* istanbul ignore if */
137 if (this.executing) {
138 this.log(`faast: warning: module wrapper execute is not re-entrant`);
139 throw new Error(`faast: module wrapper is not re-entrant`);
140 }
141 this.executing = true;
142 const { call, startTime, logUrl, executionId, instanceId } = callingContext;
143 const detail = { logUrl, executionId, instanceId };
144 const { callId } = call;
145 this.log(`calling: ${call.name}`);
146 this.log(` args: ${call.args}`);
147 this.log(` callId: ${callId}`);
148 // let startedMessageTimer: NodeJS.Timeout | undefined = setTimeout(
149 // () => messageCallback({ kind: "functionstarted", callId }),
150 // 2 * 1000
151 // );
152 // TODO: Add this code after the execute returns or yields its first value...
153 // if (startedMessageTimer) {
154 // clearTimeout(startedMessageTimer);
155 // startedMessageTimer = undefined;
156 // }
157 const memoryUsage = process.memoryUsage();
158 const memInfo = p(memoryUsage);
159 if (this.options.childProcess) {
160 if (!this.child) {
161 this.child = this.setupChildProcess();
162 }
163 this.verbose &&
164 this.log(`faast: invoking '${call.name}' in child process, memory: ${memInfo}`);
165 this.child.send(callingContext, err => {
166 /* istanbul ignore if */
167 if (err) {
168 this.log(`child send error: rejecting with ${err}`);
169 this.queue.push(Promise.reject(err));
170 }
171 });
172 if (measureCpuUsage) {
173 this.verbose &&
174 this.log(`Starting CPU monitor for pid ${this.child.pid}`);
175 // XXX CPU Monitoring not enabled for now.
176 // this.startCpuMonitoring(this.child.pid, callId);
177 }
178 let timer;
179 const timeout = this.options.childProcessTimeoutMs;
180 if (timeout) {
181 this.verbose && this.log(`Setting timeout: ${timeout}`);
182 timer = setTimeout(() => {
183 const error = new error_1.FaastError({
184 name: error_1.FaastErrorNames.ETIMEOUT,
185 info: { ...detail, functionName: call.name }
186 }, `Request exceeded timeout of ${timeout}ms`);
187 this.queue.push(Promise.reject(error));
188 this.stop();
189 }, timeout);
190 }
191 this.verbose && this.log(`awaiting async dequeue`);
192 try {
193 const promises = [];
194 for await (const result of this.queue) {
195 this.verbose && this.log(`Dequeuing ${p(result)}`);
196 if (result.kind === "promise" || result.kind === "iterator") {
197 result.logUrl = logUrl;
198 }
199 promises.push(onMessage(result));
200 }
201 await Promise.all(promises);
202 }
203 finally {
204 this.verbose && this.log(`Finalizing queue`);
205 this.stopCpuMonitoring();
206 timer && clearTimeout(timer);
207 this.queue.clear();
208 }
209 }
210 else {
211 this.verbose &&
212 this.log(`faast: Invoking '${call.name}', memory: ${memInfo}`);
213 const func = this.lookupFunction(call);
214 if (!func) {
215 throw new Error(`faast module wrapper: could not find function '${call.name}'`);
216 }
217 const args = (0, serialize_1.deserialize)(call.args);
218 let value;
219 try {
220 value = await func.apply(undefined, args);
221 this.verbose && this.log(`Finished call function`);
222 }
223 catch (err) {
224 this.log(`Function ${call.name} threw error: ${err}`);
225 throw err;
226 }
227 this.verbose &&
228 this.log(`returned value: ${p(value)}, type: ${typeof value}`);
229 const validate = this.options.validateSerialization;
230 const context = { type: "fulfill", callId, ...detail };
231 // Check for iterable.
232 if (value !== null && value !== undefined) {
233 if ((0, exports.isGenerator)(func)) {
234 let next = await value.next();
235 let sequence = 0;
236 while (true) {
237 this.verbose && this.log(`next: ${p(next)}`);
238 let result = {
239 ...context,
240 kind: "iterator",
241 value: (0, serialize_1.serializeReturnValue)(call.name, [next], validate),
242 sequence
243 };
244 if (next.done) {
245 result.remoteExecutionStartTime = startTime;
246 result.remoteExecutionEndTime = Date.now();
247 result.memoryUsage = memoryUsage;
248 }
249 await onMessage(result);
250 if (next.done) {
251 return;
252 }
253 sequence++;
254 next = await value.next();
255 }
256 }
257 }
258 await onMessage({
259 ...context,
260 kind: "promise",
261 value: (0, serialize_1.serializeReturnValue)(call.name, [value], validate),
262 remoteExecutionStartTime: startTime,
263 remoteExecutionEndTime: Date.now(),
264 memoryUsage
265 });
266 }
267 }
268 catch (err) {
269 this.log(`faast: wrapped function exception or promise rejection: ${err}`);
270 const response = createErrorResponse(processError(err), callingContext);
271 this.log(`Error response: ${(0, util_1.inspect)(response)}`);
272 await onMessage(response);
273 }
274 finally {
275 this.verbose && this.log(`Exiting execute`);
276 this.executing = false;
277 }
278 }
279 setupChildProcess() {
280 this.verbose && this.log(`faast: creating child process`);
281 let execArgv = process.execArgv.slice();
282 if (this.options.childProcessMemoryLimitMb) {
283 /* istanbul ignore next */
284 execArgv = process.execArgv.filter(arg => !arg.match(/^--max-old-space-size/) && !arg.match(/^--inspect/));
285 execArgv.push(`--max-old-space-size=${this.options.childProcessMemoryLimitMb}`);
286 }
287 const { childProcessEnvironment } = this.options;
288 const env = {
289 ...process.env,
290 ...childProcessEnvironment,
291 [FAAST_CHILD_ENV]: "true"
292 };
293 this.verbose && this.log(`Env: ${JSON.stringify(env)}`);
294 const forkOptions = {
295 silent: true,
296 env,
297 cwd: this.options.childDir,
298 execArgv
299 };
300 const child = childProcess.fork("./index.js", [], forkOptions);
301 this.childPid = child.pid;
302 child.stdout.setEncoding("utf8");
303 child.stderr.setEncoding("utf8");
304 let oom;
305 const detectOom = (chunk) => {
306 if (oomPattern.test(chunk)) {
307 oom = chunk;
308 }
309 };
310 child.stdout.on("data", this.logLines);
311 child.stderr.on("data", this.logLines);
312 child.stderr.on("data", detectOom);
313 child.on("message", (message) => {
314 this.verbose && this.log(`child message: resolving with ${p(message)}`);
315 if (message.done) {
316 this.queue.done();
317 }
318 else {
319 this.queue.push(message.value);
320 }
321 });
322 /* istanbul ignore next */
323 child.on("error", err => {
324 this.verbose && this.log(`child error: rejecting with ${err}`);
325 this.child = undefined;
326 this.queue.push(Promise.reject(err));
327 });
328 child.on("exit", (code, signal) => {
329 this.verbose && this.log(`child exit: code: ${code}, signal: ${signal}`);
330 this.child = undefined;
331 if (code) {
332 this.queue.push(Promise.reject(new Error(`Exited with error code ${code}`)));
333 }
334 else if (signal !== null && signal !== "SIGTERM") {
335 let errorMessage = `Aborted with signal ${signal}`;
336 if (signal === "SIGABRT" && oom) {
337 errorMessage += ` (${oom})`;
338 oom = undefined;
339 }
340 this.queue.push(Promise.reject(new Error(errorMessage)));
341 }
342 else {
343 this.verbose && this.log(`child exiting normally`);
344 }
345 });
346 return child;
347 }
348}
349exports.Wrapper = Wrapper;
350function cpuMonitor(pid, interval, callback) {
351 const start = Date.now();
352 const timer = setInterval(() => proctor.lookup(pid, (err, result) => {
353 if (err) {
354 callback(err);
355 return;
356 }
357 const { stime, utime } = result;
358 callback(err, result && {
359 stime: stime * 10,
360 utime: utime * 10,
361 elapsed: Date.now() - start
362 });
363 }), interval);
364 return timer;
365}
366//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JhcHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy93cmFwcGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDhDQUE4QztBQUM5QyxtQ0FBbUM7QUFDbkMsMENBQTBDO0FBQzFDLCtCQUErQjtBQUUvQiwyQ0FBZ0U7QUFDaEUseUNBQWdEO0FBRWhELG1DQUFzRDtBQUV0RCxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQVEsRUFBRSxFQUFFLENBQUMsSUFBQSxjQUFPLEVBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUV4RSxNQUFNLFdBQVcsR0FBRyxDQUFDLEVBQVksRUFBRSxFQUFFLENBQ3hDLEVBQUUsWUFBWSxRQUFRLENBQUMsTUFBSyxDQUFDLENBQUMsV0FBVztJQUN6QyxFQUFFLFlBQVksS0FBSyxTQUFTLENBQUMsTUFBSyxDQUFDLENBQUMsV0FBVyxDQUFDO0FBRnZDLFFBQUEsV0FBVyxlQUU0QjtBQUV2QyxRQUFBLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO0FBa0N4QyxTQUFnQixtQkFBbUIsQ0FDL0IsR0FBUSxFQUNSLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFrQjtJQUV4RCxPQUFPO1FBQ0gsSUFBSSxFQUFFLFNBQVM7UUFDZixJQUFJLEVBQUUsUUFBUTtRQUNkLEtBQUssRUFBRSxJQUFBLGdDQUFvQixFQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQztRQUNsRCxhQUFhLEVBQUUsT0FBTyxHQUFHLEtBQUssUUFBUSxJQUFJLEdBQUcsWUFBWSxLQUFLO1FBQzlELE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtRQUNuQix3QkFBd0IsRUFBRSxTQUFTO1FBQ25DLHNCQUFzQixFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7UUFDbEMsTUFBTTtRQUNO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bnQiOlsiaW1wb3J0ICogYXMgY2hpbGRQcm9jZXNzIGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgKiBhcyBwcm9jZXNzIGZyb20gXCJwcm9jZXNzXCI7XG5pbXBvcnQgKiBhcyBwcm9jdG9yIGZyb20gXCJwcm9jZXNzLWRvY3RvclwiO1xuaW1wb3J0IHsgaW5zcGVjdCB9IGZyb20gXCJ1dGlsXCI7XG5pbXBvcnQgeyBJdGVyYXRvclJlc3BvbnNlTWVzc2FnZSwgTWVzc2FnZSwgUHJvbWlzZVJlc3BvbnNlTWVzc2FnZSB9IGZyb20gXCIuL3Byb3ZpZGVyXCI7XG5pbXBvcnQgeyBkZXNlcmlhbGl6ZSwgc2VyaWFsaXplUmV0dXJuVmFsdWUgfSBmcm9tIFwiLi9zZXJpYWxpemVcIjtcbmltcG9ydCB7IEFzeW5jSXRlcmFibGVRdWV1ZSB9IGZyb20gXCIuL3Rocm90dGxlXCI7XG5pbXBvcnQgeyBBbnlGdW5jdGlvbiB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBGYWFzdEVycm9yLCBGYWFzdEVycm9yTmFtZXMgfSBmcm9tIFwiLi9lcnJvclwiO1xuXG5jb25zdCBwID0gKHZhbDogYW55KSA9PiBpbnNwZWN0KHZhbCwgeyBjb21wYWN0OiB0cnVlLCBicmVha0xlbmd0aDogSW5maW5pdHkgfSk7XG5cbmV4cG9ydCBjb25zdCBpc0dlbmVyYXRvciA9IChmbjogRnVuY3Rpb24pID0+XG4gICAgZm4gaW5zdGFuY2VvZiBmdW5jdGlvbiogKCkge30uY29uc3RydWN0b3IgfHxcbiAgICBmbiBpbnN0YW5jZW9mIGFzeW5jIGZ1bmN0aW9uKiAoKSB7fS5jb25zdHJ1Y3RvcjtcblxuZXhwb3J0IGNvbnN0IGZpbGVuYW1lID0gbW9kdWxlLmZpbGVuYW1lO1xuXG5leHBvcnQgaW50ZXJmYWNlIENhbGxJZCB7XG4gICAgY2FsbElkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbXBvbGluZSB7XG4gICAgdHJhbXBvbGluZTogQW55RnVuY3Rpb247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbXBvbGluZUZhY3Rvcnkge1xuICAgIGZpbGVuYW1lOiBzdHJpbmc7XG4gICAgbWFrZVRyYW1wb2xpbmU6ICh3cmFwcGVyOiBXcmFwcGVyKSA9PiBUcmFtcG9saW5lO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZ1bmN0aW9uQ2FsbCBleHRlbmRzIENhbGxJZCB7XG4gICAgYXJnczogc3RyaW5nO1xuICAgIG1vZHVsZVBhdGg6IHN0cmluZztcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgUmVzcG9uc2VRdWV1ZUlkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FsbGluZ0NvbnRleHQge1xuICAgIGNhbGw6IEZ1bmN0aW9uQ2FsbDtcbiAgICBzdGFydFRpbWU6IG51bWJlcjtcbiAgICBsb2dVcmw/OiBzdHJpbmc7XG4gICAgZXhlY3V0aW9uSWQ/OiBzdHJpbmc7XG4gICAgaW5zdGFuY2VJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNb2R1bGVUeXBlIHtcbiAgICBbbmFtZTogc3RyaW5nXTogYW55O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRXJyb3JSZXNwb25zZShcbiAgICBlcnI6IGFueSxcbiAgICB7IGNhbGwsIHN0YXJ0VGltZSwgbG9nVXJsLCBleGVjdXRpb25JZCB9OiBDYWxsaW5nQ29udGV4dFxuKTogUHJvbWlzZVJlc3BvbnNlTWVzc2FnZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAga2luZDogXCJwcm9taXNlXCIsXG4gICAgICAgIHR5cGU6IFwicmVqZWN0XCIsXG4gICAgICAgIHZhbHVlOiBzZXJpYWxpemVSZXR1cm5WYWx1ZShjYWxsLm5hbWUsIGVyciwgZmFsc2UpLFxuICAgICAgICBpc0Vycm9yT2JqZWN0OiB0eXBlb2YgZXJyID09PSBcIm9iamVjdFwiICYmIGVyciBpbnN0YW5jZW9mIEVycm9yLFxuICAgICAgICBjYWxsSWQ6IGNhbGwuY2FsbElkLFxuICAgICAgICByZW1vdGVFeGVjdXRpb25TdGFydFRpbWU6IHN0YXJ0VGltZSxcbiAgICAgICAgcmVtb3RlRXhlY3V0aW9uRW5kVGltZTogRGF0ZS5ub3coKSxcbiAgICAgICAgbG9nVXJsLFxuICAgICAgICBleGVjdXRpb25JZFxuICAgIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV3JhcHBlck9wdGlvbnMge1xuICAgIC8qKlxuICAgICAqIExvZ2dpbmcgZnVuY3Rpb24gZm9yIGNvbnNvbGUubG9nL3dhcm4vZXJyb3Igb3V0cHV0LiBPbmx5IGF2YWlsYWJsZSBpblxuICAgICAqIGNoaWxkIHByb2Nlc3MgbW9kZS4gVGhpcyBpcyBtYWlubHkgdXNlZnVsIGZvciBkZWJ1Z2dpbmcgdGhlIFwibG9jYWxcIlxuICAgICAqIG1vZGUgd2hpY2ggcnVucyBjb2RlIGxvY2FsbHkuIEluIHJlYWwgY2xvdWRzIHRoZSBsb2dzIHdpbGwgZW5kIHVwIGluIHRoZVxuICAgICAqIGNsb3VkIGxvZ2dpbmcgc2VydmljZSAoZS5nLiBDbG91ZHdhdGNoIExvZ3MsIG9yIEdvb2dsZSBTdGFja2RyaXZlciBsb2dzKS5cbiAgICAgKiBEZWZhdWx0cyB0byBjb25zb2xlLmxvZy5cbiAgICAgKi9cbiAgICB3cmFwcGVyTG9nPzogKG1zZzogc3RyaW5nKSA9PiB2b2lkO1xuICAgIGNoaWxkUHJvY2Vzcz86IGJvb2xlYW47XG4gICAgY2hpbGRQcm9jZXNzTWVtb3J5TGltaXRNYj86IG51bWJlcjtcbiAgICBjaGlsZFByb2Nlc3NUaW1lb3V0TXM/OiBudW1iZXI7XG4gICAgY2hpbGRQcm9jZXNzRW52aXJvbm1lbnQ/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICAgIGNoaWxkRGlyPzogc3RyaW5nO1xuICAgIHdyYXBwZXJWZXJib3NlPzogYm9vbGVhbjtcbiAgICB2YWxpZGF0ZVNlcmlhbGl6YXRpb24/OiBib29sZWFuO1xufVxuXG5leHBvcnQgY29uc3QgV3JhcHBlck9wdGlvbkRlZmF1bHRzOiBSZXF1aXJlZDxXcmFwcGVyT3B0aW9ucz4gPSB7XG4gICAgd3JhcHBlckxvZzogY29uc29sZS5sb2csXG4gICAgY2hpbGRQcm9jZXNzOiB0cnVlLFxuICAgIGNoaWxkUHJvY2Vzc01lbW9yeUxpbWl0TWI6IDAsXG4gICAgY2hpbGRQcm9jZXNzVGltZW91dE1zOiAwLFxuICAgIGNoaWxkUHJvY2Vzc0Vudmlyb25tZW50OiB7fSxcbiAgICBjaGlsZERpcjogXCIuXCIsXG4gICAgd3JhcHBlclZlcmJvc2U6IGZhbHNlLFxuICAgIHZhbGlkYXRlU2VyaWFsaXphdGlvbjogdHJ1ZVxufTtcblxudHlwZSBFcnJvckNhbGxiYWNrID0gKGVycjogRXJyb3IpID0+IEVycm9yO1xudHlwZSBNZXNzYWdlQ2FsbGJhY2sgPSAobXNnOiBNZXNzYWdlKSA9PiBQcm9taXNlPHZvaWQ+O1xuXG5leHBvcnQgaW50ZXJmYWNlIFdyYXBwZXJFeGVjdXRlT3B0aW9ucyB7XG4gICAgZXJyb3JDYWxsYmFjaz86IEVycm9yQ2FsbGJhY2s7XG4gICAgb25NZXNzYWdlOiBNZXNzYWdlQ2FsbGJhY2s7XG4gICAgbWVhc3VyZUNwdVVzYWdlPzogYm9vbGVhbjtcbn1cblxuY29uc3Qgb29tUGF0dGVybiA9IC9BbGxvY2F0aW9uIGZhaWxlZCAtIEphdmFTY3JpcHQgaGVhcCBvdXQgb2YgbWVtb3J5LztcblxuY29uc3QgRkFBU1RfQ0hJTERfRU5WID0gXCJGQUFTVF9DSElMRFwiO1xuXG5leHBvcnQgY2xhc3MgV3JhcHBlciB7XG4gICAgZXhlY3V0aW5nID0gZmFsc2U7XG4gICAgcHJvdGVjdGVkIHZlcmJvc2UgPSBmYWxzZTtcbiAgICBwcm90ZWN0ZWQgZnVuY3M6IE1vZHVsZVR5cGUgPSB7fTtcbiAgICBwcm90ZWN0ZWQgY2hpbGQ/OiBjaGlsZFByb2Nlc3MuQ2hpbGRQcm9jZXNzO1xuICAgIHByb3RlY3RlZCBjaGlsZFBpZD86IG51bWJlcjtcbiAgICBwcm90ZWN0ZWQgbG9nOiAobXNnOiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgcHJvdGVjdGVkIHF1ZXVlOiBBc3luY0l0ZXJhYmxlUXVldWU8TWVzc2FnZT47XG4gICAgcmVhZG9ubHkgb3B0aW9uczogUmVxdWlyZWQ8V3JhcHBlck9wdGlvbnM+O1xuICAgIHByb3RlY3RlZCBtb25pdG9yaW5nVGltZXI/OiBOb2RlSlMuVGltZXI7XG5cbiAgICBjb25zdHJ1Y3RvcihmTW9kdWxlOiBNb2R1bGVUeXBlLCBvcHRpb25zOiBXcmFwcGVyT3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IHsgLi4uV3JhcHBlck9wdGlvbkRlZmF1bHRzLCAuLi5vcHRpb25zIH07XG4gICAgICAgIHRoaXMubG9nID0gdGhpcy5vcHRpb25zLndyYXBwZXJMb2c7XG4gICAgICAgIHRoaXMudmVyYm9zZSA9IHRoaXMub3B0aW9ucy53cmFwcGVyVmVyYm9zZTtcbiAgICAgICAgdGhpcy5mdW5jcyA9IGZNb2R1bGU7XG4gICAgICAgIHRoaXMucXVldWUgPSBuZXcgQXN5bmNJdGVyYWJsZVF1ZXVlKCk7XG5cbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICAqL1xuICAgICAgICBpZiAocHJvY2Vzcy5lbnZbRkFBU1RfQ0hJTERfRU5WXSkge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmNoaWxkUHJvY2VzcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5sb2coYGZhYXN0OiBzdGFydGVkIGNoaWxkIHByb2Nlc3MgZm9yIG1vZHVsZSB3cmFwcGVyLmApO1xuICAgICAgICAgICAgcHJvY2Vzcy5vbihcIm1lc3NhZ2VcIiwgYXN5bmMgKGNjOiBDYWxsaW5nQ29udGV4dCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5leGVjdXRlKFxuICAgICAgICAgICAgICAgICAgICAgICAgeyAuLi5jYywgc3RhcnRUaW1lIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25NZXNzYWdlOiBhc3luYyBtc2cgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgUmVjZWl2ZWQgbWVzc2FnZSAke21zZy5raW5kfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLnNlbmQhKHsgZG9uZTogZmFsc2UsIHZhbHVlOiBtc2cgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgRG9uZSB3aXRoIHRoaXMuZXhlY3V0ZSgpYCk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2coZXJyKTtcbiAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLnNlbmQhKHsgZG9uZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghcHJvY2Vzcy5lbnYuRkFBU1RfU0lMRU5UKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2coYGZhYXN0OiBzdWNjZXNzZnVsIGNvbGQgc3RhcnQuYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbG9va3VwRnVuY3Rpb24ocmVxdWVzdDogb2JqZWN0KTogQW55RnVuY3Rpb24ge1xuICAgICAgICBjb25zdCB7IG5hbWUsIGFyZ3MgfSA9IHJlcXVlc3QgYXMgRnVuY3Rpb25DYWxsO1xuICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgZnVuY3Rpb24gY2FsbCByZXF1ZXN0OiBubyBuYW1lXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZnVuYyA9IHRoaXMuZnVuY3NbbmFtZV07XG4gICAgICAgIGlmICghZnVuYykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGdW5jdGlvbiBuYW1lZCBcIiR7bmFtZX1cIiBub3QgZm91bmRgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghYXJncykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBhcmd1bWVudHMgdG8gZnVuY3Rpb24gY2FsbFwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc3RvcENwdU1vbml0b3JpbmcoKSB7XG4gICAgICAgIHRoaXMubW9uaXRvcmluZ1RpbWVyICYmIGNsZWFySW50ZXJ2YWwodGhpcy5tb25pdG9yaW5nVGltZXIpO1xuICAgICAgICB0aGlzLm1vbml0b3JpbmdUaW1lciA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc3RhcnRDcHVNb25pdG9yaW5nKHBpZDogbnVtYmVyLCBjYWxsSWQ6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5tb25pdG9yaW5nVGltZXIpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcENwdU1vbml0b3JpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1vbml0b3JpbmdUaW1lciA9IGNwdU1vbml0b3IocGlkLCAxMDAwLCAoZXJyLCByZXN1bHQpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZyhgY3B1IG1vbml0b3IgZXJyb3I6ICR7ZXJyfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHRoaXMucXVldWUucHVzaCh7IGtpbmQ6IFwiY3B1bWV0cmljc1wiLCBjYWxsSWQsIG1ldHJpY3M6IHJlc3VsdCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc3RvcCgpIHtcbiAgICAgICAgdGhpcy5zdG9wQ3B1TW9uaXRvcmluZygpO1xuICAgICAgICBpZiAodGhpcy5jaGlsZCkge1xuICAgICAgICAgICAgdGhpcy5sb2coYFN0b3BwaW5nIGNoaWxkIHByb2Nlc3MuYCk7XG4gICAgICAgICAgICB0aGlzLmNoaWxkLnN0ZG91dCEucmVtb3ZlTGlzdGVuZXIoXCJkYXRhXCIsIHRoaXMubG9nTGluZXMpO1xuICAgICAgICAgICAgdGhpcy5jaGlsZC5zdGRlcnIhLnJlbW92ZUxpc3RlbmVyKFwiZGF0YVwiLCB0aGlzLmxvZ0xpbmVzKTtcbiAgICAgICAgICAgIHRoaXMuY2hpbGQhLmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgIHRoaXMuY2hpbGQhLmtpbGwoKTtcbiAgICAgICAgICAgIHRoaXMuY2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGluZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgZXhlY3V0ZShcbiAgICAgICAgY2FsbGluZ0NvbnRleHQ6IENhbGxpbmdDb250ZXh0LFxuICAgICAgICB7IGVycm9yQ2FsbGJhY2ssIG9uTWVzc2FnZSwgbWVhc3VyZUNwdVVzYWdlIH06IFdyYXBwZXJFeGVjdXRlT3B0aW9uc1xuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBwcm9jZXNzRXJyb3IgPSAoZXJyOiBhbnkpID0+XG4gICAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvckNhbGxiYWNrID8gZXJyb3JDYWxsYmFjayhlcnIpIDogZXJyO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICAqL1xuICAgICAgICAgICAgaWYgKHRoaXMuZXhlY3V0aW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2coYGZhYXN0OiB3YXJuaW5nOiBtb2R1bGUgd3JhcHBlciBleGVjdXRlIGlzIG5vdCByZS1lbnRyYW50YCk7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBmYWFzdDogbW9kdWxlIHdyYXBwZXIgaXMgbm90IHJlLWVudHJhbnRgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZXhlY3V0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnN0IHsgY2FsbCwgc3RhcnRUaW1lLCBsb2dVcmwsIGV4ZWN1dGlvbklkLCBpbnN0YW5jZUlkIH0gPSBjYWxsaW5nQ29udGV4dDtcbiAgICAgICAgICAgIGNvbnN0IGRldGFpbCA9IHsgbG9nVXJsLCBleGVjdXRpb25JZCwgaW5zdGFuY2VJZCB9O1xuICAgICAgICAgICAgY29uc3QgeyBjYWxsSWQgfSA9IGNhbGw7XG4gICAgICAgICAgICB0aGlzLmxvZyhgY2FsbGluZzogJHtjYWxsLm5hbWV9YCk7XG4gICAgICAgICAgICB0aGlzLmxvZyhgICAgYXJnczogJHtjYWxsLmFyZ3N9YCk7XG4gICAgICAgICAgICB0aGlzLmxvZyhgICAgY2FsbElkOiAke2NhbGxJZH1gKTtcbiAgICAgICAgICAgIC8vIGxldCBzdGFydGVkTWVzc2FnZVRpbWVyOiBOb2RlSlMuVGltZW91dCB8IHVuZGVmaW5lZCA9IHNldFRpbWVvdXQoXG4gICAgICAgICAgICAvLyAgICAgKCkgPT4gbWVzc2FnZUNhbGxiYWNrKHsga2luZDogXCJmdW5jdGlvbnN0YXJ0ZWRcIiwgY2FsbElkIH0pLFxuICAgICAgICAgICAgLy8gICAgIDIgKiAxMDAwXG4gICAgICAgICAgICAvLyApO1xuXG4gICAgICAgICAgICAvLyBUT0RPOiBBZGQgdGhpcyBjb2RlIGFmdGVyIHRoZSBleGVjdXRlIHJldHVybnMgb3IgeWllbGRzIGl0cyBmaXJzdCB2YWx1ZS4uLlxuICAgICAgICAgICAgLy8gaWYgKHN0YXJ0ZWRNZXNzYWdlVGltZXIpIHtcbiAgICAgICAgICAgIC8vICAgICBjbGVhclRpbWVvdXQoc3RhcnRlZE1lc3NhZ2VUaW1lcik7XG4gICAgICAgICAgICAvLyAgICAgc3RhcnRlZE1lc3NhZ2VUaW1lciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIC8vIH1cblxuICAgICAgICAgICAgY29uc3QgbWVtb3J5VXNhZ2UgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCk7XG4gICAgICAgICAgICBjb25zdCBtZW1JbmZvID0gcChtZW1vcnlVc2FnZSk7XG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNoaWxkUHJvY2Vzcykge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5jaGlsZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNoaWxkID0gdGhpcy5zZXR1cENoaWxkUHJvY2VzcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2coXG4gICAgICAgICAgICAgICAgICAgICAgICBgZmFhc3Q6IGludm9raW5nICcke2NhbGwubmFtZX0nIGluIGNoaWxkIHByb2Nlc3MsIG1lbW9yeTogJHttZW1JbmZvfWBcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkLnNlbmQoY2FsbGluZ0NvbnRleHQsIGVyciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAgKi9cbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2coYGNoaWxkIHNlbmQgZXJyb3I6IHJlamVjdGluZyB3aXRoICR7ZXJyfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKFByb21pc2UucmVqZWN0KGVycikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKG1lYXN1cmVDcHVVc2FnZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nKGBTdGFydGluZyBDUFUgbW9uaXRvciBmb3IgcGlkICR7dGhpcy5jaGlsZC5waWR9YCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIFhYWCBDUFUgTW9uaXRvcmluZyBub3QgZW5hYmxlZCBmb3Igbm93LlxuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzLnN0YXJ0Q3B1TW9uaXRvcmluZyh0aGlzLmNoaWxkLnBpZCwgY2FsbElkKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgdGltZXI7XG4gICAgICAgICAgICAgICAgY29uc3QgdGltZW91dCA9IHRoaXMub3B0aW9ucy5jaGlsZFByb2Nlc3NUaW1lb3V0TXM7XG4gICAgICAgICAgICAgICAgaWYgKHRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52ZXJib3NlICYmIHRoaXMubG9nKGBTZXR0aW5nIHRpbWVvdXQ6ICR7dGltZW91dH1gKTtcbiAgICAgICAgICAgICAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IEZhYXN0RXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBGYWFzdEVycm9yTmFtZXMuRVRJTUVPVVQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm86IHsgLi4uZGV0YWlsLCBmdW5jdGlvbk5hbWU6IGNhbGwubmFtZSB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgUmVxdWVzdCBleGNlZWRlZCB0aW1lb3V0IG9mICR7dGltZW91dH1tc2BcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucXVldWUucHVzaChQcm9taXNlLnJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIH0sIHRpbWVvdXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiYgdGhpcy5sb2coYGF3YWl0aW5nIGFzeW5jIGRlcXVldWVgKTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBmb3IgYXdhaXQgKGNvbnN0IHJlc3VsdCBvZiB0aGlzLnF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiYgdGhpcy5sb2coYERlcXVldWluZyAke3AocmVzdWx0KX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQua2luZCA9PT0gXCJwcm9taXNlXCIgfHwgcmVzdWx0LmtpbmQgPT09IFwiaXRlcmF0b3JcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5sb2dVcmwgPSBsb2dVcmw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKG9uTWVzc2FnZShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52ZXJib3NlICYmIHRoaXMubG9nKGBGaW5hbGl6aW5nIHF1ZXVlYCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RvcENwdU1vbml0b3JpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgdGltZXIgJiYgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5xdWV1ZS5jbGVhcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy52ZXJib3NlICYmXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nKGBmYWFzdDogSW52b2tpbmcgJyR7Y2FsbC5uYW1lfScsIG1lbW9yeTogJHttZW1JbmZvfWApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZ1bmMgPSB0aGlzLmxvb2t1cEZ1bmN0aW9uKGNhbGwpO1xuICAgICAgICAgICAgICAgIGlmICghZnVuYykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBgZmFhc3QgbW9kdWxlIHdyYXBwZXI6IGNvdWxkIG5vdCBmaW5kIGZ1bmN0aW9uICcke2NhbGwubmFtZX0nYFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBhcmdzID0gZGVzZXJpYWxpemUoY2FsbC5hcmdzKTtcbiAgICAgICAgICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBhd2FpdCBmdW5jLmFwcGx5KHVuZGVmaW5lZCwgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudmVyYm9zZSAmJiB0aGlzLmxvZyhgRmluaXNoZWQgY2FsbCBmdW5jdGlvbmApO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nKGBGdW5jdGlvbiAke2NhbGwubmFtZX0gdGhyZXcgZXJyb3I6ICR7ZXJyfWApO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMudmVyYm9zZSAmJlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgcmV0dXJuZWQgdmFsdWU6ICR7cCh2YWx1ZSl9LCB0eXBlOiAke3R5cGVvZiB2YWx1ZX1gKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHZhbGlkYXRlID0gdGhpcy5vcHRpb25zLnZhbGlkYXRlU2VyaWFsaXphdGlvbjtcbiAgICAgICAgICAgICAgICBjb25zdCBjb250ZXh0ID0geyB0eXBlOiBcImZ1bGZpbGxcIiwgY2FsbElkLCAuLi5kZXRhaWwgfSBhcyBjb25zdDtcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBmb3IgaXRlcmFibGUuXG5cbiAgICAgICAgICAgICAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNHZW5lcmF0b3IoZnVuYykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBuZXh0ID0gYXdhaXQgdmFsdWUubmV4dCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNlcXVlbmNlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52ZXJib3NlICYmIHRoaXMubG9nKGBuZXh0OiAke3AobmV4dCl9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlc3VsdDogSXRlcmF0b3JSZXNwb25zZU1lc3NhZ2UgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ6IFwiaXRlcmF0b3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHNlcmlhbGl6ZVJldHVyblZhbHVlKGNhbGwubmFtZSwgW25leHRdLCB2YWxpZGF0ZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcXVlbmNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBhcyBjb25zdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV4dC5kb25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5yZW1vdGVFeGVjdXRpb25TdGFydFRpbWUgPSBzdGFydFRpbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5yZW1vdGVFeGVjdXRpb25FbmRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0Lm1lbW9yeVVzYWdlID0gbWVtb3J5VXNhZ2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IG9uTWVzc2FnZShyZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXh0LmRvbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXF1ZW5jZSsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5leHQgPSBhd2FpdCB2YWx1ZS5uZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBhd2FpdCBvbk1lc3NhZ2Uoe1xuICAgICAgICAgICAgICAgICAgICAuLi5jb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICBraW5kOiBcInByb21pc2VcIixcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHNlcmlhbGl6ZVJldHVyblZhbHVlKGNhbGwubmFtZSwgW3ZhbHVlXSwgdmFsaWRhdGUpLFxuICAgICAgICAgICAgICAgICAgICByZW1vdGVFeGVjdXRpb25TdGFydFRpbWU6IHN0YXJ0VGltZSxcbiAgICAgICAgICAgICAgICAgICAgcmVtb3RlRXhlY3V0aW9uRW5kVGltZTogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgICAgICAgbWVtb3J5VXNhZ2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgIHRoaXMubG9nKGBmYWFzdDogd3JhcHBlZCBmdW5jdGlvbiBleGNlcHRpb24gb3IgcHJvbWlzZSByZWplY3Rpb246ICR7ZXJyfWApO1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBjcmVhdGVFcnJvclJlc3BvbnNlKHByb2Nlc3NFcnJvcihlcnIpLCBjYWxsaW5nQ29udGV4dCk7XG4gICAgICAgICAgICB0aGlzLmxvZyhgRXJyb3IgcmVzcG9uc2U6ICR7aW5zcGVjdChyZXNwb25zZSl9YCk7XG4gICAgICAgICAgICBhd2FpdCBvbk1lc3NhZ2UocmVzcG9uc2UpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgdGhpcy52ZXJib3NlICYmIHRoaXMubG9nKGBFeGl0aW5nIGV4ZWN1dGVgKTtcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0aW5nID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbG9nTGluZXMgPSAobXNnOiBzdHJpbmcpID0+IHtcbiAgICAgICAgbGV0IGxpbmVzID0gbXNnLnNwbGl0KFwiXFxuXCIpO1xuICAgICAgICBpZiAobGluZXNbbGluZXMubGVuZ3RoIC0gMV0gPT09IFwiXCIpIHtcbiAgICAgICAgICAgIGxpbmVzID0gbGluZXMuc2xpY2UoMCwgbGluZXMubGVuZ3RoIC0gMSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgICAgICAgICB0aGlzLmxvZyhgWyR7dGhpcy5jaGlsZFBpZH1dOiAke2xpbmV9YCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJvdGVjdGVkIHNldHVwQ2hpbGRQcm9jZXNzKCkge1xuICAgICAgICB0aGlzLnZlcmJvc2UgJiYgdGhpcy5sb2coYGZhYXN0OiBjcmVhdGluZyBjaGlsZCBwcm9jZXNzYCk7XG5cbiAgICAgICAgbGV0IGV4ZWNBcmd2ID0gcHJvY2Vzcy5leGVjQXJndi5zbGljZSgpO1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmNoaWxkUHJvY2Vzc01lbW9yeUxpbWl0TWIpIHtcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICAqL1xuICAgICAgICAgICAgZXhlY0FyZ3YgPSBwcm9jZXNzLmV4ZWNBcmd2LmZpbHRlcihcbiAgICAgICAgICAgICAgICBhcmcgPT4gIWFyZy5tYXRjaCgvXi0tbWF4LW9sZC1zcGFjZS1zaXplLykgJiYgIWFyZy5tYXRjaCgvXi0taW5zcGVjdC8pXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgZXhlY0FyZ3YucHVzaChcbiAgICAgICAgICAgICAgICBgLS1tYXgtb2xkLXNwYWNlLXNpemU9JHt0aGlzLm9wdGlvbnMuY2hpbGRQcm9jZXNzTWVtb3J5TGltaXRNYn1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBjaGlsZFByb2Nlc3NFbnZpcm9ubWVudCB9ID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBjb25zdCBlbnYgPSB7XG4gICAgICAgICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgICAgICAgIC4uLmNoaWxkUHJvY2Vzc0Vudmlyb25tZW50LFxuICAgICAgICAgICAgW0ZBQVNUX0NISUxEX0VOVl06IFwidHJ1ZVwiXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMudmVyYm9zZSAmJiB0aGlzLmxvZyhgRW52OiAke0pTT04uc3RyaW5naWZ5KGVudil9YCk7XG4gICAgICAgIGNvbnN0IGZvcmtPcHRpb25zOiBjaGlsZFByb2Nlc3MuRm9ya09wdGlvbnMgPSB7XG4gICAgICAgICAgICBzaWxlbnQ6IHRydWUsIC8vIHJlZGlyZWN0cyBzdGRvdXQgYW5kIHN0ZGVyciB0byBJUEMuXG4gICAgICAgICAgICBlbnYsXG4gICAgICAgICAgICBjd2Q6IHRoaXMub3B0aW9ucy5jaGlsZERpcixcbiAgICAgICAgICAgIGV4ZWNBcmd2XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgY2hpbGQgPSBjaGlsZFByb2Nlc3MuZm9yayhcIi4vaW5kZXguanNcIiwgW10sIGZvcmtPcHRpb25zKTtcbiAgICAgICAgdGhpcy5jaGlsZFBpZCA9IGNoaWxkLnBpZDtcblxuICAgICAgICBjaGlsZC5zdGRvdXQhLnNldEVuY29kaW5nKFwidXRmOFwiKTtcbiAgICAgICAgY2hpbGQuc3RkZXJyIS5zZXRFbmNvZGluZyhcInV0ZjhcIik7XG5cbiAgICAgICAgbGV0IG9vbTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBkZXRlY3RPb20gPSAoY2h1bms6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgaWYgKG9vbVBhdHRlcm4udGVzdChjaHVuaykpIHtcbiAgICAgICAgICAgICAgICBvb20gPSBjaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY2hpbGQuc3Rkb3V0IS5vbihcImRhdGFcIiwgdGhpcy5sb2dMaW5lcyk7XG4gICAgICAgIGNoaWxkLnN0ZGVyciEub24oXCJkYXRhXCIsIHRoaXMubG9nTGluZXMpO1xuICAgICAgICBjaGlsZC5zdGRlcnIhLm9uKFwiZGF0YVwiLCBkZXRlY3RPb20pO1xuICAgICAgICBjaGlsZC5vbihcIm1lc3NhZ2VcIiwgKG1lc3NhZ2U6IEl0ZXJhdG9yUmVzdWx0PE1lc3NhZ2U+KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiYgdGhpcy5sb2coYGNoaWxkIG1lc3NhZ2U6IHJlc29sdmluZyB3aXRoICR7cChtZXNzYWdlKX1gKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnF1ZXVlLmRvbmUoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKG1lc3NhZ2UudmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG4gICAgICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgZXJyID0+IHtcbiAgICAgICAgICAgIHRoaXMudmVyYm9zZSAmJiB0aGlzLmxvZyhgY2hpbGQgZXJyb3I6IHJlamVjdGluZyB3aXRoICR7ZXJyfWApO1xuICAgICAgICAgICAgdGhpcy5jaGlsZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMucXVldWUucHVzaChQcm9taXNlLnJlamVjdChlcnIpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNoaWxkLm9uKFwiZXhpdFwiLCAoY29kZSwgc2lnbmFsKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiYgdGhpcy5sb2coYGNoaWxkIGV4aXQ6IGNvZGU6ICR7Y29kZX0sIHNpZ25hbDogJHtzaWduYWx9YCk7XG4gICAgICAgICAgICB0aGlzLmNoaWxkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKGNvZGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnF1ZXVlLnB1c2goXG4gICAgICAgICAgICAgICAgICAgIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcihgRXhpdGVkIHdpdGggZXJyb3IgY29kZSAke2NvZGV9YCkpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2lnbmFsICE9PSBudWxsICYmIHNpZ25hbCAhPT0gXCJTSUdURVJNXCIpIHtcbiAgICAgICAgICAgICAgICBsZXQgZXJyb3JNZXNzYWdlID0gYEFib3J0ZWQgd2l0aCBzaWduYWwgJHtzaWduYWx9YDtcbiAgICAgICAgICAgICAgICBpZiAoc2lnbmFsID09PSBcIlNJR0FCUlRcIiAmJiBvb20pIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlICs9IGAgKCR7b29tfSlgO1xuICAgICAgICAgICAgICAgICAgICBvb20gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucXVldWUucHVzaChQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKSkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiYgdGhpcy5sb2coYGNoaWxkIGV4aXRpbmcgbm9ybWFsbHlgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBjaGlsZDtcbiAgICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3B1TWVhc3VyZW1lbnQge1xuICAgIHN0aW1lOiBudW1iZXI7XG4gICAgdXRpbWU6IG51bWJlcjtcbiAgICBlbGFwc2VkOiBudW1iZXI7XG59XG5cbmZ1bmN0aW9uIGNwdU1vbml0b3IoXG4gICAgcGlkOiBudW1iZXIsXG4gICAgaW50ZXJ2YWw6IG51bWJlcixcbiAgICBjYWxsYmFjazogKGVycj86IEVycm9yLCByZXN1bHQ/OiBDcHVNZWFzdXJlbWVudCkgPT4gdm9pZFxuKSB7XG4gICAgY29uc3Qgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHRpbWVyID0gc2V0SW50ZXJ2YWwoXG4gICAgICAgICgpID0+XG4gICAgICAgICAgICBwcm9jdG9yLmxvb2t1cChwaWQsIChlcnIsIHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCB7IHN0aW1lLCB1dGltZSB9ID0gcmVzdWx0O1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKFxuICAgICAgICAgICAgICAgICAgICBlcnIsXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCAmJiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGltZTogc3RpbWUgKiAxMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHV0aW1lOiB1dGltZSAqIDEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxhcHNlZDogRGF0ZS5ub3coKSAtIHN0YXJ0XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSksXG4gICAgICAgIGludGVydmFsXG4gICAgKTtcbiAgICByZXR1cm4gdGltZXI7XG59XG4iXX0=
\No newline at end of file