UNPKG

@synerty/vortexjs

Version:

Custom observable data serialisation and routing based on Angular 2+

128 lines 19.8 kB
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