@synerty/vortexjs
Version:
Custom observable data serialisation and routing based on Angular 2+
209 lines • 26.9 kB
JavaScript
import { dateStr } from "./UtilMisc";
import { rapuiClientEcho } from "./PayloadFilterKeys";
import { payloadIO } from "./PayloadIO";
import { PayloadEnvelope } from "./PayloadEnvelope";
import { Network } from "@capacitor/network";
/**
* Server response timeout in milliseconds
* @type {number}
*/
export let SERVER_RESPONSE_TIMEOUT_SECONDS = 20.0;
export var VortexClientStateE;
(function (VortexClientStateE) {
VortexClientStateE[VortexClientStateE["Idle"] = 0] = "Idle";
VortexClientStateE[VortexClientStateE["Connecting"] = 1] = "Connecting";
VortexClientStateE[VortexClientStateE["Online"] = 2] = "Online";
VortexClientStateE[VortexClientStateE["Closing"] = 3] = "Closing";
VortexClientStateE[VortexClientStateE["Closed"] = 4] = "Closed";
VortexClientStateE[VortexClientStateE["Shutdown"] = 5] = "Shutdown";
})(VortexClientStateE || (VortexClientStateE = {}));
export class VortexClientABC {
vortexStatusService;
HEART_BEAT_PERIOD_SECONDS = 10.0;
HEART_BEAT_TIMEOUT_SECONDS = 180.0;
RECONNECT_BACKOFF_SECONDS = 10.0;
beatTimer = null;
_uuid;
_name;
_url;
_vortexState = VortexClientStateE.Idle;
serverVortexUuid = null;
serverVortexName = null;
processingNetworkStateChange = false;
/**
* RapUI VortexService, This class is responsible for sending and receiving payloads to/from
* the server.
*/
constructor(vortexStatusService, url, vortexClientName) {
this.vortexStatusService = vortexStatusService;
this._uuid = VortexClientABC.makeUuid();
this._name = vortexClientName;
this._url = url;
// If the user switches network types, then reset the abort timer
Network.addListener("networkStatusChange", (status) => {
// We only want to do something if we DISconnect
if (status.connected) {
return;
}
// If we're already doing something, then do nothing
if (this.processingNetworkStateChange) {
return;
}
this.processingNetworkStateChange = true;
this.shutdown()
.catch((e) => console.log(`ERROR: VortexClientABC - Network State Change failed - ${e}`))
.then(() => (this.processingNetworkStateChange = false));
});
}
static makeUuid() {
function func(c) {
let r = (Math.random() * 16) | 0, v = c === "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
}
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, func);
}
get url() {
return this._url;
}
get uuid() {
return this._uuid;
}
get name() {
return this._name;
}
get isClosed() {
return this._vortexState === VortexClientStateE.Closed;
}
get isClosing() {
return this._vortexState === VortexClientStateE.Closing;
}
get isOnline() {
return this._vortexState === VortexClientStateE.Online;
}
get isShutdown() {
return this._vortexState === VortexClientStateE.Shutdown;
}
async close() {
this._vortexState = VortexClientStateE.Closing;
this.vortexStatusService.logInfo(`VortexClientABC shutting down vortex`);
this.clearBeatTimer();
await this.shutdown();
this._vortexState = VortexClientStateE.Shutdown;
}
setOnline() {
this._vortexState = VortexClientStateE.Online;
this.vortexStatusService.setOnline(true);
this.restartTimer();
}
setClosing() {
this._vortexState = VortexClientStateE.Closing;
this.vortexStatusService.setOnline(false);
}
setClosed() {
this._vortexState = VortexClientStateE.Closed;
this.vortexStatusService.setOnline(false);
if (!this.isShutdown)
this.restartTimer();
}
reconnect() {
this._vortexState = VortexClientStateE.Idle;
this.send(new PayloadEnvelope());
this.restartTimer();
return Promise.resolve();
}
beat() {
// We may still get a beat before the connection closes
if (!this.isOnline)
return;
this.restartTimer();
}
restartTimer() {
this.clearBeatTimer();
// If we're online, then use the heartbeat timeout
// If we're not online, then use the reconnect backoff
const timerSeconds = this.isOnline
? this.HEART_BEAT_TIMEOUT_SECONDS
: this.RECONNECT_BACKOFF_SECONDS;
this.beatTimer = setTimeout(() => {
if (this.isShutdown)
return;
this.dead();
this.reconnect()
.then(() => {
this.restartTimer();
})
.catch((e) => {
this.vortexStatusService.logError(`restartTimer ${e}`);
});
}, timerSeconds * 1000);
}
clearBeatTimer() {
if (this.beatTimer != null) {
clearTimeout(this.beatTimer);
this.beatTimer = null;
}
}
dead() {
this.vortexStatusService.setOnline(false);
this.vortexStatusService.logInfo(`VortexService server heartbeats have timed out : ${this._url}`);
}
send(payloadEnvelope) {
if (this.isShutdown) {
let msg = dateStr() +
"VortexService is closed, Probably due to a login page reload";
console.log(msg);
throw new Error("An attempt was made to reconnect a closed vortex");
}
let payloadEnvelopes = [];
if (payloadEnvelope instanceof Array)
payloadEnvelopes = payloadEnvelope;
else
payloadEnvelopes = [payloadEnvelope];
for (let p of payloadEnvelopes) {
// Empty payloadEnvelopes are like heart beats, don't check them
if (!p.isEmpty() && p.filt["key"] == null) {
throw new Error("There is no 'key' in the payloadEnvelopes filt" +
", There must be one for routing");
}
}
let vortexMsgs = [];
let promises = [];
for (let payloadEnvelope of payloadEnvelopes) {
promises.push(payloadEnvelope
.toVortexMsg()
.then((vortexMsg) => vortexMsgs.push(vortexMsg)));
}
return Promise.all(promises)
.then(() => this.sendVortexMsg(vortexMsgs))
.catch((e) => {
let msg = `ERROR VortexClientABC: ${e.toString()}`;
console.log(msg);
throw new Error(msg);
});
}
/**
* Receive
* This should only be called only from VortexConnection
* @param payloadEnvelope {Payload}
*/
receive(payloadEnvelope) {
this.beat();
if (payloadEnvelope.filt.hasOwnProperty(rapuiClientEcho)) {
delete payloadEnvelope[rapuiClientEcho];
this.send(payloadEnvelope);
}
if (payloadEnvelope.isEmpty()) {
if (payloadEnvelope.filt[PayloadEnvelope.vortexUuidKey] != null)
this.serverVortexUuid =
payloadEnvelope.filt[PayloadEnvelope.vortexUuidKey];
if (payloadEnvelope.filt[PayloadEnvelope.vortexNameKey] != null)
this.serverVortexName =
payloadEnvelope.filt[PayloadEnvelope.vortexNameKey];
return;
}
// console.log(dateStr() + "Received payloadEnvelope with filt : " + JSON.stringify(payloadEnvelope.filt));
// TODO, Tell the payloadIO the vortexUuid
payloadIO.process(payloadEnvelope);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVm9ydGV4Q2xpZW50QUJDLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3ZvcnRleC9Wb3J0ZXhDbGllbnRBQkMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNyQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUV4QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRTdDOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxJQUFJLCtCQUErQixHQUFHLElBQUksQ0FBQztBQUVsRCxNQUFNLENBQU4sSUFBWSxrQkFPWDtBQVBELFdBQVksa0JBQWtCO0lBQzFCLDJEQUFJLENBQUE7SUFDSix1RUFBVSxDQUFBO0lBQ1YsK0RBQU0sQ0FBQTtJQUNOLGlFQUFPLENBQUE7SUFDUCwrREFBTSxDQUFBO0lBQ04sbUVBQVEsQ0FBQTtBQUNaLENBQUMsRUFQVyxrQkFBa0IsS0FBbEIsa0JBQWtCLFFBTzdCO0FBRUQsTUFBTSxPQUFnQixlQUFlO0lBcUJuQjtJQXBCTCx5QkFBeUIsR0FBRyxJQUFJLENBQUM7SUFDakMsMEJBQTBCLEdBQUcsS0FBSyxDQUFDO0lBQ25DLHlCQUF5QixHQUFHLElBQUksQ0FBQztJQUVsQyxTQUFTLEdBQWUsSUFBSSxDQUFDO0lBQ3BCLEtBQUssQ0FBUztJQUNkLEtBQUssQ0FBUztJQUNaLElBQUksQ0FBUztJQUN0QixZQUFZLEdBQXVCLGtCQUFrQixDQUFDLElBQUksQ0FBQztJQUU3RCxnQkFBZ0IsR0FBa0IsSUFBSSxDQUFDO0lBQ3ZDLGdCQUFnQixHQUFrQixJQUFJLENBQUM7SUFFdkMsNEJBQTRCLEdBQUcsS0FBSyxDQUFDO0lBRTdDOzs7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QWMsQ0FBQyxlQUFlLENBQUMsRUFBRTtZQUN0RCxPQUFPLGVBQWUsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUN4QyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1NBQzlCO1FBRUQsSUFBSSxlQUFlLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDM0IsSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsSUFBSSxJQUFJO2dCQUMzRCxJQUFJLENBQUMsZ0JBQWdCO29CQUNqQixlQUFlLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUU1RCxJQUFJLGVBQWUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxJQUFJLElBQUk7Z0JBQzNELElBQUksQ0FBQyxnQkFBZ0I7b0JBQ2pCLGVBQWUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBRTVELE9BQU87U0FDVjtRQUVELDJHQUEyRztRQUUzRywwQ0FBMEM7UUFDMUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUN2QyxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBQYXlsb2FkIH0gZnJvbSBcIi4vUGF5bG9hZFwiO1xuaW1wb3J0IHsgZGF0ZVN0ciB9IGZyb20gXCIuL1V0aWxNaXNjXCI7XG5pbXBvcnQgeyByYXB1aUNsaWVudEVjaG8gfSBmcm9tIFwiLi9QYXlsb2FkRmlsdGVyS2V5c1wiO1xuaW1wb3J0IHsgcGF5bG9hZElPIH0gZnJvbSBcIi4vUGF5bG9hZElPXCI7XG5pbXBvcnQgeyBWb3J0ZXhTdGF0dXNTZXJ2aWNlIH0gZnJvbSBcIi4vVm9ydGV4U3RhdHVzU2VydmljZVwiO1xuaW1wb3J0IHsgUGF5bG9hZEVudmVsb3BlIH0gZnJvbSBcIi4vUGF5bG9hZEVudmVsb3BlXCI7XG5pbXBvcnQgeyBOZXR3b3JrIH0gZnJvbSBcIkBjYXBhY2l0b3IvbmV0d29ya1wiO1xuXG4vKipcbiAqIFNlcnZlciByZXNwb25zZSB0aW1lb3V0IGluIG1pbGxpc2Vjb25kc1xuICogQHR5cGUge251bWJlcn1cbiAqL1xuZXhwb3J0IGxldCBTRVJWRVJfUkVTUE9OU0VfVElNRU9VVF9TRUNPTkRTID0gMjAuMDtcblxuZXhwb3J0IGVudW0gVm9ydGV4Q2xpZW50U3RhdGVFIHtcbiAgICBJZGxlLFxuICAgIENvbm5lY3RpbmcsXG4gICAgT25saW5lLFxuICAgIENsb3NpbmcsXG4gICAgQ2xvc2VkLFxuICAgIFNodXRkb3duLFxufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVm9ydGV4Q2xpZW50QUJDIHtcbiAgICByZWFkb25seSBIRUFSVF9CRUFUX1BFUklPRF9TRUNPTkRTID0gMTAuMDtcbiAgICByZWFkb25seSBIRUFSVF9CRUFUX1RJTUVPVVRfU0VDT05EUyA9IDE4MC4wO1xuICAgIHJlYWRvbmx5IFJFQ09OTkVDVF9CQUNLT0ZGX1NFQ09ORFMgPSAxMC4wO1xuXG4gICAgcHJpdmF0ZSBiZWF0VGltZXI6IGFueSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX3V1aWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9uYW1lOiBzdHJpbmc7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IF91cmw6IHN0cmluZztcbiAgICBwcm90ZWN0ZWQgX3ZvcnRleFN0YXRlOiBWb3J0ZXhDbGllbnRTdGF0ZUUgPSBWb3J0ZXhDbGllbnRTdGF0ZUUuSWRsZTtcblxuICAgIHByaXZhdGUgc2VydmVyVm9ydGV4VXVpZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBzZXJ2ZXJWb3J0ZXhOYW1lOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAgIHByaXZhdGUgcHJvY2Vzc2luZ05ldHdvcmtTdGF0ZUNoYW5nZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogUmFwVUkgVm9ydGV4U2VydmljZSwgVGhpcyBjbGFzcyBpcyByZXNwb25zaWJsZSBmb3Igc2VuZGluZyBhbmQgcmVjZWl2aW5nIHBheWxvYWRzIHRvL2Zyb21cbiAgICAgKiB0aGUgc2VydmVyLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJvdGVjdGVkIHZvcnRleFN0YXR1c1NlcnZpY2U6IFZvcnRleFN0YXR1c1NlcnZpY2UsXG4gICAgICAgIHVybDogc3RyaW5nLFxuICAgICAgICB2b3J0ZXhDbGllbnROYW1lOiBzdHJpbmdcbiAgICApIHtcbiAgICAgICAgdGhpcy5fdXVpZCA9IFZvcnRleENsaWVudEFCQy5tYWtlVXVpZCgpO1xuICAgICAgICB0aGlzLl9uYW1lID0gdm9ydGV4Q2xpZW50TmFtZTtcbiAgICAgICAgdGhpcy5fdXJsID0gdXJsO1xuXG4gICAgICAgIC8vIElmIHRoZSB1c2VyIHN3aXRjaGVzIG5ldHdvcmsgdHlwZXMsIHRoZW4gcmVzZXQgdGhlIGFib3J0IHRpbWVyXG4gICAgICAgIE5ldHdvcmsuYWRkTGlzdGVuZXIoXCJuZXR3b3JrU3RhdHVzQ2hhbmdlXCIsIChzdGF0dXMpID0+IHtcbiAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBkbyBzb21ldGhpbmcgaWYgd2UgRElTY29ubmVjdFxuICAgICAgICAgICAgaWYgKHN0YXR1cy5jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIHdlJ3JlIGFscmVhZHkgZG9pbmcgc29tZXRoaW5nLCB0aGVuIGRvIG5vdGhpbmdcbiAgICAgICAgICAgIGlmICh0aGlzLnByb2Nlc3NpbmdOZXR3b3JrU3RhdGVDaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc2luZ05ldHdvcmtTdGF0ZUNoYW5nZSA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnNodXRkb3duKClcbiAgICAgICAgICAgICAgICAuY2F0Y2goKGUpID0+XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgICAgICAgICAgYEVSUk9SOiBWb3J0ZXhDbGllbnRBQkMgLSBOZXR3b3JrIFN0YXRlIENoYW5nZSBmYWlsZWQgLSAke2V9YFxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+ICh0aGlzLnByb2Nlc3NpbmdOZXR3b3JrU3RhdGVDaGFuZ2UgPSBmYWxzZSkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgbWFrZVV1aWQoKSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bmMoYykge1xuICAgICAgICAgICAgbGV0IHIgPSAoTWF0aC5yYW5kb20oKSAqIDE2KSB8IDAsXG4gICAgICAgICAgICAgICAgdiA9IGMgPT09IFwieFwiID8gciA6IChyICYgMHgzKSB8IDB4ODtcbiAgICAgICAgICAgIHJldHVybiB2LnRvU3RyaW5nKDE2KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBcInh4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eFwiLnJlcGxhY2UoL1t4eV0vZywgZnVuYyk7XG4gICAgfVxuXG4gICAgZ2V0IHVybCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5fdXJsO1xuICAgIH1cblxuICAgIGdldCB1dWlkKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl91dWlkO1xuICAgIH1cblxuICAgIGdldCBuYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9uYW1lO1xuICAgIH1cblxuICAgIGdldCBpc0Nsb3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZvcnRleFN0YXRlID09PSBWb3J0ZXhDbGllbnRTdGF0ZUUuQ2xvc2VkO1xuICAgIH1cblxuICAgIGdldCBpc0Nsb3NpbmcoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl92b3J0ZXhTdGF0ZSA9PT0gVm9ydGV4Q2xpZW50U3RhdGVFLkNsb3Npbmc7XG4gICAgfVxuXG4gICAgZ2V0IGlzT25saW5lKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fdm9ydGV4U3RhdGUgPT09IFZvcnRleENsaWVudFN0YXRlRS5PbmxpbmU7XG4gICAgfVxuXG4gICAgZ2V0IGlzU2h1dGRvd24oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl92b3J0ZXhTdGF0ZSA9PT0gVm9ydGV4Q2xpZW50U3RhdGVFLlNodXRkb3duO1xuICAgIH1cblxuICAgIGFzeW5jIGNsb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLl92b3J0ZXhTdGF0ZSA9IFZvcnRleENsaWVudFN0YXRlRS5DbG9zaW5nO1xuXG4gICAgICAgIHRoaXMudm9ydGV4U3RhdHVzU2VydmljZS5sb2dJbmZvKFxuICAgICAgICAgICAgYFZvcnRleENsaWVudEFCQyBzaHV0dGluZyBkb3duIHZvcnRleGBcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5jbGVhckJlYXRUaW1lcigpO1xuICAgICAgICBhd2FpdCB0aGlzLnNodXRkb3duKCk7XG4gICAgICAgIHRoaXMuX3ZvcnRleFN0YXRlID0gVm9ydGV4Q2xpZW50U3RhdGVFLlNodXRkb3duO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzZXRPbmxpbmUoKSB7XG4gICAgICAgIHRoaXMuX3ZvcnRleFN0YXRlID0gVm9ydGV4Q2xpZW50U3RhdGVFLk9ubGluZTtcbiAgICAgICAgdGhpcy52b3J0ZXhTdGF0dXNTZXJ2aWNlLnNldE9ubGluZSh0cnVlKTtcbiAgICAgICAgdGhpcy5yZXN0YXJ0VGltZXIoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc2V0Q2xvc2luZygpIHtcbiAgICAgICAgdGhpcy5fdm9ydGV4U3RhdGUgPSBWb3J0ZXhDbGllbnRTdGF0ZUUuQ2xvc2luZztcbiAgICAgICAgdGhpcy52b3J0ZXhTdGF0dXNTZXJ2aWNlLnNldE9ubGluZShmYWxzZSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHNldENsb3NlZCgpIHtcbiAgICAgICAgdGhpcy5fdm9ydGV4U3RhdGUgPSBWb3J0ZXhDbGllbnRTdGF0ZUUuQ2xvc2VkO1xuICAgICAgICB0aGlzLnZvcnRleFN0YXR1c1NlcnZpY2Uuc2V0T25saW5lKGZhbHNlKTtcblxuICAgICAgICBpZiAoIXRoaXMuaXNTaHV0ZG93bikgdGhpcy5yZXN0YXJ0VGltZXIoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3Qgc2h1dGRvd24oKTogUHJvbWlzZTx2b2lkPjtcblxuICAgIHJlY29ubmVjdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5fdm9ydGV4U3RhdGUgPSBWb3J0ZXhDbGllbnRTdGF0ZUUuSWRsZTtcbiAgICAgICAgdGhpcy5zZW5kKG5ldyBQYXlsb2FkRW52ZWxvcGUoKSk7XG4gICAgICAgIHRoaXMucmVzdGFydFRpbWVyKCk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYmVhdCgpOiB2b2lkIHtcbiAgICAgICAgLy8gV2UgbWF5IHN0aWxsIGdldCBhIGJlYXQgYmVmb3JlIHRoZSBjb25uZWN0aW9uIGNsb3Nlc1xuICAgICAgICBpZiAoIXRoaXMuaXNPbmxpbmUpIHJldHVybjtcblxuICAgICAgICB0aGlzLnJlc3RhcnRUaW1lcigpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCByZXN0YXJ0VGltZXIoKSB7XG4gICAgICAgIHRoaXMuY2xlYXJCZWF0VGltZXIoKTtcblxuICAgICAgICAvLyBJZiB3ZSdyZSBvbmxpbmUsIHRoZW4gdXNlIHRoZSBoZWFydGJlYXQgdGltZW91dFxuICAgICAgICAvLyBJZiB3ZSdyZSBub3Qgb25saW5lLCB0aGVuIHVzZSB0aGUgcmVjb25uZWN0IGJhY2tvZmZcbiAgICAgICAgY29uc3QgdGltZXJTZWNvbmRzID0gdGhpcy5pc09ubGluZVxuICAgICAgICAgICAgPyB0aGlzLkhFQVJUX0JFQVRfVElNRU9VVF9TRUNPTkRTXG4gICAgICAgICAgICA6IHRoaXMuUkVDT05ORUNUX0JBQ0tPRkZfU0VDT05EUztcblxuICAgICAgICB0aGlzLmJlYXRUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNTaHV0ZG93bikgcmV0dXJuO1xuXG4gICAgICAgICAgICB0aGlzLmRlYWQoKTtcbiAgICAgICAgICAgIHRoaXMucmVjb25uZWN0KClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdGFydFRpbWVyKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52b3J0ZXhTdGF0dXNTZXJ2aWNlLmxvZ0Vycm9yKGByZXN0YXJ0VGltZXIgJHtlfWApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCB0aW1lclNlY29uZHMgKiAxMDAwKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgY2xlYXJCZWF0VGltZXIoKSB7XG4gICAgICAgIGlmICh0aGlzLmJlYXRUaW1lciAhPSBudWxsKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5iZWF0VGltZXIpO1xuICAgICAgICAgICAgdGhpcy5iZWF0VGltZXIgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBkZWFkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnZvcnRleFN0YXR1c1NlcnZpY2Uuc2V0T25saW5lKGZhbHNlKTtcbiAgICAgICAgdGhpcy52b3J0ZXhTdGF0dXNTZXJ2aWNlLmxvZ0luZm8oXG4gICAgICAgICAgICBgVm9ydGV4U2VydmljZSBzZXJ2ZXIgaGVhcnRiZWF0cyBoYXZlIHRpbWVkIG91dCA6ICR7dGhpcy5fdXJsfWBcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3Qgc2VuZFZvcnRleE1zZyh2b3J0ZXhNc2dzOiBzdHJpbmdbXSk6IHZvaWQ7XG5cbiAgICBzZW5kKHBheWxvYWRFbnZlbG9wZTogUGF5bG9hZEVudmVsb3BlIHwgUGF5bG9hZEVudmVsb3BlW10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHRoaXMuaXNTaHV0ZG93bikge1xuICAgICAgICAgICAgbGV0IG1zZyA9XG4gICAgICAgICAgICAgICAgZGF0ZVN0cigpICtcbiAgICAgICAgICAgICAgICBcIlZvcnRleFNlcnZpY2UgaXMgY2xvc2VkLCBQcm9iYWJseSBkdWUgdG8gYSBsb2dpbiBwYWdlIHJlbG9hZFwiO1xuICAgICAgICAgICAgY29uc29sZS5sb2cobXNnKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkFuIGF0dGVtcHQgd2FzIG1hZGUgdG8gcmVjb25uZWN0IGEgY2xvc2VkIHZvcnRleFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBwYXlsb2FkRW52ZWxvcGVzOiBQYXlsb2FkRW52ZWxvcGVbXSA9IFtdO1xuICAgICAgICBpZiAocGF5bG9hZEVudmVsb3BlIGluc3RhbmNlb2YgQXJyYXkpXG4gICAgICAgICAgICBwYXlsb2FkRW52ZWxvcGVzID0gcGF5bG9hZEVudmVsb3BlO1xuICAgICAgICBlbHNlIHBheWxvYWRFbnZlbG9wZXMgPSBbcGF5bG9hZEVudmVsb3BlXTtcblxuICAgICAgICBmb3IgKGxldCBwIG9mIHBheWxvYWRFbnZlbG9wZXMpIHtcbiAgICAgICAgICAgIC8vIEVtcHR5IHBheWxvYWRFbnZlbG9wZXMgYXJlIGxpa2UgaGVhcnQgYmVhdHMsIGRvbid0IGNoZWNrIHRoZW1cbiAgICAgICAgICAgIGlmICghcC5pc0VtcHR5KCkgJiYgcC5maWx0W1wia2V5XCJdID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIFwiVGhlcmUgaXMgbm8gJ2tleScgaW4gdGhlIHBheWxvYWRFbnZlbG9wZXMgZmlsdFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiLCBUaGVyZSBtdXN0IGJlIG9uZSBmb3Igcm91dGluZ1wiXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB2b3J0ZXhNc2dzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICBsZXQgcHJvbWlzZXMgPSBbXTtcblxuICAgICAgICBmb3IgKGxldCBwYXlsb2FkRW52ZWxvcGUgb2YgcGF5bG9hZEVudmVsb3Blcykge1xuICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcbiAgICAgICAgICAgICAgICBwYXlsb2FkRW52ZWxvcGVcbiAgICAgICAgICAgICAgICAgICAgLnRvVm9ydGV4TXNnKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKHZvcnRleE1zZykgPT4gdm9ydGV4TXNncy5wdXNoKHZvcnRleE1zZykpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5zZW5kVm9ydGV4TXNnKHZvcnRleE1zZ3MpKVxuICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IG1zZyA9IGBFUlJPUiBWb3J0ZXhDbGllbnRBQkM6ICR7ZS50b1N0cmluZygpfWA7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cobXNnKTtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY2VpdmVcbiAgICAgKiBUaGlzIHNob3VsZCBvbmx5IGJlIGNhbGxlZCBvbmx5IGZyb20gVm9ydGV4Q29ubmVjdGlvblxuICAgICAqIEBwYXJhbSBwYXlsb2FkRW52ZWxvcGUge1BheWxvYWR9XG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlY2VpdmUocGF5bG9hZEVudmVsb3BlOiBQYXlsb2FkRW52ZWxvcGUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5iZWF0KCk7XG4gICAgICAgIGlmIChwYXlsb2FkRW52ZWxvcGUuZmlsdC5oYXNPd25Qcm9wZXJ0eShyYXB1aUNsaWVudEVjaG8pKSB7XG4gICAgICAgICAgICBkZWxldGUgcGF5bG9hZEVudmVsb3BlW3JhcHVpQ2xpZW50RWNob107XG4gICAgICAgICAgICB0aGlzLnNlbmQocGF5bG9hZEVudmVsb3BlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXlsb2FkRW52ZWxvcGUuaXNFbXB0eSgpKSB7XG4gICAgICAgICAgICBpZiAocGF5bG9hZEVudmVsb3BlLmZpbHRbUGF5bG9hZEVudmVsb3BlLnZvcnRleFV1aWRLZXldICE9IG51bGwpXG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXJWb3J0ZXhVdWlkID1cbiAgICAgICAgICAgICAgICAgICAgcGF5bG9hZEVudmVsb3BlLmZpbHRbUGF5bG9hZEVudmVsb3BlLnZvcnRleFV1aWRLZXldO1xuXG4gICAgICAgICAgICBpZiAocGF5bG9hZEVudmVsb3BlLmZpbHRbUGF5bG9hZEVudmVsb3BlLnZvcnRleE5hbWVLZXldICE9IG51bGwpXG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXJWb3J0ZXhOYW1lID1cbiAgICAgICAgICAgICAgICAgICAgcGF5bG9hZEVudmVsb3BlLmZpbHRbUGF5bG9hZEVudmVsb3BlLnZvcnRleE5hbWVLZXldO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjb25zb2xlLmxvZyhkYXRlU3RyKCkgKyBcIlJlY2VpdmVkIHBheWxvYWRFbnZlbG9wZSB3aXRoIGZpbHQgOiBcIiArIEpTT04uc3RyaW5naWZ5KHBheWxvYWRFbnZlbG9wZS5maWx0KSk7XG5cbiAgICAgICAgLy8gVE9ETywgVGVsbCB0aGUgcGF5bG9hZElPIHRoZSB2b3J0ZXhVdWlkXG4gICAgICAgIHBheWxvYWRJTy5wcm9jZXNzKHBheWxvYWRFbnZlbG9wZSk7XG4gICAgfVxufVxuIl19