faastjs
Version:
Serverless batch computing made simple.
176 lines • 26.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const ava_1 = tslib_1.__importDefault(require("ava"));
const uuid_1 = require("uuid");
const index_1 = require("../index");
const aws_faast_1 = require("../src/aws/aws-faast");
const functions = tslib_1.__importStar(require("./fixtures/functions"));
const util_1 = require("./fixtures/util");
const util_aws_1 = require("./fixtures/util-aws");
const assert_1 = tslib_1.__importDefault(require("assert"));
async function waitForLogGroupCreation(cloudwatch, logGroupName, message) {
let n = 0;
while (true) {
await (0, util_1.sleep)(1000);
try {
n++;
const described = await cloudwatch.describeLogGroups({
logGroupNamePrefix: logGroupName
});
if (!described.logGroups) {
continue;
}
const retrievedLogGroup = described.logGroups?.[0]?.logGroupName;
if (!retrievedLogGroup) {
continue;
}
(0, assert_1.default)(retrievedLogGroup === logGroupName, `Unexpected logGroupName: ${retrievedLogGroup}, expecting ${logGroupName}`);
const logResult = await cloudwatch.filterLogEvents({ logGroupName });
const events = logResult.events ?? [];
// console.log(`[${n}] Found log group: ${logGroupName}`);
let foundMessage = false;
for (const event of events) {
// console.log(
// `[${n}] ${event.logStreamName} ${event.eventId} ${event.timestamp} ${event.message}`
// );
if (event.message.includes(message)) {
foundMessage = true;
}
if (foundMessage && event.message.match(/REPORT RequestId/)) {
return;
}
}
}
catch (err) {
console.error(`Transient error waiting for log group creation: ${err}`);
}
}
}
ava_1.default.serial((0, util_1.title)("aws", "garbage collects functions that are called"), async (t) => {
// Idea behind this test: create a faast module and make a call. Then
// cleanup while leaving the resources in place. Then create another faast
// module and set its retention to 0, and use a synthetic gc worker to
// observe and verify the garbage collector actually cleans up.
const mod = await (0, index_1.faastAws)(functions, {
gc: "off",
mode: "queue",
description: t.title,
packageJson: {
name: (0, uuid_1.v4)(),
dependencies: {
tslib: "^1.9.1"
}
},
maxRetries: 0
});
try {
await mod.functions.consoleLog("gc-test-string");
const { cloudwatch } = mod.state.services;
const { logGroupName } = mod.state.resources;
await waitForLogGroupCreation(cloudwatch, logGroupName, "gc-test-string");
await mod.cleanup({ deleteResources: false, gcTimeout: 0 });
// Create some work for gc to do by removing the log retention policy, gc
// should add it back.
const deleteRetentionPolicy = (0, index_1.throttle)({ concurrency: 1, retry: 5 }, () => cloudwatch.deleteRetentionPolicy({ logGroupName }));
await deleteRetentionPolicy();
let deletedLayer = false;
const { layer, FunctionName } = mod.state.resources;
// log.gc.enabled = true;
const mod2 = await (0, index_1.faastAws)(functions, {
gc: "force",
retentionInDays: 0,
description: t.title,
_gcWorker: async (work, services) => {
switch (work.type) {
case "SetLogRetention":
// checkResourcesCleanedUp will verify the log group is
// deleted.
await (0, aws_faast_1.defaultGcWorker)(work, services);
break;
case "DeleteLayerVersion":
if (work.LayerName === layer.LayerName) {
index_1.log.gc(`deleting layer ${work.LayerName}`);
await (0, aws_faast_1.defaultGcWorker)(work, services);
deletedLayer = true;
}
break;
case "DeleteResources":
if (work.resources.FunctionName === FunctionName) {
index_1.log.gc(`deleting resources for ${FunctionName}`);
await (0, aws_faast_1.defaultGcWorker)(work, services);
}
}
}
});
await mod2.cleanup({ gcTimeout: 0 });
t.true(deletedLayer, "Deleted layer is true");
await (0, util_1.checkResourcesCleanedUp)(t, await (0, util_aws_1.getAWSResources)(mod, true));
}
finally {
index_1.log.gc.enabled = false;
await mod.cleanup({ deleteResources: true, deleteCaches: true, gcTimeout: 0 });
}
});
ava_1.default.serial((0, util_1.title)("aws", "garbage collects functions that are never called"), async (t) => {
const mod = await (0, index_1.faastAws)(functions, {
gc: "off",
mode: "queue",
description: t.title,
maxRetries: 0
});
try {
await mod.cleanup({ deleteResources: false, gcTimeout: 0 });
const { FunctionName } = mod.state.resources;
const mod2 = await (0, index_1.faastAws)(functions, {
gc: "force",
retentionInDays: 0,
description: t.title,
_gcWorker: async (work, services) => {
switch (work.type) {
case "DeleteResources":
if (work.resources.FunctionName === FunctionName) {
index_1.log.gc(`deleting resources for ${FunctionName}`);
await (0, aws_faast_1.defaultGcWorker)(work, services);
}
}
}
});
await mod2.cleanup({ gcTimeout: 0 });
// Don't fail if a log group exists because we didn't wait for its
// creation; it might be created by AWS after the cleanup occurs. The
// reason is that the log group will only be created if there's an
// invocation test, which only happens in the special case that the role
// was recently created. Which is true for the nightly testsuite but
// rarely elsewhere.
const { logGroupResult, ...resources } = await (0, util_aws_1.getAWSResources)(mod, true);
await (0, util_1.checkResourcesCleanedUp)(t, resources);
}
finally {
await mod.cleanup({ deleteResources: true, deleteCaches: true, gcTimeout: 0 });
}
});
ava_1.default.skip((0, util_1.title)("aws", "garbage collection caching"), async (t) => {
{
// Run a real gc so the build account doesn't accumulate garbage.
const mod = await (0, index_1.faastAws)(functions, { gc: "force", description: t.title });
await mod.cleanup({ gcTimeout: 0 });
t.is(await mod.state.gcPromise, "done");
}
{
// Test the in-memory cache that prevents gc from multiple faast.js
// instances from running at the same time.
const mod = await (0, index_1.faastAws)(functions, { description: t.title });
await mod.cleanup();
t.is(await mod.state.gcPromise, "skipped");
}
{
// Test the persistent cache that prevents gc from running too often
// even across processes.
(0, aws_faast_1.clearLastGc)();
const mod = await (0, index_1.faastAws)(functions, { description: t.title });
await mod.cleanup();
t.is(await mod.state.gcPromise, "skipped");
}
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLWdjLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0L2F3cy1nYy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHNEQUF1QjtBQUN2QiwrQkFBa0M7QUFDbEMsb0NBQW1EO0FBQ25ELG9EQUFvRTtBQUNwRSx3RUFBa0Q7QUFDbEQsMENBQXdFO0FBQ3hFLGtEQUFzRDtBQUN0RCw0REFBNEI7QUFFNUIsS0FBSyxVQUFVLHVCQUF1QixDQUNsQyxVQUEwQixFQUMxQixZQUFvQixFQUNwQixPQUFlO0lBRWYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUNWLE1BQU0sSUFBQSxZQUFLLEVBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEIsSUFBSSxDQUFDO1lBQ0QsQ0FBQyxFQUFFLENBQUM7WUFDSixNQUFNLFNBQVMsR0FBRyxNQUFNLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDakQsa0JBQWtCLEVBQUUsWUFBWTthQUNuQyxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUN2QixTQUFTO1lBQ2IsQ0FBQztZQUNELE1BQU0saUJBQWlCLEdBQUcsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLFlBQVksQ0FBQztZQUNqRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztnQkFDckIsU0FBUztZQUNiLENBQUM7WUFDRCxJQUFBLGdCQUFNLEVBQ0YsaUJBQWlCLEtBQUssWUFBWSxFQUNsQyw0QkFBNEIsaUJBQWlCLGVBQWUsWUFBWSxFQUFFLENBQzdFLENBQUM7WUFDRixNQUFNLFNBQVMsR0FBRyxNQUFNLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO1lBQ3JFLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDO1lBQ3RDLDBE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QyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQsQ0FBQztRQUNHLG9FQUFvRTtRQUNwRSx5QkFBeUI7UUFDekIsSUFBQSx1QkFBVyxHQUFFLENBQUM7UUFDZCxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUEsZ0JBQVEsRUFBQyxTQUFTLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDaEUsTUFBTSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQy9DLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENsb3VkV2F0Y2hMb2dzIH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1jbG91ZHdhdGNoLWxvZ3NcIjtcbmltcG9ydCB0ZXN0IGZyb20gXCJhdmFcIjtcbmltcG9ydCB7IHY0IGFzIHV1aWQgfSBmcm9tIFwidXVpZFwiO1xuaW1wb3J0IHsgZmFhc3RBd3MsIGxvZywgdGhyb3R0bGUgfSBmcm9tIFwiLi4vaW5kZXhcIjtcbmltcG9ydCB7IGNsZWFyTGFzdEdjLCBkZWZhdWx0R2NXb3JrZXIgfSBmcm9tIFwiLi4vc3JjL2F3cy9hd3MtZmFhc3RcIjtcbmltcG9ydCAqIGFzIGZ1bmN0aW9ucyBmcm9tIFwiLi9maXh0dXJlcy9mdW5jdGlvbnNcIjtcbmltcG9ydCB7IGNoZWNrUmVzb3VyY2VzQ2xlYW5lZFVwLCBzbGVlcCwgdGl0bGUgfSBmcm9tIFwiLi9maXh0dXJlcy91dGlsXCI7XG5pbXBvcnQgeyBnZXRBV1NSZXNvdXJjZXMgfSBmcm9tIFwiLi9maXh0dXJlcy91dGlsLWF3c1wiO1xuaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5cbmFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JMb2dHcm91cENyZWF0aW9uKFxuICAgIGNsb3Vkd2F0Y2g6IENsb3VkV2F0Y2hMb2dzLFxuICAgIGxvZ0dyb3VwTmFtZTogc3RyaW5nLFxuICAgIG1lc3NhZ2U6IHN0cmluZ1xuKSB7XG4gICAgbGV0IG4gPSAwO1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGF3YWl0IHNsZWVwKDEwMDApO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbisrO1xuICAgICAgICAgICAgY29uc3QgZGVzY3JpYmVkID0gYXdhaXQgY2xvdWR3YXRjaC5kZXNjcmliZUxvZ0dyb3Vwcyh7XG4gICAgICAgICAgICAgICAgbG9nR3JvdXBOYW1lUHJlZml4OiBsb2dHcm91cE5hbWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCFkZXNjcmliZWQubG9nR3JvdXBzKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXRyaWV2ZWRMb2dHcm91cCA9IGRlc2NyaWJlZC5sb2dHcm91cHM/LlswXT8ubG9nR3JvdXBOYW1lO1xuICAgICAgICAgICAgaWYgKCFyZXRyaWV2ZWRMb2dHcm91cCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXNzZXJ0KFxuICAgICAgICAgICAgICAgIHJldHJpZXZlZExvZ0dyb3VwID09PSBsb2dHcm91cE5hbWUsXG4gICAgICAgICAgICAgICAgYFVuZXhwZWN0ZWQgbG9nR3JvdXBOYW1lOiAke3JldHJpZXZlZExvZ0dyb3VwfSwgZXhwZWN0aW5nICR7bG9nR3JvdXBOYW1lfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBsb2dSZXN1bHQgPSBhd2FpdCBjbG91ZHdhdGNoLmZpbHRlckxvZ0V2ZW50cyh7IGxvZ0dyb3VwTmFtZSB9KTtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IGxvZ1Jlc3VsdC5ldmVudHMgPz8gW107XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhgWyR7bn1dIEZvdW5kIGxvZyBncm91cDogJHtsb2dHcm91cE5hbWV9YCk7XG4gICAgICAgICAgICBsZXQgZm91bmRNZXNzYWdlID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgIC8vICAgICBgWyR7bn1dICR7ZXZlbnQubG9nU3RyZWFtTmFtZX0gJHtldmVudC5ldmVudElkfSAke2V2ZW50LnRpbWVzdGFtcH0gJHtldmVudC5tZXNzYWdlfWBcbiAgICAgICAgICAgICAgICAvLyApO1xuICAgICAgICAgICAgICAgIGlmIChldmVudC5tZXNzYWdlIS5pbmNsdWRlcyhtZXNzYWdlKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3VuZE1lc3NhZ2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZm91bmRNZXNzYWdlICYmIGV2ZW50Lm1lc3NhZ2UhLm1hdGNoKC9SRVBPUlQgUmVxdWVzdElkLykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFRyYW5zaWVudCBlcnJvciB3YWl0aW5nIGZvciBsb2cgZ3JvdXAgY3JlYXRpb246ICR7ZXJyfWApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG50ZXN0LnNlcmlhbCh0aXRsZShcImF3c1wiLCBcImdhcmJhZ2UgY29sbGVjdHMgZnVuY3Rpb25zIHRoYXQgYXJlIGNhbGxlZFwiKSwgYXN5bmMgdCA9PiB7XG4gICAgLy8gSWRlYSBiZWhpbmQgdGhpcyB0ZXN0OiBjcmVhdGUgYSBmYWFzdCBtb2R1bGUgYW5kIG1ha2UgYSBjYWxsLiBUaGVuXG4gICAgLy8gY2xlYW51cCB3aGlsZSBsZWF2aW5nIHRoZSByZXNvdXJjZXMgaW4gcGxhY2UuIFRoZW4gY3JlYXRlIGFub3RoZXIgZmFhc3RcbiAgICAvLyBtb2R1bGUgYW5kIHNldCBpdHMgcmV0ZW50aW9uIHRvIDAsIGFuZCB1c2UgYSBzeW50aGV0aWMgZ2Mgd29ya2VyIHRvXG4gICAgLy8gb2JzZXJ2ZSBhbmQgdmVyaWZ5IHRoZSBnYXJiYWdlIGNvbGxlY3RvciBhY3R1YWxseSBjbGVhbnMgdXAuXG4gICAgY29uc3QgbW9kID0gYXdhaXQgZmFhc3RBd3MoZnVuY3Rpb25zLCB7XG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBtb2RlOiBcInF1ZXVlXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlLFxuICAgICAgICBwYWNrYWdlSnNvbjoge1xuICAgICAgICAgICAgbmFtZTogdXVpZCgpLFxuICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiB7XG4gICAgICAgICAgICAgICAgdHNsaWI6IFwiXjEuOS4xXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWF4UmV0cmllczogMFxuICAgIH0pO1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IG1vZC5mdW5jdGlvbnMuY29uc29sZUxvZyhcImdjLXRlc3Qtc3RyaW5nXCIpO1xuICAgICAgICBjb25zdCB7IGNsb3Vkd2F0Y2ggfSA9IG1vZC5zdGF0ZS5zZXJ2aWNlcztcbiAgICAgICAgY29uc3QgeyBsb2dHcm91cE5hbWUgfSA9IG1vZC5zdGF0ZS5yZXNvdXJjZXM7XG4gICAgICAgIGF3YWl0IHdhaXRGb3JMb2dHcm91cENyZWF0aW9uKGNsb3Vkd2F0Y2gsIGxvZ0dyb3VwTmFtZSwgXCJnYy10ZXN0LXN0cmluZ1wiKTtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoeyBkZWxldGVSZXNvdXJjZXM6IGZhbHNlLCBnY1RpbWVvdXQ6IDAgfSk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHNvbWUgd29yayBmb3IgZ2MgdG8gZG8gYnkgcmVtb3ZpbmcgdGhlIGxvZyByZXRlbnRpb24gcG9saWN5LCBnY1xuICAgICAgICAvLyBzaG91bGQgYWRkIGl0IGJhY2suXG4gICAgICAgIGNvbnN0IGRlbGV0ZVJldGVudGlvblBvbGljeSA9IHRocm90dGxlKHsgY29uY3VycmVuY3k6IDEsIHJldHJ5OiA1IH0sICgpID0+XG4gICAgICAgICAgICBjbG91ZHdhdGNoLmRlbGV0ZVJldGVudGlvblBvbGljeSh7IGxvZ0dyb3VwTmFtZSB9KVxuICAgICAgICApO1xuICAgICAgICBhd2FpdCBkZWxldGVSZXRlbnRpb25Qb2xpY3koKTtcblxuICAgICAgICBsZXQgZGVsZXRlZExheWVyID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IHsgbGF5ZXIsIEZ1bmN0aW9uTmFtZSB9ID0gbW9kLnN0YXRlLnJlc291cmNlcztcbiAgICAgICAgLy8gbG9nLmdjLmVuYWJsZWQgPSB0cnVlO1xuICAgICAgICBjb25zdCBtb2QyID0gYXdhaXQgZmFhc3RBd3MoZnVuY3Rpb25zLCB7XG4gICAgICAgICAgICBnYzogXCJmb3JjZVwiLFxuICAgICAgICAgICAgcmV0ZW50aW9uSW5EYXlzOiAwLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHQudGl0bGUsXG4gICAgICAgICAgICBfZ2NXb3JrZXI6IGFzeW5jICh3b3JrLCBzZXJ2aWNlcykgPT4ge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAod29yay50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJTZXRMb2dSZXRlbnRpb25cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrUmVzb3VyY2VzQ2xlYW5lZFVwIHdpbGwgdmVyaWZ5IHRoZSBsb2cgZ3JvdXAgaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBkZWZhdWx0R2NXb3JrZXIod29yaywgc2VydmljZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJEZWxldGVMYXllclZlcnNpb25cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3b3JrLkxheWVyTmFtZSA9PT0gbGF5ZXIhLkxheWVyTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5nYyhgZGVsZXRpbmcgbGF5ZXIgJHt3b3JrLkxheWVyTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBkZWZhdWx0R2NXb3JrZXIod29yaywgc2VydmljZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZWRMYXllciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkRlbGV0ZVJlc291cmNlc1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdvcmsucmVzb3VyY2VzLkZ1bmN0aW9uTmFtZSA9PT0gRnVuY3Rpb25OYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmdjKGBkZWxldGluZyByZXNvdXJjZXMgZm9yICR7RnVuY3Rpb25OYW1lfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGRlZmF1bHRHY1dvcmtlcih3b3JrLCBzZXJ2aWNlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCBtb2QyLmNsZWFudXAoeyBnY1RpbWVvdXQ6IDAgfSk7XG4gICAgICAgIHQudHJ1ZShkZWxldGVkTGF5ZXIsIFwiRGVsZXRlZCBsYXllciBpcyB0cnVlXCIpO1xuICAgICAgICBhd2FpdCBjaGVja1Jlc291cmNlc0NsZWFuZWRVcCh0LCBhd2FpdCBnZXRBV1NSZXNvdXJjZXMobW9kLCB0cnVlKSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgbG9nLmdjLmVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoeyBkZWxldGVSZXNvdXJjZXM6IHRydWUsIGRlbGV0ZUNhY2hlczogdHJ1ZSwgZ2NUaW1lb3V0OiAwIH0pO1xuICAgIH1cbn0pO1xuXG50ZXN0LnNlcmlhbCh0aXRsZShcImF3c1wiLCBcImdhcmJhZ2UgY29sbGVjdHMgZnVuY3Rpb25zIHRoYXQgYXJlIG5ldmVyIGNhbGxlZFwiKSwgYXN5bmMgdCA9PiB7XG4gICAgY29uc3QgbW9kID0gYXdhaXQgZmFhc3RBd3MoZnVuY3Rpb25zLCB7XG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBtb2RlOiBcInF1ZXVlXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlLFxuICAgICAgICBtYXhSZXRyaWVzOiAwXG4gICAgfSk7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoeyBkZWxldGVSZXNvdXJjZXM6IGZhbHNlLCBnY1RpbWVvdXQ6IDAgfSk7XG4gICAgICAgIGNvbnN0IHsgRnVuY3Rpb25OYW1lIH0gPSBtb2Quc3RhdGUucmVzb3VyY2VzO1xuICAgICAgICBjb25zdCBtb2QyID0gYXdhaXQgZmFhc3RBd3MoZnVuY3Rpb25zLCB7XG4gICAgICAgICAgICBnYzogXCJmb3JjZVwiLFxuICAgICAgICAgICAgcmV0ZW50aW9uSW5EYXlzOiAwLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHQudGl0bGUsXG4gICAgICAgICAgICBfZ2NXb3JrZXI6IGFzeW5jICh3b3JrLCBzZXJ2aWNlcykgPT4ge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAod29yay50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJEZWxldGVSZXNvdXJjZXNcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3b3JrLnJlc291cmNlcy5GdW5jdGlvbk5hbWUgPT09IEZ1bmN0aW9uTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5nYyhgZGVsZXRpbmcgcmVzb3VyY2VzIGZvciAke0Z1bmN0aW9uTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBkZWZhdWx0R2NXb3JrZXIod29yaywgc2VydmljZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgbW9kMi5jbGVhbnVwKHsgZ2NUaW1lb3V0OiAwIH0pO1xuICAgICAgICAvLyBEb24ndCBmYWlsIGlmIGEgbG9nIGdyb3VwIGV4aXN0cyBiZWNhdXNlIHdlIGRpZG4ndCB3YWl0IGZvciBpdHNcbiAgICAgICAgLy8gY3JlYXRpb247IGl0IG1pZ2h0IGJlIGNyZWF0ZWQgYnkgQVdTIGFmdGVyIHRoZSBjbGVhbnVwIG9jY3Vycy4gVGhlXG4gICAgICAgIC8vIHJlYXNvbiBpcyB0aGF0IHRoZSBsb2cgZ3JvdXAgd2lsbCBvbmx5IGJlIGNyZWF0ZWQgaWYgdGhlcmUncyBhblxuICAgICAgICAvLyBpbnZvY2F0aW9uIHRlc3QsIHdoaWNoIG9ubHkgaGFwcGVucyBpbiB0aGUgc3BlY2lhbCBjYXNlIHRoYXQgdGhlIHJvbGVcbiAgICAgICAgLy8gd2FzIHJlY2VudGx5IGNyZWF0ZWQuIFdoaWNoIGlzIHRydWUgZm9yIHRoZSBuaWdodGx5IHRlc3RzdWl0ZSBidXRcbiAgICAgICAgLy8gcmFyZWx5IGVsc2V3aGVyZS5cbiAgICAgICAgY29uc3QgeyBsb2dHcm91cFJlc3VsdCwgLi4ucmVzb3VyY2VzIH0gPSBhd2FpdCBnZXRBV1NSZXNvdXJjZXMobW9kLCB0cnVlKTtcbiAgICAgICAgYXdhaXQgY2hlY2tSZXNvdXJjZXNDbGVhbmVkVXAodCwgcmVzb3VyY2VzKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBtb2QuY2xlYW51cCh7IGRlbGV0ZVJlc291cmNlczogdHJ1ZSwgZGVsZXRlQ2FjaGVzOiB0cnVlLCBnY1RpbWVvdXQ6IDAgfSk7XG4gICAgfVxufSk7XG5cbnRlc3Quc2tpcCh0aXRsZShcImF3c1wiLCBcImdhcmJhZ2UgY29sbGVjdGlvbiBjYWNoaW5nXCIpLCBhc3luYyB0ID0+IHtcbiAgICB7XG4gICAgICAgIC8vIFJ1biBhIHJlYWwgZ2Mgc28gdGhlIGJ1aWxkIGFjY291bnQgZG9lc24ndCBhY2N1bXVsYXRlIGdhcmJhZ2UuXG4gICAgICAgIGNvbnN0IG1vZCA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywgeyBnYzogXCJmb3JjZVwiLCBkZXNjcmlwdGlvbjogdC50aXRsZSB9KTtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoeyBnY1RpbWVvdXQ6IDAgfSk7XG4gICAgICAgIHQuaXMoYXdhaXQgbW9kLnN0YXRlLmdjUHJvbWlzZSwgXCJkb25lXCIpO1xuICAgIH1cblxuICAgIHtcbiAgICAgICAgLy8gVGVzdCB0aGUgaW4tbWVtb3J5IGNhY2hlIHRoYXQgcHJldmVudHMgZ2MgZnJvbSBtdWx0aXBsZSBmYWFzdC5qc1xuICAgICAgICAvLyBpbnN0YW5jZXMgZnJvbSBydW5uaW5nIGF0IHRoZSBzYW1lIHRpbWUuXG4gICAgICAgIGNvbnN0IG1vZCA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywgeyBkZXNjcmlwdGlvbjogdC50aXRsZSB9KTtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoKTtcbiAgICAgICAgdC5pcyhhd2FpdCBtb2Quc3RhdGUuZ2NQcm9taXNlLCBcInNraXBwZWRcIik7XG4gICAgfVxuXG4gICAge1xuICAgICAgICAvLyBUZXN0IHRoZSBwZXJzaXN0ZW50IGNhY2hlIHRoYXQgcHJldmVudHMgZ2MgZnJvbSBydW5uaW5nIHRvbyBvZnRlblxuICAgICAgICAvLyBldmVuIGFjcm9zcyBwcm9jZXNzZXMuXG4gICAgICAgIGNsZWFyTGFzdEdjKCk7XG4gICAgICAgIGNvbnN0IG1vZCA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywgeyBkZXNjcmlwdGlvbjogdC50aXRsZSB9KTtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoKTtcbiAgICAgICAgdC5pcyhhd2FpdCBtb2Quc3RhdGUuZ2NQcm9taXNlLCBcInNraXBwZWRcIik7XG4gICAgfVxufSk7XG4iXX0=