UNPKG

faastjs

Version:

Serverless batch computing made simple.

165 lines 22.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ava_1 = require("ava"); const util_1 = require("util"); const index_1 = require("../index"); const funcs = require("./fixtures/functions"); const util_2 = require("./fixtures/util"); /** * Note that there is an AWS Lambda bug where timeouts are not delivered if the * function has a timeout >= 300s, and the function is invoked directly with the * Invoke API (e.g. in faast.js' "https" mode, which is the default.). In this * case if faast.js has childProcess mode on (the default), then it will set its * own timeout. This situation is not explicitly tested here because it would * make the entire testsuite slower for just one test. To test this situation * manually, change the timeout to 300 or more, and run one of these tests: * * $ ava --timeout=10m -m="remote aws generator timeout { mode: 'https', childProcess: true }" * $ ava --timeout=10m -m="remote aws timeout { mode: 'https', childProcess: true }" */ async function testTimeout(t, provider, options) { const lambda = await (0, index_1.faast)(provider, funcs, { ...options, timeout: 5, maxRetries: 0, gc: "off", description: t.title }); t.plan(1); // t.log(`${lambda.logUrl()}`); try { try { await lambda.functions.infiniteLoop(); } catch (err) { const isTimeout = index_1.FaastError.hasCauseWithName(err, index_1.FaastErrorNames.ETIMEOUT); t.is(isTimeout, true, `${(0, util_1.inspect)(err)}`); } } finally { await lambda.cleanup(); } } /** * The purpose of this test is to verify that a CPU hogging async generator * function won't starve the sending logic, so yield messages prior to the CPU * intensive work are delivered. */ async function testGenerator(t, provider, options) { t.plan(2); const lambda = await (0, index_1.faast)(provider, funcs, { ...options, timeout: 5, maxRetries: 0, gc: "off", description: t.title }); // t.log(`${lambda.logUrl()}`); try { const arg = "hello, generator!"; for await (const result of lambda.functions.generateThenInfiniteLoop(arg)) { t.is(result, arg); } t.fail("Did not timeout"); } catch (err) { t.is(index_1.FaastError.hasCauseWithName(err, index_1.FaastErrorNames.ETIMEOUT), true); } finally { await lambda.cleanup(); } } async function memoryLimitOk(t, provider, options) { const lambda = await (0, index_1.faast)(provider, funcs, { ...options, timeout: 200, memorySize: 512, maxRetries: 0, gc: "off", description: t.title }); try { const bytes = 64 * 1024 * 1024; const rv = await lambda.functions.allocate(bytes); t.is(rv.elems, bytes / 8); } finally { await lambda.cleanup(); } } async function memoryLimitFail(t, provider, options) { const lambda = await (0, index_1.faast)(provider, funcs, { ...options, timeout: 200, memorySize: 512, maxRetries: 0, gc: "off", description: t.title }); try { const bytes = 512 * 1024 * 1024; await t.throwsAsync(lambda.functions.allocate(bytes), { message: /memory/i }); } finally { lambda && (await lambda.cleanup()); } } // Note that this test takes 180s by default. Set the ava timeout to 2m or // longer otherwise it will fail with a timeout error. async function testLongInvoke(t, provider, options) { // The http timeout is 120s in awssdk by default. Uncomment the following // line to shorten it to 20s for focused testing. Note that shortening it // below 20s causes (harmless) timeout error messages from SQS on the long // polling response queue. If faast.js is working correctly, the shortened // timeout should not cause a test failure. // // config.update({ httpOptions: { timeout: 20000 } }); const opts = { timeout: 500, gc: "off", description: t.title, ...options }; const faastModule = await (0, index_1.faast)(provider, funcs, opts); const remote = faastModule.functions; try { let i = 0; const args = ["a", "b", "c"]; // The use of an async generator is to mimick a real use case from a // client of faast.js. The presence of an error should also be revealed // with a regular remote function call. for await (const arg of remote.asyncGeneratorDelay(args, 60000)) { t.is(arg, args[i++]); } } finally { await faastModule.cleanup(); } } const allLimits = ["memory", "timeout", "long", "generator"]; const configurations = [ ["aws", { mode: "https", childProcess: true }, allLimits], ["aws", { mode: "queue", childProcess: true }, allLimits], ["aws", { mode: "https", childProcess: false }, ["memory", "timeout", "generator"]], ["aws", { mode: "queue", childProcess: false }, ["memory", "timeout", "generator"]], ["google", { mode: "https", childProcess: true }, ["memory", "timeout", "long"]], ["google", { mode: "queue", childProcess: true }, []], ["local", {}, ["timeout"]] ]; for (const [provider, config, limitTypes] of configurations) { const opts = (0, util_1.inspect)(config); if (limitTypes.find(t => t === "memory")) { (0, ava_1.default)((0, util_2.title)(provider, `memory under limit ${opts}`), memoryLimitOk, provider, config); (0, ava_1.default)((0, util_2.title)(provider, `out of memory`, config), memoryLimitFail, provider, config); } if (limitTypes.find(t => t === "timeout")) { (0, ava_1.default)((0, util_2.title)(provider, `timeout`, config), testTimeout, provider, config); } if (limitTypes.find(t => t === "long")) { (0, ava_1.default)((0, util_2.title)(provider, `long invoke`, config), testLongInvoke, provider, config); } if (limitTypes.find(t => t === "generator")) { (0, ava_1.default)((0, util_2.title)(provider, `generator timeout`, config), testGenerator, provider, config); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGltaXRzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0L2xpbWl0cy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkJBQTZDO0FBQzdDLCtCQUErQjtBQUMvQixvQ0FBdUY7QUFDdkYsOENBQThDO0FBQzlDLDBDQUF3QztBQUV4Qzs7Ozs7Ozs7Ozs7R0FXRztBQUNILEtBQUssVUFBVSxXQUFXLENBQ3RCLENBQW1CLEVBQ25CLFFBQWtCLEVBQ2xCLE9BQXNCO0lBRXRCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBQSxhQUFLLEVBQUMsUUFBUSxFQUFFLEtBQUssRUFBRTtRQUN4QyxHQUFHLE9BQU87UUFDVixPQUFPLEVBQUUsQ0FBQztRQUNWLFVBQVUsRUFBRSxDQUFDO1FBQ2IsRUFBRSxFQUFFLEtBQUs7UUFDVCxXQUFXLEVBQUUsQ0FBQyxDQUFDLEtBQUs7S0FDdkIsQ0FBQyxDQUFDO0lBQ0gsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNWLCtCQUErQjtJQUMvQixJQUFJO1FBQ0EsSUFBSTtZQUNBLE1BQU0sTUFBTSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztTQUN6QztRQUFDLE9BQU8sR0FBUSxFQUFFO1lBQ2YsTUFBTSxTQUFTLEdBQUcsa0JBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsdUJBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3RSxDQUFDLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFBLGNBQU8sRUFBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDNUM7S0FDSjtZQUFTO1FBQ04sTUFBTSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7S0FDMUI7QUFDTCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxhQUFhLENBQ3hCLENBQW1CLEVBQ25CLFFBQWtCLEVBQ2xCLE9BQXNCO0lBRXRCLENB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QyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssU0FBUyxDQUFDLEVBQUU7UUFDdkMsSUFBQSxhQUFJLEVBQUMsSUFBQSxZQUFLLEVBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0tBQzNFO0lBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxFQUFFO1FBQ3BDLElBQUEsYUFBSSxFQUFDLElBQUEsWUFBSyxFQUFDLFFBQVEsRUFBRSxhQUFhLEVBQUUsTUFBTSxDQUFDLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztLQUNsRjtJQUNELElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxXQUFXLENBQUMsRUFBRTtRQUN6QyxJQUFBLGFBQUksRUFDQSxJQUFBLFlBQUssRUFBQyxRQUFRLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxDQUFDLEVBQzVDLGFBQWEsRUFDYixRQUFRLEVBQ1IsTUFBTSxDQUNULENBQUM7S0FDTDtDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRlc3QsIHsgRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gXCJhdmFcIjtcbmltcG9ydCB7IGluc3BlY3QgfSBmcm9tIFwidXRpbFwiO1xuaW1wb3J0IHsgQ29tbW9uT3B0aW9ucywgZmFhc3QsIEZhYXN0RXJyb3IsIEZhYXN0RXJyb3JOYW1lcywgUHJvdmlkZXIgfSBmcm9tIFwiLi4vaW5kZXhcIjtcbmltcG9ydCAqIGFzIGZ1bmNzIGZyb20gXCIuL2ZpeHR1cmVzL2Z1bmN0aW9uc1wiO1xuaW1wb3J0IHsgdGl0bGUgfSBmcm9tIFwiLi9maXh0dXJlcy91dGlsXCI7XG5cbi8qKlxuICogTm90ZSB0aGF0IHRoZXJlIGlzIGFuIEFXUyBMYW1iZGEgYnVnIHdoZXJlIHRpbWVvdXRzIGFyZSBub3QgZGVsaXZlcmVkIGlmIHRoZVxuICogZnVuY3Rpb24gaGFzIGEgdGltZW91dCA+PSAzMDBzLCBhbmQgdGhlIGZ1bmN0aW9uIGlzIGludm9rZWQgZGlyZWN0bHkgd2l0aCB0aGVcbiAqIEludm9rZSBBUEkgKGUuZy4gaW4gZmFhc3QuanMnIFwiaHR0cHNcIiBtb2RlLCB3aGljaCBpcyB0aGUgZGVmYXVsdC4pLiBJbiB0aGlzXG4gKiBjYXNlIGlmIGZhYXN0LmpzIGhhcyBjaGlsZFByb2Nlc3MgbW9kZSBvbiAodGhlIGRlZmF1bHQpLCB0aGVuIGl0IHdpbGwgc2V0IGl0c1xuICogb3duIHRpbWVvdXQuIFRoaXMgc2l0dWF0aW9uIGlzIG5vdCBleHBsaWNpdGx5IHRlc3RlZCBoZXJlIGJlY2F1c2UgaXQgd291bGRcbiAqIG1ha2UgdGhlIGVudGlyZSB0ZXN0c3VpdGUgc2xvd2VyIGZvciBqdXN0IG9uZSB0ZXN0LiBUbyB0ZXN0IHRoaXMgc2l0dWF0aW9uXG4gKiBtYW51YWxseSwgY2hhbmdlIHRoZSB0aW1lb3V0IHRvIDMwMCBvciBtb3JlLCBhbmQgcnVuIG9uZSBvZiB0aGVzZSB0ZXN0czpcbiAqXG4gKiAgICAkIGF2YSAtLXRpbWVvdXQ9MTBtIC1tPVwicmVtb3RlIGF3cyBnZW5lcmF0b3IgdGltZW91dCB7IG1vZGU6ICdodHRwcycsIGNoaWxkUHJvY2VzczogdHJ1ZSB9XCJcbiAqICAgICQgYXZhIC0tdGltZW91dD0xMG0gLW09XCJyZW1vdGUgYXdzIHRpbWVvdXQgeyBtb2RlOiAnaHR0cHMnLCBjaGlsZFByb2Nlc3M6IHRydWUgfVwiXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHRlc3RUaW1lb3V0KFxuICAgIHQ6IEV4ZWN1dGlvbkNvbnRleHQsXG4gICAgcHJvdmlkZXI6IFByb3ZpZGVyLFxuICAgIG9wdGlvbnM6IENvbW1vbk9wdGlvbnNcbikge1xuICAgIGNvbnN0IGxhbWJkYSA9IGF3YWl0IGZhYXN0KHByb3ZpZGVyLCBmdW5jcywge1xuICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICB0aW1lb3V0OiA1LFxuICAgICAgICBtYXhSZXRyaWVzOiAwLFxuICAgICAgICBnYzogXCJvZmZcIixcbiAgICAgICAgZGVzY3JpcHRpb246IHQudGl0bGVcbiAgICB9KTtcbiAgICB0LnBsYW4oMSk7XG4gICAgLy8gdC5sb2coYCR7bGFtYmRhLmxvZ1VybCgpfWApO1xuICAgIHRyeSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBsYW1iZGEuZnVuY3Rpb25zLmluZmluaXRlTG9vcCgpO1xuICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgY29uc3QgaXNUaW1lb3V0ID0gRmFhc3RFcnJvci5oYXNDYXVzZVdpdGhOYW1lKGVyciwgRmFhc3RFcnJvck5hbWVzLkVUSU1FT1VUKTtcbiAgICAgICAgICAgIHQuaXMoaXNUaW1lb3V0LCB0cnVlLCBgJHtpbnNwZWN0KGVycil9YCk7XG4gICAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBsYW1iZGEuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBUaGUgcHVycG9zZSBvZiB0aGlzIHRlc3QgaXMgdG8gdmVyaWZ5IHRoYXQgYSBDUFUgaG9nZ2luZyBhc3luYyBnZW5lcmF0b3JcbiAqIGZ1bmN0aW9uIHdvbid0IHN0YXJ2ZSB0aGUgc2VuZGluZyBsb2dpYywgc28geWllbGQgbWVzc2FnZXMgcHJpb3IgdG8gdGhlIENQVVxuICogaW50ZW5zaXZlIHdvcmsgYXJlIGRlbGl2ZXJlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdGVzdEdlbmVyYXRvcihcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIHByb3ZpZGVyOiBQcm92aWRlcixcbiAgICBvcHRpb25zOiBDb21tb25PcHRpb25zXG4pIHtcbiAgICB0LnBsYW4oMik7XG4gICAgY29uc3QgbGFtYmRhID0gYXdhaXQgZmFhc3QocHJvdmlkZXIsIGZ1bmNzLCB7XG4gICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgIHRpbWVvdXQ6IDUsXG4gICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuICAgIH0pO1xuICAgIC8vIHQubG9nKGAke2xhbWJkYS5sb2dVcmwoKX1gKTtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBhcmcgPSBcImhlbGxvLCBnZW5lcmF0b3IhXCI7XG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgcmVzdWx0IG9mIGxhbWJkYS5mdW5jdGlvbnMuZ2VuZXJhdGVUaGVuSW5maW5pdGVMb29wKGFyZykpIHtcbiAgICAgICAgICAgIHQuaXMocmVzdWx0LCBhcmcpO1xuICAgICAgICB9XG4gICAgICAgIHQuZmFpbChcIkRpZCBub3QgdGltZW91dFwiKTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICB0LmlzKEZhYXN0RXJyb3IuaGFzQ2F1c2VXaXRoTmFtZShlcnIsIEZhYXN0RXJyb3JOYW1lcy5FVElNRU9VVCksIHRydWUpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGxhbWJkYS5jbGVhbnVwKCk7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBtZW1vcnlMaW1pdE9rKFxuICAgIHQ6IEV4ZWN1dGlvbkNvbnRleHQsXG4gICAgcHJvdmlkZXI6IFByb3ZpZGVyLFxuICAgIG9wdGlvbnM6IENvbW1vbk9wdGlvbnNcbikge1xuICAgIGNvbnN0IGxhbWJkYSA9IGF3YWl0IGZhYXN0KHByb3ZpZGVyLCBmdW5jcywge1xuICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICB0aW1lb3V0OiAyMDAsXG4gICAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgbWF4UmV0cmllczogMCxcbiAgICAgICAgZ2M6IFwib2ZmXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlXG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgICBjb25zdCBieXRlcyA9IDY0ICogMTAyNCAqIDEwMjQ7XG4gICAgICAgIGNvbnN0IHJ2ID0gYXdhaXQgbGFtYmRhLmZ1bmN0aW9ucy5hbGxvY2F0ZShieXRlcyk7XG4gICAgICAgIHQuaXMocnYuZWxlbXMsIGJ5dGVzIC8gOCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgbGFtYmRhLmNsZWFudXAoKTtcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lbW9yeUxpbWl0RmFpbChcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIHByb3ZpZGVyOiBQcm92aWRlcixcbiAgICBvcHRpb25zOiBDb21tb25PcHRpb25zXG4pIHtcbiAgICBjb25zdCBsYW1iZGEgPSBhd2FpdCBmYWFzdChwcm92aWRlciwgZnVuY3MsIHtcbiAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgdGltZW91dDogMjAwLFxuICAgICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuICAgIH0pO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgYnl0ZXMgPSA1MTIgKiAxMDI0ICogMTAyNDtcbiAgICAgICAgYXdhaXQgdC50aHJvd3NBc3luYyhsYW1iZGEuZnVuY3Rpb25zLmFsbG9jYXRlKGJ5dGVzKSwgeyBtZXNzYWdlOiAvbWVtb3J5L2kgfSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgbGFtYmRhICYmIChhd2FpdCBsYW1iZGEuY2xlYW51cCgpKTtcbiAgICB9XG59XG5cbi8vIE5vdGUgdGhhdCB0aGlzIHRlc3QgdGFrZXMgMTgwcyBieSBkZWZhdWx0LiBTZXQgdGhlIGF2YSB0aW1lb3V0IHRvIDJtIG9yXG4vLyBsb25nZXIgb3RoZXJ3aXNlIGl0IHdpbGwgZmFpbCB3aXRoIGEgdGltZW91dCBlcnJvci5cbmFzeW5jIGZ1bmN0aW9uIHRlc3RMb25nSW52b2tlKFxuICAgIHQ6IEV4ZWN1dGlvbkNvbnRleHQsXG4gICAgcHJvdmlkZXI6IFByb3ZpZGVyLFxuICAgIG9wdGlvbnM6IENvbW1vbk9wdGlvbnNcbikge1xuICAgIC8vIFRoZSBodHRwIHRpbWVvdXQgaXMgMTIwcyBpbiBhd3NzZGsgYnkgZGVmYXVsdC4gVW5jb21tZW50IHRoZSBmb2xsb3dpbmdcbiAgICAvLyBsaW5lIHRvIHNob3J0ZW4gaXQgdG8gMjBzIGZvciBmb2N1c2VkIHRlc3RpbmcuIE5vdGUgdGhhdCBzaG9ydGVuaW5nIGl0XG4gICAgLy8gYmVsb3cgMjBzIGNhdXNlcyAoaGFybWxlc3MpIHRpbWVvdXQgZXJyb3IgbWVzc2FnZXMgZnJvbSBTUVMgb24gdGhlIGxvbmdcbiAgICAvLyBwb2xsaW5nIHJlc3BvbnNlIHF1ZXVlLiBJZiBmYWFzdC5qcyBpcyB3b3JraW5nIGNvcnJlY3RseSwgdGhlIHNob3J0ZW5lZFxuICAgIC8vIHRpbWVvdXQgc2hvdWxkIG5vdCBjYXVzZSBhIHRlc3QgZmFpbHVyZS5cbiAgICAvL1xuICAgIC8vIGNvbmZpZy51cGRhdGUoeyBodHRwT3B0aW9uczogeyB0aW1lb3V0OiAyMDAwMCB9IH0pO1xuICAgIGNvbnN0IG9wdHM6IENvbW1vbk9wdGlvbnMgPSB7XG4gICAgICAgIHRpbWVvdXQ6IDUwMCxcbiAgICAgICAgZ2M6IFwib2ZmXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlLFxuICAgICAgICAuLi5vcHRpb25zXG4gICAgfTtcbiAgICBjb25zdCBmYWFzdE1vZHVsZSA9IGF3YWl0IGZhYXN0KHByb3ZpZGVyLCBmdW5jcywgb3B0cyk7XG4gICAgY29uc3QgcmVtb3RlID0gZmFhc3RNb2R1bGUuZnVuY3Rpb25zO1xuICAgIHRyeSB7XG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgY29uc3QgYXJncyA9IFtcImFcIiwgXCJiXCIsIFwiY1wiXTtcbiAgICAgICAgLy8gVGhlIHVzZSBvZiBhbiBhc3luYyBnZW5lcmF0b3IgaXMgdG8gbWltaWNrIGEgcmVhbCB1c2UgY2FzZSBmcm9tIGFcbiAgICAgICAgLy8gY2xpZW50IG9mIGZhYXN0LmpzLiBUaGUgcHJlc2VuY2Ugb2YgYW4gZXJyb3Igc2hvdWxkIGFsc28gYmUgcmV2ZWFsZWRcbiAgICAgICAgLy8gd2l0aCBhIHJlZ3VsYXIgcmVtb3RlIGZ1bmN0aW9uIGNhbGwuXG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgYXJnIG9mIHJlbW90ZS5hc3luY0dlbmVyYXRvckRlbGF5KGFyZ3MsIDYwMDAwKSkge1xuICAgICAgICAgICAgdC5pcyhhcmcsIGFyZ3NbaSsrXSk7XG4gICAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBmYWFzdE1vZHVsZS5jbGVhbnVwKCk7XG4gICAgfVxufVxuXG50eXBlIExpbWl0VHlwZSA9IFwibWVtb3J5XCIgfCBcInRpbWVvdXRcIiB8IFwiZ2VuZXJhdG9yXCIgfCBcImxvbmdcIjtcbmNvbnN0IGFsbExpbWl0cyA9IFtcIm1lbW9yeVwiLCBcInRpbWVvdXRcIiwgXCJsb25nXCIsIFwiZ2VuZXJhdG9yXCJdIGFzIGNvbnN0O1xuXG5jb25zdCBjb25maWd1cmF0aW9uczogW1Byb3ZpZGVyLCBDb21tb25PcHRpb25zLCByZWFkb25seSBMaW1pdFR5cGVbXV1bXSA9IFtcbiAgICBbXCJhd3NcIiwgeyBtb2RlOiBcImh0dHBzXCIsIGNoaWxkUHJvY2VzczogdHJ1ZSB9LCBhbGxMaW1pdHNdLFxuICAgIFtcImF3c1wiLCB7IG1vZGU6IFwicXVldWVcIiwgY2hpbGRQcm9jZXNzOiB0cnVlIH0sIGFsbExpbWl0c10sXG4gICAgW1wiYXdzXCIsIHsgbW9kZTogXCJodHRwc1wiLCBjaGlsZFByb2Nlc3M6IGZhbHNlIH0sIFtcIm1lbW9yeVwiLCBcInRpbWVvdXRcIiwgXCJnZW5lcmF0b3JcIl1dLFxuICAgIFtcImF3c1wiLCB7IG1vZGU6IFwicXVldWVcIiwgY2hpbGRQcm9jZXNzOiBmYWxzZSB9LCBbXCJtZW1vcnlcIiwgXCJ0aW1lb3V0XCIsIFwiZ2VuZXJhdG9yXCJdXSxcbiAgICBbXCJnb29nbGVcIiwgeyBtb2RlOiBcImh0dHBzXCIsIGNoaWxkUHJvY2VzczogdHJ1ZSB9LCBbXCJtZW1vcnlcIiwgXCJ0aW1lb3V0XCIsIFwibG9uZ1wiXV0sXG4gICAgW1wiZ29vZ2xlXCIsIHsgbW9kZTogXCJxdWV1ZVwiLCBjaGlsZFByb2Nlc3M6IHRydWUgfSwgW11dLFxuICAgIFtcImxvY2FsXCIsIHt9LCBbXCJ0aW1lb3V0XCJdXVxuXTtcblxuZm9yIChjb25zdCBbcHJvdmlkZXIsIGNvbmZpZywgbGltaXRUeXBlc10gb2YgY29uZmlndXJhdGlvbnMpIHtcbiAgICBjb25zdCBvcHRzID0gaW5zcGVjdChjb25maWcpO1xuICAgIGlmIChsaW1pdFR5cGVzLmZpbmQodCA9PiB0ID09PSBcIm1lbW9yeVwiKSkge1xuICAgICAgICB0ZXN0KFxuICAgICAgICAgICAgdGl0bGUocHJvdmlkZXIsIGBtZW1vcnkgdW5kZXIgbGltaXQgJHtvcHRzfWApLFxuICAgICAgICAgICAgbWVtb3J5TGltaXRPayxcbiAgICAgICAgICAgIHByb3ZpZGVyLFxuICAgICAgICAgICAgY29uZmlnXG4gICAgICAgICk7XG4gICAgICAgIHRlc3QodGl0bGUocHJvdmlkZXIsIGBvdXQgb2YgbWVtb3J5YCwgY29uZmlnKSwgbWVtb3J5TGltaXRGYWlsLCBwcm92aWRlciwgY29uZmlnKTtcbiAgICB9XG4gICAgaWYgKGxpbWl0VHlwZXMuZmluZCh0ID0+IHQgPT09IFwidGltZW91dFwiKSkge1xuICAgICAgICB0ZXN0KHRpdGxlKHByb3ZpZGVyLCBgdGltZW91dGAsIGNvbmZpZyksIHRlc3RUaW1lb3V0LCBwcm92aWRlciwgY29uZmlnKTtcbiAgICB9XG4gICAgaWYgKGxpbWl0VHlwZXMuZmluZCh0ID0+IHQgPT09IFwibG9uZ1wiKSkge1xuICAgICAgICB0ZXN0KHRpdGxlKHByb3ZpZGVyLCBgbG9uZyBpbnZva2VgLCBjb25maWcpLCB0ZXN0TG9uZ0ludm9rZSwgcHJvdmlkZXIsIGNvbmZpZyk7XG4gICAgfVxuICAgIGlmIChsaW1pdFR5cGVzLmZpbmQodCA9PiB0ID09PSBcImdlbmVyYXRvclwiKSkge1xuICAgICAgICB0ZXN0KFxuICAgICAgICAgICAgdGl0bGUocHJvdmlkZXIsIGBnZW5lcmF0b3IgdGltZW91dGAsIGNvbmZpZyksXG4gICAgICAgICAgICB0ZXN0R2VuZXJhdG9yLFxuICAgICAgICAgICAgcHJvdmlkZXIsXG4gICAgICAgICAgICBjb25maWdcbiAgICAgICAgKTtcbiAgICB9XG59XG4iXX0=