@synerty/vortexjs
Version:
Custom observable data serialisation and routing based on Angular 2+
128 lines • 19.8 kB
JavaScript
import { Inject, Injectable } from "@angular/core";
import { VortexStatusService } from "../VortexStatusService";
import { VortexService } from "../VortexService";
import { errToStr } from "../UtilMisc";
import { PayloadResponse } from "../PayloadResponse";
import { TupleStorageFactoryService } from "../storage-factory/TupleStorageFactoryService";
import { filter } from "rxjs/operators";
import * as i0 from "@angular/core";
export class TupleActionPushOfflineSingletonService {
vortexService;
vortexStatus;
factoryService;
storage;
sendingTuple = false;
lastSendFailTime = null;
SEND_FAIL_RETRY_TIMEOUT = 5000; // milliseconds
SERVER_PROCESSING_TIMEOUT = 5000; // milliseconds
SEND_FAIL_RETRY_BACKOFF = 5000; // milliseconds
constructor(vortexService, vortexStatus, factoryService) {
this.vortexService = vortexService;
this.vortexStatus = vortexStatus;
this.factoryService = factoryService;
this.storage = factoryService.createActionStorage();
// This is a global service, there is no point unsubscribing it
this.vortexStatus.isOnline
.pipe(filter(online => online === true))
.subscribe(online => this.sendNextAction());
this.storage.countActions()
.then(count => {
this.vortexStatus.setQueuedActionCount(count);
})
.catch(err => {
let errStr = errToStr(err);
let msg = `Failed to count actions : ${errStr}`;
this.vortexStatus.logError(msg);
})
.then(() => this.sendNextAction());
}
queueAction(scope, tupleAction, payload) {
return this.storage
.storeAction(scope, tupleAction, payload)
.then(() => {
this.vortexStatus.incrementQueuedActionCount();
this.sendNextAction();
})
.catch((err) => {
let errStr = errToStr(err);
let msg = `Failed to store action : ${errStr}`;
console.log(msg);
throw new Error(msg);
});
}
sendNextAction() {
if (this.sendingTuple)
return;
if (!this.vortexStatus.snapshot.isOnline)
return;
// Don't continually retry, if we have a last send fail, ensure we wait
// {SEND_FAIL_RETRY_BACKOFF} before sending again.
if (this.lastSendFailTime != null) {
let reconnectDiffMs = Date.now() - this.lastSendFailTime;
if (reconnectDiffMs < this.SEND_FAIL_RETRY_BACKOFF) {
// +10ms to ensure we're just out of the backoff time.
setTimeout(() => this.sendNextAction(), this.SEND_FAIL_RETRY_BACKOFF - reconnectDiffMs + 10);
return;
}
else {
this.lastSendFailTime = null;
}
}
this.sendingTuple = true;
// Get the next tuple from the persistent queue
this.storage.loadNextAction()
// If this was successful?
.then((sendPayload) => {
// Is the end the end of the queue?
if (sendPayload == null) {
this.sendingTuple = false;
return;
}
return sendPayload.makePayloadEnvelope()
.then((sendPayloadEnvelope) => {
let uuid = sendPayload.tuples[0].uuid;
let scope = sendPayload.filt["name"];
return new PayloadResponse(this.vortexService, sendPayloadEnvelope, PayloadResponse.RESPONSE_TIMEOUT_SECONDS, // Timeout
false // don't check result, only reject if it times out
).then(responsePayload => {
// If we received a payload, but it has an error message
// Log an error, it's out of our hands, move on.
let r = responsePayload.result; // success is null or true
if (!(r == null || r === true)) {
this.vortexStatus.logError("Server failed to process Action: " + responsePayload.result.toString());
}
this.storage.deleteAction(scope, uuid)
.then(() => {
this.vortexStatus.decrementQueuedActionCount();
});
this.sendingTuple = false;
this.sendNextAction();
});
});
})
// Or catch and handle any of the errors from either loading or sending
.catch(err => {
this.lastSendFailTime = Date.now();
let errStr = errToStr(err);
console.error(`Failed to send TupleAction : ${errStr}\nRetrying in ${this.SEND_FAIL_RETRY_TIMEOUT / 1000} seconds`);
this.sendingTuple = false;
setTimeout(() => this.sendNextAction(), this.SEND_FAIL_RETRY_TIMEOUT);
return null; // Handle the error
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TupleActionPushOfflineSingletonService, deps: [{ token: VortexService }, { token: VortexStatusService }, { token: TupleStorageFactoryService }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TupleActionPushOfflineSingletonService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TupleActionPushOfflineSingletonService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [VortexService]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [VortexStatusService]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TupleStorageFactoryService]
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHVwbGVBY3Rpb25QdXNoT2ZmbGluZVNpbmdsZXRvblNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvdm9ydGV4L2FjdGlvbi1zZXJ2aWNlL1R1cGxlQWN0aW9uUHVzaE9mZmxpbmVTaW5nbGV0b25TZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQ2xELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHdCQUF3QixDQUFBO0FBRzVELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUNoRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ3RDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUNwRCxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQTtBQUcxRixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7O0FBR3ZDLE1BQU0sT0FBTyxzQ0FBc0M7SUFVWjtJQUNNO0lBQ087SUFYeEMsT0FBTyxDQUE4QjtJQUNyQyxZQUFZLEdBQUcsS0FBSyxDQUFBO0lBQ3BCLGdCQUFnQixHQUFrQixJQUFJLENBQUE7SUFFdEMsdUJBQXVCLEdBQUcsSUFBSSxDQUFBLENBQUEsZUFBZTtJQUM3Qyx5QkFBeUIsR0FBRyxJQUFJLENBQUEsQ0FBQSxlQUFlO0lBQy9DLHVCQUF1QixHQUFHLElBQUksQ0FBQSxDQUFDLGVBQWU7SUFFdEQsWUFDbUMsYUFBYSxFQUNQLFlBQVksRUFDTCxjQUFjO1FBRjNCLGtCQUFhLEdBQWIsYUFBYSxDQUFBO1FBQ1AsaUJBQVksR0FBWixZQUFZLENBQUE7UUFDTCxtQkFBYyxHQUFkLGNBQWMsQ0FBQTtRQUUxRCxJQUFJLENBQUMsT0FBTyxHQUFHLGNBQWMsQ0FBQyxtQkFBbUIsRUFBRSxD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RUFBRSxDQUFBO1lBRWxDLElBQUksTUFBTSxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUMxQixPQUFPLENBQUMsS0FBSyxDQUNULGdDQUFnQyxNQUFNLGlCQUFpQixJQUFJLENBQUMsdUJBQXVCLEdBQUMsSUFBSSxVQUFVLENBQ3JHLENBQUE7WUFDRCxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQTtZQUN6QixVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxFQUFFLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFBO1lBQ3JFLE9BQU8sSUFBSSxDQUFBLENBQUMsbUJBQW1CO1FBQ25DLENBQUMsQ0FBQyxDQUFBO0lBQ1YsQ0FBQzt3R0FuSVEsc0NBQXNDLGtCQVVuQyxhQUFhLGFBQ2IsbUJBQW1CLGFBQ25CLDBCQUEwQjs0R0FaN0Isc0NBQXNDOzs0RkFBdEMsc0NBQXNDO2tCQURsRCxVQUFVOzswQkFXRixNQUFNOzJCQUFDLGFBQWE7OzBCQUNwQixNQUFNOzJCQUFDLG1CQUFtQjs7MEJBQzFCLE1BQU07MkJBQUMsMEJBQTBCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIlxuaW1wb3J0IHsgVm9ydGV4U3RhdHVzU2VydmljZSB9IGZyb20gXCIuLi9Wb3J0ZXhTdGF0dXNTZXJ2aWNlXCJcbmltcG9ydCB7IFR1cGxlQWN0aW9uQUJDIH0gZnJvbSBcIi4uL1R1cGxlQWN0aW9uXCJcbmltcG9ydCB7IFBheWxvYWQgfSBmcm9tIFwiLi4vUGF5bG9hZFwiXG5pbXBvcnQgeyBWb3J0ZXhTZXJ2aWNlIH0gZnJvbSBcIi4uL1ZvcnRleFNlcnZpY2VcIlxuaW1wb3J0IHsgZXJyVG9TdHIgfSBmcm9tIFwiLi4vVXRpbE1pc2NcIlxuaW1wb3J0IHsgUGF5bG9hZFJlc3BvbnNlIH0gZnJvbSBcIi4uL1BheWxvYWRSZXNwb25zZVwiXG5pbXBvcnQgeyBUdXBsZVN0b3JhZ2VGYWN0b3J5U2VydmljZSB9IGZyb20gXCIuLi9zdG9yYWdlLWZhY3RvcnkvVHVwbGVTdG9yYWdlRmFjdG9yeVNlcnZpY2VcIlxuaW1wb3J0IHsgVHVwbGVBY3Rpb25TdG9yYWdlU2VydmljZUFCQyB9IGZyb20gXCIuLi9hY3Rpb24tc3RvcmFnZS9UdXBsZUFjdGlvblN0b3JhZ2VTZXJ2aWNlQUJDXCJcbmltcG9ydCB7IFBheWxvYWRFbnZlbG9wZSB9IGZyb20gXCIuLi9QYXlsb2FkRW52ZWxvcGVcIlxuaW1wb3J0IHsgZmlsdGVyIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCJcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFR1cGxlQWN0aW9uUHVzaE9mZmxpbmVTaW5nbGV0b25TZXJ2aWNlIHtcbiAgICBwcml2YXRlIHN0b3JhZ2U6IFR1cGxlQWN0aW9uU3RvcmFnZVNlcnZpY2VBQkNcbiAgICBwcml2YXRlIHNlbmRpbmdUdXBsZSA9IGZhbHNlXG4gICAgcHJpdmF0ZSBsYXN0U2VuZEZhaWxUaW1lOiBudWxsIHwgbnVtYmVyID0gbnVsbFxuICAgIFxuICAgIHByaXZhdGUgU0VORF9GQUlMX1JFVFJZX1RJTUVPVVQgPSA1MDAwLy8gbWlsbGlzZWNvbmRzXG4gICAgcHJpdmF0ZSBTRVJWRVJfUFJPQ0VTU0lOR19USU1FT1VUID0gNTAwMC8vIG1pbGxpc2Vjb25kc1xuICAgIHByaXZhdGUgU0VORF9GQUlMX1JFVFJZX0JBQ0tPRkYgPSA1MDAwIC8vIG1pbGxpc2Vjb25kc1xuICAgIFxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBASW5qZWN0KFZvcnRleFNlcnZpY2UpIHByaXZhdGUgdm9ydGV4U2VydmljZSxcbiAgICAgICAgQEluamVjdChWb3J0ZXhTdGF0dXNTZXJ2aWNlKSBwcml2YXRlIHZvcnRleFN0YXR1cyxcbiAgICAgICAgQEluamVjdChUdXBsZVN0b3JhZ2VGYWN0b3J5U2VydmljZSkgcHJpdmF0ZSBmYWN0b3J5U2VydmljZSxcbiAgICApIHtcbiAgICAgICAgdGhpcy5zdG9yYWdlID0gZmFjdG9yeVNlcnZpY2UuY3JlYXRlQWN0aW9uU3RvcmFnZSgpXG4gICAgICAgIFxuICAgICAgICAvLyBUaGlzIGlzIGEgZ2xvYmFsIHNlcnZpY2UsIHRoZXJlIGlzIG5vIHBvaW50IHVuc3Vic2NyaWJpbmcgaXRcbiAgICAgICAgdGhpcy52b3J0ZXhTdGF0dXMuaXNPbmxpbmVcbiAgICAgICAgICAgIC5waXBlKGZpbHRlcihvbmxpbmUgPT4gb25saW5lID09PSB0cnVlKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUob25saW5lID0+IHRoaXMuc2VuZE5leHRBY3Rpb24oKSlcbiAgICAgICAgXG4gICAgICAgIHRoaXMuc3RvcmFnZS5jb3VudEFjdGlvbnMoKVxuICAgICAgICAgICAgLnRoZW4oY291bnQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudm9ydGV4U3RhdHVzLnNldFF1ZXVlZEFjdGlvbkNvdW50KGNvdW50KVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBlcnJTdHIgPSBlcnJUb1N0cihlcnIpXG4gICAgICAgICAgICAgICAgbGV0IG1zZyA9IGBGYWlsZWQgdG8gY291bnQgYWN0aW9ucyA6ICR7ZXJyU3RyfWBcbiAgICAgICAgICAgICAgICB0aGlzLnZvcnRleFN0YXR1cy5sb2dFcnJvcihtc2cpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5zZW5kTmV4dEFjdGlvbigpKVxuICAgIH1cbiAgICBcbiAgICBxdWV1ZUFjdGlvbihcbiAgICAgICAgc2NvcGU6IHN0cmluZyxcbiAgICAgICAgdHVwbGVBY3Rpb246IFR1cGxlQWN0aW9uQUJDLFxuICAgICAgICBwYXlsb2FkOiBQYXlsb2FkXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2VcbiAgICAgICAgICAgIC5zdG9yZUFjdGlvbihzY29wZSwgdHVwbGVBY3Rpb24sIHBheWxvYWQpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy52b3J0ZXhTdGF0dXMuaW5jcmVtZW50UXVldWVkQWN0aW9uQ291bnQoKVxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE5leHRBY3Rpb24oKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IGVyclN0ciA9IGVyclRvU3RyKGVycilcbiAgICAgICAgICAgICAgICBsZXQgbXNnID0gYEZhaWxlZCB0byBzdG9yZSBhY3Rpb24gOiAke2VyclN0cn1gXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cobXNnKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpXG4gICAgICAgICAgICB9KVxuICAgIH1cbiAgICBcbiAgICBwcml2YXRlIHNlbmROZXh0QWN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5zZW5kaW5nVHVwbGUpXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgXG4gICAgICAgIGlmICghdGhpcy52b3J0ZXhTdGF0dXMuc25hcHNob3QuaXNPbmxpbmUpXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgXG4gICAgICAgIC8vIERvbid0IGNvbnRpbnVhbGx5IHJldHJ5LCBpZiB3ZSBoYXZlIGEgbGFzdCBzZW5kIGZhaWwsIGVuc3VyZSB3ZSB3YWl0XG4gICAgICAgIC8vIHtTRU5EX0ZBSUxfUkVUUllfQkFDS09GRn0gYmVmb3JlIHNlbmRpbmcgYWdhaW4uXG4gICAgICAgIGlmICh0aGlzLmxhc3RTZW5kRmFpbFRpbWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgbGV0IHJlY29ubmVjdERpZmZNcyA9IERhdGUubm93KCkgLSB0aGlzLmxhc3RTZW5kRmFpbFRpbWVcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKHJlY29ubmVjdERpZmZNcyA8IHRoaXMuU0VORF9GQUlMX1JFVFJZX0JBQ0tPRkYpIHtcbiAgICAgICAgICAgICAgICAvLyArMTBtcyB0byBlbnN1cmUgd2UncmUganVzdCBvdXQgb2YgdGhlIGJhY2tvZmYgdGltZS5cbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuc2VuZE5leHRBY3Rpb24oKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5TRU5EX0ZBSUxfUkVUUllfQkFDS09GRiAtIHJlY29ubmVjdERpZmZNcyArIDEwKVxuICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0U2VuZEZhaWxUaW1lID0gbnVsbFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICB0aGlzLnNlbmRpbmdUdXBsZSA9IHRydWVcbiAgICAgICAgXG4gICAgICAgIC8vIEdldCB0aGUgbmV4dCB0dXBsZSBmcm9tIHRoZSBwZXJzaXN0ZW50IHF1ZXVlXG4gICAgICAgIHRoaXMuc3RvcmFnZS5sb2FkTmV4dEFjdGlvbigpXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIElmIHRoaXMgd2FzIHN1Y2Nlc3NmdWw/XG4gICAgICAgICAgICAudGhlbigoc2VuZFBheWxvYWQ6IFBheWxvYWQpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBJcyB0aGUgZW5kIHRoZSBlbmQgb2YgdGhlIHF1ZXVlP1xuICAgICAgICAgICAgICAgIGlmIChzZW5kUGF5bG9hZCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZGluZ1R1cGxlID0gZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBzZW5kUGF5bG9hZC5tYWtlUGF5bG9hZEVudmVsb3BlKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKHNlbmRQYXlsb2FkRW52ZWxvcGU6IFBheWxvYWRFbnZlbG9wZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdXVpZCA9ICg8VHVwbGVBY3Rpb25BQkM+c2VuZFBheWxvYWQudHVwbGVzWzBdKS51dWlkXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2NvcGUgPSBzZW5kUGF5bG9hZC5maWx0W1wibmFtZVwiXVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFBheWxvYWRSZXNwb25zZSh0aGlzLnZvcnRleFNlcnZpY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBheWxvYWRFbnZlbG9wZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXlsb2FkUmVzcG9uc2UuUkVTUE9OU0VfVElNRU9VVF9TRUNPTkRTLCAvLyBUaW1lb3V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2UgLy8gZG9uJ3QgY2hlY2sgcmVzdWx0LCBvbmx5IHJlamVjdCBpZiBpdCB0aW1lcyBvdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICkudGhlbihyZXNwb25zZVBheWxvYWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIHJlY2VpdmVkIGEgcGF5bG9hZCwgYnV0IGl0IGhhcyBhbiBlcnJvciBtZXNzYWdlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTG9nIGFuIGVycm9yLCBpdCdzIG91dCBvZiBvdXIgaGFuZHMsIG1vdmUgb24uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHIgPSByZXNwb25zZVBheWxvYWQucmVzdWx0IC8vIHN1Y2Nlc3MgaXMgbnVsbCBvciB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEociA9PSBudWxsIHx8IHIgPT09IHRydWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudm9ydGV4U3RhdHVzLmxvZ0Vycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJTZXJ2ZXIgZmFpbGVkIHRvIHByb2Nlc3MgQWN0aW9uOiBcIiArIHJlc3BvbnNlUGF5bG9hZC5yZXN1bHQudG9TdHJpbmcoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLmRlbGV0ZUFjdGlvbihzY29wZSwgdXVpZClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52b3J0ZXhTdGF0dXMuZGVjcmVtZW50UXVldWVkQWN0aW9uQ291bnQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZGluZ1R1cGxlID0gZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbmROZXh0QWN0aW9uKClcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBPciBjYXRjaCBhbmQgaGFuZGxlIGFueSBvZiB0aGUgZXJyb3JzIGZyb20gZWl0aGVyIGxvYWRpbmcgb3Igc2VuZGluZ1xuICAgICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0U2VuZEZhaWxUaW1lID0gRGF0ZS5ub3coKVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGxldCBlcnJTdHIgPSBlcnJUb1N0cihlcnIpXG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgICAgICAgICAgICAgYEZhaWxlZCB0byBzZW5kIFR1cGxlQWN0aW9uIDogJHtlcnJTdHJ9XFxuUmV0cnlpbmcgaW4gJHt0aGlzLlNFTkRfRkFJTF9SRVRSWV9USU1FT1VULzEwMDB9IHNlY29uZHNgXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZGluZ1R1cGxlID0gZmFsc2VcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuc2VuZE5leHRBY3Rpb24oKSwgdGhpcy5TRU5EX0ZBSUxfUkVUUllfVElNRU9VVClcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbCAvLyBIYW5kbGUgdGhlIGVycm9yXG4gICAgICAgICAgICB9KVxuICAgIH1cbn1cblxuIl19