faastjs
Version:
Serverless batch computing made simple.
371 lines • 56.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Wrapper = exports.WrapperOptionDefaults = exports.createErrorResponse = exports.filename = exports.isGenerator = void 0;
const tslib_1 = require("tslib");
const child_process_1 = tslib_1.__importDefault(require("child_process"));
const process_1 = tslib_1.__importDefault(require("process"));
const process_doctor_1 = tslib_1.__importDefault(require("process-doctor"));
const util_1 = require("util");
const serialize_1 = require("./serialize");
const throttle_1 = require("./throttle");
const error_1 = require("./error");
const p = (val) => (0, util_1.inspect)(val, { compact: true, breakLength: Infinity });
const isGenerator = (fn) => fn instanceof function* () { }.constructor ||
fn instanceof async function* () { }.constructor;
exports.isGenerator = isGenerator;
exports.filename = module.filename;
function createErrorResponse(err, { call, startTime, logUrl, executionId }) {
return {
kind: "promise",
type: "reject",
value: (0, serialize_1.serializeReturnValue)(call.name, err, false),
isErrorObject: typeof err === "object" && err instanceof Error,
callId: call.callId,
remoteExecutionStartTime: startTime,
remoteExecutionEndTime: Date.now(),
logUrl,
executionId
};
}
exports.createErrorResponse = createErrorResponse;
exports.WrapperOptionDefaults = {
wrapperLog: console.log,
childProcess: true,
childProcessMemoryLimitMb: 0,
childProcessTimeoutMs: 0,
childProcessEnvironment: {},
childDir: ".",
wrapperVerbose: false,
validateSerialization: true
};
const oomPattern = /Allocation failed - JavaScript heap out of memory/;
const FAAST_CHILD_ENV = "FAAST_CHILD";
class Wrapper {
constructor(fModule, options = {}) {
this.executing = false;
this.selected = false;
this.verbose = false;
this.funcs = {};
this.logLines = (msg) => {
let lines = msg.split("\n");
if (lines[lines.length - 1] === "") {
lines = lines.slice(0, lines.length - 1);
}
for (const line of lines) {
this.log(`[${this.childPid}]: ${line}`);
}
};
this.options = { ...exports.WrapperOptionDefaults, ...options };
this.log = this.options.wrapperLog;
this.verbose = this.options.wrapperVerbose;
this.funcs = fModule;
this.queue = new throttle_1.AsyncIterableQueue();
/* c8 ignore start */
if (process_1.default.env[FAAST_CHILD_ENV]) {
this.options.childProcess = false;
this.log(`faast: started child process for module wrapper.`);
process_1.default.on("message", async (cc) => {
const startTime = Date.now();
try {
await this.execute({ ...cc, startTime }, {
onMessage: async (msg) => {
this.log(`Received message ${msg.kind}`);
process_1.default.send({ done: false, value: msg });
}
});
this.log(`Done with this.execute()`);
}
catch (err) {
this.log(err);
}
finally {
process_1.default.send({ done: true });
}
});
}
else {
if (!process_1.default.env.FAAST_SILENT) {
this.log(`faast: successful cold start.`);
}
}
/* c8 ignore stop */
}
lookupFunction(request) {
const { name, args } = request;
if (!name) {
throw new Error("Invalid function call request: no name");
}
const func = this.funcs[name];
if (!func) {
throw new Error(`Function named "${name}" not found`);
}
if (!args) {
throw new Error("Invalid arguments to function call");
}
return func;
}
stopCpuMonitoring() {
this.monitoringTimer && clearInterval(this.monitoringTimer);
this.monitoringTimer = undefined;
}
startCpuMonitoring(pid, callId) {
if (this.monitoringTimer) {
this.stopCpuMonitoring();
}
this.monitoringTimer = cpuMonitor(pid, 1000, (err, result) => {
if (err) {
this.log(`cpu monitor error: ${err}`);
}
if (result) {
this.queue.push({ kind: "cpumetrics", callId, metrics: result });
}
});
}
stop() {
this.stopCpuMonitoring();
if (this.child) {
this.log(`Stopping child process.`);
this.child.stdout.removeListener("data", this.logLines);
this.child.stderr.removeListener("data", this.logLines);
this.child.disconnect();
this.child.kill();
this.child = undefined;
this.executing = false;
}
}
async execute(callingContext, { errorCallback, onMessage, measureCpuUsage }) {
const processError = (err) => err instanceof Error && errorCallback ? errorCallback(err) : err;
try {
/* c8 ignore start */
if (this.executing) {
this.log(`faast: warning: module wrapper execute is not re-entrant`);
throw new Error(`faast: module wrapper is not re-entrant`);
}
/* c8 ignore stop */
this.executing = true;
const { call, startTime, logUrl, executionId, instanceId } = callingContext;
const detail = { logUrl, executionId, instanceId };
const { callId } = call;
this.log(`calling: ${call.name}`);
this.log(` args: ${call.args}`);
this.log(` callId: ${callId}`);
// let startedMessageTimer: NodeJS.Timeout | undefined = setTimeout(
// () => messageCallback({ kind: "functionstarted", callId }),
// 2 * 1000
// );
// TODO: Add this code after the execute returns or yields its first value...
// if (startedMessageTimer) {
// clearTimeout(startedMessageTimer);
// startedMessageTimer = undefined;
// }
const memoryUsage = process_1.default.memoryUsage();
const memInfo = p(memoryUsage);
if (this.options.childProcess) {
if (!this.child) {
this.child = this.setupChildProcess();
}
this.verbose &&
this.log(`faast: invoking '${call.name}' in child process, memory: ${memInfo}`);
this.child.send(callingContext, err => {
/* c8 ignore start */
if (err) {
this.log(`child send error: rejecting with ${err}`);
this.queue.push(Promise.reject(err));
}
/* c8 ignore stop */
});
if (measureCpuUsage) {
this.verbose &&
this.log(`Starting CPU monitor for pid ${this.child.pid}`);
// XXX CPU Monitoring not enabled for now.
// this.startCpuMonitoring(this.child.pid, callId);
}
let timer;
const timeout = this.options.childProcessTimeoutMs;
if (timeout) {
this.verbose && this.log(`Setting timeout: ${timeout}`);
timer = setTimeout(() => {
const error = new error_1.FaastError({
name: error_1.FaastErrorNames.ETIMEOUT,
info: { ...detail, functionName: call.name }
}, `Request exceeded timeout of ${timeout}ms`);
this.queue.push(Promise.reject(error));
this.stop();
}, timeout);
}
this.verbose && this.log(`awaiting async dequeue`);
try {
const promises = [];
for await (const result of this.queue) {
this.verbose && this.log(`Dequeuing ${p(result)}`);
if (result.kind === "promise" || result.kind === "iterator") {
result.logUrl = logUrl;
}
promises.push(onMessage(result));
}
await Promise.all(promises);
}
finally {
this.verbose && this.log(`Finalizing queue`);
this.stopCpuMonitoring();
timer && clearTimeout(timer);
this.queue.clear();
}
}
else {
this.verbose &&
this.log(`faast: Invoking '${call.name}', memory: ${memInfo}`);
const func = this.lookupFunction(call);
if (!func) {
throw new Error(`faast module wrapper: could not find function '${call.name}'`);
}
const args = (0, serialize_1.deserialize)(call.args);
let value;
try {
value = await func.apply(undefined, args);
this.verbose && this.log(`Finished call function`);
}
catch (err) {
this.log(`Function ${call.name} threw error: ${err}`);
throw err;
}
this.verbose &&
this.log(`returned value: ${p(value)}, type: ${typeof value}`);
const validate = this.options.validateSerialization;
const context = { type: "fulfill", callId, ...detail };
// Check for iterable.
if (value !== null && value !== undefined) {
if ((0, exports.isGenerator)(func)) {
let next = await value.next();
let sequence = 0;
while (true) {
this.verbose && this.log(`next: ${p(next)}`);
let result = {
...context,
kind: "iterator",
value: (0, serialize_1.serializeReturnValue)(call.name, [next], validate),
sequence
};
if (next.done) {
result.remoteExecutionStartTime = startTime;
result.remoteExecutionEndTime = Date.now();
result.memoryUsage = memoryUsage;
}
await onMessage(result);
if (next.done) {
return;
}
sequence++;
next = await value.next();
}
}
}
await onMessage({
...context,
kind: "promise",
value: (0, serialize_1.serializeReturnValue)(call.name, [value], validate),
remoteExecutionStartTime: startTime,
remoteExecutionEndTime: Date.now(),
memoryUsage
});
}
}
catch (err) {
this.log(`faast: wrapped function exception or promise rejection: ${err}`);
const response = createErrorResponse(processError(err), callingContext);
this.log(`Error response: ${(0, util_1.inspect)(response)}`);
await onMessage(response);
}
finally {
this.verbose && this.log(`Exiting execute`);
this.executing = false;
}
}
setupChildProcess() {
this.verbose && this.log(`faast: creating child process`);
let execArgv = process_1.default.execArgv.slice();
if (this.options.childProcessMemoryLimitMb) {
/* c8 ignore next */
execArgv = process_1.default.execArgv.filter(arg => !arg.match(/^--max-old-space-size/) && !arg.match(/^--inspect/));
execArgv.push(`--max-old-space-size=${this.options.childProcessMemoryLimitMb}`);
}
const { childProcessEnvironment } = this.options;
const env = {
...process_1.default.env,
...childProcessEnvironment,
[FAAST_CHILD_ENV]: "true"
};
this.verbose && this.log(`Env: ${JSON.stringify(env)}`);
const forkOptions = {
silent: true,
env,
cwd: this.options.childDir,
execArgv
};
const child = child_process_1.default.fork("./index.js", [], forkOptions);
this.childPid = child.pid;
child.stdout.setEncoding("utf8");
child.stderr.setEncoding("utf8");
let oom;
const detectOom = (chunk) => {
if (oomPattern.test(chunk)) {
oom = chunk;
}
};
child.stdout.on("data", this.logLines);
child.stderr.on("data", this.logLines);
child.stderr.on("data", detectOom);
child.on("message", (message) => {
this.verbose && this.log(`child message: resolving with ${p(message)}`);
if (message.done) {
this.queue.done();
}
else {
this.queue.push(message.value);
}
});
/* c8 ignore next */
child.on("error", err => {
this.verbose && this.log(`child error: rejecting with ${err}`);
this.child = undefined;
this.queue.push(Promise.reject(err));
});
child.on("exit", (code, signal) => {
this.verbose && this.log(`child exit: code: ${code}, signal: ${signal}`);
this.child = undefined;
if (code) {
this.queue.push(Promise.reject(new Error(`Exited with error code ${code}`)));
}
else if (signal !== null && signal !== "SIGTERM") {
let errorMessage = `Aborted with signal ${signal}`;
if (signal === "SIGABRT" && oom) {
errorMessage += ` (${oom})`;
oom = undefined;
}
this.queue.push(Promise.reject(new Error(errorMessage)));
}
else {
this.verbose && this.log(`child exiting normally`);
}
});
return child;
}
}
exports.Wrapper = Wrapper;
function cpuMonitor(pid, interval, callback) {
const start = Date.now();
const timer = setInterval(() => process_doctor_1.default.lookup(pid, (err, result) => {
if (err) {
callback(err);
return;
}
const { stime, utime } = result;
callback(err, result && {
stime: stime * 10,
utime: utime * 10,
elapsed: Date.now() - start
});
}), interval);
return timer;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JhcHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy93cmFwcGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSwwRUFBeUM7QUFDekMsOERBQThCO0FBQzlCLDRFQUFxQztBQUNyQywrQkFBK0I7QUFFL0IsMkNBQWdFO0FBQ2hFLHlDQUFnRDtBQUVoRCxtQ0FBc0Q7QUFFdEQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFRLEVBQUUsRUFBRSxDQUFDLElBQUEsY0FBTyxFQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7QUFFeEUsTUFBTSxXQUFXLEdBQUcsQ0FBQyxFQUFZLEVBQUUsRUFBRSxDQUN4QyxFQUFFLFlBQVksUUFBUSxDQUFDLE1BQUssQ0FBQyxDQUFDLFdBQVc7SUFDekMsRUFBRSxZQUFZLEtBQUssU0FBUyxDQUFDLE1BQUssQ0FBQyxDQUFDLFdBQVcsQ0FBQztBQUZ2QyxRQUFBLFdBQVcsZUFFNEI7QUFFdkMsUUFBQSxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztBQWtDeEMsU0FBZ0IsbUJBQW1CLENBQy9CLEdBQVEsRUFDUixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBa0I7SUFFeEQsT0FBTztRQUNILElBQUksRUFBRSxTQUFTO1FBQ2YsSUFBSSxFQUFFLFFBQVE7UUFDZCxLQUFLLEVBQUUsSUFBQSxnQ0FBb0IsRUFBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUM7UUFDbEQsYUFBYSxFQUFFLE9BQU8sR0FBRyxLQUFLLFFBQVEsSUFBSSxHQUFHLFlBQVksS0FBSztRQUM5RCxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07UUFDbkIsd0JBQXdCLEVBQUUsU0FBUztRQUNuQyxzQkFBc0IsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1FBQ2xDLE1BQU07UUFD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Q04sQ0FBQyxDQUFDLEVBQ04sUUFBUSxDQUNYLENBQUM7SUFDRixPQUFPLEtBQUssQ0FBQztBQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNoaWxkUHJvY2VzcyBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHByb2Nlc3MgZnJvbSBcInByb2Nlc3NcIjtcbmltcG9ydCBwcm9jdG9yIGZyb20gXCJwcm9jZXNzLWRvY3RvclwiO1xuaW1wb3J0IHsgaW5zcGVjdCB9IGZyb20gXCJ1dGlsXCI7XG5pbXBvcnQgeyBJdGVyYXRvclJlc3BvbnNlTWVzc2FnZSwgTWVzc2FnZSwgUHJvbWlzZVJlc3BvbnNlTWVzc2FnZSB9IGZyb20gXCIuL3Byb3ZpZGVyXCI7XG5pbXBvcnQgeyBkZXNlcmlhbGl6ZSwgc2VyaWFsaXplUmV0dXJuVmFsdWUgfSBmcm9tIFwiLi9zZXJpYWxpemVcIjtcbmltcG9ydCB7IEFzeW5jSXRlcmFibGVRdWV1ZSB9IGZyb20gXCIuL3Rocm90dGxlXCI7XG5pbXBvcnQgeyBBbnlGdW5jdGlvbiB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBGYWFzdEVycm9yLCBGYWFzdEVycm9yTmFtZXMgfSBmcm9tIFwiLi9lcnJvclwiO1xuXG5jb25zdCBwID0gKHZhbDogYW55KSA9PiBpbnNwZWN0KHZhbCwgeyBjb21wYWN0OiB0cnVlLCBicmVha0xlbmd0aDogSW5maW5pdHkgfSk7XG5cbmV4cG9ydCBjb25zdCBpc0dlbmVyYXRvciA9IChmbjogRnVuY3Rpb24pID0+XG4gICAgZm4gaW5zdGFuY2VvZiBmdW5jdGlvbiogKCkge30uY29uc3RydWN0b3IgfHxcbiAgICBmbiBpbnN0YW5jZW9mIGFzeW5jIGZ1bmN0aW9uKiAoKSB7fS5jb25zdHJ1Y3RvcjtcblxuZXhwb3J0IGNvbnN0IGZpbGVuYW1lID0gbW9kdWxlLmZpbGVuYW1lO1xuXG5leHBvcnQgaW50ZXJmYWNlIENhbGxJZCB7XG4gICAgY2FsbElkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbXBvbGluZSB7XG4gICAgdHJhbXBvbGluZTogQW55RnVuY3Rpb247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbXBvbGluZUZhY3Rvcnkge1xuICAgIGZpbGVuYW1lOiBzdHJpbmc7XG4gICAgbWFrZVRyYW1wb2xpbmU6ICh3cmFwcGVyOiBXcmFwcGVyKSA9PiBUcmFtcG9saW5lO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZ1bmN0aW9uQ2FsbCBleHRlbmRzIENhbGxJZCB7XG4gICAgYXJnczogc3RyaW5nO1xuICAgIG1vZHVsZVBhdGg6IHN0cmluZztcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgUmVzcG9uc2VRdWV1ZUlkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FsbGluZ0NvbnRleHQge1xuICAgIGNhbGw6IEZ1bmN0aW9uQ2FsbDtcbiAgICBzdGFydFRpbWU6IG51bWJlcjtcbiAgICBsb2dVcmw/OiBzdHJpbmc7XG4gICAgZXhlY3V0aW9uSWQ/OiBzdHJpbmc7XG4gICAgaW5zdGFuY2VJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNb2R1bGVUeXBlIHtcbiAgICBbbmFtZTogc3RyaW5nXTogYW55O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRXJyb3JSZXNwb25zZShcbiAgICBlcnI6IGFueSxcbiAgICB7IGNhbGwsIHN0YXJ0VGltZSwgbG9nVXJsLCBleGVjdXRpb25JZCB9OiBDYWxsaW5nQ29udGV4dFxuKTogUHJvbWlzZVJlc3BvbnNlTWVzc2FnZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAga2luZDogXCJwcm9taXNlXCIsXG4gICAgICAgIHR5cGU6IFwicmVqZWN0XCIsXG4gICAgICAgIHZhbHVlOiBzZXJpYWxpemVSZXR1cm5WYWx1ZShjYWxsLm5hbWUsIGVyciwgZmFsc2UpLFxuICAgICAgICBpc0Vycm9yT2JqZWN0OiB0eXBlb2YgZXJyID09PSBcIm9iamVjdFwiICYmIGVyciBpbnN0YW5jZW9mIEVycm9yLFxuICAgICAgICBjYWxsSWQ6IGNhbGwuY2FsbElkLFxuICAgICAgICByZW1vdGVFeGVjdXRpb25TdGFydFRpbWU6IHN0YXJ0VGltZSxcbiAgICAgICAgcmVtb3RlRXhlY3V0aW9uRW5kVGltZTogRGF0ZS5ub3coKSxcbiAgICAgICAgbG9nVXJsLFxuICAgICAgICBleGVjdXRpb25JZFxuICAgIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV3JhcHBlck9wdGlvbnMge1xuICAgIC8qKlxuICAgICAqIExvZ2dpbmcgZnVuY3Rpb24gZm9yIGNvbnNvbGUubG9nL3dhcm4vZXJyb3Igb3V0cHV0LiBPbmx5IGF2YWlsYWJsZSBpblxuICAgICAqIGNoaWxkIHByb2Nlc3MgbW9kZS4gVGhpcyBpcyBtYWlubHkgdXNlZnVsIGZvciBkZWJ1Z2dpbmcgdGhlIFwibG9jYWxcIlxuICAgICAqIG1vZGUgd2hpY2ggcnVucyBjb2RlIGxvY2FsbHkuIEluIHJlYWwgY2xvdWRzIHRoZSBsb2dzIHdpbGwgZW5kIHVwIGluIHRoZVxuICAgICAqIGNsb3VkIGxvZ2dpbmcgc2VydmljZSAoZS5nLiBDbG91ZHdhdGNoIExvZ3MpLlxuICAgICAqIERlZmF1bHRzIHRvIGNvbnNvbGUubG9nLlxuICAgICAqL1xuICAgIHdyYXBwZXJMb2c/OiAobXNnOiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgY2hpbGRQcm9jZXNzPzogYm9vbGVhbjtcbiAgICBjaGlsZFByb2Nlc3NNZW1vcnlMaW1pdE1iPzogbnVtYmVyO1xuICAgIGNoaWxkUHJvY2Vzc1RpbWVvdXRNcz86IG51bWJlcjtcbiAgICBjaGlsZFByb2Nlc3NFbnZpcm9ubWVudD86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG4gICAgY2hpbGREaXI/OiBzdHJpbmc7XG4gICAgd3JhcHBlclZlcmJvc2U/OiBib29sZWFuO1xuICAgIHZhbGlkYXRlU2VyaWFsaXphdGlvbj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjb25zdCBXcmFwcGVyT3B0aW9uRGVmYXVsdHM6IFJlcXVpcmVkPFdyYXBwZXJPcHRpb25zPiA9IHtcbiAgICB3cmFwcGVyTG9nOiBjb25zb2xlLmxvZyxcbiAgICBjaGlsZFByb2Nlc3M6IHRydWUsXG4gICAgY2hpbGRQcm9jZXNzTWVtb3J5TGltaXRNYjogMCxcbiAgICBjaGlsZFByb2Nlc3NUaW1lb3V0TXM6IDAsXG4gICAgY2hpbGRQcm9jZXNzRW52aXJvbm1lbnQ6IHt9LFxuICAgIGNoaWxkRGlyOiBcIi5cIixcbiAgICB3cmFwcGVyVmVyYm9zZTogZmFsc2UsXG4gICAgdmFsaWRhdGVTZXJpYWxpemF0aW9uOiB0cnVlXG59O1xuXG50eXBlIEVycm9yQ2FsbGJhY2sgPSAoZXJyOiBFcnJvcikgPT4gRXJyb3I7XG50eXBlIE1lc3NhZ2VDYWxsYmFjayA9IChtc2c6IE1lc3NhZ2UpID0+IFByb21pc2U8dm9pZD47XG5cbmV4cG9ydCBpbnRlcmZhY2UgV3JhcHBlckV4ZWN1dGVPcHRpb25zIHtcbiAgICBlcnJvckNhbGxiYWNrPzogRXJyb3JDYWxsYmFjaztcbiAgICBvbk1lc3NhZ2U6IE1lc3NhZ2VDYWxsYmFjaztcbiAgICBtZWFzdXJlQ3B1VXNhZ2U/OiBib29sZWFuO1xufVxuXG5jb25zdCBvb21QYXR0ZXJuID0gL0FsbG9jYXRpb24gZmFpbGVkIC0gSmF2YVNjcmlwdCBoZWFwIG91dCBvZiBtZW1vcnkvO1xuXG5jb25zdCBGQUFTVF9DSElMRF9FTlYgPSBcIkZBQVNUX0NISUxEXCI7XG5cbmV4cG9ydCBjbGFzcyBXcmFwcGVyIHtcbiAgICBleGVjdXRpbmcgPSBmYWxzZTtcbiAgICBzZWxlY3RlZCA9IGZhbHNlO1xuICAgIHByb3RlY3RlZCB2ZXJib3NlID0gZmFsc2U7XG4gICAgcHJvdGVjdGVkIGZ1bmNzOiBNb2R1bGVUeXBlID0ge307XG4gICAgcHJvdGVjdGVkIGNoaWxkPzogY2hpbGRQcm9jZXNzLkNoaWxkUHJvY2VzcztcbiAgICBwcm90ZWN0ZWQgY2hpbGRQaWQ/OiBudW1iZXI7XG4gICAgcHJvdGVjdGVkIGxvZzogKG1zZzogc3RyaW5nKSA9PiB2b2lkO1xuICAgIHByb3RlY3RlZCBxdWV1ZTogQXN5bmNJdGVyYWJsZVF1ZXVlPE1lc3NhZ2U+O1xuICAgIHJlYWRvbmx5IG9wdGlvbnM6IFJlcXVpcmVkPFdyYXBwZXJPcHRpb25zPjtcbiAgICBwcm90ZWN0ZWQgbW9uaXRvcmluZ1RpbWVyPzogTm9kZUpTLlRpbWVyO1xuXG4gICAgY29uc3RydWN0b3IoZk1vZHVsZTogTW9kdWxlVHlwZSwgb3B0aW9uczogV3JhcHBlck9wdGlvbnMgPSB7fSkge1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSB7IC4uLldyYXBwZXJPcHRpb25EZWZhdWx0cywgLi4ub3B0aW9ucyB9O1xuICAgICAgICB0aGlzLmxvZyA9IHRoaXMub3B0aW9ucy53cmFwcGVyTG9nO1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSB0aGlzLm9wdGlvbnMud3JhcHBlclZlcmJvc2U7XG4gICAgICAgIHRoaXMuZnVuY3MgPSBmTW9kdWxlO1xuICAgICAgICB0aGlzLnF1ZXVlID0gbmV3IEFzeW5jSXRlcmFibGVRdWV1ZSgpO1xuXG4gICAgICAgIC8qIGM4IGlnbm9yZSBzdGFydCAqL1xuICAgICAgICBpZiAocHJvY2Vzcy5lbnZbRkFBU1RfQ0hJTERfRU5WXSkge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmNoaWxkUHJvY2VzcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5sb2coYGZhYXN0OiBzdGFydGVkIGNoaWxkIHByb2Nlc3MgZm9yIG1vZHVsZSB3cmFwcGVyLmApO1xuICAgICAgICAgICAgcHJvY2Vzcy5vbihcIm1lc3NhZ2VcIiwgYXN5bmMgKGNjOiBDYWxsaW5nQ29udGV4dCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5leGVjdXRlKFxuICAgICAgICAgICAgICAgICAgICAgICAgeyAuLi5jYywgc3RhcnRUaW1lIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25NZXNzYWdlOiBhc3luYyBtc2cgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgUmVjZWl2ZWQgbWVzc2FnZSAke21zZy5raW5kfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLnNlbmQhKHsgZG9uZTogZmFsc2UsIHZhbHVlOiBtc2cgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgRG9uZSB3aXRoIHRoaXMuZXhlY3V0ZSgpYCk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2coZXJyKTtcbiAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLnNlbmQhKHsgZG9uZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghcHJvY2Vzcy5lbnYuRkFBU1RfU0lMRU5UKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2coYGZhYXN0OiBzdWNjZXNzZnVsIGNvbGQgc3RhcnQuYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyogYzggaWdub3JlIHN0b3AgKi9cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbG9va3VwRnVuY3Rpb24ocmVxdWVzdDogb2JqZWN0KTogQW55RnVuY3Rpb24ge1xuICAgICAgICBjb25zdCB7IG5hbWUsIGFyZ3MgfSA9IHJlcXVlc3QgYXMgRnVuY3Rpb25DYWxsO1xuICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgZnVuY3Rpb24gY2FsbCByZXF1ZXN0OiBubyBuYW1lXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZnVuYyA9IHRoaXMuZnVuY3NbbmFtZV07XG4gICAgICAgIGlmICghZnVuYykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGdW5jdGlvbiBuYW1lZCBcIiR7bmFtZX1cIiBub3QgZm91bmRgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghYXJncykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBhcmd1bWVudHMgdG8gZnVuY3Rpb24gY2FsbFwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc3RvcENwdU1vbml0b3JpbmcoKSB7XG4gICAgICAgIHRoaXMubW9uaXRvcmluZ1RpbWVyICYmIGNsZWFySW50ZXJ2YWwodGhpcy5tb25pdG9yaW5nVGltZXIpO1xuICAgICAgICB0aGlzLm1vbml0b3JpbmdUaW1lciA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc3RhcnRDcHVNb25pdG9yaW5nKHBpZDogbnVtYmVyLCBjYWxsSWQ6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5tb25pdG9yaW5nVGltZXIpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcENwdU1vbml0b3JpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1vbml0b3JpbmdUaW1lciA9IGNwdU1vbml0b3IocGlkLCAxMDAwLCAoZXJyLCByZXN1bHQpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZyhgY3B1IG1vbml0b3IgZXJyb3I6ICR7ZXJyfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHRoaXMucXVldWUucHVzaCh7IGtpbmQ6IFwiY3B1bWV0cmljc1wiLCBjYWxsSWQsIG1ldHJpY3M6IHJlc3VsdCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc3RvcCgpIHtcbiAgICAgICAgdGhpcy5zdG9wQ3B1TW9uaXRvcmluZygpO1xuICAgICAgICBpZiAodGhpcy5jaGlsZCkge1xuICAgICAgICAgICAgdGhpcy5sb2coYFN0b3BwaW5nIGNoaWxkIHByb2Nlc3MuYCk7XG4gICAgICAgICAgICB0aGlzLmNoaWxkLnN0ZG91dCEucmVtb3ZlTGlzdGVuZXIoXCJkYXRhXCIsIHRoaXMubG9nTGluZXMpO1xuICAgICAgICAgICAgdGhpcy5jaGlsZC5zdGRlcnIhLnJlbW92ZUxpc3RlbmVyKFwiZGF0YVwiLCB0aGlzLmxvZ0xpbmVzKTtcbiAgICAgICAgICAgIHRoaXMuY2hpbGQhLmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgIHRoaXMuY2hpbGQhLmtpbGwoKTtcbiAgICAgICAgICAgIHRoaXMuY2hpbGQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGluZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgZXhlY3V0ZShcbiAgICAgICAgY2FsbGluZ0NvbnRleHQ6IENhbGxpbmdDb250ZXh0LFxuICAgICAgICB7IGVycm9yQ2FsbGJhY2ssIG9uTWVzc2FnZSwgbWVhc3VyZUNwdVVzYWdlIH06IFdyYXBwZXJFeGVjdXRlT3B0aW9uc1xuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBwcm9jZXNzRXJyb3IgPSAoZXJyOiBhbnkpID0+XG4gICAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvckNhbGxiYWNrID8gZXJyb3JDYWxsYmFjayhlcnIpIDogZXJyO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLyogYzggaWdub3JlIHN0YXJ0ICAqL1xuICAgICAgICAgICAgaWYgKHRoaXMuZXhlY3V0aW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2coYGZhYXN0OiB3YXJuaW5nOiBtb2R1bGUgd3JhcHBlciBleGVjdXRlIGlzIG5vdCByZS1lbnRyYW50YCk7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBmYWFzdDogbW9kdWxlIHdyYXBwZXIgaXMgbm90IHJlLWVudHJhbnRgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8qIGM4IGlnbm9yZSBzdG9wICAqL1xuICAgICAgICAgICAgdGhpcy5leGVjdXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgY29uc3QgeyBjYWxsLCBzdGFydFRpbWUsIGxvZ1VybCwgZXhlY3V0aW9uSWQsIGluc3RhbmNlSWQgfSA9IGNhbGxpbmdDb250ZXh0O1xuICAgICAgICAgICAgY29uc3QgZGV0YWlsID0geyBsb2dVcmwsIGV4ZWN1dGlvbklkLCBpbnN0YW5jZUlkIH07XG4gICAgICAgICAgICBjb25zdCB7IGNhbGxJZCB9ID0gY2FsbDtcbiAgICAgICAgICAgIHRoaXMubG9nKGBjYWxsaW5nOiAke2NhbGwubmFtZX1gKTtcbiAgICAgICAgICAgIHRoaXMubG9nKGAgICBhcmdzOiAke2NhbGwuYXJnc31gKTtcbiAgICAgICAgICAgIHRoaXMubG9nKGAgICBjYWxsSWQ6ICR7Y2FsbElkfWApO1xuICAgICAgICAgICAgLy8gbGV0IHN0YXJ0ZWRNZXNzYWdlVGltZXI6IE5vZGVKUy5UaW1lb3V0IHwgdW5kZWZpbmVkID0gc2V0VGltZW91dChcbiAgICAgICAgICAgIC8vICAgICAoKSA9PiBtZXNzYWdlQ2FsbGJhY2soeyBraW5kOiBcImZ1bmN0aW9uc3RhcnRlZFwiLCBjYWxsSWQgfSksXG4gICAgICAgICAgICAvLyAgICAgMiAqIDEwMDBcbiAgICAgICAgICAgIC8vICk7XG5cbiAgICAgICAgICAgIC8vIFRPRE86IEFkZCB0aGlzIGNvZGUgYWZ0ZXIgdGhlIGV4ZWN1dGUgcmV0dXJucyBvciB5aWVsZHMgaXRzIGZpcnN0IHZhbHVlLi4uXG4gICAgICAgICAgICAvLyBpZiAoc3RhcnRlZE1lc3NhZ2VUaW1lcikge1xuICAgICAgICAgICAgLy8gICAgIGNsZWFyVGltZW91dChzdGFydGVkTWVzc2FnZVRpbWVyKTtcbiAgICAgICAgICAgIC8vICAgICBzdGFydGVkTWVzc2FnZVRpbWVyID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgLy8gfVxuXG4gICAgICAgICAgICBjb25zdCBtZW1vcnlVc2FnZSA9IHByb2Nlc3MubWVtb3J5VXNhZ2UoKTtcbiAgICAgICAgICAgIGNvbnN0IG1lbUluZm8gPSBwKG1lbW9yeVVzYWdlKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuY2hpbGRQcm9jZXNzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNoaWxkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2hpbGQgPSB0aGlzLnNldHVwQ2hpbGRQcm9jZXNzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMudmVyYm9zZSAmJlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhcbiAgICAgICAgICAgICAgICAgICAgICAgIGBmYWFzdDogaW52b2tpbmcgJyR7Y2FsbC5uYW1lfScgaW4gY2hpbGQgcHJvY2VzcywgbWVtb3J5OiAke21lbUluZm99YFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGQuc2VuZChjYWxsaW5nQ29udGV4dCwgZXJyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLyogYzggaWdub3JlIHN0YXJ0ICovXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nKGBjaGlsZCBzZW5kIGVycm9yOiByZWplY3Rpbmcgd2l0aCAke2Vycn1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucXVldWUucHVzaChQcm9taXNlLnJlamVjdChlcnIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBjOCBpZ25vcmUgc3RvcCAqL1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChtZWFzdXJlQ3B1VXNhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52ZXJib3NlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgU3RhcnRpbmcgQ1BVIG1vbml0b3IgZm9yIHBpZCAke3RoaXMuY2hpbGQucGlkfWApO1xuICAgICAgICAgICAgICAgICAgICAvLyBYWFggQ1BVIE1vbml0b3Jpbmcgbm90IGVuYWJsZWQgZm9yIG5vdy5cbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcy5zdGFydENwdU1vbml0b3JpbmcodGhpcy5jaGlsZC5waWQsIGNhbGxJZCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IHRpbWVyO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRpbWVvdXQgPSB0aGlzLm9wdGlvbnMuY2hpbGRQcm9jZXNzVGltZW91dE1zO1xuICAgICAgICAgICAgICAgIGlmICh0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudmVyYm9zZSAmJiB0aGlzLmxvZyhgU2V0dGluZyB0aW1lb3V0OiAke3RpbWVvdXR9YCk7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBGYWFzdEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogRmFhc3RFcnJvck5hbWVzLkVUSU1FT1VULFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvOiB7IC4uLmRldGFpbCwgZnVuY3Rpb25OYW1lOiBjYWxsLm5hbWUgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYFJlcXVlc3QgZXhjZWVkZWQgdGltZW91dCBvZiAke3RpbWVvdXR9bXNgXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnF1ZXVlLnB1c2goUHJvbWlzZS5yZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICB9LCB0aW1lb3V0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy52ZXJib3NlICYmIHRoaXMubG9nKGBhd2FpdGluZyBhc3luYyBkZXF1ZXVlYCk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCByZXN1bHQgb2YgdGhpcy5xdWV1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52ZXJib3NlICYmIHRoaXMubG9nKGBEZXF1ZXVpbmcgJHtwKHJlc3VsdCl9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LmtpbmQgPT09IFwicHJvbWlzZVwiIHx8IHJlc3VsdC5raW5kID09PSBcIml0ZXJhdG9yXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQubG9nVXJsID0gbG9nVXJsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChvbk1lc3NhZ2UocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgICAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudmVyYm9zZSAmJiB0aGlzLmxvZyhgRmluYWxpemluZyBxdWV1ZWApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0b3BDcHVNb25pdG9yaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVyICYmIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucXVldWUuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMudmVyYm9zZSAmJlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgZmFhc3Q6IEludm9raW5nICcke2NhbGwubmFtZX0nLCBtZW1vcnk6ICR7bWVtSW5mb31gKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmdW5jID0gdGhpcy5sb29rdXBGdW5jdGlvbihjYWxsKTtcbiAgICAgICAgICAgICAgICBpZiAoIWZ1bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYGZhYXN0IG1vZHVsZSB3cmFwcGVyOiBjb3VsZCBub3QgZmluZCBmdW5jdGlvbiAnJHtjYWxsLm5hbWV9J2BcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgYXJncyA9IGRlc2VyaWFsaXplKGNhbGwuYXJncyk7XG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gYXdhaXQgZnVuYy5hcHBseSh1bmRlZmluZWQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiYgdGhpcy5sb2coYEZpbmlzaGVkIGNhbGwgZnVuY3Rpb25gKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgRnVuY3Rpb24gJHtjYWxsLm5hbWV9IHRocmV3IGVycm9yOiAke2Vycn1gKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnZlcmJvc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2coYHJldHVybmVkIHZhbHVlOiAke3AodmFsdWUpfSwgdHlwZTogJHt0eXBlb2YgdmFsdWV9YCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCB2YWxpZGF0ZSA9IHRoaXMub3B0aW9ucy52YWxpZGF0ZVNlcmlhbGl6YXRpb247XG4gICAgICAgICAgICAgICAgY29uc3QgY29udGV4dCA9IHsgdHlwZTogXCJmdWxmaWxsXCIsIGNhbGxJZCwgLi4uZGV0YWlsIH0gYXMgY29uc3Q7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgZm9yIGl0ZXJhYmxlLlxuXG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzR2VuZXJhdG9yKGZ1bmMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbmV4dCA9IGF3YWl0IHZhbHVlLm5leHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzZXF1ZW5jZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmVyYm9zZSAmJiB0aGlzLmxvZyhgbmV4dDogJHtwKG5leHQpfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXN1bHQ6IEl0ZXJhdG9yUmVzcG9uc2VNZXNzYWdlID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBraW5kOiBcIml0ZXJhdG9yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBzZXJpYWxpemVSZXR1cm5WYWx1ZShjYWxsLm5hbWUsIFtuZXh0XSwgdmFsaWRhdGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXF1ZW5jZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gYXMgY29uc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5leHQuZG9uZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucmVtb3RlRXhlY3V0aW9uU3RhcnRUaW1lID0gc3RhcnRUaW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucmVtb3RlRXhlY3V0aW9uRW5kVGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5tZW1vcnlVc2FnZSA9IG1lbW9yeVVzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBvbk1lc3NhZ2UocmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV4dC5kb25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VxdWVuY2UrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXh0ID0gYXdhaXQgdmFsdWUubmV4dCgpO1xuICAgICAgICAgICAgICAgI