UNPKG

23.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.receiveMessages = exports.processAwsErrorMessage = exports.createSQSQueue = exports.publishFunctionCallMessage = exports.sendResponseQueueMessage = exports.createSNSTopic = void 0;
4const error_1 = require("../error");
5const log_1 = require("../log");
6const serialize_1 = require("../serialize");
7const shared_1 = require("../shared");
8const throttle_1 = require("../throttle");
9const wrapper_1 = require("../wrapper");
10async function createSNSTopic(sns, Name) {
11 const topic = await sns.createTopic({ Name }).promise();
12 return topic.TopicArn;
13}
14exports.createSNSTopic = createSNSTopic;
15function countRequests(bytes) {
16 return Math.ceil(bytes / (64 * 1024));
17}
18async function sendResponseQueueMessage(sqs, QueueUrl, message) {
19 try {
20 const request = { QueueUrl, MessageBody: (0, serialize_1.serialize)(message) };
21 await sqs.sendMessage(request).promise();
22 }
23 catch (err) {
24 log_1.log.warn(err);
25 }
26}
27exports.sendResponseQueueMessage = sendResponseQueueMessage;
28function publishFunctionCallMessage(sns, TopicArn, message, metrics) {
29 const serialized = (0, serialize_1.serialize)(message);
30 metrics.sns64kRequests += countRequests(serialized.length);
31 return (0, throttle_1.retryOp)((err, n) => n < 6 && err?.message?.match(/does not exist/), () => sns
32 .publish({
33 TopicArn,
34 Message: serialized
35 })
36 .promise());
37}
38exports.publishFunctionCallMessage = publishFunctionCallMessage;
39async function createSQSQueue(QueueName, VTimeout, sqs) {
40 try {
41 const createQueueRequest = {
42 QueueName,
43 Attributes: {
44 VisibilityTimeout: `${VTimeout}`
45 }
46 };
47 const response = await sqs.createQueue(createQueueRequest).promise();
48 const QueueUrl = response.QueueUrl;
49 const arnResponse = await sqs
50 .getQueueAttributes({ QueueUrl, AttributeNames: ["QueueArn"] })
51 .promise();
52 const QueueArn = arnResponse.Attributes?.QueueArn;
53 return { QueueUrl, QueueArn };
54 }
55 catch (err) {
56 throw new error_1.FaastError(err, "create sqs queue");
57 }
58}
59exports.createSQSQueue = createSQSQueue;
60/* istanbul ignore next */
61function processAwsErrorMessage(message) {
62 let err = new error_1.FaastError(message);
63 if (message?.match(/Process exited before completing/) ||
64 message?.match(/signal: killed/)) {
65 err = new error_1.FaastError({ cause: err, name: error_1.FaastErrorNames.EMEMORY }, "possibly out of memory");
66 }
67 else if (message?.match(/time/)) {
68 err = new error_1.FaastError({ cause: err, name: error_1.FaastErrorNames.ETIMEOUT }, "timeout");
69 }
70 else if (message?.match(/EventAgeExceeded/)) {
71 err = new error_1.FaastError({ cause: err, name: error_1.FaastErrorNames.ECONCURRENCY }, "concurrency limit exceeded");
72 }
73 return err;
74}
75exports.processAwsErrorMessage = processAwsErrorMessage;
76async function receiveMessages(sqs, ResponseQueueUrl, metrics, cancel) {
77 try {
78 const MaxNumberOfMessages = 10;
79 const request = sqs.receiveMessage({
80 QueueUrl: ResponseQueueUrl,
81 WaitTimeSeconds: 20,
82 MaxNumberOfMessages,
83 MessageAttributeNames: ["All"],
84 AttributeNames: ["SentTimestamp"]
85 });
86 const response = await Promise.race([request.promise(), cancel]);
87 if (!response) {
88 request.abort();
89 return { Messages: [] };
90 }
91 const { Messages = [] } = response;
92 const { httpResponse } = response.$response;
93 const receivedBytes = (0, shared_1.computeHttpResponseBytes)(httpResponse.headers);
94 metrics.outboundBytes += receivedBytes;
95 const inferredSqsRequestsReceived = countRequests(receivedBytes);
96 const inferredSqsRequestsSent = (0, shared_1.sum)(Messages.map(m => countRequests(m.Body?.length ?? 1)));
97 metrics.sqs64kRequests += inferredSqsRequestsSent + inferredSqsRequestsReceived;
98 if (Messages.length > 0) {
99 sqs.deleteMessageBatch({
100 QueueUrl: ResponseQueueUrl,
101 Entries: Messages.map(m => ({
102 Id: m.MessageId,
103 ReceiptHandle: m.ReceiptHandle
104 }))
105 })
106 .promise()
107 .catch(_ => { });
108 metrics.sqs64kRequests++;
109 }
110 return {
111 Messages: Messages.map(processIncomingQueueMessage).filter(shared_1.defined),
112 isFullMessageBatch: Messages.length === MaxNumberOfMessages
113 };
114 }
115 catch (err) {
116 throw new error_1.FaastError(err, "receiveMessages");
117 }
118}
119exports.receiveMessages = receiveMessages;
120function processIncomingQueueMessage(m) {
121 // AWS Lambda Destinations
122 // (https://aws.amazon.com/blogs/compute/introducing-aws-lambda-destinations/)
123 // are used to route failures to the response queue. These
124 // messages are generated by AWS Lambda and are constrained to the format it
125 // provides.
126 const raw = (0, serialize_1.deserialize)(m.Body);
127 if (raw.responseContext) {
128 const message = raw;
129 const snsMessage = message.requestPayload;
130 const record = snsMessage.Records[0];
131 const sCall = (0, serialize_1.deserialize)(record.Sns.Message);
132 let error;
133 const destinationError = message.responsePayload;
134 if (destinationError) {
135 error = processAwsErrorMessage(destinationError.errorMessage);
136 error.stack = destinationError.stackTrace?.join("\n");
137 }
138 else {
139 error = processAwsErrorMessage(message.requestContext.condition);
140 }
141 const executionId = message.requestContext.requestId;
142 return {
143 ...(0, wrapper_1.createErrorResponse)(error, {
144 call: sCall,
145 startTime: new Date(record.Sns.Timestamp).getTime(),
146 executionId
147 }),
148 timestamp: new Date(message.timestamp).getTime()
149 };
150 }
151 else {
152 const message = raw;
153 switch (message.kind) {
154 case "promise":
155 case "iterator":
156 message.timestamp = Number(m.Attributes.SentTimestamp);
157 break;
158 case "cpumetrics":
159 break;
160 case "functionstarted":
161 break;
162 default: {
163 console.warn(`Unknown message received from response queue`);
164 }
165 }
166 return raw;
167 }
168}
169//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLXF1ZXVlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2F3cy9hd3MtcXVldWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsb0NBQXVEO0FBQ3ZELGdDQUE2QjtBQUU3Qiw0Q0FBc0Q7QUFDdEQsc0NBQW1FO0FBQ25FLDBDQUFzQztBQUN0Qyx3Q0FBK0Q7QUFHeEQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxHQUFRLEVBQUUsSUFBWTtJQUN2RCxNQUFNLEtBQUssR0FBRyxNQUFNLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3hELE9BQU8sS0FBSyxDQUFDLFFBQVMsQ0FBQztBQUMzQixDQUFDO0FBSEQsd0NBR0M7QUFFRCxTQUFTLGFBQWEsQ0FBQyxLQUFhO0lBQ2hDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUMxQyxDQUFDO0FBRU0sS0FBSyxVQUFVLHdCQUF3QixDQUMxQyxHQUFRLEVBQ1IsUUFBZ0IsRUFDaEIsT0FBZ0I7SUFFaEIsSUFBSTtRQUNBLE1BQU0sT0FBTyxHQUFHLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxJQUFBLHFCQUFTLEVBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUM5RCxNQUFNLEdBQUcsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7S0FDNUM7SUFBQyxPQUFPLEdBQVEsRUFBRTtRQUNmLFNBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDakI7QUFDTCxDQUFDO0FBWEQsNERBV0M7QUFFRCxTQUFnQiwwQkFBMEIsQ0FDdEMsR0FBUSxFQUNSLFFBQWdCLEVBQ2hCLE9BQXFCLEVBQ3JCLE9BQW1CO0lBRW5CLE1BQU0sVUFBVSxHQUFHLElBQUEscUJBQVMsRUFBQyxPQUFPLENB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XG5pbXBvcnQgeyBTTlMsIFNRUyB9IGZyb20gXCJhd3Mtc2RrXCI7XG5pbXBvcnQgeyBGYWFzdEVycm9yLCBGYWFzdEVycm9yTmFtZXMgfSBmcm9tIFwiLi4vZXJyb3JcIjtcbmltcG9ydCB7IGxvZyB9IGZyb20gXCIuLi9sb2dcIjtcbmltcG9ydCB7IE1lc3NhZ2UsIFBvbGxSZXN1bHQgfSBmcm9tIFwiLi4vcHJvdmlkZXJcIjtcbmltcG9ydCB7IGRlc2VyaWFsaXplLCBzZXJpYWxpemUgfSBmcm9tIFwiLi4vc2VyaWFsaXplXCI7XG5pbXBvcnQgeyBjb21wdXRlSHR0cFJlc3BvbnNlQnl0ZXMsIGRlZmluZWQsIHN1bSB9IGZyb20gXCIuLi9zaGFyZWRcIjtcbmltcG9ydCB7IHJldHJ5T3AgfSBmcm9tIFwiLi4vdGhyb3R0bGVcIjtcbmltcG9ydCB7IGNyZWF0ZUVycm9yUmVzcG9uc2UsIEZ1bmN0aW9uQ2FsbCB9IGZyb20gXCIuLi93cmFwcGVyXCI7XG5pbXBvcnQgeyBBd3NNZXRyaWNzIH0gZnJvbSBcIi4vYXdzLWZhYXN0XCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVTTlNUb3BpYyhzbnM6IFNOUywgTmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgdG9waWMgPSBhd2FpdCBzbnMuY3JlYXRlVG9waWMoeyBOYW1lIH0pLnByb21pc2UoKTtcbiAgICByZXR1cm4gdG9waWMuVG9waWNBcm4hO1xufVxuXG5mdW5jdGlvbiBjb3VudFJlcXVlc3RzKGJ5dGVzOiBudW1iZXIpIHtcbiAgICByZXR1cm4gTWF0aC5jZWlsKGJ5dGVzIC8gKDY0ICogMTAyNCkpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZFJlc3BvbnNlUXVldWVNZXNzYWdlKFxuICAgIHNxczogU1FTLFxuICAgIFF1ZXVlVXJsOiBzdHJpbmcsXG4gICAgbWVzc2FnZTogTWVzc2FnZVxuKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHsgUXVldWVVcmwsIE1lc3NhZ2VCb2R5OiBzZXJpYWxpemUobWVzc2FnZSkgfTtcbiAgICAgICAgYXdhaXQgc3FzLnNlbmRNZXNzYWdlKHJlcXVlc3QpLnByb21pc2UoKTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICBsb2cud2FybihlcnIpO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHB1Ymxpc2hGdW5jdGlvbkNhbGxNZXNzYWdlKFxuICAgIHNuczogU05TLFxuICAgIFRvcGljQXJuOiBzdHJpbmcsXG4gICAgbWVzc2FnZTogRnVuY3Rpb25DYWxsLFxuICAgIG1ldHJpY3M6IEF3c01ldHJpY3Ncbikge1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBzZXJpYWxpemUobWVzc2FnZSk7XG4gICAgbWV0cmljcy5zbnM2NGtSZXF1ZXN0cyArPSBjb3VudFJlcXVlc3RzKHNlcmlhbGl6ZWQubGVuZ3RoKTtcbiAgICByZXR1cm4gcmV0cnlPcChcbiAgICAgICAgKGVyciwgbikgPT4gbiA8IDYgJiYgZXJyPy5tZXNzYWdlPy5tYXRjaCgvZG9lcyBub3QgZXhpc3QvKSxcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICAgIHNuc1xuICAgICAgICAgICAgICAgIC5wdWJsaXNoKHtcbiAgICAgICAgICAgICAgICAgICAgVG9waWNBcm4sXG4gICAgICAgICAgICAgICAgICAgIE1lc3NhZ2U6IHNlcmlhbGl6ZWRcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5wcm9taXNlKClcbiAgICApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlU1FTUXVldWUoUXVldWVOYW1lOiBzdHJpbmcsIFZUaW1lb3V0OiBudW1iZXIsIHNxczogU1FTKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY3JlYXRlUXVldWVSZXF1ZXN0OiBTUVMuQ3JlYXRlUXVldWVSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgUXVldWVOYW1lLFxuICAgICAgICAgICAgQXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAgIFZpc2liaWxpdHlUaW1lb3V0OiBgJHtWVGltZW91dH1gXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgc3FzLmNyZWF0ZVF1ZXVlKGNyZWF0ZVF1ZXVlUmVxdWVzdCkucHJvbWlzZSgpO1xuICAgICAgICBjb25zdCBRdWV1ZVVybCA9IHJlc3BvbnNlLlF1ZXVlVXJsITtcbiAgICAgICAgY29uc3QgYXJuUmVzcG9uc2UgPSBhd2FpdCBzcXNcbiAgICAgICAgICAgIC5nZXRRdWV1ZUF0dHJpYnV0ZXMoeyBRdWV1ZVVybCwgQXR0cmlidXRlTmFtZXM6IFtcIlF1ZXVlQXJuXCJdIH0pXG4gICAgICAgICAgICAucHJvbWlzZSgpO1xuICAgICAgICBjb25zdCBRdWV1ZUFybiA9IGFyblJlc3BvbnNlLkF0dHJpYnV0ZXM/LlF1ZXVlQXJuO1xuICAgICAgICByZXR1cm4geyBRdWV1ZVVybCwgUXVldWVBcm4gfTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihlcnIsIFwiY3JlYXRlIHNxcyBxdWV1ZVwiKTtcbiAgICB9XG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NBd3NFcnJvck1lc3NhZ2UobWVzc2FnZTogc3RyaW5nKTogRXJyb3Ige1xuICAgIGxldCBlcnIgPSBuZXcgRmFhc3RFcnJvcihtZXNzYWdlKTtcbiAgICBpZiAoXG4gICAgICAgIG1lc3NhZ2U/Lm1hdGNoKC9Qcm9jZXNzIGV4aXRlZCBiZWZvcmUgY29tcGxldGluZy8pIHx8XG4gICAgICAgIG1lc3NhZ2U/Lm1hdGNoKC9zaWduYWw6IGtpbGxlZC8pXG4gICAgKSB7XG4gICAgICAgIGVyciA9IG5ldyBGYWFzdEVycm9yKFxuICAgICAgICAgICAgeyBjYXVzZTogZXJyLCBuYW1lOiBGYWFzdEVycm9yTmFtZXMuRU1FTU9SWSB9LFxuICAgICAgICAgICAgXCJwb3NzaWJseSBvdXQgb2YgbWVtb3J5XCJcbiAgICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKG1lc3NhZ2U/Lm1hdGNoKC90aW1lLykpIHtcbiAgICAgICAgZXJyID0gbmV3IEZhYXN0RXJyb3IoeyBjYXVzZTogZXJyLCBuYW1lOiBGYWFzdEVycm9yTmFtZXMuRVRJTUVPVVQgfSwgXCJ0aW1lb3V0XCIpO1xuICAgIH0gZWxzZSBpZiAobWVzc2FnZT8ubWF0Y2goL0V2ZW50QWdlRXhjZWVkZWQvKSkge1xuICAgICAgICBlcnIgPSBuZXcgRmFhc3RFcnJvcihcbiAgICAgICAgICAgIHsgY2F1c2U6IGVyciwgbmFtZTogRmFhc3RFcnJvck5hbWVzLkVDT05DVVJSRU5DWSB9LFxuICAgICAgICAgICAgXCJjb25jdXJyZW5jeSBsaW1pdCBleGNlZWRlZFwiXG4gICAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBlcnI7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWNlaXZlTWVzc2FnZXMoXG4gICAgc3FzOiBTUVMsXG4gICAgUmVzcG9uc2VRdWV1ZVVybDogc3RyaW5nLFxuICAgIG1ldHJpY3M6IEF3c01ldHJpY3MsXG4gICAgY2FuY2VsOiBQcm9taXNlPHZvaWQ+XG4pOiBQcm9taXNlPFBvbGxSZXN1bHQ+IHtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBNYXhOdW1iZXJPZk1lc3NhZ2VzID0gMTA7XG4gICAgICAgIGNvbnN0IHJlcXVlc3QgPSBzcXMucmVjZWl2ZU1lc3NhZ2Uoe1xuICAgICAgICAgICAgUXVldWVVcmw6IFJlc3BvbnNlUXVldWVVcmwhLFxuICAgICAgICAgICAgV2FpdFRpbWVTZWNvbmRzOiAyMCxcbiAgICAgICAgICAgIE1heE51bWJlck9mTWVzc2FnZXMsXG4gICAgICAgICAgICBNZXNzYWdlQXR0cmlidXRlTmFtZXM6IFtcIkFsbFwiXSxcbiAgICAgICAgICAgIEF0dHJpYnV0ZU5hbWVzOiBbXCJTZW50VGltZXN0YW1wXCJdXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgUHJvbWlzZS5yYWNlKFtyZXF1ZXN0LnByb21pc2UoKSwgY2FuY2VsXSk7XG4gICAgICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgICAgICAgIHJlcXVlc3QuYWJvcnQoKTtcbiAgICAgICAgICAgIHJldHVybiB7IE1lc3NhZ2VzOiBbXSB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBNZXNzYWdlcyA9IFtdIH0gPSByZXNwb25zZTtcbiAgICAgICAgY29uc3QgeyBodHRwUmVzcG9uc2UgfSA9IHJlc3BvbnNlLiRyZXNwb25zZTtcbiAgICAgICAgY29uc3QgcmVjZWl2ZWRCeXRlcyA9IGNvbXB1dGVIdHRwUmVzcG9uc2VCeXRlcyhodHRwUmVzcG9uc2UuaGVhZGVycyk7XG4gICAgICAgIG1ldHJpY3Mub3V0Ym91bmRCeXRlcyArPSByZWNlaXZlZEJ5dGVzO1xuICAgICAgICBjb25zdCBpbmZlcnJlZFNxc1JlcXVlc3RzUmVjZWl2ZWQgPSBjb3VudFJlcXVlc3RzKHJlY2VpdmVkQnl0ZXMpO1xuICAgICAgICBjb25zdCBpbmZlcnJlZFNxc1JlcXVlc3RzU2VudCA9IHN1bShcbiAgICAgICAgICAgIE1lc3NhZ2VzLm1hcChtID0+IGNvdW50UmVxdWVzdHMobS5Cb2R5Py5sZW5ndGggPz8gMSkpXG4gICAgICAgICk7XG4gICAgICAgIG1ldHJpY3Muc3FzNjRrUmVxdWVzdHMgKz0gaW5mZXJyZWRTcXNSZXF1ZXN0c1NlbnQgKyBpbmZlcnJlZFNxc1JlcXVlc3RzUmVjZWl2ZWQ7XG4gICAgICAgIGlmIChNZXNzYWdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzcXMuZGVsZXRlTWVzc2FnZUJhdGNoKHtcbiAgICAgICAgICAgICAgICBRdWV1ZVVybDogUmVzcG9uc2VRdWV1ZVVybCEsXG4gICAgICAgICAgICAgICAgRW50cmllczogTWVzc2FnZXMubWFwKG0gPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgSWQ6IG0uTWVzc2FnZUlkISxcbiAgICAgICAgICAgICAgICAgICAgUmVjZWlwdEhhbmRsZTogbS5SZWNlaXB0SGFuZGxlIVxuICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAucHJvbWlzZSgpXG4gICAgICAgICAgICAgICAgLmNhdGNoKF8gPT4ge30pO1xuICAgICAgICAgICAgbWV0cmljcy5zcXM2NGtSZXF1ZXN0cysrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBNZXNzYWdlczogTWVzc2FnZXMubWFwKHByb2Nlc3NJbmNvbWluZ1F1ZXVlTWVzc2FnZSkuZmlsdGVyKGRlZmluZWQpLFxuICAgICAgICAgICAgaXNGdWxsTWVzc2FnZUJhdGNoOiBNZXNzYWdlcy5sZW5ndGggPT09IE1heE51bWJlck9mTWVzc2FnZXNcbiAgICAgICAgfTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihlcnIsIFwicmVjZWl2ZU1lc3NhZ2VzXCIpO1xuICAgIH1cbn1cblxuaW50ZXJmYWNlIExhbWJkYURlc3RpbmF0aW9uRXJyb3Ige1xuICAgIGVycm9yTWVzc2FnZTogc3RyaW5nO1xuICAgIGVycm9yVHlwZT86IHN0cmluZztcbiAgICBzdGFja1RyYWNlPzogc3RyaW5nW107XG59XG5cbmludGVyZmFjZSBMYW1iZGFEZXN0aW5hdGlvbk1lc3NhZ2Uge1xuICAgIHZlcnNpb246IHN0cmluZztcbiAgICB0aW1lc3RhbXA6IHN0cmluZztcbiAgICByZXF1ZXN0Q29udGV4dDoge1xuICAgICAgICByZXF1ZXN0SWQ6IHN0cmluZztcbiAgICAgICAgZnVuY3Rpb25Bcm46IHN0cmluZztcbiAgICAgICAgY29uZGl0aW9uOiBcIlJldHJpZXNFeGhhdXN0ZWRcIiB8IFwiU3VjY2Vzc1wiO1xuICAgICAgICBhcHByb3hpbWF0ZUludm9rZUNvdW50OiBudW1iZXI7XG4gICAgfTtcbiAgICByZXF1ZXN0UGF5bG9hZDogb2JqZWN0O1xuICAgIHJlc3BvbnNlQ29udGV4dDoge1xuICAgICAgICBzdGF0dXNDb2RlOiBudW1iZXI7XG4gICAgICAgIGV4ZWN1dGVkVmVyc2lvbjogc3RyaW5nO1xuICAgICAgICBmdW5jdGlvbkVycm9yPzogc3RyaW5nO1xuICAgIH07XG4gICAgcmVzcG9uc2VQYXlsb2FkOiBMYW1iZGFEZXN0aW5hdGlvbkVycm9yIHwgb2JqZWN0O1xufVxuXG5mdW5jdGlvbiBwcm9jZXNzSW5jb21pbmdRdWV1ZU1lc3NhZ2UobTogU1FTLk1lc3NhZ2UpOiBNZXNzYWdlIHwgdm9pZCB7XG4gICAgLy8gQVdTIExhbWJkYSBEZXN0aW5hdGlvbnNcbiAgICAvLyAoaHR0cHM6Ly9hd3MuYW1hem9uLmNvbS9ibG9ncy9jb21wdXRlL2ludHJvZHVjaW5nLWF3cy1sYW1iZGEtZGVzdGluYXRpb25zLylcbiAgICAvLyBhcmUgdXNlZCB0byByb3V0ZSBmYWlsdXJlcyB0byB0aGUgcmVzcG9uc2UgcXVldWUuIFRoZXNlXG4gICAgLy8gbWVzc2FnZXMgYXJlIGdlbmVyYXRlZCBieSBBV1MgTGFtYmRhIGFuZCBhcmUgY29uc3RyYWluZWQgdG8gdGhlIGZvcm1hdCBpdFxuICAgIC8vIHByb3ZpZGVzLlxuICAgIGNvbnN0IHJhdyA9IGRlc2VyaWFsaXplKG0uQm9keSEpO1xuICAgIGlmIChyYXcucmVzcG9uc2VDb250ZXh0KSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSByYXcgYXMgTGFtYmRhRGVzdGluYXRpb25NZXNzYWdlO1xuICAgICAgICBjb25zdCBzbnNNZXNzYWdlID0gbWVzc2FnZS5yZXF1ZXN0UGF5bG9hZCBhcyBTTlNFdmVudDtcbiAgICAgICAgY29uc3QgcmVjb3JkID0gc25zTWVzc2FnZS5SZWNvcmRzWzBdO1xuICAgICAgICBjb25zdCBzQ2FsbDogRnVuY3Rpb25DYWxsID0gZGVzZXJpYWxpemUocmVjb3JkLlNucy5NZXNzYWdlKTtcbiAgICAgICAgbGV0IGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgZGVzdGluYXRpb25FcnJvciA9IG1lc3NhZ2UucmVzcG9uc2VQYXlsb2FkIGFzIExhbWJkYURlc3RpbmF0aW9uRXJyb3I7XG4gICAgICAgIGlmIChkZXN0aW5hdGlvbkVycm9yKSB7XG4gICAgICAgICAgICBlcnJvciA9IHByb2Nlc3NBd3NFcnJvck1lc3NhZ2UoZGVzdGluYXRpb25FcnJvci5lcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgZXJyb3Iuc3RhY2sgPSBkZXN0aW5hdGlvbkVycm9yLnN0YWNrVHJhY2U/LmpvaW4oXCJcXG5cIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlcnJvciA9IHByb2Nlc3NBd3NFcnJvck1lc3NhZ2UobWVzc2FnZS5yZXF1ZXN0Q29udGV4dC5jb25kaXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGV4ZWN1dGlvbklkID0gbWVzc2FnZS5yZXF1ZXN0Q29udGV4dC5yZXF1ZXN0SWQ7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5jcmVhdGVFcnJvclJlc3BvbnNlKGVycm9yLCB7XG4gICAgICAgICAgICAgICAgY2FsbDogc0NhbGwsXG4gICAgICAgICAgICAgICAgc3RhcnRUaW1lOiBuZXcgRGF0ZShyZWNvcmQuU25zLlRpbWVzdGFtcCkuZ2V0VGltZSgpLFxuICAgICAgICAgICAgICAgIGV4ZWN1dGlvbklkXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUobWVzc2FnZS50aW1lc3RhbXApLmdldFRpbWUoKVxuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSByYXcgYXMgTWVzc2FnZTtcbiAgICAgICAgc3dpdGNoIChtZXNzYWdlLmtpbmQpIHtcbiAgICAgICAgICAgIGNhc2UgXCJwcm9taXNlXCI6XG4gICAgICAgICAgICBjYXNlIFwiaXRlcmF0b3JcIjpcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnRpbWVzdGFtcCA9IE51bWJlcihtLkF0dHJpYnV0ZXMhLlNlbnRUaW1lc3RhbXApO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcImNwdW1ldHJpY3NcIjpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJmdW5jdGlvbnN0YXJ0ZWRcIjpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFVua25vd24gbWVzc2FnZSByZWNlaXZlZCBmcm9tIHJlc3BvbnNlIHF1ZXVlYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJhdztcbiAgICB9XG59XG4iXX0=
\No newline at end of file