sliftutils 1.7.29 → 1.7.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builders/extensionBuild.ts +1 -1
- package/bundler/bundleEntry.ts +1 -3
- package/bundler/bundler.ts +2 -4
- package/bundler/sourceMaps.ts +1 -2
- package/examplestorage/browser.tsx +1 -2
- package/examplestorage/exampleserver.ts +1 -2
- package/index.d.ts +106 -99
- package/misc/dist/environment.ts.cache +2 -2
- package/misc/dist/getSecret.ts.cache +2 -2
- package/misc/dist/strings.ts.cache +2 -2
- package/misc/dist/zip.ts.cache +2 -2
- package/misc/https/dist/certs.ts.cache +2 -2
- package/misc/https/dist/dns.ts.cache +7 -16
- package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
- package/misc/https/dns.d.ts +1 -4
- package/misc/https/dns.ts +5 -14
- package/misc/https/hostServer.d.ts +2 -0
- package/misc/https/hostServer.ts +6 -7
- package/misc/https/httpsCerts.ts +4 -10
- package/misc/openrouter.ts +1 -2
- package/package.json +1 -1
- package/render-utils/FullscreenModal.tsx +1 -4
- package/render-utils/GenericFormat.tsx +2 -8
- package/render-utils/Input.tsx +5 -13
- package/render-utils/InputLabel.tsx +4 -6
- package/render-utils/InputPicker.tsx +1 -2
- package/render-utils/URLParam.ts +2 -3
- package/render-utils/dist/observer.tsx.cache +2 -2
- package/render-utils/mobxTyped.ts +2 -3
- package/render-utils/niceStringify.ts +2 -4
- package/storage/ArchivesDisk.ts +4 -14
- package/storage/BulkDatabase2/BulkDatabase2.d.ts +1 -2
- package/storage/BulkDatabase2/BulkDatabase2.ts +4 -11
- package/storage/BulkDatabase2/BulkDatabaseBase.ts +42 -114
- package/storage/BulkDatabase2/BulkDatabaseFormat.ts +31 -91
- package/storage/BulkDatabase2/BulkDatabaseMerge.ts +19 -57
- package/storage/BulkDatabase2/BulkDatabaseReader.ts +4 -12
- package/storage/BulkDatabase2/LoadedIndex.ts +6 -18
- package/storage/BulkDatabase2/WriteOverlay.ts +3 -8
- package/storage/BulkDatabase2/blockCache.ts +12 -28
- package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +40 -103
- package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +19 -50
- package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +18 -50
- package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +7 -15
- package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +9 -21
- package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +6 -11
- package/storage/BulkDatabase2/dist/blockCache.ts.cache +15 -31
- package/storage/BulkDatabase2/dist/mergeLock.ts.cache +10 -29
- package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +10 -18
- package/storage/BulkDatabase2/dist/streamLog.ts.cache +17 -43
- package/storage/BulkDatabase2/dist/syncClient.ts.cache +11 -27
- package/storage/BulkDatabase2/mergeLock.ts +7 -26
- package/storage/BulkDatabase2/mergeMarkers.ts +7 -15
- package/storage/BulkDatabase2/streamLog.ts +14 -40
- package/storage/BulkDatabase2/syncClient.ts +8 -24
- package/storage/FileFolderAPI.tsx +28 -75
- package/storage/IArchives.d.ts +3 -3
- package/storage/IArchives.ts +21 -50
- package/storage/IStorage.ts +2 -4
- package/storage/PendingManager.tsx +2 -3
- package/storage/TransactionStorage.ts +11 -24
- package/storage/backblaze.ts +12 -43
- package/storage/dist/ArchivesDisk.ts.cache +7 -17
- package/storage/dist/FileFolderAPI.tsx.cache +25 -63
- package/storage/dist/IArchives.ts.cache +10 -20
- package/storage/dist/IndexedDBFileFolderAPI.ts.cache +2 -2
- package/storage/dist/JSONStorage.ts.cache +2 -2
- package/storage/dist/PendingManager.tsx.cache +5 -6
- package/storage/dist/TransactionStorage.ts.cache +14 -27
- package/storage/dist/backblaze.ts.cache +15 -46
- package/storage/dist/embeddingFormats.ts.cache +11 -24
- package/storage/dist/fileSystemPointer.ts.cache +4 -7
- package/storage/dist/remoteFileStorage.ts.cache +17 -36
- package/storage/embeddingFormats.ts +11 -27
- package/storage/fileSystemPointer.ts +2 -7
- package/storage/proxydatabase/dist/ivfEmbeddingDatabase.ts.cache +8 -18
- package/storage/proxydatabase/dist/transactionSet.ts.cache +4 -7
- package/storage/proxydatabase/inMemoryDatabase.ts +1 -3
- package/storage/proxydatabase/ivfEmbeddingDatabase.ts +8 -23
- package/storage/proxydatabase/transactionSet.ts +2 -5
- package/storage/remoteFileServer.ts +20 -48
- package/storage/remoteFileStorage.ts +14 -33
- package/storage/remoteStorage/ArchivesRemote.d.ts +1 -4
- package/storage/remoteStorage/ArchivesRemote.ts +11 -26
- package/storage/remoteStorage/ArchivesUrl.ts +2 -4
- package/storage/remoteStorage/accessPage.tsx +1 -5
- package/storage/remoteStorage/blobStore.d.ts +5 -13
- package/storage/remoteStorage/blobStore.ts +52 -130
- package/storage/remoteStorage/createArchives.d.ts +9 -13
- package/storage/remoteStorage/createArchives.ts +43 -187
- package/storage/remoteStorage/deployTakeover.d.ts +18 -32
- package/storage/remoteStorage/deployTakeover.ts +70 -384
- package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +12 -24
- package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +5 -7
- package/storage/remoteStorage/dist/blobStore.ts.cache +47 -117
- package/storage/remoteStorage/dist/cliArgs.ts.cache +2 -2
- package/storage/remoteStorage/dist/createArchives.ts.cache +54 -186
- package/storage/remoteStorage/dist/deployTakeover.ts.cache +81 -387
- package/storage/remoteStorage/dist/intermediateSources.ts.cache +119 -0
- package/storage/remoteStorage/dist/remoteConfig.ts.cache +36 -24
- package/storage/remoteStorage/dist/sourceWrapper.ts.cache +20 -40
- package/storage/remoteStorage/dist/storageClientController.ts.cache +32 -0
- package/storage/remoteStorage/dist/storageController.ts.cache +30 -64
- package/storage/remoteStorage/dist/storageServerState.ts.cache +269 -186
- package/storage/remoteStorage/grantAccessCli.ts +1 -3
- package/storage/remoteStorage/intermediateSources.d.ts +21 -0
- package/storage/remoteStorage/intermediateSources.ts +117 -0
- package/storage/remoteStorage/remoteConfig.ts +33 -20
- package/storage/remoteStorage/sourceWrapper.d.ts +8 -19
- package/storage/remoteStorage/sourceWrapper.ts +19 -41
- package/storage/remoteStorage/storageClientController.ts +1 -3
- package/storage/remoteStorage/storageController.d.ts +5 -3
- package/storage/remoteStorage/storageController.ts +12 -83
- package/storage/remoteStorage/storageServer.ts +20 -34
- package/storage/remoteStorage/storageServerState.d.ts +28 -6
- package/storage/remoteStorage/storageServerState.ts +275 -221
|
@@ -1,433 +1,127 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
|
|
2
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
6
|
-
//exports.getMainPortAcquireDelay = exports.
|
|
6
|
+
//exports.getMainPortAcquireDelay = exports.getAltPortListenEnd = exports.getTakeoverIntermediate = exports.setAltPort = exports.detectDeployTakeover = void 0;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const
|
|
10
|
-
const remoteConfig_1 = require("./remoteConfig");
|
|
11
|
-
// Deploy takeover: the deploy manager (querysub's parametersTimeline) writes <n>-parameters.json
|
|
12
|
-
// files into our instance folder describing when each version runs and when it is shut down. Old
|
|
13
|
-
// and new version overlap for the overlap time (O = oldEnd - newStart). We turn that overlap into
|
|
14
|
-
// an atomic write handoff by REINTERPRETING every routing source that points at us: its valid
|
|
15
|
-
// window is split so that the middle of the overlap ([S + 0.5*O, S + 1.5*O]) points at the new
|
|
16
|
-
// process's temporary alternate port. The existing valid-window machinery then does everything -
|
|
17
|
-
// the old process starts rejecting fresh writes at the first boundary, clients re-resolve, and the
|
|
18
|
-
// new process (which recognizes the alternate port as itself) takes over. The remap is an
|
|
19
|
-
// INTERPRETATION OVERLAY, applied where routing configs are used (see applyDeployRemap callers) -
|
|
20
|
-
// it is never written to disk, never synchronized, and never part of any stored configuration.
|
|
21
|
-
//
|
|
22
|
-
// Everything here is recomputed idempotently from its inputs (timeline files, the port registry,
|
|
23
|
-
// our ancestor pids, the clock) - files can appear or change at any moment, and we can start at
|
|
24
|
-
// any point during a switchover.
|
|
9
|
+
const storageServerState_1 = require("./storageServerState");
|
|
25
10
|
const PARAMETERS_TIMELINE_FILE_REGEX = /^(\d+)-parameters\.json$/;
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const PORT_REGISTRY_FOLDER_NAME = "storagePortRegistry";
|
|
31
|
-
// Main-port acquisition attempts run this often, tightening near the predecessor's scheduled death
|
|
11
|
+
const DEPLOY_DETECT_RETRY_DELAY = 5 * 1000;
|
|
12
|
+
const DEPLOY_DETECT_ATTEMPTS = 6;
|
|
13
|
+
const DEPLOY_RELEASE_MATCH_WINDOW = 5 * 60 * 1000;
|
|
14
|
+
const ALT_PORT_LINGER = 30 * 60 * 1000;
|
|
32
15
|
const ACQUIRE_SLOW_DELAY = 30 * 1000;
|
|
33
|
-
const ACQUIRE_FAST_DELAY =
|
|
16
|
+
const ACQUIRE_FAST_DELAY = 1000;
|
|
34
17
|
const ACQUIRE_FAST_WINDOW = 60 * 1000;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
let initialized;
|
|
39
|
-
let ancestorPids = new Set();
|
|
40
|
-
let timelineFolder;
|
|
41
|
-
let ourAltPort;
|
|
42
|
-
let current = {};
|
|
43
|
-
let currentKey = JSON.stringify(current);
|
|
44
|
-
let eventListeners = [];
|
|
45
|
-
let eventTimers = [];
|
|
46
|
-
let loggedNoMatch = false;
|
|
47
|
-
let loggedIdentity = false;
|
|
48
|
-
function execText(command) {
|
|
49
|
-
return new Promise((resolve, reject) => {
|
|
50
|
-
(0, child_process_1.exec)(command, (error, stdout) => {
|
|
51
|
-
if (error) {
|
|
52
|
-
reject(error);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
resolve(stdout);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
18
|
+
let takeover;
|
|
19
|
+
function iso(time) {
|
|
20
|
+
return new Date(time).toISOString();
|
|
58
21
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
async function getAncestorPids() {
|
|
62
|
-
let pids = new Set([process.pid]);
|
|
63
|
-
let currentPid = process.pid;
|
|
64
|
-
while (true) {
|
|
65
|
-
let ppid;
|
|
66
|
-
if (currentPid === process.pid && process.ppid) {
|
|
67
|
-
ppid = process.ppid;
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
try {
|
|
71
|
-
ppid = parseInt((await execText(`ps -o ppid= -p ${currentPid}`)).trim());
|
|
72
|
-
}
|
|
73
|
-
catch (_a) {
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (!ppid || Number.isNaN(ppid) || ppid <= 1 || pids.has(ppid))
|
|
78
|
-
break;
|
|
79
|
-
pids.add(ppid);
|
|
80
|
-
currentPid = ppid;
|
|
81
|
-
}
|
|
82
|
-
return pids;
|
|
22
|
+
function logPrefix() {
|
|
23
|
+
return `[pid ${process.pid}]`;
|
|
83
24
|
}
|
|
84
|
-
// The instance folder is ALWAYS the parent of our cwd (services run in <instance>/git/) - never
|
|
85
|
-
// search for it, a walk could latch onto the wrong folder
|
|
86
25
|
function getTimelineFolder() {
|
|
87
26
|
return path_1.default.dirname(process.cwd()).replaceAll("\\", "/") + "/";
|
|
88
27
|
}
|
|
89
|
-
function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
catch (e) {
|
|
95
|
-
return e.code === "EPERM";
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function getRegistryFolder() {
|
|
99
|
-
if (!initialized) {
|
|
100
|
-
throw new Error(`Deploy takeover is not initialized`);
|
|
101
|
-
}
|
|
102
|
-
return path_1.default.join(path_1.default.dirname(path_1.default.resolve(initialized.storageFolder)), PORT_REGISTRY_FOLDER_NAME);
|
|
103
|
-
}
|
|
104
|
-
async function readPortRegistry() {
|
|
105
|
-
let folder = getRegistryFolder();
|
|
106
|
-
let files = [];
|
|
28
|
+
async function readTimelineEntries() {
|
|
29
|
+
var _a, _b;
|
|
30
|
+
let folder = getTimelineFolder();
|
|
31
|
+
let files;
|
|
107
32
|
try {
|
|
108
33
|
files = await fs_1.default.promises.readdir(folder);
|
|
109
34
|
}
|
|
110
|
-
catch (
|
|
35
|
+
catch (e) {
|
|
36
|
+
console.warn(`${logPrefix()} Could not read the deploy timeline folder ${folder}: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
|
|
111
37
|
return [];
|
|
112
38
|
}
|
|
113
39
|
let entries = [];
|
|
114
40
|
for (let file of files) {
|
|
115
|
-
let match = /^(\d+)\.json$/.exec(file);
|
|
116
|
-
if (!match)
|
|
117
|
-
continue;
|
|
118
|
-
let pid = parseInt(match[1]);
|
|
119
|
-
if (!pidAlive(pid)) {
|
|
120
|
-
try {
|
|
121
|
-
await fs_1.default.promises.unlink(path_1.default.join(folder, file));
|
|
122
|
-
}
|
|
123
|
-
catch (_b) { }
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
try {
|
|
127
|
-
let entry = JSON.parse(await fs_1.default.promises.readFile(path_1.default.join(folder, file), "utf8"));
|
|
128
|
-
entries.push({ ...entry, pid });
|
|
129
|
-
}
|
|
130
|
-
catch (_c) { }
|
|
131
|
-
}
|
|
132
|
-
return entries;
|
|
133
|
-
}
|
|
134
|
-
async function readTimelineEntries() {
|
|
135
|
-
var _a;
|
|
136
|
-
if (!timelineFolder)
|
|
137
|
-
return [];
|
|
138
|
-
let entries = [];
|
|
139
|
-
for (let file of await fs_1.default.promises.readdir(timelineFolder)) {
|
|
140
41
|
if (!PARAMETERS_TIMELINE_FILE_REGEX.test(file))
|
|
141
42
|
continue;
|
|
142
43
|
try {
|
|
143
|
-
entries.push(JSON.parse(await fs_1.default.promises.readFile(
|
|
44
|
+
entries.push(JSON.parse(await fs_1.default.promises.readFile(folder + file, "utf8")));
|
|
144
45
|
}
|
|
145
46
|
catch (e) {
|
|
146
|
-
console.warn(
|
|
47
|
+
console.warn(`${logPrefix()} Could not read deploy timeline file ${folder + file}: ${(_b = e.stack) !== null && _b !== void 0 ? _b : e}`);
|
|
147
48
|
}
|
|
148
49
|
}
|
|
149
50
|
return entries;
|
|
150
51
|
}
|
|
151
|
-
function
|
|
152
|
-
|
|
153
|
-
boundaryA: successorStart + overlap * BOUNDARY_A_FRACTION,
|
|
154
|
-
boundaryB: successorStart + overlap * BOUNDARY_B_FRACTION,
|
|
155
|
-
expire: successorStart + overlap * REMAP_EXPIRE_FRACTION,
|
|
156
|
-
altPort,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
function emit(event) {
|
|
160
|
-
var _a;
|
|
161
|
-
for (let listener of eventListeners) {
|
|
162
|
-
try {
|
|
163
|
-
listener(event);
|
|
164
|
-
}
|
|
165
|
-
catch (e) {
|
|
166
|
-
console.error(`Deploy takeover listener failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
function scheduleEvents() {
|
|
171
|
-
for (let timer of eventTimers) {
|
|
172
|
-
clearTimeout(timer);
|
|
173
|
-
}
|
|
174
|
-
eventTimers = [];
|
|
175
|
-
let now = Date.now();
|
|
176
|
-
let schedule = (time, fnc) => {
|
|
177
|
-
var _a, _b;
|
|
178
|
-
if (time <= now)
|
|
179
|
-
return;
|
|
180
|
-
let timer = setTimeout(fnc, time - now);
|
|
181
|
-
(_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
182
|
-
eventTimers.push(timer);
|
|
183
|
-
};
|
|
184
|
-
const remap = current.remap;
|
|
185
|
-
if (remap) {
|
|
186
|
-
let altPort = remap.altPort;
|
|
187
|
-
schedule(remap.boundaryA, () => console.log(`${logPrefix()} Deploy switchover write handoff boundary ${iso(remap.boundaryA)} passed: fresh writes now belong to the alternate-port side (port ${altPort})`));
|
|
188
|
-
schedule(remap.boundaryB, () => console.log(`${logPrefix()} Deploy switchover second boundary ${iso(remap.boundaryB)} passed: fresh writes return to the main port`));
|
|
189
|
-
schedule(remap.expire, () => void recompute().catch((e) => { var _a; return console.error(`Deploy takeover recompute failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); }));
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
// Multiple processes (predecessor + successor) often share one journal during a switchover, so
|
|
193
|
-
// every lifecycle line identifies its process
|
|
194
|
-
function logPrefix() {
|
|
195
|
-
return `[pid ${process.pid}]`;
|
|
196
|
-
}
|
|
197
|
-
// Recompute is invoked from init, registerAltPort, the poll, and the expiry timer - possibly
|
|
198
|
-
// concurrently. Runs are serialized, or two in-flight runs would both pass the changed-state check
|
|
199
|
-
// and double-fire every transition (logs, rebuild events, timers).
|
|
200
|
-
let recomputeChain = Promise.resolve();
|
|
201
|
-
function recompute() {
|
|
202
|
-
let next = recomputeChain.then(() => recomputeNow());
|
|
203
|
-
recomputeChain = next.then(() => { }, () => { });
|
|
204
|
-
return next;
|
|
205
|
-
}
|
|
206
|
-
async function recomputeNow() {
|
|
207
|
-
if (!initialized || !timelineFolder)
|
|
208
|
-
return;
|
|
209
|
-
let now = Date.now();
|
|
210
|
-
let entries = await readTimelineEntries();
|
|
211
|
-
let registry = await readPortRegistry();
|
|
212
|
-
let us;
|
|
52
|
+
function findOurRelease(entries, now) {
|
|
53
|
+
let best;
|
|
213
54
|
for (let entry of entries) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// Matching failures must be loud, or takeover detection fails silently forever
|
|
219
|
-
if (!us && entries.length && !loggedNoMatch) {
|
|
220
|
-
loggedNoMatch = true;
|
|
221
|
-
console.warn(`${logPrefix()} No deploy timeline entry matches our pid chain (${[...ancestorPids].join(", ")}) - takeover detection cannot work. Entries: ${entries.map(x => { var _a; return `pid=${(_a = x.pid) !== null && _a !== void 0 ? _a : "none"} releaseTime=${x.parameters.releaseTime}`; }).join(" | ")}`);
|
|
222
|
-
}
|
|
223
|
-
if (us && !loggedIdentity) {
|
|
224
|
-
loggedIdentity = true;
|
|
225
|
-
console.log(`${logPrefix()} Deploy timeline entry matched: we are pid=${us.pid}, releaseTime=${us.parameters.releaseTime !== undefined && iso(us.parameters.releaseTime) || "unknown"}, ${entries.length} entries total`);
|
|
226
|
-
}
|
|
227
|
-
let computed = {};
|
|
228
|
-
let usRelease = us === null || us === void 0 ? void 0 : us.parameters.releaseTime;
|
|
229
|
-
if (us && usRelease !== undefined) {
|
|
230
|
-
// The newer entry's releaseTime is when it starts; releaseTime + overlapTime is when the
|
|
231
|
-
// older one is killed. That's the whole timeline.
|
|
232
|
-
let next;
|
|
233
|
-
let prev;
|
|
234
|
-
for (let entry of entries) {
|
|
235
|
-
if (entry === us)
|
|
236
|
-
continue;
|
|
237
|
-
let release = entry.parameters.releaseTime;
|
|
238
|
-
if (release === undefined)
|
|
239
|
-
continue;
|
|
240
|
-
if (release > usRelease && (!next || release < next.release)) {
|
|
241
|
-
next = { entry, release };
|
|
242
|
-
}
|
|
243
|
-
if (release < usRelease && (!prev || release > prev.release)) {
|
|
244
|
-
prev = { entry, release };
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
if (next) {
|
|
248
|
-
let successorStart = next.release;
|
|
249
|
-
let overlap = next.entry.parameters.overlapTime || us.parameters.overlapTime || 0;
|
|
250
|
-
// Tracked even for a ZERO-overlap deploy (the scheduled-switchover log must still
|
|
251
|
-
// fire); only the remap (the alternate-port middle window) needs an actual overlap.
|
|
252
|
-
// Flushing before the handoff needs nothing special here: the remap ends our valid
|
|
253
|
-
// window, and fast writes always flush ahead of their window's end.
|
|
254
|
-
computed.dying = { successorStart, overlap };
|
|
255
|
-
if (overlap > 0 && now < successorStart + overlap * REMAP_EXPIRE_FRACTION) {
|
|
256
|
-
const successorPid = next.entry.pid;
|
|
257
|
-
if (successorPid) {
|
|
258
|
-
let successorEntry = registry.find(x => x.ancestorPids.includes(successorPid));
|
|
259
|
-
if (successorEntry) {
|
|
260
|
-
computed.remap = makeRemap(successorStart, overlap, successorEntry.port);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
if (prev) {
|
|
266
|
-
let overlap = us.parameters.overlapTime || prev.entry.parameters.overlapTime || 0;
|
|
267
|
-
// The predecessor holds the main port until OUR release + the overlap
|
|
268
|
-
computed.predecessorEnd = usRelease + overlap;
|
|
269
|
-
if (overlap > 0 && ourAltPort && now < usRelease + overlap * REMAP_EXPIRE_FRACTION && !computed.remap) {
|
|
270
|
-
computed.remap = makeRemap(usRelease, overlap, ourAltPort);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
let key = JSON.stringify(computed);
|
|
275
|
-
if (key === currentKey)
|
|
276
|
-
return;
|
|
277
|
-
logTransitions(current, computed);
|
|
278
|
-
current = computed;
|
|
279
|
-
currentKey = key;
|
|
280
|
-
scheduleEvents();
|
|
281
|
-
emit("remapChanged");
|
|
282
|
-
}
|
|
283
|
-
function iso(time) {
|
|
284
|
-
return new Date(time).toISOString();
|
|
285
|
-
}
|
|
286
|
-
// The switchover lifecycle is rare and important, so every stage gets a clear line
|
|
287
|
-
function logTransitions(prev, next) {
|
|
288
|
-
if (!prev.dying && next.dying) {
|
|
289
|
-
let { successorStart, overlap } = next.dying;
|
|
290
|
-
console.log(`${logPrefix()} Deploy switchover scheduled: our successor starts at ${iso(successorStart)}; fresh writes hand off at ${iso(successorStart + overlap * BOUNDARY_A_FRACTION)}, and we are killed at ${iso(successorStart + overlap)}`);
|
|
291
|
-
}
|
|
292
|
-
if (!prev.predecessorEnd && next.predecessorEnd) {
|
|
293
|
-
console.log(`${logPrefix()} We are a deploy successor: our predecessor holds the main port until ${iso(next.predecessorEnd)}`);
|
|
294
|
-
}
|
|
295
|
-
if (!prev.remap && next.remap) {
|
|
296
|
-
console.log(`${logPrefix()} Deploy switchover remap active: sources pointing at us are split so [${iso(next.remap.boundaryA)} .. ${iso(next.remap.boundaryB)}] routes to alternate port ${next.remap.altPort} (remap expires at ${iso(next.remap.expire)})`);
|
|
297
|
-
}
|
|
298
|
-
if (prev.remap && !next.remap) {
|
|
299
|
-
console.log(`${logPrefix()} Deploy switchover remap ended; running on the plain stored routing config`);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
/** Starts the takeover machinery. Port fallback (alternate port + registry + acquisition polling)
|
|
303
|
-
* works regardless; without a deploy timeline folder the switchover-specific parts (the remap,
|
|
304
|
-
* the tighter acquisition pacing) simply stay inert. */
|
|
305
|
-
async function initDeployTakeover(config) {
|
|
306
|
-
var _a, _b;
|
|
307
|
-
initialized = config;
|
|
308
|
-
ancestorPids = await getAncestorPids();
|
|
309
|
-
timelineFolder = getTimelineFolder();
|
|
310
|
-
let entries = await readTimelineEntries();
|
|
311
|
-
if (!entries.length) {
|
|
312
|
-
console.log(`${logPrefix()} No deploy timeline entries in ${timelineFolder}; deploy takeover inactive until they appear (port fallback still works)`);
|
|
313
|
-
}
|
|
314
|
-
else {
|
|
315
|
-
console.log(`${logPrefix()} Deploy timeline found at ${timelineFolder} (${entries.length} entries); our pid chain: ${[...ancestorPids].join(" -> ")}`);
|
|
316
|
-
}
|
|
317
|
-
await recompute();
|
|
318
|
-
let poll = setInterval(() => {
|
|
319
|
-
void recompute().catch((e) => { var _a; return console.error(`Deploy takeover recompute failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
|
|
320
|
-
}, TIMELINE_POLL_INTERVAL);
|
|
321
|
-
(_b = (_a = poll).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
322
|
-
}
|
|
323
|
-
exports.initDeployTakeover = initDeployTakeover;
|
|
324
|
-
/** Called when we had to listen on an alternate port (the main port was still held by our
|
|
325
|
-
* predecessor): registers it so the predecessor can route the middle overlap window to us. */
|
|
326
|
-
async function registerAltPort(port) {
|
|
327
|
-
ourAltPort = port;
|
|
328
|
-
let folder = getRegistryFolder();
|
|
329
|
-
await fs_1.default.promises.mkdir(folder, { recursive: true });
|
|
330
|
-
let entry = { pid: process.pid, port, ancestorPids: [...ancestorPids] };
|
|
331
|
-
await fs_1.default.promises.writeFile(path_1.default.join(folder, `${process.pid}.json`), JSON.stringify(entry));
|
|
332
|
-
await recompute();
|
|
333
|
-
}
|
|
334
|
-
exports.registerAltPort = registerAltPort;
|
|
335
|
-
function onTakeoverEvent(listener) {
|
|
336
|
-
eventListeners.push(listener);
|
|
337
|
-
}
|
|
338
|
-
exports.onTakeoverEvent = onTakeoverEvent;
|
|
339
|
-
/** The interpretation overlay: splits every source pointing at our domain+main port so the middle
|
|
340
|
-
* of the deploy overlap points at the alternate port. Pure, in-memory only - the stored routing
|
|
341
|
-
* config is never modified, and this must never be applied to data that gets persisted. */
|
|
342
|
-
function applyDeployRemap(routing) {
|
|
343
|
-
let remap = current.remap;
|
|
344
|
-
let init = initialized;
|
|
345
|
-
if (!remap || !init)
|
|
346
|
-
return routing;
|
|
347
|
-
let sources = [];
|
|
348
|
-
let slice = (source, start, end, url) => {
|
|
349
|
-
return { ...source, url: url || source.url, validWindow: [start, end] };
|
|
350
|
-
};
|
|
351
|
-
for (let source of routing.sources) {
|
|
352
|
-
if (typeof source === "string" || source.type !== "remote") {
|
|
353
|
-
sources.push(source);
|
|
55
|
+
let releaseTime = entry.parameters.releaseTime;
|
|
56
|
+
if (releaseTime === undefined)
|
|
354
57
|
continue;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
try {
|
|
358
|
-
parsed = (0, remoteConfig_1.parseHostedUrl)(source.url);
|
|
359
|
-
}
|
|
360
|
-
catch (_a) {
|
|
361
|
-
sources.push(source);
|
|
58
|
+
let overlapTime = entry.parameters.overlapTime || 0;
|
|
59
|
+
if (releaseTime > now + DEPLOY_RELEASE_MATCH_WINDOW)
|
|
362
60
|
continue;
|
|
363
|
-
|
|
364
|
-
if (parsed.address !== init.domain || parsed.port !== init.mainPort) {
|
|
365
|
-
sources.push(source);
|
|
61
|
+
if (now > releaseTime + overlapTime + DEPLOY_RELEASE_MATCH_WINDOW)
|
|
366
62
|
continue;
|
|
63
|
+
if (best && best.releaseTime >= releaseTime)
|
|
64
|
+
continue;
|
|
65
|
+
best = { releaseTime, overlapTime };
|
|
66
|
+
}
|
|
67
|
+
return best;
|
|
68
|
+
}
|
|
69
|
+
/** Called when the main port is already in use, which on a healthy machine only happens while our predecessor is still running a deploy overlap. Confirms that against the deploy timeline; if no deploy is in progress we are in a bad state (someone else holds our port) and the process must not keep running. */
|
|
70
|
+
async function detectDeployTakeover() {
|
|
71
|
+
for (let attempt = 1; attempt <= DEPLOY_DETECT_ATTEMPTS; attempt++) {
|
|
72
|
+
let entries = await readTimelineEntries();
|
|
73
|
+
let found = findOurRelease(entries, Date.now());
|
|
74
|
+
if (found) {
|
|
75
|
+
takeover = found;
|
|
76
|
+
console.log(`${logPrefix()} Our main port is in use and the deploy timeline confirms a release at ${iso(found.releaseTime)} with an overlap of ${found.overlapTime}ms: we are the successor. Our predecessor is killed at ${iso(found.releaseTime + found.overlapTime)}.`);
|
|
77
|
+
return found;
|
|
367
78
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
let added = false;
|
|
372
|
-
if (a > start) {
|
|
373
|
-
sources.push(slice(source, start, a));
|
|
374
|
-
added = true;
|
|
375
|
-
}
|
|
376
|
-
if (b > a) {
|
|
377
|
-
sources.push(slice(source, a, b, (0, remoteConfig_1.replaceHostedUrlPort)(source.url, remap.altPort)));
|
|
378
|
-
added = true;
|
|
379
|
-
}
|
|
380
|
-
if (end > b) {
|
|
381
|
-
sources.push(slice(source, b, end));
|
|
382
|
-
added = true;
|
|
383
|
-
}
|
|
384
|
-
if (!added) {
|
|
385
|
-
sources.push(source);
|
|
79
|
+
console.log(`${logPrefix()} Our main port is in use but the deploy timeline in ${getTimelineFolder()} shows no release in progress (attempt ${attempt} of ${DEPLOY_DETECT_ATTEMPTS}); retrying in ${DEPLOY_DETECT_RETRY_DELAY}ms`);
|
|
80
|
+
if (attempt < DEPLOY_DETECT_ATTEMPTS) {
|
|
81
|
+
await new Promise(resolve => setTimeout(resolve, DEPLOY_DETECT_RETRY_DELAY));
|
|
386
82
|
}
|
|
387
83
|
}
|
|
388
|
-
|
|
84
|
+
throw new Error(`Our main port is in use, but no deploy is in progress after ${DEPLOY_DETECT_ATTEMPTS * DEPLOY_DETECT_RETRY_DELAY}ms of checking the deploy timeline in ${getTimelineFolder()}. Something else is holding our port, so this process is in a bad state and is exiting.`);
|
|
389
85
|
}
|
|
390
|
-
exports.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return JSON.stringify(remap);
|
|
399
|
-
}
|
|
400
|
-
exports.getTakeoverStamp = getTakeoverStamp;
|
|
401
|
-
/** The middle-window alternate port of an active remap. The OTHER process of the takeover lives on
|
|
402
|
-
* this port on OUR machine (same disk!), so sources pointing at it are self, never sync targets. */
|
|
403
|
-
function getTakeoverAltPort() {
|
|
404
|
-
var _a;
|
|
405
|
-
return (_a = current.remap) === null || _a === void 0 ? void 0 : _a.altPort;
|
|
86
|
+
exports.detectDeployTakeover = detectDeployTakeover;
|
|
87
|
+
function setAltPort(port) {
|
|
88
|
+
if (!takeover) {
|
|
89
|
+
throw new Error(`An alternate port (${port}) was taken without a detected deploy takeover - detectDeployTakeover must run first`);
|
|
90
|
+
}
|
|
91
|
+
takeover.altPort = port;
|
|
92
|
+
console.log(`${logPrefix()} Listening on alternate port ${port}: writes route here until ${iso(getIntermediateEnd())}, and we keep listening until ${iso(getAltPortListenEnd())}`);
|
|
93
|
+
(0, storageServerState_1.startIntermediateMaintenance)();
|
|
406
94
|
}
|
|
407
|
-
exports.
|
|
408
|
-
/**
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
* the only way the dying side knows the post-handoff windows belong to the other process. */
|
|
412
|
-
function getOwnWindowEndClip() {
|
|
413
|
-
let dying = current.dying;
|
|
414
|
-
if (!dying)
|
|
95
|
+
exports.setAltPort = setAltPort;
|
|
96
|
+
/** The window in which writes belong to our alternate port: from the release until our predecessor is killed and we take the main port. */
|
|
97
|
+
function getTakeoverIntermediate() {
|
|
98
|
+
if (!(takeover === null || takeover === void 0 ? void 0 : takeover.altPort))
|
|
415
99
|
return undefined;
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
100
|
+
return { start: takeover.releaseTime, end: getIntermediateEnd(), altPort: takeover.altPort };
|
|
101
|
+
}
|
|
102
|
+
exports.getTakeoverIntermediate = getTakeoverIntermediate;
|
|
103
|
+
function getIntermediateEnd() {
|
|
104
|
+
if (!takeover)
|
|
105
|
+
return 0;
|
|
106
|
+
return takeover.releaseTime + takeover.overlapTime;
|
|
107
|
+
}
|
|
108
|
+
/** We never stop listening on the alternate port while its window is still valid, and hold it well past that for clients that have not caught up yet. */
|
|
109
|
+
function getAltPortListenEnd() {
|
|
110
|
+
if (!takeover)
|
|
111
|
+
return 0;
|
|
112
|
+
return Math.max(takeover.releaseTime + takeover.overlapTime * 2, getIntermediateEnd() + ALT_PORT_LINGER);
|
|
113
|
+
}
|
|
114
|
+
exports.getAltPortListenEnd = getAltPortListenEnd;
|
|
115
|
+
/** How long to wait between main-port acquisition attempts: tight around our predecessor's scheduled death (when the port actually frees), relaxed otherwise. */
|
|
424
116
|
function getMainPortAcquireDelay() {
|
|
425
|
-
|
|
426
|
-
|
|
117
|
+
if (!takeover)
|
|
118
|
+
return ACQUIRE_SLOW_DELAY;
|
|
119
|
+
let predecessorEnd = takeover.releaseTime + takeover.overlapTime;
|
|
120
|
+
if (Date.now() >= predecessorEnd - ACQUIRE_FAST_WINDOW) {
|
|
427
121
|
return ACQUIRE_FAST_DELAY;
|
|
428
122
|
}
|
|
429
123
|
return ACQUIRE_SLOW_DELAY;
|
|
430
124
|
}
|
|
431
125
|
exports.getMainPortAcquireDelay = getMainPortAcquireDelay;
|
|
432
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95VGFrZW92ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkZXBsb3lUYWtlb3Zlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw0Q0FBb0I7QUFDcEIsZ0RBQXdCO0FBQ3hCLGlEQUFxQztBQUVyQyxpREFBc0U7QUFFdEUsaUdBQWlHO0FBQ2pHLGlHQUFpRztBQUNqRyxrR0FBa0c7QUFDbEcsOEZBQThGO0FBQzlGLCtGQUErRjtBQUMvRixpR0FBaUc7QUFDakcsbUdBQW1HO0FBQ25HLDBGQUEwRjtBQUMxRixrR0FBa0c7QUFDbEcsK0ZBQStGO0FBQy9GLEVBQUU7QUFDRixpR0FBaUc7QUFDakcsZ0dBQWdHO0FBQ2hHLGlDQUFpQztBQUVqQyxNQUFNLDhCQUE4QixHQUFHLDBCQUEwQixDQUFDO0FBQ2xFLE1BQU0sc0JBQXNCLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUN6QyxtR0FBbUc7QUFDbkcsK0ZBQStGO0FBQy9GLDhEQUE4RDtBQUM5RCxNQUFNLHlCQUF5QixHQUFHLHFCQUFxQixDQUFDO0FBQ3hELG1HQUFtRztBQUNuRyxNQUFNLGtCQUFrQixHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDckMsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO0FBQ3BDLE1BQU0sbUJBQW1CLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUN0QyxNQUFNLG1CQUFtQixHQUFHLEdBQUcsQ0FBQztBQUNoQyxNQUFNLG1CQUFtQixHQUFHLEdBQUcsQ0FBQztBQUNoQyxNQUFNLHFCQUFxQixHQUFHLENBQUMsQ0FBQztBQXVCaEMsSUFBSSxXQUFvRixDQUFDO0FBQ3pGLElBQUksWUFBWSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7QUFDckMsSUFBSSxjQUFrQyxDQUFDO0FBQ3ZDLElBQUksVUFBOEIsQ0FBQztBQUNuQyxJQUFJLE9BQU8sR0FBcUIsRUFBRSxDQUFDO0FBQ25DLElBQUksVUFBVSxHQUFH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bSBcInBhdGhcIjtcbmltcG9ydCB7IGV4ZWMgfSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgUmVtb3RlQ29uZmlnLCBSZW1vdGVDb25maWdCYXNlLCBIb3N0ZWRDb25maWcgfSBmcm9tIFwiLi4vSUFyY2hpdmVzXCI7XG5pbXBvcnQgeyBwYXJzZUhvc3RlZFVybCwgcmVwbGFjZUhvc3RlZFVybFBvcnQgfSBmcm9tIFwiLi9yZW1vdGVDb25maWdcIjtcblxuLy8gRGVwbG95IHRha2VvdmVyOiB0aGUgZGVwbG95IG1hbmFnZXIgKHF1ZXJ5c3ViJ3MgcGFyYW1ldGVyc1RpbWVsaW5lKSB3cml0ZXMgPG4+LXBhcmFtZXRlcnMuanNvblxuLy8gZmlsZXMgaW50byBvdXIgaW5zdGFuY2UgZm9sZGVyIGRlc2NyaWJpbmcgd2hlbiBlYWNoIHZlcnNpb24gcnVucyBhbmQgd2hlbiBpdCBpcyBzaHV0IGRvd24uIE9sZFxuLy8gYW5kIG5ldyB2ZXJzaW9uIG92ZXJsYXAgZm9yIHRoZSBvdmVybGFwIHRpbWUgKE8gPSBvbGRFbmQgLSBuZXdTdGFydCkuIFdlIHR1cm4gdGhhdCBvdmVybGFwIGludG9cbi8vIGFuIGF0b21pYyB3cml0ZSBoYW5kb2ZmIGJ5IFJFSU5URVJQUkVUSU5HIGV2ZXJ5IHJvdXRpbmcgc291cmNlIHRoYXQgcG9pbnRzIGF0IHVzOiBpdHMgdmFsaWRcbi8vIHdpbmRvdyBpcyBzcGxpdCBzbyB0aGF0IHRoZSBtaWRkbGUgb2YgdGhlIG92ZXJsYXAgKFtTICsgMC41Kk8sIFMgKyAxLjUqT10pIHBvaW50cyBhdCB0aGUgbmV3XG4vLyBwcm9jZXNzJ3MgdGVtcG9yYXJ5IGFsdGVybmF0ZSBwb3J0LiBUaGUgZXhpc3RpbmcgdmFsaWQtd2luZG93IG1hY2hpbmVyeSB0aGVuIGRvZXMgZXZlcnl0aGluZyAtXG4vLyB0aGUgb2xkIHByb2Nlc3Mgc3RhcnRzIHJlamVjdGluZyBmcmVzaCB3cml0ZXMgYXQgdGhlIGZpcnN0IGJvdW5kYXJ5LCBjbGllbnRzIHJlLXJlc29sdmUsIGFuZCB0aGVcbi8vIG5ldyBwcm9jZXNzICh3aGljaCByZWNvZ25pemVzIHRoZSBhbHRlcm5hdGUgcG9ydCBhcyBpdHNlbGYpIHRha2VzIG92ZXIuIFRoZSByZW1hcCBpcyBhblxuLy8gSU5URVJQUkVUQVRJT04gT1ZFUkxBWSwgYXBwbGllZCB3aGVyZSByb3V0aW5nIGNvbmZpZ3MgYXJlIHVzZWQgKHNlZSBhcHBseURlcGxveVJlbWFwIGNhbGxlcnMpIC1cbi8vIGl0IGlzIG5ldmVyIHdyaXR0ZW4gdG8gZGlzaywgbmV2ZXIgc3luY2hyb25pemVkLCBhbmQgbmV2ZXIgcGFydCBvZiBhbnkgc3RvcmVkIGNvbmZpZ3VyYXRpb24uXG4vL1xuLy8gRXZlcnl0aGluZyBoZXJlIGlzIHJlY29tcHV0ZWQgaWRlbXBvdGVudGx5IGZyb20gaXRzIGlucHV0cyAodGltZWxpbmUgZmlsZXMsIHRoZSBwb3J0IHJlZ2lzdHJ5LFxuLy8gb3VyIGFuY2VzdG9yIHBpZHMsIHRoZSBjbG9jaykgLSBmaWxlcyBjYW4gYXBwZWFyIG9yIGNoYW5nZSBhdCBhbnkgbW9tZW50LCBhbmQgd2UgY2FuIHN0YXJ0IGF0XG4vLyBhbnkgcG9pbnQgZHVyaW5nIGEgc3dpdGNob3Zlci5cblxuY29uc3QgUEFSQU1FVEVSU19USU1FTElORV9GSUxFX1JFR0VYID0gL14oXFxkKyktcGFyYW1ldGVyc1xcLmpzb24kLztcbmNvbnN0IFRJTUVMSU5FX1BPTExfSU5URVJWQUwgPSA2MCAqIDEwMDA7XG4vLyBQcm9jZXNzZXMgbGlzdGVuaW5nIG9uIGFuIGFsdGVybmF0ZSBwb3J0IHJlZ2lzdGVyIGl0IGhlcmUgKHNpYmxpbmcgb2YgdGhlIHN0b3JhZ2UgZm9sZGVyKSwga2V5ZWRcbi8vIGJ5IHRoZWlyIGFjdHVhbCBwaWQ7IGNvbnRlbnQgaW5jbHVkZXMgdGhlaXIgYW5jZXN0b3IgcGlkcyBzbyB0aGUgdGltZWxpbmUgZW50cnkgcGlkIChhIHNoZWxsXG4vLyBhbmNlc3RvciBvZiB0aGUgcHJvY2VzcykgY2FuIGJlIG1hdGNoZWQgdG8gYSByZWdpc3RyeSBlbnRyeVxuY29uc3QgUE9SVF9SRUdJU1RSWV9GT0xERVJfTkFNRSA9IFwic3RvcmFnZVBvcnRSZWdpc3RyeVwiO1xuLy8gTWFpbi1wb3J0IGFjcXVpc2l0aW9uIGF0dGVtcHRzIHJ1biB0aGlzIG9mdGVuLCB0aWdodGVuaW5nIG5lYXIgdGhlIHByZWRlY2Vzc29yJ3Mgc2NoZWR1bGVkIGRlYXRoXG5jb25zdCBBQ1FVSVJFX1NMT1dfREVMQVkgPSAzMCAqIDEwMDA7XG5jb25zdCBBQ1FVSVJFX0ZBU1RfREVMQVkgPSA1ICogMTAwMDtcbmNvbnN0IEFDUVVJUkVfRkFTVF9XSU5ET1cgPSA2MCAqIDEwMDA7XG5jb25zdCBCT1VOREFSWV9BX0ZSQUNUSU9OID0gMC41O1xuY29uc3QgQk9VTkRBUllfQl9GUkFDVElPTiA9IDEuNTtcbmNvbnN0IFJFTUFQX0VYUElSRV9GUkFDVElPTiA9IDI7XG5cbnR5cGUgVGltZWxpbmVFbnRyeSA9IHtcbiAgICBwaWQ/OiBudW1iZXI7XG4gICAgLy8gcmVsZWFzZVRpbWUgKyBvdmVybGFwVGltZSBkZWZpbmUgZXZlcnl0aGluZzogdGhlIG5ld2VyIGVudHJ5J3MgcmVsZWFzZVRpbWUgaXMgd2hlbiBpdFxuICAgIC8vIHN0YXJ0cywgYW5kIHJlbGVhc2VUaW1lICsgb3ZlcmxhcFRpbWUgaXMgd2hlbiB0aGUgb2xkZXIgb25lIGlzIGtpbGxlZCAoZnJlZWluZyB0aGUgcG9ydCkuXG4gICAgLy8gVGhlIGZpbGVzIGFsc28gY2FycnkgYW4gYWxpdmVXaW5kb3csIHdoaWNoIGlzIGRlbGliZXJhdGVseSBpZ25vcmVkLlxuICAgIHBhcmFtZXRlcnM6IHsgcmVsZWFzZVRpbWU/OiBudW1iZXI7IG92ZXJsYXBUaW1lPzogbnVtYmVyIH07XG59O1xuXG50eXBlIFRha2VvdmVyQ29tcHV0ZWQgPSB7XG4gICAgLy8gV2UgYXJlIHNjaGVkdWxlZCB0byBkaWUgd2l0aCBhIHN1Y2Nlc3NvciBvdmVybGFwcGluZyB1cyAoa25vd24gZnJvbSB0aGUgZmlsZXMgYWxvbmUsIGJlZm9yZVxuICAgIC8vIHRoZSBzdWNjZXNzb3IncyBwb3J0IGlzIGRpc2NvdmVyZWQgLSB0aGUgZmx1c2ggZGVhZGxpbmUgYXBwbGllcyBpbW1lZGlhdGVseSlcbiAgICBkeWluZz86IHsgc3VjY2Vzc29yU3RhcnQ6IG51bWJlcjsgb3ZlcmxhcDogbnVtYmVyIH07XG4gICAgLy8gVGhlIHdpbmRvdyByZWludGVycHJldGF0aW9uLCBvbmNlIHRoZSBtaWRkbGUgd2luZG93J3MgcG9ydCBpcyBrbm93biAodGhlIHN1Y2Nlc3NvcidzXG4gICAgLy8gcmVnaXN0ZXJlZCBhbHRlcm5hdGUgcG9ydCAtIG9yIG91ciBvd24sIHdoZW4gd2UgQVJFIHRoZSBzdWNjZXNzb3IpXG4gICAgcmVtYXA/OiB7IGJvdW5kYXJ5QTogbnVtYmVyOyBib3VuZGFyeUI6IG51bWJlcjsgZXhwaXJlOiBudW1iZXI7IGFsdFBvcnQ6IG51bWJlciB9O1xuICAgIC8vIFdoZW4gb3VyIHByZWRlY2Vzc29yIGRpZXMgYW5kIGZyZWVzIHRoZSBtYWluIHBvcnQgKGZvciBhY3F1aXNpdGlvbiBwYWNpbmcpXG4gICAgcHJlZGVjZXNzb3JFbmQ/OiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBUYWtlb3ZlckV2ZW50ID0gXCJyZW1hcENoYW5nZWRcIjtcblxubGV0IGluaXRpYWxpemVkOiB7IGRvbWFpbjogc3RyaW5nOyBtYWluUG9ydDogbnVtYmVyOyBzdG9yYWdlRm9sZGVyOiBzdHJpbmcgfSB8IHVuZGVmaW5lZDtcbmxldCBhbmNlc3RvclBpZHMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbmxldCB0aW1lbGluZUZvbGRlcjogc3RyaW5nIHwgdW5kZWZpbmVkO1xubGV0IG91ckFsdFBvcnQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbmxldCBjdXJyZW50OiBUYWtlb3ZlckNvbXB1dGVkID0ge307XG5sZXQgY3VycmVudEtleSA9IEpTT04uc3RyaW5naWZ5KGN1cnJlbnQpO1xubGV0IGV2ZW50TGlzdGVuZXJzOiAoKGV2ZW50OiBUYWtlb3ZlckV2ZW50KSA9PiB2b2lkKVtdID0gW107XG5sZXQgZXZlbnRUaW1lcnM6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+W10gPSBbXTtcbmxldCBsb2dnZWROb01hdGNoID0gZmFsc2U7XG5sZXQgbG9nZ2VkSWRlbnRpdHkgPSBmYWxzZTtcblxuZnVuY3Rpb24gZXhlY1RleHQoY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBleGVjKGNvbW1hbmQsIChlcnJvciwgc3Rkb3V0KSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc29sdmUoc3Rkb3V0KTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbi8vIFRoZSB0aW1lbGluZSBlbnRyeSBwaWQgaXMgdGhlIHNjcmVlbiBzaGVsbCB0aGF0IHNwYXduZWQgdXMgLSBhbiBhbmNlc3RvciAtIHNvIHdlIHdhbGsgb3VyIHdob2xlXG4vLyBhbmNlc3RvciBjaGFpbiB0byBmaW5kIHdoaWNoIGVudHJ5IGlzIHVzXG5hc3luYyBmdW5jdGlvbiBnZXRBbmNlc3RvclBpZHMoKTogUHJvbWlzZTxTZXQ8bnVtYmVyPj4ge1xuICAgIGxldCBwaWRzID0gbmV3IFNldDxudW1iZXI+KFtwcm9jZXNzLnBpZF0pO1xuICAgIGxldCBjdXJyZW50UGlkID0gcHJvY2Vzcy5waWQ7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgbGV0IHBwaWQ6IG51bWJlcjtcbiAgICAgICAgaWYgKGN1cnJlbnRQaWQgPT09IHByb2Nlc3MucGlkICYmIHByb2Nlc3MucHBpZCkge1xuICAgICAgICAgICAgcHBpZCA9IHByb2Nlc3MucHBpZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcHBpZCA9IHBhcnNlSW50KChhd2FpdCBleGVjVGV4dChgcHMgLW8gcHBpZD0gLXAgJHtjdXJyZW50UGlkfWApKS50cmltKCkpO1xuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFwcGlkIHx8IE51bWJlci5pc05hTihwcGlkKSB8fCBwcGlkIDw9IDEgfHwgcGlkcy5oYXMocHBpZCkpIGJyZWFrO1xuICAgICAgICBwaWRzLmFkZChwcGlkKTtcbiAgICAgICAgY3VycmVudFBpZCA9IHBwaWQ7XG4gICAgfVxuICAgIHJldHVybiBwaWRzO1xufVxuXG4vLyBUaGUgaW5zdGFuY2UgZm9sZGVyIGlzIEFMV0FZUyB0aGUgcGFyZW50IG9mIG91ciBjd2QgKHNlcnZpY2VzIHJ1biBpbiA8aW5zdGFuY2U+L2dpdC8pIC0gbmV2ZXJcbi8vIHNlYXJjaCBmb3IgaXQsIGEgd2FsayBjb3VsZCBsYXRjaCBvbnRvIHRoZSB3cm9uZyBmb2xkZXJcbmZ1bmN0aW9uIGdldFRpbWVsaW5lRm9sZGVyKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHBhdGguZGlybmFtZShwcm9jZXNzLmN3ZCgpKS5yZXBsYWNlQWxsKFwiXFxcXFwiLCBcIi9cIikgKyBcIi9cIjtcbn1cblxuZnVuY3Rpb24gcGlkQWxpdmUocGlkOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgICBwcm9jZXNzLmtpbGwocGlkLCAwKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gKGUgYXMgeyBjb2RlPzogc3RyaW5nIH0pLmNvZGUgPT09IFwiRVBFUk1cIjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldFJlZ2lzdHJ5Rm9sZGVyKCk6IHN0cmluZyB7XG4gICAgaWYgKCFpbml0aWFsaXplZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERlcGxveSB0YWtlb3ZlciBpcyBub3QgaW5pdGlhbGl6ZWRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhdGguam9pbihwYXRoLmRpcm5hbWUocGF0aC5yZXNvbHZlKGluaXRpYWxpemVkLnN0b3JhZ2VGb2xkZXIpKSwgUE9SVF9SRUdJU1RSWV9GT0xERVJfTkFNRSk7XG59XG5cbnR5cGUgUmVnaXN0cnlFbnRyeSA9IHsgcGlkOiBudW1iZXI7IHBvcnQ6IG51bWJlcjsgYW5jZXN0b3JQaWRzOiBudW1iZXJbXSB9O1xuXG5hc3luYyBmdW5jdGlvbiByZWFkUG9ydFJlZ2lzdHJ5KCk6IFByb21pc2U8UmVnaXN0cnlFbnRyeVtdPiB7XG4gICAgbGV0IGZvbGRlciA9IGdldFJlZ2lzdHJ5Rm9sZGVyKCk7XG4gICAgbGV0IGZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIHRyeSB7XG4gICAgICAgIGZpbGVzID0gYXdhaXQgZnMucHJvbWlzZXMucmVhZGRpcihmb2xkZXIpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGxldCBlbnRyaWVzOiBSZWdpc3RyeUVudHJ5W10gPSBbXTtcbiAgICBmb3IgKGxldCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgICAgIGxldCBtYXRjaCA9IC9eKFxcZCspXFwuanNvbiQvLmV4ZWMoZmlsZSk7XG4gICAgICAgIGlmICghbWF0Y2gpIGNvbnRpbnVlO1xuICAgICAgICBsZXQgcGlkID0gcGFyc2VJbnQobWF0Y2hbMV0pO1xuICAgICAgICBpZiAoIXBpZEFsaXZlKHBpZCkpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgZnMucHJvbWlzZXMudW5saW5rKHBhdGguam9pbihmb2xkZXIsIGZpbGUpKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggeyB9XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbGV0IGVudHJ5ID0gSlNPTi5wYXJzZShhd2FpdCBmcy5wcm9taXNlcy5yZWFkRmlsZShwYXRoLmpvaW4oZm9sZGVyLCBmaWxlKSwgXCJ1dGY4XCIpKSBhcyBSZWdpc3RyeUVudHJ5O1xuICAgICAgICAgICAgZW50cmllcy5wdXNoKHsgLi4uZW50cnksIHBpZCB9KTtcbiAgICAgICAgfSBjYXRjaCB7IH1cbiAgICB9XG4gICAgcmV0dXJuIGVudHJpZXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRUaW1lbGluZUVudHJpZXMoKTogUHJvbWlzZTxUaW1lbGluZUVudHJ5W10+IHtcbiAgICBpZiAoIXRpbWVsaW5lRm9sZGVyKSByZXR1cm4gW107XG4gICAgbGV0IGVudHJpZXM6IFRpbWVsaW5lRW50cnlbXSA9IFtdO1xuICAgIGZvciAobGV0IGZpbGUgb2YgYXdhaXQgZnMucHJvbWlzZXMucmVhZGRpcih0aW1lbGluZUZvbGRlcikpIHtcbiAgICAgICAgaWYgKCFQQVJBTUVURVJTX1RJTUVMSU5FX0ZJTEVfUkVHRVgudGVzdChmaWxlKSkgY29udGludWU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBlbnRyaWVzLnB1c2goSlNPTi5wYXJzZShhd2FpdCBmcy5wcm9taXNlcy5yZWFkRmlsZSh0aW1lbGluZUZvbGRlciArIGZpbGUsIFwidXRmOFwiKSkgYXMgVGltZWxpbmVFbnRyeSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgQ291bGQgbm90IHJlYWQgZGVwbG95IHRpbWVsaW5lIGZpbGUgJHt0aW1lbGluZUZvbGRlciArIGZpbGV9OiAkeyhlIGFzIEVycm9yKS5zdGFjayA/PyBlfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBlbnRyaWVzO1xufVxuXG5mdW5jdGlvbiBtYWtlUmVtYXAoc3VjY2Vzc29yU3RhcnQ6IG51bWJlciwgb3ZlcmxhcDogbnVtYmVyLCBhbHRQb3J0OiBudW1iZXIpOiBUYWtlb3ZlckNvbXB1dGVkW1wicmVtYXBcIl0ge1xuICAgIHJldHVybiB7XG4gICAgICAgIGJvdW5kYXJ5QTogc3VjY2Vzc29yU3RhcnQgKyBvdmVybGFwICogQk9VTkRBUllfQV9GUkFDVElPTixcbiAgICAgICAgYm91bmRhcnlCOiBzdWNjZXNzb3JTdGFydCArIG92ZXJsYXAgKiBCT1VOREFSWV9CX0ZSQUNUSU9OLFxuICAgICAgICBleHBpcmU6IHN1Y2Nlc3NvclN0YXJ0ICsgb3ZlcmxhcCAqIFJFTUFQX0VYUElSRV9GUkFDVElPTixcbiAgICAgICAgYWx0UG9ydCxcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBlbWl0KGV2ZW50OiBUYWtlb3ZlckV2ZW50KTogdm9pZCB7XG4gICAgZm9yIChsZXQgbGlzdGVuZXIgb2YgZXZlbnRMaXN0ZW5lcnMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGxpc3RlbmVyKGV2ZW50KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRGVwbG95IHRha2VvdmVyIGxpc3RlbmVyIGZhaWxlZDogJHsoZSBhcyBFcnJvcikuc3RhY2sgPz8gZX1gKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gc2NoZWR1bGVFdmVudHMoKTogdm9pZCB7XG4gICAgZm9yIChsZXQgdGltZXIgb2YgZXZlbnRUaW1lcnMpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICB9XG4gICAgZXZlbnRUaW1lcnMgPSBbXTtcbiAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBsZXQgc2NoZWR1bGUgPSAodGltZTogbnVtYmVyLCBmbmM6ICgpID0+IHZvaWQpID0+IHtcbiAgICAgICAgaWYgKHRpbWUgPD0gbm93KSByZXR1cm47XG4gICAgICAgIGxldCB0aW1lciA9IHNldFRpbWVvdXQoZm5jLCB0aW1lIC0gbm93KTtcbiAgICAgICAgKHRpbWVyIGFzIHsgdW5yZWY/OiAoKSA9PiB2b2lkIH0pLnVucmVmPy4oKTtcbiAgICAgICAgZXZlbnRUaW1lcnMucHVzaCh0aW1lcik7XG4gICAgfTtcbiAgICBjb25zdCByZW1hcCA9IGN1cnJlbnQucmVtYXA7XG4gICAgaWYgKHJlbWFwKSB7XG4gICAgICAgIGxldCBhbHRQb3J0ID0gcmVtYXAuYWx0UG9ydDtcbiAgICAgICAgc2NoZWR1bGUocmVtYXAuYm91bmRhcnlBLCAoKSA9PiBjb25zb2xlLmxvZyhgJHtsb2dQcmVmaXgoKX0gRGVwbG95IHN3aXRjaG92ZXIgd3JpdGUgaGFuZG9mZiBib3VuZGFyeSAke2lzbyhyZW1hcC5ib3VuZGFyeUEpfSBwYXNzZWQ6IGZyZXNoIHdyaXRlcyBub3cgYmVsb25nIHRvIHRoZSBhbHRlcm5hdGUtcG9ydCBzaWRlIChwb3J0ICR7YWx0UG9ydH0pYCkpO1xuICAgICAgICBzY2hlZHVsZShyZW1hcC5ib3VuZGFyeUIsICgpID0+IGNvbnNvbGUubG9nKGAke2xvZ1ByZWZpeCgpfSBEZXBsb3kgc3dpdGNob3ZlciBzZWNvbmQgYm91bmRhcnkgJHtpc28ocmVtYXAuYm91bmRhcnlCKX0gcGFzc2VkOiBmcmVzaCB3cml0ZXMgcmV0dXJuIHRvIHRoZSBtYWluIHBvcnRgKSk7XG4gICAgICAgIHNjaGVkdWxlKHJlbWFwLmV4cGlyZSwgKCkgPT4gdm9pZCByZWNvbXB1dGUoKS5jYXRjaCgoZTogRXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoYERlcGxveSB0YWtlb3ZlciByZWNvbXB1dGUgZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSkpO1xuICAgIH1cbn1cblxuLy8gTXVsdGlwbGUgcHJvY2Vzc2VzIChwcmVkZWNlc3NvciArIHN1Y2Nlc3Nvcikgb2Z0ZW4gc2hhcmUgb25lIGpvdXJuYWwgZHVyaW5nIGEgc3dpdGNob3Zlciwgc29cbi8vIGV2ZXJ5IGxpZmVjeWNsZSBsaW5lIGlkZW50aWZpZXMgaXRzIHByb2Nlc3NcbmZ1bmN0aW9uIGxvZ1ByZWZpeCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgW3BpZCAke3Byb2Nlc3MucGlkfV1gO1xufVxuXG4vLyBSZWNvbXB1dGUgaXMgaW52b2tlZCBmcm9tIGluaXQsIHJlZ2lzdGVyQWx0UG9ydCwgdGhlIHBvbGwsIGFuZCB0aGUgZXhwaXJ5IHRpbWVyIC0gcG9zc2libHlcbi8vIGNvbmN1cnJlbnRseS4gUnVucyBhcmUgc2VyaWFsaXplZCwgb3IgdHdvIGluLWZsaWdodCBydW5zIHdvdWxkIGJvdGggcGFzcyB0aGUgY2hhbmdlZC1zdGF0ZSBjaGVja1xuLy8gYW5kIGRvdWJsZS1maXJlIGV2ZXJ5IHRyYW5zaXRpb24gKGxvZ3MsIHJlYnVpbGQgZXZlbnRzLCB0aW1lcnMpLlxubGV0IHJlY29tcHV0ZUNoYWluID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5mdW5jdGlvbiByZWNvbXB1dGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IG5leHQgPSByZWNvbXB1dGVDaGFpbi50aGVuKCgpID0+IHJlY29tcHV0ZU5vdygpKTtcbiAgICByZWNvbXB1dGVDaGFpbiA9IG5leHQudGhlbigoKSA9PiB7IH0sICgpID0+IHsgfSk7XG4gICAgcmV0dXJuIG5leHQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlY29tcHV0ZU5vdygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWluaXRpYWxpemVkIHx8ICF0aW1lbGluZUZvbGRlcikgcmV0dXJuO1xuICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGxldCBlbnRyaWVzID0gYXdhaXQgcmVhZFRpbWVsaW5lRW50cmllcygpO1xuICAgIGxldCByZWdpc3RyeSA9IGF3YWl0IHJlYWRQb3J0UmVnaXN0cnkoKTtcbiAgICBsZXQgdXM6IFRpbWVsaW5lRW50cnkgfCB1bmRlZmluZWQ7XG4gICAgZm9yIChsZXQgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICBpZiAoZW50cnkucGlkICYmIGFuY2VzdG9yUGlkcy5oYXMoZW50cnkucGlkKSkge1xuICAgICAgICAgICAgdXMgPSBlbnRyeTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBNYXRjaGluZyBmYWlsdXJlcyBtdXN0IGJlIGxvdWQsIG9yIHRha2VvdmVyIGRldGVjdGlvbiBmYWlscyBzaWxlbnRseSBmb3JldmVyXG4gICAgaWYgKCF1cyAmJiBlbnRyaWVzLmxlbmd0aCAmJiAhbG9nZ2VkTm9NYXRjaCkge1xuICAgICAgICBsb2dnZWROb01hdGNoID0gdHJ1ZTtcbiAgICAgICAgY29uc29sZS53YXJuKGAke2xvZ1ByZWZpeCgpfSBObyBkZXBsb3kgdGltZWxpbmUgZW50cnkgbWF0Y2hlcyBvdXIgcGlkIGNoYWluICgke1suLi5hbmNlc3RvclBpZHNdLmpvaW4oXCIsIFwiKX0pIC0gdGFrZW92ZXIgZGV0ZWN0aW9uIGNhbm5vdCB3b3JrLiBFbnRyaWVzOiAke2VudHJpZXMubWFwKHggPT4gYHBpZD0ke3gucGlkID8/IFwibm9uZVwifSByZWxlYXNlVGltZT0ke3gucGFyYW1ldGVycy5yZWxlYXNlVGltZX1gKS5qb2luKFwiIHwgXCIpfWApO1xuICAgIH1cbiAgICBpZiAodXMgJiYgIWxvZ2dlZElkZW50aXR5KSB7XG4gICAgICAgIGxvZ2dlZElkZW50aXR5ID0gdHJ1ZTtcbiAgICAgICAgY29uc29sZS5sb2coYCR7bG9nUHJlZml4KCl9IERlcGxveSB0aW1lbGluZSBlbnRyeSBtYXRjaGVkOiB3ZSBhcmUgcGlkPSR7dXMucGlkfSwgcmVsZWFzZVRpbWU9JHt1cy5wYXJhbWV0ZXJzLnJlbGVhc2VUaW1lICE9PSB1bmRlZmluZWQgJiYgaXNvKHVzLnBhcmFtZXRlcnMucmVsZWFzZVRpbWUpIHx8IFwidW5rbm93blwifSwgJHtlbnRyaWVzLmxlbmd0aH0gZW50cmllcyB0b3RhbGApO1xuICAgIH1cbiAgICBsZXQgY29tcHV0ZWQ6IFRha2VvdmVyQ29tcHV0ZWQgPSB7fTtcbiAgICBsZXQgdXNSZWxlYXNlID0gdXM/LnBhcmFtZXRlcnMucmVsZWFzZVRpbWU7XG4gICAgaWYgKHVzICYmIHVzUmVsZWFzZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIFRoZSBuZXdlciBlbnRyeSdzIHJlbGVhc2VUaW1lIGlzIHdoZW4gaXQgc3RhcnRzOyByZWxlYXNlVGltZSArIG92ZXJsYXBUaW1lIGlzIHdoZW4gdGhlXG4gICAgICAgIC8vIG9sZGVyIG9uZSBpcyBraWxsZWQuIFRoYXQncyB0aGUgd2hvbGUgdGltZWxpbmUuXG4gICAgICAgIGxldCBuZXh0OiB7IGVudHJ5OiBUaW1lbGluZUVudHJ5OyByZWxlYXNlOiBudW1iZXIgfSB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHByZXY6IHsgZW50cnk6IFRpbWVsaW5lRW50cnk7IHJlbGVhc2U6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICAgICAgICBmb3IgKGxldCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICAgICAgICBpZiAoZW50cnkgPT09IHVzKSBjb250aW51ZTtcbiAgICAgICAgICAgIGxldCByZWxlYXNlID0gZW50cnkucGFyYW1ldGVycy5yZWxlYXNlVGltZTtcbiAgICAgICAgICAgIGlmIChyZWxlYXNlID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKHJlbGVhc2UgPiB1c1JlbGVhc2UgJiYgKCFuZXh0IHx8IHJlbGVhc2UgPCBuZXh0LnJlbGVhc2UpKSB7XG4gICAgICAgICAgICAgICAgbmV4dCA9IHsgZW50cnksIHJlbGVhc2UgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZWxlYXNlIDwgdXNSZWxlYXNlICYmICghcHJldiB8fCByZWxlYXNlID4gcHJldi5yZWxlYXNlKSkge1xuICAgICAgICAgICAgICAgIHByZXYgPSB7IGVudHJ5LCByZWxlYXNlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5leHQpIHtcbiAgICAgICAgICAgIGxldCBzdWNjZXNzb3JTdGFydCA9IG5leHQucmVsZWFzZTtcbiAgICAgICAgICAgIGxldCBvdmVybGFwID0gbmV4dC5lbnRyeS5wYXJhbWV0ZXJzLm92ZXJsYXBUaW1lIHx8IHVzLnBhcmFtZXRlcnMub3ZlcmxhcFRpbWUgfHwgMDtcbiAgICAgICAgICAgIC8vIFRyYWNrZWQgZXZlbiBmb3IgYSBaRVJPLW92ZXJsYXAgZGVwbG95ICh0aGUgc2NoZWR1bGVkLXN3aXRjaG92ZXIgbG9nIG11c3Qgc3RpbGxcbiAgICAgICAgICAgIC8vIGZpcmUpOyBvbmx5IHRoZSByZW1hcCAodGhlIGFsdGVybmF0ZS1wb3J0IG1pZGRsZSB3aW5kb3cpIG5lZWRzIGFuIGFjdHVhbCBvdmVybGFwLlxuICAgICAgICAgICAgLy8gRmx1c2hpbmcgYmVmb3JlIHRoZSBoYW5kb2ZmIG5lZWRzIG5vdGhpbmcgc3BlY2lhbCBoZXJlOiB0aGUgcmVtYXAgZW5kcyBvdXIgdmFsaWRcbiAgICAgICAgICAgIC8vIHdpbmRvdywgYW5kIGZhc3Qgd3JpdGVzIGFsd2F5cyBmbHVzaCBhaGVhZCBvZiB0aGVpciB3aW5kb3cncyBlbmQuXG4gICAgICAgICAgICBjb21wdXRlZC5keWluZyA9IHsgc3VjY2Vzc29yU3RhcnQsIG92ZXJsYXAgfTtcbiAgICAgICAgICAgIGlmIChvdmVybGFwID4gMCAmJiBub3cgPCBzdWNjZXNzb3JTdGFydCArIG92ZXJsYXAgKiBSRU1BUF9FWFBJUkVfRlJBQ1RJT04pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdWNjZXNzb3JQaWQgPSBuZXh0LmVudHJ5LnBpZDtcbiAgICAgICAgICAgICAgICBpZiAoc3VjY2Vzc29yUGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBzdWNjZXNzb3JFbnRyeSA9IHJlZ2lzdHJ5LmZpbmQoeCA9PiB4LmFuY2VzdG9yUGlkcy5pbmNsdWRlcyhzdWNjZXNzb3JQaWQpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN1Y2Nlc3NvckVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wdXRlZC5yZW1hcCA9IG1ha2VSZW1hcChzdWNjZXNzb3JTdGFydCwgb3ZlcmxhcCwgc3VjY2Vzc29yRW50cnkucG9ydCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByZXYpIHtcbiAgICAgICAgICAgIGxldCBvdmVybGFwID0gdXMucGFyYW1ldGVycy5vdmVybGFwVGltZSB8fCBwcmV2LmVudHJ5LnBhcmFtZXRlcnMub3ZlcmxhcFRpbWUgfHwgMDtcbiAgICAgICAgICAgIC8vIFRoZSBwcmVkZWNlc3NvciBob2xkcyB0aGUgbWFpbiBwb3J0IHVudGlsIE9VUiByZWxlYXNlICsgdGhlIG92ZXJsYXBcbiAgICAgICAgICAgIGNvbXB1dGVkLnByZWRlY2Vzc29yRW5kID0gdXNSZWxlYXNlICsgb3ZlcmxhcDtcbiAgICAgICAgICAgIGlmIChvdmVybGFwID4gMCAmJiBvdXJBbHRQb3J0ICYmIG5vdyA8IHVzUmVsZWFzZSArIG92ZXJsYXAgKiBSRU1BUF9FWFBJUkVfRlJBQ1RJT04gJiYgIWNvbXB1dGVkLnJlbWFwKSB7XG4gICAgICAgICAgICAgICAgY29tcHV0ZWQucmVtYXAgPSBtYWtlUmVtYXAodXNSZWxlYXNlLCBvdmVybGFwLCBvdXJBbHRQb3J0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBsZXQga2V5ID0gSlNPTi5zdHJpbmdpZnkoY29tcHV0ZWQpO1xuICAgIGlmIChrZXkgPT09IGN1cnJlbnRLZXkpIHJldHVybjtcbiAgICBsb2dUcmFuc2l0aW9ucyhjdXJyZW50LCBjb21wdXRlZCk7XG4gICAgY3VycmVudCA9IGNvbXB1dGVkO1xuICAgIGN1cnJlbnRLZXkgPSBrZXk7XG4gICAgc2NoZWR1bGVFdmVudHMoKTtcbiAgICBlbWl0KFwicmVtYXBDaGFuZ2VkXCIpO1xufVxuXG5mdW5jdGlvbiBpc28odGltZTogbnVtYmVyKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IERhdGUodGltZSkudG9JU09TdHJpbmcoKTtcbn1cblxuLy8gVGhlIHN3aXRjaG92ZXIgbGlmZWN5Y2xlIGlzIHJhcmUgYW5kIGltcG9ydGFudCwgc28gZXZlcnkgc3RhZ2UgZ2V0cyBhIGNsZWFyIGxpbmVcbmZ1bmN0aW9uIGxvZ1RyYW5zaXRpb25zKHByZXY6IFRha2VvdmVyQ29tcHV0ZWQsIG5leHQ6IFRha2VvdmVyQ29tcHV0ZWQpOiB2b2lkIHtcbiAgICBpZiAoIXByZXYuZHlpbmcgJiYgbmV4dC5keWluZykge1xuICAgICAgICBsZXQgeyBzdWNjZXNzb3JTdGFydCwgb3ZlcmxhcCB9ID0gbmV4dC5keWluZztcbiAgICAgICAgY29uc29sZS5sb2coYCR7bG9nUHJlZml4KCl9IERlcGxveSBzd2l0Y2hvdmVyIHNjaGVkdWxlZDogb3VyIHN1Y2Nlc3NvciBzdGFydHMgYXQgJHtpc28oc3VjY2Vzc29yU3RhcnQpfTsgZnJlc2ggd3JpdGVzIGhhbmQgb2ZmIGF0ICR7aXNvKHN1Y2Nlc3NvclN0YXJ0ICsgb3ZlcmxhcCAqIEJPVU5EQVJZX0FfRlJBQ1RJT04pfSwgYW5kIHdlIGFyZSBraWxsZWQgYXQgJHtpc28oc3VjY2Vzc29yU3RhcnQgKyBvdmVybGFwKX1gKTtcbiAgICB9XG4gICAgaWYgKCFwcmV2LnByZWRlY2Vzc29yRW5kICYmIG5leHQucHJlZGVjZXNzb3JFbmQpIHtcbiAgICAgICAgY29uc29sZS5sb2coYCR7bG9nUHJlZml4KCl9IFdlIGFyZSBhIGRlcGxveSBzdWNjZXNzb3I6IG91ciBwcmVkZWNlc3NvciBob2xkcyB0aGUgbWFpbiBwb3J0IHVudGlsICR7aXNvKG5leHQucHJlZGVjZXNzb3JFbmQpfWApO1xuICAgIH1cbiAgICBpZiAoIXByZXYucmVtYXAgJiYgbmV4dC5yZW1hcCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgJHtsb2dQcmVmaXgoKX0gRGVwbG95IHN3aXRjaG92ZXIgcmVtYXAgYWN0aXZlOiBzb3VyY2VzIHBvaW50aW5nIGF0IHVzIGFyZSBzcGxpdCBzbyBbJHtpc28obmV4dC5yZW1hcC5ib3VuZGFyeUEpfSAuLiAke2lzbyhuZXh0LnJlbWFwLmJvdW5kYXJ5Qil9XSByb3V0ZXMgdG8gYWx0ZXJuYXRlIHBvcnQgJHtuZXh0LnJlbWFwLmFsdFBvcnR9IChyZW1hcCBleHBpcmVzIGF0ICR7aXNvKG5leHQucmVtYXAuZXhwaXJlKX0pYCk7XG4gICAgfVxuICAgIGlmIChwcmV2LnJlbWFwICYmICFuZXh0LnJlbWFwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGAke2xvZ1ByZWZpeCgpfSBEZXBsb3kgc3dpdGNob3ZlciByZW1hcCBlbmRlZDsgcnVubmluZyBvbiB0aGUgcGxhaW4gc3RvcmVkIHJvdXRpbmcgY29uZmlnYCk7XG4gICAgfVxufVxuXG4vKiogU3RhcnRzIHRoZSB0YWtlb3ZlciBtYWNoaW5lcnkuIFBvcnQgZmFsbGJhY2sgKGFsdGVybmF0ZSBwb3J0ICsgcmVnaXN0cnkgKyBhY3F1aXNpdGlvbiBwb2xsaW5nKVxuICogIHdvcmtzIHJlZ2FyZGxlc3M7IHdpdGhvdXQgYSBkZXBsb3kgdGltZWxpbmUgZm9sZGVyIHRoZSBzd2l0Y2hvdmVyLXNwZWNpZmljIHBhcnRzICh0aGUgcmVtYXAsXG4gKiAgdGhlIHRpZ2h0ZXIgYWNxdWlzaXRpb24gcGFjaW5nKSBzaW1wbHkgc3RheSBpbmVydC4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbml0RGVwbG95VGFrZW92ZXIoY29uZmlnOiB7IGRvbWFpbjogc3RyaW5nOyBtYWluUG9ydDogbnVtYmVyOyBzdG9yYWdlRm9sZGVyOiBzdHJpbmcgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGluaXRpYWxpemVkID0gY29uZmlnO1xuICAgIGFuY2VzdG9yUGlkcyA9IGF3YWl0IGdldEFuY2VzdG9yUGlkcygpO1xuICAgIHRpbWVsaW5lRm9sZGVyID0gZ2V0VGltZWxpbmVGb2xkZXIoKTtcbiAgICBsZXQgZW50cmllcyA9IGF3YWl0IHJlYWRUaW1lbGluZUVudHJpZXMoKTtcbiAgICBpZiAoIWVudHJpZXMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGAke2xvZ1ByZWZpeCgpfSBObyBkZXBsb3kgdGltZWxpbmUgZW50cmllcyBpbiAke3RpbWVsaW5lRm9sZGVyfTsgZGVwbG95IHRha2VvdmVyIGluYWN0aXZlIHVudGlsIHRoZXkgYXBwZWFyIChwb3J0IGZhbGxiYWNrIHN0aWxsIHdvcmtzKWApO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGAke2xvZ1ByZWZpeCgpfSBEZXBsb3kgdGltZWxpbmUgZm91bmQgYXQgJHt0aW1lbGluZUZvbGRlcn0gKCR7ZW50cmllcy5sZW5ndGh9IGVudHJpZXMpOyBvdXIgcGlkIGNoYWluOiAke1suLi5hbmNlc3RvclBpZHNdLmpvaW4oXCIgLT4gXCIpfWApO1xuICAgIH1cbiAgICBhd2FpdCByZWNvbXB1dGUoKTtcbiAgICBsZXQgcG9sbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgdm9pZCByZWNvbXB1dGUoKS5jYXRjaCgoZTogRXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoYERlcGxveSB0YWtlb3ZlciByZWNvbXB1dGUgZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgfSwgVElNRUxJTkVfUE9MTF9JTlRFUlZBTCk7XG4gICAgKHBvbGwgYXMgeyB1bnJlZj86ICgpID0+IHZvaWQgfSkudW5yZWY/LigpO1xufVxuXG4vKiogQ2FsbGVkIHdoZW4gd2UgaGFkIHRvIGxpc3RlbiBvbiBhbiBhbHRlcm5hdGUgcG9ydCAodGhlIG1haW4gcG9ydCB3YXMgc3RpbGwgaGVsZCBieSBvdXJcbiAqICBwcmVkZWNlc3Nvcik6IHJlZ2lzdGVycyBpdCBzbyB0aGUgcHJlZGVjZXNzb3IgY2FuIHJvdXRlIHRoZSBtaWRkbGUgb3ZlcmxhcCB3aW5kb3cgdG8gdXMuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVnaXN0ZXJBbHRQb3J0KHBvcnQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIG91ckFsdFBvcnQgPSBwb3J0O1xuICAgIGxldCBmb2xkZXIgPSBnZXRSZWdpc3RyeUZvbGRlcigpO1xuICAgIGF3YWl0IGZzLnByb21pc2VzLm1rZGlyKGZvbGRlciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgbGV0IGVudHJ5OiBSZWdpc3RyeUVudHJ5ID0geyBwaWQ6IHByb2Nlc3MucGlkLCBwb3J0LCBhbmNlc3RvclBpZHM6IFsuLi5hbmNlc3RvclBpZHNdIH07XG4gICAgYXdhaXQgZnMucHJvbWlzZXMud3JpdGVGaWxlKHBhdGguam9pbihmb2xkZXIsIGAke3Byb2Nlc3MucGlkfS5qc29uYCksIEpTT04uc3RyaW5naWZ5KGVudHJ5KSk7XG4gICAgYXdhaXQgcmVjb21wdXRlKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblRha2VvdmVyRXZlbnQobGlzdGVuZXI6IChldmVudDogVGFrZW92ZXJFdmVudCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIGV2ZW50TGlzdGVuZXJzLnB1c2gobGlzdGVuZXIpO1xufVxuXG4vKiogVGhlIGludGVycHJldGF0aW9uIG92ZXJsYXk6IHNwbGl0cyBldmVyeSBzb3VyY2UgcG9pbnRpbmcgYXQgb3VyIGRvbWFpbittYWluIHBvcnQgc28gdGhlIG1pZGRsZVxuICogIG9mIHRoZSBkZXBsb3kgb3ZlcmxhcCBwb2ludHMgYXQgdGhlIGFsdGVybmF0ZSBwb3J0LiBQdXJlLCBpbi1tZW1vcnkgb25seSAtIHRoZSBzdG9yZWQgcm91dGluZ1xuICogIGNvbmZpZyBpcyBuZXZlciBtb2RpZmllZCwgYW5kIHRoaXMgbXVzdCBuZXZlciBiZSBhcHBsaWVkIHRvIGRhdGEgdGhhdCBnZXRzIHBlcnNpc3RlZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseURlcGxveVJlbWFwKHJvdXRpbmc6IFJlbW90ZUNvbmZpZyk6IFJlbW90ZUNvbmZpZyB7XG4gICAgbGV0IHJlbWFwID0gY3VycmVudC5yZW1hcDtcbiAgICBsZXQgaW5pdCA9IGluaXRpYWxpemVkO1xuICAgIGlmICghcmVtYXAgfHwgIWluaXQpIHJldHVybiByb3V0aW5nO1xuICAgIGxldCBzb3VyY2VzOiBSZW1vdGVDb25maWdCYXNlW10gPSBbXTtcbiAgICBsZXQgc2xpY2UgPSAoc291cmNlOiBIb3N0ZWRDb25maWcsIHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyLCB1cmw/OiBzdHJpbmcpOiBIb3N0ZWRDb25maWcgPT4ge1xuICAgICAgICByZXR1cm4geyAuLi5zb3VyY2UsIHVybDogdXJsIHx8IHNvdXJjZS51cmwsIHZhbGlkV2luZG93OiBbc3RhcnQsIGVuZF0gfTtcbiAgICB9O1xuICAgIGZvciAobGV0IHNvdXJjZSBvZiByb3V0aW5nLnNvdXJjZXMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2UgPT09IFwic3RyaW5nXCIgfHwgc291cmNlLnR5cGUgIT09IFwicmVtb3RlXCIpIHtcbiAgICAgICAgICAgIHNvdXJjZXMucHVzaChzb3VyY2UpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHBhcnNlZDogeyBhZGRyZXNzOiBzdHJpbmc7IHBvcnQ6IG51bWJlciB9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcGFyc2VkID0gcGFyc2VIb3N0ZWRVcmwoc291cmNlLnVybCk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgc291cmNlcy5wdXNoKHNvdXJjZSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyc2VkLmFkZHJlc3MgIT09IGluaXQuZG9tYWluIHx8IHBhcnNlZC5wb3J0ICE9PSBpbml0Lm1haW5Qb3J0KSB7XG4gICAgICAgICAgICBzb3VyY2VzLnB1c2goc291cmNlKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGxldCBbc3RhcnQsIGVuZF0gPSBzb3VyY2UudmFsaWRXaW5kb3c7XG4gICAgICAgIGxldCBhID0gTWF0aC5tYXgoc3RhcnQsIE1hdGgubWluKHJlbWFwLmJvdW5kYXJ5QSwgZW5kKSk7XG4gICAgICAgIGxldCBiID0gTWF0aC5tYXgoc3RhcnQsIE1hdGgubWluKHJlbWFwLmJvdW5kYXJ5QiwgZW5kKSk7XG4gICAgICAgIGxldCBhZGRlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoYSA+IHN0YXJ0KSB7XG4gICAgICAgICAgICBzb3VyY2VzLnB1c2goc2xpY2Uoc291cmNlLCBzdGFydCwgYSkpO1xuICAgICAgICAgICAgYWRkZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChiID4gYSkge1xuICAgICAgICAgICAgc291cmNlcy5wdXNoKHNsaWNlKHNvdXJjZSwgYSwgYiwgcmVwbGFjZUhvc3RlZFVybFBvcnQoc291cmNlLnVybCwgcmVtYXAuYWx0UG9ydCkpKTtcbiAgICAgICAgICAgIGFkZGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW5kID4gYikge1xuICAgICAgICAgICAgc291cmNlcy5wdXNoKHNsaWNlKHNvdXJjZSwgYiwgZW5kKSk7XG4gICAgICAgICAgICBhZGRlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFhZGRlZCkge1xuICAgICAgICAgICAgc291cmNlcy5wdXNoKHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgdmVyc2lvbjogcm91dGluZy52ZXJzaW9uLCBzb3VyY2VzIH07XG59XG5cbi8qKiBBIHN0YW1wIG9mIHRoZSBjdXJyZW50IHJlbWFwIGludGVycHJldGF0aW9uLCBhZHZlcnRpc2VkIGluIHBpbmcgcmVzcG9uc2VzIC0gc28gZXZlcnkgY29ubmVjdGVkXG4gKiAgY2xpZW50IGxlYXJucyBvZiBhIHRha2VvdmVyIHdpdGhpbiBvbmUgcGluZyBpbnRlcnZhbCwgaW5zdGVhZCBvZiB3YWl0aW5nIGZvciBpdHMgY29uZmlnIHBvbGxcbiAqICBvciBhIHdyaXRlIHJlamVjdGlvbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUYWtlb3ZlclN0YW1wKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgbGV0IHJlbWFwID0gY3VycmVudC5yZW1hcDtcbiAgICBpZiAoIXJlbWFwKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShyZW1hcCk7XG59XG5cbi8qKiBUaGUgbWlkZGxlLXdpbmRvdyBhbHRlcm5hdGUgcG9ydCBvZiBhbiBhY3RpdmUgcmVtYXAuIFRoZSBPVEhFUiBwcm9jZXNzIG9mIHRoZSB0YWtlb3ZlciBsaXZlcyBvblxuICogIHRoaXMgcG9ydCBvbiBPVVIgbWFjaGluZSAoc2FtZSBkaXNrISksIHNvIHNvdXJjZXMgcG9pbnRpbmcgYXQgaXQgYXJlIHNlbGYsIG5ldmVyIHN5bmMgdGFyZ2V0cy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUYWtlb3ZlckFsdFBvcnQoKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gY3VycmVudC5yZW1hcD8uYWx0UG9ydDtcbn1cblxuLyoqIEZvciB0aGUgZHlpbmcgcHJvY2VzcyBvZiBhIHRha2VvdmVyOiBvdXIgb3duIHByb2Nlc3MncyBkYXRhIGVuZHMgYXQgdGhlIHdyaXRlIGhhbmRvZmYgLSBmYXN0XG4gKiAgd3JpdGVzIG11c3QgYmUgb24gZGlzayBieSB0aGVuLiBVbmRlZmluZWQgZm9yIHRoZSBzdWNjZXNzb3IgYW5kIGluIG5vcm1hbCBvcGVyYXRpb24uIEJvdGhcbiAqICBwcm9jZXNzZXMgc2hhcmUgdGhlIGNvbmZpZyBpZGVudGl0eSAoYWxsIHNlbGYgd2luZG93cyBsb29rIGxpa2UgXCJvdXJzXCIgdG8gYm90aCksIHNvIHRoaXMgaXNcbiAqICB0aGUgb25seSB3YXkgdGhlIGR5aW5nIHNpZGUga25vd3MgdGhlIHBvc3QtaGFuZG9mZiB3aW5kb3dzIGJlbG9uZyB0byB0aGUgb3RoZXIgcHJvY2Vzcy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRPd25XaW5kb3dFbmRDbGlwKCk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgbGV0IGR5aW5nID0gY3VycmVudC5keWluZztcbiAgICBpZiAoIWR5aW5nKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGxldCByZW1hcCA9IGN1cnJlbnQucmVtYXA7XG4gICAgaWYgKHJlbWFwKSByZXR1cm4gcmVtYXAuYm91bmRhcnlBO1xuICAgIHJldHVybiBkeWluZy5zdWNjZXNzb3JTdGFydDtcbn1cblxuLyoqIEhvdyBsb25nIHRvIHdhaXQgYmV0d2VlbiBtYWluLXBvcnQgYWNxdWlzaXRpb24gYXR0ZW1wdHM6IHRpZ2h0IGFyb3VuZCB0aGUgcHJlZGVjZXNzb3Inc1xuICogIHNjaGVkdWxlZCBkZWF0aCAod2hlbiB0aGUgcG9ydCBhY3R1YWxseSBmcmVlcyksIHJlbGF4ZWQgb3RoZXJ3aXNlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1haW5Qb3J0QWNxdWlyZURlbGF5KCk6IG51bWJlciB7XG4gICAgbGV0IGVuZCA9IGN1cnJlbnQucHJlZGVjZXNzb3JFbmQ7XG4gICAgaWYgKGVuZCAhPT0gdW5kZWZpbmVkICYmIE1hdGguYWJzKERhdGUubm93KCkgLSBlbmQpIDw9IEFDUVVJUkVfRkFTVF9XSU5ET1cpIHtcbiAgICAgICAgcmV0dXJuIEFDUVVJUkVfRkFTVF9ERUxBWTtcbiAgICB9XG4gICAgcmV0dXJuIEFDUVVJUkVfU0xPV19ERUxBWTtcbn1cbiJdfQ==
|
|
433
|
-
/* _JS_SOURCE_HASH = "
|
|
126
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95VGFrZW92ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkZXBsb3lUYWtlb3Zlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw0Q0FBb0I7QUFDcEIsZ0RBQXdCO0FBQ3hCLDZEQUFvRTtBQUVwRSxNQUFNLDhCQUE4QixHQUFHLDBCQUEwQixDQUFDO0FBQ2xFLE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztBQUMzQyxNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLDJCQUEyQixHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQ2xELE1BQU0sZUFBZSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQ3ZDLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUNyQyxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQztBQUNoQyxNQUFNLG1CQUFtQixHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFZdEMsSUFBSSxRQUFvQyxDQUFDO0FBRXpDLFNBQVMsR0FBRyxDQUFDLElBQVk7SUFDckIsT0FBTyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztBQUN4QyxDQUFDO0FBRUQsU0FBUyxTQUFTO0lBQ2QsT0FBTyxRQUFRLE9BQU8sQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUNsQyxDQUFDO0FBRUQsU0FBUyxpQkFBaUI7SUFDdEIsT0FBTyxjQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0FBQ25FLENBQUM7QUFFRCxLQUFLLFVBQVUsbUJBQW1COztJQUM5QixJQUFJLE1BQU0sR0FBRyxpQkFBaUIsRUFBRSxDQUFDO0lBQ2pDLElBQUksS0FBZSxDQUFDO0lBQ3BCLElBQUksQ0FB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O0lBQ3hCLE9BQU8sUUFBUSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDO0FBQ3ZELENBQUM7QUFFRCx5SkFBeUo7QUFDekosU0FBZ0IsbUJBQW1CO0lBQy9CLElBQUksQ0FBQyxRQUFRO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDeEIsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDLFdBQVcsR0FBRyxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxlQUFlLENBQUMsQ0FBQztBQUM3RyxDQUFDO0FBSEQsa0RBR0M7QUFFRCxpS0FBaUs7QUFDakssU0FBZ0IsdUJBQXVCO0lBQ25DLElBQUksQ0FBQyxRQUFRO1FBQUUsT0FBTyxrQkFBa0IsQ0FBQztJQUN6QyxJQUFJLGNBQWMsR0FBRyxRQUFRLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUM7SUFDakUsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksY0FBYyxHQUFHLG1CQUFtQixFQUFFLENBQUM7UUFDckQsT0FBTyxrQkFBa0IsQ0FBQztJQUM5QixDQUFDO0lBQ0QsT0FBTyxrQkFBa0IsQ0FBQztBQUM5QixDQUFDO0FBUEQsMERBT0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgc3RhcnRJbnRlcm1lZGlhdGVNYWludGVuYW5jZSB9IGZyb20gXCIuL3N0b3JhZ2VTZXJ2ZXJTdGF0ZVwiO1xuXG5jb25zdCBQQVJBTUVURVJTX1RJTUVMSU5FX0ZJTEVfUkVHRVggPSAvXihcXGQrKS1wYXJhbWV0ZXJzXFwuanNvbiQvO1xuY29uc3QgREVQTE9ZX0RFVEVDVF9SRVRSWV9ERUxBWSA9IDUgKiAxMDAwO1xuY29uc3QgREVQTE9ZX0RFVEVDVF9BVFRFTVBUUyA9IDY7XG5jb25zdCBERVBMT1lfUkVMRUFTRV9NQVRDSF9XSU5ET1cgPSA1ICogNjAgKiAxMDAwO1xuY29uc3QgQUxUX1BPUlRfTElOR0VSID0gMzAgKiA2MCAqIDEwMDA7XG5jb25zdCBBQ1FVSVJFX1NMT1dfREVMQVkgPSAzMCAqIDEwMDA7XG5jb25zdCBBQ1FVSVJFX0ZBU1RfREVMQVkgPSAxMDAwO1xuY29uc3QgQUNRVUlSRV9GQVNUX1dJTkRPVyA9IDYwICogMTAwMDtcblxudHlwZSBUaW1lbGluZUVudHJ5ID0ge1xuICAgIHBhcmFtZXRlcnM6IHsgcmVsZWFzZVRpbWU/OiBudW1iZXI7IG92ZXJsYXBUaW1lPzogbnVtYmVyIH07XG59O1xuXG50eXBlIERlcGxveVRha2VvdmVyID0ge1xuICAgIHJlbGVhc2VUaW1lOiBudW1iZXI7XG4gICAgb3ZlcmxhcFRpbWU6IG51bWJlcjtcbiAgICBhbHRQb3J0PzogbnVtYmVyO1xufTtcblxubGV0IHRha2VvdmVyOiBEZXBsb3lUYWtlb3ZlciB8IHVuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNvKHRpbWU6IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHRpbWUpLnRvSVNPU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIGxvZ1ByZWZpeCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgW3BpZCAke3Byb2Nlc3MucGlkfV1gO1xufVxuXG5mdW5jdGlvbiBnZXRUaW1lbGluZUZvbGRlcigpOiBzdHJpbmcge1xuICAgIHJldHVybiBwYXRoLmRpcm5hbWUocHJvY2Vzcy5jd2QoKSkucmVwbGFjZUFsbChcIlxcXFxcIiwgXCIvXCIpICsgXCIvXCI7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRUaW1lbGluZUVudHJpZXMoKTogUHJvbWlzZTxUaW1lbGluZUVudHJ5W10+IHtcbiAgICBsZXQgZm9sZGVyID0gZ2V0VGltZWxpbmVGb2xkZXIoKTtcbiAgICBsZXQgZmlsZXM6IHN0cmluZ1tdO1xuICAgIHRyeSB7XG4gICAgICAgIGZpbGVzID0gYXdhaXQgZnMucHJvbWlzZXMucmVhZGRpcihmb2xkZXIpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGAke2xvZ1ByZWZpeCgpfSBDb3VsZCBub3QgcmVhZCB0aGUgZGVwbG95IHRpbWVsaW5lIGZvbGRlciAke2ZvbGRlcn06ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgbGV0IGVudHJpZXM6IFRpbWVsaW5lRW50cnlbXSA9IFtdO1xuICAgIGZvciAobGV0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgaWYgKCFQQVJBTUVURVJTX1RJTUVMSU5FX0ZJTEVfUkVHRVgudGVzdChmaWxlKSkgY29udGludWU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBlbnRyaWVzLnB1c2goSlNPTi5wYXJzZShhd2FpdCBmcy5wcm9taXNlcy5yZWFkRmlsZShmb2xkZXIgKyBmaWxlLCBcInV0ZjhcIikpIGFzIFRpbWVsaW5lRW50cnkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYCR7bG9nUHJlZml4KCl9IENvdWxkIG5vdCByZWFkIGRlcGxveSB0aW1lbGluZSBmaWxlICR7Zm9sZGVyICsgZmlsZX06ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGVudHJpZXM7XG59XG5cbmZ1bmN0aW9uIGZpbmRPdXJSZWxlYXNlKGVudHJpZXM6IFRpbWVsaW5lRW50cnlbXSwgbm93OiBudW1iZXIpOiBEZXBsb3lUYWtlb3ZlciB8IHVuZGVmaW5lZCB7XG4gICAgbGV0IGJlc3Q6IERlcGxveVRha2VvdmVyIHwgdW5kZWZpbmVkO1xuICAgIGZvciAobGV0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgICAgbGV0IHJlbGVhc2VUaW1lID0gZW50cnkucGFyYW1ldGVycy5yZWxlYXNlVGltZTtcbiAgICAgICAgaWYgKHJlbGVhc2VUaW1lID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgICAgICBsZXQgb3ZlcmxhcFRpbWUgPSBlbnRyeS5wYXJhbWV0ZXJzLm92ZXJsYXBUaW1lIHx8IDA7XG4gICAgICAgIGlmIChyZWxlYXNlVGltZSA+IG5vdyArIERFUExPWV9SRUxFQVNFX01BVENIX1dJTkRPVykgY29udGludWU7XG4gICAgICAgIGlmIChub3cgPiByZWxlYXNlVGltZSArIG92ZXJsYXBUaW1lICsgREVQTE9ZX1JFTEVBU0VfTUFUQ0hfV0lORE9XKSBjb250aW51ZTtcbiAgICAgICAgaWYgKGJlc3QgJiYgYmVzdC5yZWxlYXNlVGltZSA+PSByZWxlYXNlVGltZSkgY29udGludWU7XG4gICAgICAgIGJlc3QgPSB7IHJlbGVhc2VUaW1lLCBvdmVybGFwVGltZSB9O1xuICAgIH1cbiAgICByZXR1cm4gYmVzdDtcbn1cblxuLyoqIENhbGxlZCB3aGVuIHRoZSBtYWluIHBvcnQgaXMgYWxyZWFkeSBpbiB1c2UsIHdoaWNoIG9uIGEgaGVhbHRoeSBtYWNoaW5lIG9ubHkgaGFwcGVucyB3aGlsZSBvdXIgcHJlZGVjZXNzb3IgaXMgc3RpbGwgcnVubmluZyBhIGRlcGxveSBvdmVybGFwLiBDb25maXJtcyB0aGF0IGFnYWluc3QgdGhlIGRlcGxveSB0aW1lbGluZTsgaWYgbm8gZGVwbG95IGlzIGluIHByb2dyZXNzIHdlIGFyZSBpbiBhIGJhZCBzdGF0ZSAoc29tZW9uZSBlbHNlIGhvbGRzIG91ciBwb3J0KSBhbmQgdGhlIHByb2Nlc3MgbXVzdCBub3Qga2VlcCBydW5uaW5nLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRldGVjdERlcGxveVRha2VvdmVyKCk6IFByb21pc2U8RGVwbG95VGFrZW92ZXI+IHtcbiAgICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSBERVBMT1lfREVURUNUX0FUVEVNUFRTOyBhdHRlbXB0KyspIHtcbiAgICAgICAgbGV0IGVudHJpZXMgPSBhd2FpdCByZWFkVGltZWxpbmVFbnRyaWVzKCk7XG4gICAgICAgIGxldCBmb3VuZCA9IGZpbmRPdXJSZWxlYXNlKGVudHJpZXMsIERhdGUubm93KCkpO1xuICAgICAgICBpZiAoZm91bmQpIHtcbiAgICAgICAgICAgIHRha2VvdmVyID0gZm91bmQ7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgJHtsb2dQcmVmaXgoKX0gT3VyIG1haW4gcG9ydCBpcyBpbiB1c2UgYW5kIHRoZSBkZXBsb3kgdGltZWxpbmUgY29uZmlybXMgYSByZWxlYXNlIGF0ICR7aXNvKGZvdW5kLnJlbGVhc2VUaW1lKX0gd2l0aCBhbiBvdmVybGFwIG9mICR7Zm91bmQub3ZlcmxhcFRpbWV9bXM6IHdlIGFyZSB0aGUgc3VjY2Vzc29yLiBPdXIgcHJlZGVjZXNzb3IgaXMga2lsbGVkIGF0ICR7aXNvKGZvdW5kLnJlbGVhc2VUaW1lICsgZm91bmQub3ZlcmxhcFRpbWUpfS5gKTtcbiAgICAgICAgICAgIHJldHVybiBmb3VuZDtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhgJHtsb2dQcmVmaXgoKX0gT3VyIG1haW4gcG9ydCBpcyBpbiB1c2UgYnV0IHRoZSBkZXBsb3kgdGltZWxpbmUgaW4gJHtnZXRUaW1lbGluZUZvbGRlcigpfSBzaG93cyBubyByZWxlYXNlIGluIHByb2dyZXNzIChhdHRlbXB0ICR7YXR0ZW1wdH0gb2YgJHtERVBMT1lfREVURUNUX0FUVEVNUFRTfSk7IHJldHJ5aW5nIGluICR7REVQTE9ZX0RFVEVDVF9SRVRSWV9ERUxBWX1tc2ApO1xuICAgICAgICBpZiAoYXR0ZW1wdCA8IERFUExPWV9ERVRFQ1RfQVRURU1QVFMpIHtcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBERVBMT1lfREVURUNUX1JFVFJZX0RFTEFZKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBPdXIgbWFpbiBwb3J0IGlzIGluIHVzZSwgYnV0IG5vIGRlcGxveSBpcyBpbiBwcm9ncmVzcyBhZnRlciAke0RFUExPWV9ERVRFQ1RfQVRURU1QVFMgKiBERVBMT1lfREVURUNUX1JFVFJZX0RFTEFZfW1zIG9mIGNoZWNraW5nIHRoZSBkZXBsb3kgdGltZWxpbmUgaW4gJHtnZXRUaW1lbGluZUZvbGRlcigpfS4gU29tZXRoaW5nIGVsc2UgaXMgaG9sZGluZyBvdXIgcG9ydCwgc28gdGhpcyBwcm9jZXNzIGlzIGluIGEgYmFkIHN0YXRlIGFuZCBpcyBleGl0aW5nLmApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0QWx0UG9ydChwb3J0OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIXRha2VvdmVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQW4gYWx0ZXJuYXRlIHBvcnQgKCR7cG9ydH0pIHdhcyB0YWtlbiB3aXRob3V0IGEgZGV0ZWN0ZWQgZGVwbG95IHRha2VvdmVyIC0gZGV0ZWN0RGVwbG95VGFrZW92ZXIgbXVzdCBydW4gZmlyc3RgKTtcbiAgICB9XG4gICAgdGFrZW92ZXIuYWx0UG9ydCA9IHBvcnQ7XG4gICAgY29uc29sZS5sb2coYCR7bG9nUHJlZml4KCl9IExpc3RlbmluZyBvbiBhbHRlcm5hdGUgcG9ydCAke3BvcnR9OiB3cml0ZXMgcm91dGUgaGVyZSB1bnRpbCAke2lzbyhnZXRJbnRlcm1lZGlhdGVFbmQoKSl9LCBhbmQgd2Uga2VlcCBsaXN0ZW5pbmcgdW50aWwgJHtpc28oZ2V0QWx0UG9ydExpc3RlbkVuZCgpKX1gKTtcbiAgICBzdGFydEludGVybWVkaWF0ZU1haW50ZW5hbmNlKCk7XG59XG5cbi8qKiBUaGUgd2luZG93IGluIHdoaWNoIHdyaXRlcyBiZWxvbmcgdG8gb3VyIGFsdGVybmF0ZSBwb3J0OiBmcm9tIHRoZSByZWxlYXNlIHVudGlsIG91ciBwcmVkZWNlc3NvciBpcyBraWxsZWQgYW5kIHdlIHRha2UgdGhlIG1haW4gcG9ydC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUYWtlb3ZlckludGVybWVkaWF0ZSgpOiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyOyBhbHRQb3J0OiBudW1iZXIgfSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF0YWtlb3Zlcj8uYWx0UG9ydCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4geyBzdGFydDogdGFrZW92ZXIucmVsZWFzZVRpbWUsIGVuZDogZ2V0SW50ZXJtZWRpYXRlRW5kKCksIGFsdFBvcnQ6IHRha2VvdmVyLmFsdFBvcnQgfTtcbn1cblxuZnVuY3Rpb24gZ2V0SW50ZXJtZWRpYXRlRW5kKCk6IG51bWJlciB7XG4gICAgaWYgKCF0YWtlb3ZlcikgcmV0dXJuIDA7XG4gICAgcmV0dXJuIHRha2VvdmVyLnJlbGVhc2VUaW1lICsgdGFrZW92ZXIub3ZlcmxhcFRpbWU7XG59XG5cbi8qKiBXZSBuZXZlciBzdG9wIGxpc3RlbmluZyBvbiB0aGUgYWx0ZXJuYXRlIHBvcnQgd2hpbGUgaXRzIHdpbmRvdyBpcyBzdGlsbCB2YWxpZCwgYW5kIGhvbGQgaXQgd2VsbCBwYXN0IHRoYXQgZm9yIGNsaWVudHMgdGhhdCBoYXZlIG5vdCBjYXVnaHQgdXAgeWV0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFsdFBvcnRMaXN0ZW5FbmQoKTogbnVtYmVyIHtcbiAgICBpZiAoIXRha2VvdmVyKSByZXR1cm4gMDtcbiAgICByZXR1cm4gTWF0aC5tYXgodGFrZW92ZXIucmVsZWFzZVRpbWUgKyB0YWtlb3Zlci5vdmVybGFwVGltZSAqIDIsIGdldEludGVybWVkaWF0ZUVuZCgpICsgQUxUX1BPUlRfTElOR0VSKTtcbn1cblxuLyoqIEhvdyBsb25nIHRvIHdhaXQgYmV0d2VlbiBtYWluLXBvcnQgYWNxdWlzaXRpb24gYXR0ZW1wdHM6IHRpZ2h0IGFyb3VuZCBvdXIgcHJlZGVjZXNzb3IncyBzY2hlZHVsZWQgZGVhdGggKHdoZW4gdGhlIHBvcnQgYWN0dWFsbHkgZnJlZXMpLCByZWxheGVkIG90aGVyd2lzZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNYWluUG9ydEFjcXVpcmVEZWxheSgpOiBudW1iZXIge1xuICAgIGlmICghdGFrZW92ZXIpIHJldHVybiBBQ1FVSVJFX1NMT1dfREVMQVk7XG4gICAgbGV0IHByZWRlY2Vzc29yRW5kID0gdGFrZW92ZXIucmVsZWFzZVRpbWUgKyB0YWtlb3Zlci5vdmVybGFwVGltZTtcbiAgICBpZiAoRGF0ZS5ub3coKSA+PSBwcmVkZWNlc3NvckVuZCAtIEFDUVVJUkVfRkFTVF9XSU5ET1cpIHtcbiAgICAgICAgcmV0dXJuIEFDUVVJUkVfRkFTVF9ERUxBWTtcbiAgICB9XG4gICAgcmV0dXJuIEFDUVVJUkVfU0xPV19ERUxBWTtcbn1cbiJdfQ==
|
|
127
|
+
/* _JS_SOURCE_HASH = "fcfb2e0742a63c40c3c42d422e2047ade99ef700563ad8c3e97915a2ee9eff92"; */
|