sliftutils 1.7.96 → 1.7.97

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "1.7.96",
3
+ "version": "1.7.97",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -404,9 +404,7 @@ export class ArchivesChain implements IArchives {
404
404
  })();
405
405
  if ("values" in outcome) return outcome.values;
406
406
  let error = outcome.error;
407
- if (Date.now() >= deadline) {
408
- throw error;
409
- }
407
+ // Substitution comes BEFORE the deadline check: a single connect timeout can eat the entire deadline, and giving up then - without ever trying the substitute that fallbacks exist for - throws exactly when falling back matters most. Substitution cannot loop past the deadline forever: every pass adds its failures to `failed`, so the substitutes run out with the sources.
410
408
  if (config?.fallbacks && failed.size) {
411
409
  let substitutable = false;
412
410
  try {
@@ -420,6 +418,9 @@ export class ArchivesChain implements IArchives {
420
418
  // No substitute covers the failed routes - retry the failed sources themselves after the delay
421
419
  failed.clear();
422
420
  }
421
+ if (Date.now() >= deadline) {
422
+ throw error;
423
+ }
423
424
  console.error(`${error.message}. Retrying in ${COVERING_RETRY_DELAY / 1000}s (giving up at ${new Date(deadline).toISOString()}).`);
424
425
  void this.state.recheckAvailability();
425
426
  await delay(COVERING_RETRY_DELAY);
@@ -0,0 +1,466 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.RoutingRewriteLoop = exports.writeRoutingToAllStores = exports.chooseStartupConfig = exports.disposeProbes = exports.probeSources = exports.ChainStateManager = exports.CONFIG_WRITE_REFRESH_INTERVAL = exports.CONFIG_WRITE_RETRY_INTERVAL = void 0;
4
+ const misc_1 = require("socket-function/src/misc");
5
+ const remoteConfig_1 = require("./remoteConfig");
6
+ const sourceWrapper_1 = require("./sourceWrapper");
7
+ const intermediateSources_1 = require("./intermediateSources");
8
+ const storageClientController_1 = require("./storageClientController");
9
+ // The LIFECYCLE of an ArchivesChain's state, and nothing else: initializing it (probing every configured source, deciding which routing config to run, writing ours out when it is the newest), the retry when initialization fails, the poll that adopts newer configs, the availability recheck, and the loop that keeps re-writing our config. None of this is request dispatch - the chain (createArchives.ts) asks the ChainStateManager for the current state and dispatches over it.
10
+ const CONFIG_POLL_INTERVAL = 5 * 60 * 1000;
11
+ const AVAILABILITY_RECHECK_THROTTLE = 5 * 1000;
12
+ // The routing config write is retried on this cadence while it is failing. A store that never received the config rejects every write aimed at it, so this not landing is a big deal - each failed attempt is logged.
13
+ exports.CONFIG_WRITE_RETRY_INTERVAL = 5 * 60 * 1000;
14
+ // ...and even after success it is re-written on this cadence, in case a store lost it or a server appeared late
15
+ exports.CONFIG_WRITE_REFRESH_INTERVAL = 60 * 60 * 1000;
16
+ /** The chain's state and everything about HAVING one: init (with its retry), the config poll, availability rechecks, and the routing rewrite loop. The chain constructs one, asks it getState() on every call, and disposes it. */
17
+ class ChainStateManager {
18
+ constructor(config) {
19
+ this.config = config;
20
+ this.initRetryDelay = sourceWrapper_1.RETRY_START_DELAY;
21
+ this.disposed = false;
22
+ this.lastAvailabilityRecheck = 0;
23
+ this.configured = config.configured;
24
+ this.activeConfig = config.configured;
25
+ this.routingRewriter = new RoutingRewriteLoop({
26
+ configured: config.configured,
27
+ debugName: config.debugName,
28
+ latest: () => this.latestState,
29
+ });
30
+ this.unsubscribeRoutingPush = (0, storageClientController_1.onServerRoutingChanged)(() => {
31
+ void this.refreshActiveConfig().catch((e) => { var _a; return console.error(`Config refresh failed for ${this.config.debugName()}: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
32
+ });
33
+ }
34
+ /** The newest adopted state, synchronously - undefined until the first init finishes. */
35
+ latest() {
36
+ return this.latestState;
37
+ }
38
+ getState() {
39
+ if (this.disposed) {
40
+ return Promise.reject(new Error(`ArchivesChain ${this.config.debugName()} has been disposed`));
41
+ }
42
+ if (!this.statePromise) {
43
+ let promise = this.init();
44
+ this.statePromise = promise;
45
+ promise.then(() => {
46
+ this.initRetryDelay = sourceWrapper_1.RETRY_START_DELAY;
47
+ }, (e) => {
48
+ var _a, _b, _c;
49
+ if (this.disposed || this.initRetryTimer)
50
+ return;
51
+ console.error(`Storage init failed for ${this.config.debugName()}, retrying in ${Math.round(this.initRetryDelay / 1000)}s. ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
52
+ this.initRetryTimer = setTimeout(() => {
53
+ this.initRetryTimer = undefined;
54
+ if (this.disposed)
55
+ return;
56
+ if (this.statePromise === promise) {
57
+ this.statePromise = undefined;
58
+ }
59
+ this.getState().catch(() => { });
60
+ }, this.initRetryDelay);
61
+ (_c = (_b = this.initRetryTimer).unref) === null || _c === void 0 ? void 0 : _c.call(_b);
62
+ this.initRetryDelay = Math.min(sourceWrapper_1.RETRY_MAX_DELAY, this.initRetryDelay * sourceWrapper_1.RETRY_GROWTH);
63
+ });
64
+ }
65
+ return this.statePromise;
66
+ }
67
+ async init() {
68
+ let configs = this.configured.sources.map(remoteConfig_1.normalizeSource);
69
+ let readOnly = this.isReadOnly(this.configured);
70
+ let probes = await probeSources(configs, readOnly);
71
+ try {
72
+ let { active, needsWrite, existing } = chooseStartupConfig({ configured: this.configured, probes, debugName: this.config.debugName() });
73
+ let sources = await this.buildSources(active);
74
+ let configWriteFailed = false;
75
+ if (needsWrite) {
76
+ console.log(`Storage routing config for ${this.config.debugName()} is out of date (stored version ${existing && (0, remoteConfig_1.getConfigVersion)(existing) || "none"}, ours ${(0, remoteConfig_1.getConfigVersion)(this.configured)})`);
77
+ let { failures, total } = await writeRoutingToAllStores({ configured: this.configured, sources, debugName: this.config.debugName() });
78
+ configWriteFailed = failures.length > 0;
79
+ if (failures.length && failures.length === total) {
80
+ // Nobody has our config, so running on it would just disagree with every server. The stored one (when there is one) is what the servers actually run.
81
+ console.error(`The storage routing config for ${this.config.debugName()} (version ${(0, remoteConfig_1.getConfigVersion)(this.configured)}) could not be written to ANY of the ${total} stores. ${existing && `Running on the stored config (version ${(0, remoteConfig_1.getConfigVersion)(existing)}) until a write succeeds.` || `No stored config exists either, so servers will reject writes until this succeeds.`} Retrying in ${exports.CONFIG_WRITE_RETRY_INTERVAL / 1000}s. Failures: ${failures.join(" | ")}`);
82
+ if (existing) {
83
+ active = existing;
84
+ for (let source of sources) {
85
+ source.dispose();
86
+ }
87
+ sources = await this.buildSources(active);
88
+ }
89
+ }
90
+ else if (failures.length) {
91
+ console.error(`The storage routing config for ${this.config.debugName()} (version ${(0, remoteConfig_1.getConfigVersion)(this.configured)}) was written to ${total - failures.length} of ${total} stores. Retrying the rest in ${exports.CONFIG_WRITE_RETRY_INTERVAL / 1000}s (they also pull it from the stores that have it). Failures: ${failures.join(" | ")}`);
92
+ }
93
+ }
94
+ for (let source of sources) {
95
+ let probe = probes.find(x => x.responded && x.sourceConfig.url === source.config.url);
96
+ if (probe) {
97
+ source.seedLatency(probe.latency);
98
+ }
99
+ }
100
+ this.activeConfig = active;
101
+ this.startConfigPoll();
102
+ let state = { config: active, sources };
103
+ this.latestState = state;
104
+ this.routingRewriter.start(configWriteFailed);
105
+ return state;
106
+ }
107
+ finally {
108
+ disposeProbes(probes);
109
+ }
110
+ }
111
+ /** Clientside, a config with public sources is served entirely over plain URL downloads - no API connection, no access grant, and no writing. directConnect opts out of that. */
112
+ isReadOnly(config) {
113
+ if (this.config.directConnect || (0, misc_1.isNode)())
114
+ return false;
115
+ return config.sources.map(remoteConfig_1.normalizeSource).some(x => x.public);
116
+ }
117
+ async createChainSource(sourceConfig, readOnly) {
118
+ let source = await sourceWrapper_1.SourceWrapper.create(sourceConfig, { readOnly });
119
+ source.startPinging();
120
+ return source;
121
+ }
122
+ async buildSources(config) {
123
+ let readOnly = this.isReadOnly(config);
124
+ let sources = [];
125
+ for (let sourceConfig of config.sources.map(remoteConfig_1.normalizeSource)) {
126
+ sources.push(await this.createChainSource(sourceConfig, readOnly));
127
+ }
128
+ return sources;
129
+ }
130
+ startConfigPoll() {
131
+ var _a, _b;
132
+ if (this.pollTimer || this.disposed)
133
+ return;
134
+ this.pollTimer = setInterval(() => {
135
+ void this.refreshActiveConfig().catch((e) => {
136
+ var _a;
137
+ console.error(`Checking for a new storage routing config failed for ${this.config.debugName()}: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
138
+ });
139
+ }, CONFIG_POLL_INTERVAL);
140
+ (_b = (_a = this.pollTimer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
141
+ }
142
+ refreshActiveConfig() {
143
+ if (!this.configRefreshInFlight) {
144
+ this.configRefreshInFlight = this.checkForNewConfig().finally(() => {
145
+ this.configRefreshInFlight = undefined;
146
+ });
147
+ }
148
+ return this.configRefreshInFlight;
149
+ }
150
+ async fetchLatestConfig(state) {
151
+ var _a;
152
+ let errors = [];
153
+ for (let source of state.sources) {
154
+ try {
155
+ let latest = await source.readRoutingConfig();
156
+ if (latest)
157
+ return (0, remoteConfig_1.normalizeRemoteConfig)(latest);
158
+ }
159
+ catch (e) {
160
+ errors.push(`${source.config.url}: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
161
+ }
162
+ }
163
+ if (errors.length === state.sources.length) {
164
+ throw new Error(`No storage source could give us the routing config for ${this.config.debugName()}: ${errors.join(" | ")}`);
165
+ }
166
+ return undefined;
167
+ }
168
+ async checkForNewConfig() {
169
+ if (this.disposed || !this.statePromise)
170
+ return;
171
+ let state;
172
+ try {
173
+ state = await this.statePromise;
174
+ }
175
+ catch (_a) {
176
+ return;
177
+ }
178
+ let latest = await this.fetchLatestConfig(state);
179
+ if (!latest)
180
+ return;
181
+ await this.adoptNewConfig(state, latest);
182
+ }
183
+ async adoptNewConfig(state, latest) {
184
+ var _a;
185
+ if (JSON.stringify(latest) === JSON.stringify(state.config))
186
+ return;
187
+ let received = new Date().toISOString();
188
+ let onlyIntermediatesChanged = JSON.stringify((0, intermediateSources_1.resolveIntermediateSources)(latest)) === JSON.stringify((0, intermediateSources_1.resolveIntermediateSources)(state.config));
189
+ if (onlyIntermediatesChanged) {
190
+ console.log(`Storage routing switchover windows changed (version ${(0, remoteConfig_1.getConfigVersion)(state.config)} -> ${(0, remoteConfig_1.getConfigVersion)(latest)}), received ${received}, rebuilding sources. New config: ${JSON.stringify(latest)}`);
191
+ }
192
+ else {
193
+ console.log(`Storage routing config changed (version ${(0, remoteConfig_1.getConfigVersion)(state.config)} -> ${(0, remoteConfig_1.getConfigVersion)(latest)}), received ${received}, rebuilding sources. New config: ${JSON.stringify(latest)}`);
194
+ }
195
+ let strippedKey = (config) => JSON.stringify({ ...config, validWindow: undefined });
196
+ let oldByConfig = new Map();
197
+ for (let source of state.sources) {
198
+ let key = strippedKey(source.config);
199
+ let list = oldByConfig.get(key);
200
+ if (!list) {
201
+ list = [];
202
+ oldByConfig.set(key, list);
203
+ }
204
+ list.push(source);
205
+ }
206
+ let readOnly = this.isReadOnly(latest);
207
+ let sources = [];
208
+ for (let sourceConfig of latest.sources.map(remoteConfig_1.normalizeSource)) {
209
+ let old = (_a = oldByConfig.get(strippedKey(sourceConfig))) === null || _a === void 0 ? void 0 : _a.shift();
210
+ if (old) {
211
+ old.updateValidWindow(sourceConfig.validWindow);
212
+ sources.push(old);
213
+ }
214
+ else {
215
+ sources.push(await this.createChainSource(sourceConfig, readOnly));
216
+ }
217
+ }
218
+ for (let leftovers of oldByConfig.values()) {
219
+ for (let leftover of leftovers) {
220
+ leftover.dispose();
221
+ }
222
+ }
223
+ this.activeConfig = latest;
224
+ let newState = { config: latest, sources };
225
+ this.latestState = newState;
226
+ this.statePromise = Promise.resolve(newState);
227
+ }
228
+ /** Every source failed: re-contact all of them (routing re-read + connection re-attempt) and adopt whatever config comes back. Throttled, and deduplicated across concurrent callers. */
229
+ recheckAvailability() {
230
+ if (this.availabilityRecheckInFlight)
231
+ return this.availabilityRecheckInFlight;
232
+ if (Date.now() - this.lastAvailabilityRecheck < AVAILABILITY_RECHECK_THROTTLE)
233
+ return Promise.resolve();
234
+ this.lastAvailabilityRecheck = Date.now();
235
+ this.availabilityRecheckInFlight = this.recheckAvailabilityNow().finally(() => {
236
+ this.availabilityRecheckInFlight = undefined;
237
+ });
238
+ return this.availabilityRecheckInFlight;
239
+ }
240
+ async recheckAvailabilityNow() {
241
+ if (this.disposed || !this.statePromise)
242
+ return;
243
+ let state;
244
+ try {
245
+ state = await this.statePromise;
246
+ }
247
+ catch (_a) {
248
+ return;
249
+ }
250
+ console.log(`Every storage source failed for ${this.config.debugName()}; re-contacting all ${state.sources.length} sources (routing re-read + connection re-attempt)`);
251
+ let results = await Promise.all(state.sources.map(async (source) => {
252
+ try {
253
+ return await source.readRoutingConfig();
254
+ }
255
+ catch (_a) {
256
+ return undefined;
257
+ }
258
+ }));
259
+ let latest = results.find(x => x);
260
+ if (!latest)
261
+ return;
262
+ await this.adoptNewConfig(state, latest);
263
+ }
264
+ dispose() {
265
+ var _a;
266
+ this.disposed = true;
267
+ (_a = this.unsubscribeRoutingPush) === null || _a === void 0 ? void 0 : _a.call(this);
268
+ if (this.pollTimer) {
269
+ clearInterval(this.pollTimer);
270
+ }
271
+ if (this.initRetryTimer) {
272
+ clearTimeout(this.initRetryTimer);
273
+ }
274
+ this.routingRewriter.dispose();
275
+ let statePromise = this.statePromise;
276
+ if (statePromise) {
277
+ void statePromise.then(state => {
278
+ for (let source of state.sources) {
279
+ source.dispose();
280
+ }
281
+ }, () => { });
282
+ }
283
+ }
284
+ }
285
+ exports.ChainStateManager = ChainStateManager;
286
+ /** One throwaway SourceWrapper per configured source, each asked for its stored routing config - which also measures first-contact latency, seeded into the real sources afterwards. The probes MUST be disposed (disposeProbes) once the caller is done with them. */
287
+ async function probeSources(configs, readOnly) {
288
+ return await Promise.all(configs.map(async (sourceConfig) => {
289
+ var _a;
290
+ let probe = await sourceWrapper_1.SourceWrapper.create(sourceConfig, { background: false, readOnly });
291
+ let start = Date.now();
292
+ try {
293
+ let existing = await probe.readRoutingConfig();
294
+ return { probe, sourceConfig, responded: true, latency: Date.now() - start, existing, error: "" };
295
+ }
296
+ catch (e) {
297
+ return { probe, sourceConfig, responded: false, latency: 0, existing: undefined, error: `${sourceConfig.url}: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}` };
298
+ }
299
+ }));
300
+ }
301
+ exports.probeSources = probeSources;
302
+ function disposeProbes(probes) {
303
+ for (let probe of probes) {
304
+ probe.probe.dispose();
305
+ }
306
+ }
307
+ exports.disposeProbes = disposeProbes;
308
+ /**
309
+ * Which routing config the chain should RUN: the newest of ours and every stored one. needsWrite
310
+ * when ours is strictly the newest, meaning the stores have to be told about it. A stored config
311
+ * with our exact version but DIFFERENT content wins without a write, loudly: config updates must
312
+ * bump the version, or they are ignored - silently taking the changed one would make "what is the
313
+ * bucket running" depend on which process started last.
314
+ *
315
+ * Throws when no source answered at all: with nothing stored and nobody to write to, there is no
316
+ * config to run.
317
+ */
318
+ function chooseStartupConfig(config) {
319
+ let { configured, probes, debugName } = config;
320
+ let found = probes.find(x => x.responded);
321
+ if (!found) {
322
+ throw new Error(`Cannot initialize storage for ${debugName}: no source answered. ${probes.map(x => x.error).join(" | ")}`);
323
+ }
324
+ let existing = found.existing;
325
+ let active = configured;
326
+ let needsWrite = true;
327
+ if (existing && (0, remoteConfig_1.getConfigVersion)(existing) >= (0, remoteConfig_1.getConfigVersion)(configured)) {
328
+ if ((0, remoteConfig_1.getConfigVersion)(existing) === (0, remoteConfig_1.getConfigVersion)(configured) && JSON.stringify(existing) !== JSON.stringify(configured)) {
329
+ console.error(`Archives configuration updated without updating the version, for ${found.sourceConfig.url}. Updates will be ignored until you increase the version. Using: ${JSON.stringify(existing)}, ignoring: ${JSON.stringify(configured)}`);
330
+ }
331
+ active = existing;
332
+ needsWrite = false;
333
+ }
334
+ if (needsWrite) {
335
+ let best;
336
+ let conflictUrl;
337
+ for (let probe of probes) {
338
+ let stored = probe.existing;
339
+ if (!stored)
340
+ continue;
341
+ if (!best || (0, remoteConfig_1.getConfigVersion)(stored) > (0, remoteConfig_1.getConfigVersion)(best)) {
342
+ best = stored;
343
+ }
344
+ if ((0, remoteConfig_1.getConfigVersion)(stored) === (0, remoteConfig_1.getConfigVersion)(configured) && JSON.stringify(stored) !== JSON.stringify(configured)) {
345
+ conflictUrl = probe.sourceConfig.url;
346
+ }
347
+ }
348
+ if (best && (0, remoteConfig_1.getConfigVersion)(best) >= (0, remoteConfig_1.getConfigVersion)(configured)) {
349
+ if (conflictUrl && (0, remoteConfig_1.getConfigVersion)(best) === (0, remoteConfig_1.getConfigVersion)(configured)) {
350
+ console.error(`Archives configuration updated without updating the version, for ${conflictUrl}. Updates will be ignored until you increase the version. Using: ${JSON.stringify(best)}, ignoring: ${JSON.stringify(configured)}`);
351
+ }
352
+ active = best;
353
+ needsWrite = false;
354
+ }
355
+ }
356
+ return { active, needsWrite, existing };
357
+ }
358
+ exports.chooseStartupConfig = chooseStartupConfig;
359
+ /**
360
+ * Writes the given routing config to every configured store, one write per url+name: the write
361
+ * lands in the store the entry NAMES, so two entries sharing a URL but naming different stores are
362
+ * two separate deliveries - deduping by URL alone leaves the second store unconfigured forever. All
363
+ * in parallel, every failure tolerated (no-write-access included - the attempt classifies it,
364
+ * nothing pre-checks it): a down node must not stop the others from getting the config - they would
365
+ * then reject writes as unconfigured precisely BECAUSE it never arrived - and it must never stop
366
+ * the chain from starting. A store that missed it pulls it off its peers, and the rewrite loop
367
+ * tries again (see RoutingRewriteLoop).
368
+ */
369
+ async function writeRoutingToAllStores(config) {
370
+ let { configured, sources, debugName } = config;
371
+ let routingData = (0, remoteConfig_1.serializeRemoteConfig)(configured);
372
+ let routingWriteTime = Date.now();
373
+ let targets = [];
374
+ let seen = new Set();
375
+ for (let source of sources) {
376
+ let key = `${source.config.url}|${source.config.name}`;
377
+ if (seen.has(key))
378
+ continue;
379
+ seen.add(key);
380
+ targets.push(source);
381
+ }
382
+ console.log(`Writing routing config version ${(0, remoteConfig_1.getConfigVersion)(configured)} for ${debugName} to all ${targets.length} stores (write time ${new Date(routingWriteTime).toISOString()}): ${targets.map(x => `${x.config.url} (store ${JSON.stringify(x.config.name)})`).join(", ")}`);
383
+ let failures = [];
384
+ await Promise.all(targets.map(async (source) => {
385
+ var _a;
386
+ try {
387
+ await source.write(archives => archives.set(remoteConfig_1.ROUTING_FILE, routingData, { lastModified: routingWriteTime }));
388
+ console.log(`Wrote storage routing config version ${(0, remoteConfig_1.getConfigVersion)(configured)} to ${source.config.url} (store ${JSON.stringify(source.config.name)})`);
389
+ }
390
+ catch (e) {
391
+ failures.push(`${source.config.url} (store ${JSON.stringify(source.config.name)}): ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
392
+ }
393
+ }));
394
+ return { failures, total: targets.length };
395
+ }
396
+ exports.writeRoutingToAllStores = writeRoutingToAllStores;
397
+ /**
398
+ * The periodic re-write of the chain's in-code config: failures retried on the short interval - a
399
+ * store without the config rejects every write aimed at it, so this not landing is a big deal,
400
+ * logged on every attempt - and even success repeated hourly, in case a store lost it. The failure
401
+ * this exists for: a server whose trust was only granted AFTER startup, so the startup write was
402
+ * rejected and nothing else would ever retry it.
403
+ */
404
+ class RoutingRewriteLoop {
405
+ constructor(config) {
406
+ this.config = config;
407
+ this.disposed = false;
408
+ }
409
+ /** (Re)arms the loop - called at the end of every init, with whether that init's write failed (which picks the short retry interval). */
410
+ start(failedAtStartup) {
411
+ this.schedule(failedAtStartup && exports.CONFIG_WRITE_RETRY_INTERVAL || exports.CONFIG_WRITE_REFRESH_INTERVAL);
412
+ }
413
+ dispose() {
414
+ this.disposed = true;
415
+ if (this.timer) {
416
+ clearTimeout(this.timer);
417
+ }
418
+ }
419
+ schedule(delay) {
420
+ var _a, _b;
421
+ if (this.disposed)
422
+ return;
423
+ if (this.timer) {
424
+ clearTimeout(this.timer);
425
+ }
426
+ this.timer = setTimeout(() => {
427
+ this.timer = undefined;
428
+ void this.rewrite().catch((e) => {
429
+ var _a;
430
+ console.error(`Rewriting the storage routing config for ${this.config.debugName()} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
431
+ this.schedule(exports.CONFIG_WRITE_RETRY_INTERVAL);
432
+ });
433
+ }, delay);
434
+ (_b = (_a = this.timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
435
+ }
436
+ async rewrite() {
437
+ if (this.disposed)
438
+ return;
439
+ let configured = this.config.configured;
440
+ let state = this.config.latest();
441
+ if (!state) {
442
+ this.schedule(exports.CONFIG_WRITE_RETRY_INTERVAL);
443
+ return;
444
+ }
445
+ // The bucket adopted a NEWER config than our in-code one, so ours is stale and every store would (rightly) refuse it
446
+ if ((0, remoteConfig_1.getConfigVersion)(state.config) > (0, remoteConfig_1.getConfigVersion)(configured)) {
447
+ this.schedule(exports.CONFIG_WRITE_REFRESH_INTERVAL);
448
+ return;
449
+ }
450
+ // Same version but different content: startup already decided the stored one wins until the version is bumped (see chooseStartupConfig), and re-writing ours would flip the bucket back and forth between the two
451
+ if ((0, remoteConfig_1.getConfigVersion)(state.config) === (0, remoteConfig_1.getConfigVersion)(configured) && JSON.stringify(state.config) !== JSON.stringify(configured)) {
452
+ this.schedule(exports.CONFIG_WRITE_REFRESH_INTERVAL);
453
+ return;
454
+ }
455
+ let { failures, total } = await writeRoutingToAllStores({ configured, sources: state.sources, debugName: this.config.debugName() });
456
+ if (failures.length) {
457
+ console.error(`The periodic routing config write for ${this.config.debugName()} (version ${(0, remoteConfig_1.getConfigVersion)(configured)}) failed on ${failures.length} of ${total} stores - retrying in ${exports.CONFIG_WRITE_RETRY_INTERVAL / 1000}s: ${failures.join(" | ")}`);
458
+ this.schedule(exports.CONFIG_WRITE_RETRY_INTERVAL);
459
+ return;
460
+ }
461
+ this.schedule(exports.CONFIG_WRITE_REFRESH_INTERVAL);
462
+ }
463
+ }
464
+ exports.RoutingRewriteLoop = RoutingRewriteLoop;
465
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhaW5TdGFydHVwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2hhaW5TdGFydHVwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1EQUFrRDtBQUVsRCxpREFBK0g7QUFDL0gsbURBQWtHO0FBQ2xHLCtEQUFtRTtBQUNuRSx1RUFBbUU7QUFFbkUsNGRBQTRkO0FBRTVkLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDM0MsTUFBTSw2QkFBNkIsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO0FBQy9DLHNOQUFzTjtBQUN6TSxRQUFBLDJCQUEyQixHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQ3pELGdIQUFnSDtBQUNuRyxRQUFBLDZCQUE2QixHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBTzVELG1PQUFtTztBQUNuTyxNQUFhLGlCQUFpQjtJQWMxQixZQUFvQixNQUtuQjtRQUxtQixXQUFNLEdBQU4sTUFBTSxDQUt6QjtRQVpPLG1CQUFjLEdBQUcsaUNBQWlCLENBQUM7UUFHbkMsYUFBUSxHQUFHLEtBQUssQ0FBQztRQWtOakIsNEJBQXVCLEdBQUcsQ0FBQyxDQUFDO1FBeE1oQyxJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUM7UUFDcEMsSUFBSSxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxrQkFBa0IsQ0FBQztZQUMxQyxVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVU7WUFDN0IsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTO1lBQzNCLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVztTQUNqQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBQSxnREFBc0IsRUFBQyxHQUFHLEVBQUU7WUFDdEQsS0FBSyxJ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RUFBRSxDQUFDLENBQUM7UUFDcEksSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbEIsT0FBTyxDQUFDLEtBQUssQ0FBQyx5Q0FBeUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsYUFBYSxJQUFBLCtCQUFnQixFQUFDLFVBQVUsQ0FBQyxlQUFlLFFBQVEsQ0FBQyxNQUFNLE9BQU8sS0FBSyx5QkFBeUIsbUNBQTJCLEdBQUcsSUFBSSxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzFQLElBQUksQ0FBQyxRQUFRLENBQUMsbUNBQTJCLENBQUMsQ0FBQztZQUMzQyxPQUFPO1FBQ1gsQ0FBQztRQUNELElBQUksQ0FBQyxRQUFRLENBQUMscUNBQTZCLENBQUMsQ0FBQztJQUNqRCxDQUFDO0NBQ0o7QUFoRUQsZ0RBZ0VDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaXNOb2RlIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuaW1wb3J0IHsgUmVtb3RlQ29uZmlnLCBTb3VyY2VDb25maWcgfSBmcm9tIFwiLi4vSUFyY2hpdmVzXCI7XG5pbXBvcnQgeyBST1VUSU5HX0ZJTEUsIGdldENvbmZpZ1ZlcnNpb24sIHNlcmlhbGl6ZVJlbW90ZUNvbmZpZywgbm9ybWFsaXplUmVtb3RlQ29uZmlnLCBub3JtYWxpemVTb3VyY2UgfSBmcm9tIFwiLi9yZW1vdGVDb25maWdcIjtcbmltcG9ydCB7IFNvdXJjZVdyYXBwZXIsIFJFVFJZX1NUQVJUX0RFTEFZLCBSRVRSWV9NQVhfREVMQVksIFJFVFJZX0dST1dUSCB9IGZyb20gXCIuL3NvdXJjZVdyYXBwZXJcIjtcbmltcG9ydCB7IHJlc29sdmVJbnRlcm1lZGlhdGVTb3VyY2VzIH0gZnJvbSBcIi4vaW50ZXJtZWRpYXRlU291cmNlc1wiO1xuaW1wb3J0IHsgb25TZXJ2ZXJSb3V0aW5nQ2hhbmdlZCB9IGZyb20gXCIuL3N0b3JhZ2VDbGllbnRDb250cm9sbGVyXCI7XG5cbi8vIFRoZSBMSUZFQ1lDTEUgb2YgYW4gQXJjaGl2ZXNDaGFpbidzIHN0YXRlLCBhbmQgbm90aGluZyBlbHNlOiBpbml0aWFsaXppbmcgaXQgKHByb2JpbmcgZXZlcnkgY29uZmlndXJlZCBzb3VyY2UsIGRlY2lkaW5nIHdoaWNoIHJvdXRpbmcgY29uZmlnIHRvIHJ1biwgd3JpdGluZyBvdXJzIG91dCB3aGVuIGl0IGlzIHRoZSBuZXdlc3QpLCB0aGUgcmV0cnkgd2hlbiBpbml0aWFsaXphdGlvbiBmYWlscywgdGhlIHBvbGwgdGhhdCBhZG9wdHMgbmV3ZXIgY29uZmlncywgdGhlIGF2YWlsYWJpbGl0eSByZWNoZWNrLCBhbmQgdGhlIGxvb3AgdGhhdCBrZWVwcyByZS13cml0aW5nIG91ciBjb25maWcuIE5vbmUgb2YgdGhpcyBpcyByZXF1ZXN0IGRpc3BhdGNoIC0gdGhlIGNoYWluIChjcmVhdGVBcmNoaXZlcy50cykgYXNrcyB0aGUgQ2hhaW5TdGF0ZU1hbmFnZXIgZm9yIHRoZSBjdXJyZW50IHN0YXRlIGFuZCBkaXNwYXRjaGVzIG92ZXIgaXQuXG5cbmNvbnN0IENPTkZJR19QT0xMX0lOVEVSVkFMID0gNSAqIDYwICogMTAwMDtcbmNvbnN0IEFWQUlMQUJJTElUWV9SRUNIRUNLX1RIUk9UVExFID0gNSAqIDEwMDA7XG4vLyBUaGUgcm91dGluZyBjb25maWcgd3JpdGUgaXMgcmV0cmllZCBvbiB0aGlzIGNhZGVuY2Ugd2hpbGUgaXQgaXMgZmFpbGluZy4gQSBzdG9yZSB0aGF0IG5ldmVyIHJlY2VpdmVkIHRoZSBjb25maWcgcmVqZWN0cyBldmVyeSB3cml0ZSBhaW1lZCBhdCBpdCwgc28gdGhpcyBub3QgbGFuZGluZyBpcyBhIGJpZyBkZWFsIC0gZWFjaCBmYWlsZWQgYXR0ZW1wdCBpcyBsb2dnZWQuXG5leHBvcnQgY29uc3QgQ09ORklHX1dSSVRFX1JFVFJZX0lOVEVSVkFMID0gNSAqIDYwICogMTAwMDtcbi8vIC4uLmFuZCBldmVuIGFmdGVyIHN1Y2Nlc3MgaXQgaXMgcmUtd3JpdHRlbiBvbiB0aGlzIGNhZGVuY2UsIGluIGNhc2UgYSBzdG9yZSBsb3N0IGl0IG9yIGEgc2VydmVyIGFwcGVhcmVkIGxhdGVcbmV4cG9ydCBjb25zdCBDT05GSUdfV1JJVEVfUkVGUkVTSF9JTlRFUlZBTCA9IDYwICogNjAgKiAxMDAwO1xuXG5leHBvcnQgdHlwZSBDaGFpblN0YXRlID0ge1xuICAgIGNvbmZpZzogUmVtb3RlQ29uZmlnO1xuICAgIHNvdXJjZXM6IFNvdXJjZVdyYXBwZXJbXTtcbn07XG5cbi8qKiBUaGUgY2hhaW4ncyBzdGF0ZSBhbmQgZXZlcnl0aGluZyBhYm91dCBIQVZJTkcgb25lOiBpbml0ICh3aXRoIGl0cyByZXRyeSksIHRoZSBjb25maWcgcG9sbCwgYXZhaWxhYmlsaXR5IHJlY2hlY2tzLCBhbmQgdGhlIHJvdXRpbmcgcmV3cml0ZSBsb29wLiBUaGUgY2hhaW4gY29uc3RydWN0cyBvbmUsIGFza3MgaXQgZ2V0U3RhdGUoKSBvbiBldmVyeSBjYWxsLCBhbmQgZGlzcG9zZXMgaXQuICovXG5leHBvcnQgY2xhc3MgQ2hhaW5TdGF0ZU1hbmFnZXIge1xuICAgIHB1YmxpYyByZWFkb25seSBjb25maWd1cmVkOiBSZW1vdGVDb25maWc7XG4gICAgLyoqIFRoZSBuZXdlc3QgYWRvcHRlZCBjb25maWcgLSB3aGF0IGdldERlYnVnTmFtZSBhbmQgZGlzcGF0Y2ggZGVjaXNpb25zIHJlYWQuIFN0YXJ0cyBhcyB0aGUgY29uZmlndXJlZCBvbmUgYW5kIG1vdmVzIHdpdGggZXZlcnkgYWRvcHRpb24uICovXG4gICAgcHVibGljIGFjdGl2ZUNvbmZpZzogUmVtb3RlQ29uZmlnO1xuICAgIHByaXZhdGUgc3RhdGVQcm9taXNlOiBQcm9taXNlPENoYWluU3RhdGU+IHwgdW5kZWZpbmVkO1xuICAgIC8vIFRoZSByZXNvbHZlZCBzdGF0ZSwgZm9yIHN5bmNocm9ub3VzIGFjY2VzcyAoZ2V0R2V0VVJMcykgLSBhbHdheXMgdGhlIG5ld2VzdCBhZG9wdGVkIGNvbmZpZywgd2hlcmUgc3RhdGVQcm9taXNlIG1heSBicmllZmx5IGxhZyBkdXJpbmcgYSByZWJ1aWxkXG4gICAgcHJpdmF0ZSBsYXRlc3RTdGF0ZTogQ2hhaW5TdGF0ZSB8IHVuZGVmaW5lZDtcbiAgICBwcml2YXRlIGluaXRSZXRyeURlbGF5ID0gUkVUUllfU1RBUlRfREVMQVk7XG4gICAgcHJpdmF0ZSBpbml0UmV0cnlUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCB1bmRlZmluZWQ7XG4gICAgcHJpdmF0ZSBwb2xsVGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldEludGVydmFsPiB8IHVuZGVmaW5lZDtcbiAgICBwcml2YXRlIGRpc3Bvc2VkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSB1bnN1YnNjcmliZVJvdXRpbmdQdXNoOiAoKCkgPT4gdm9pZCkgfCB1bmRlZmluZWQ7XG4gICAgcHJpdmF0ZSByb3V0aW5nUmV3cml0ZXI6IFJvdXRpbmdSZXdyaXRlTG9vcDtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgY29uZmlnOiB7XG4gICAgICAgIGNvbmZpZ3VyZWQ6IFJlbW90ZUNvbmZpZztcbiAgICAgICAgZGVidWdOYW1lOiAoKSA9PiBzdHJpbmc7XG4gICAgICAgIC8qKiBTZWUgQXJjaGl2ZXNDaGFpbk9wdGlvbnMuZGlyZWN0Q29ubmVjdC4gKi9cbiAgICAgICAgZGlyZWN0Q29ubmVjdD86IGJvb2xlYW47XG4gICAgfSkge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyZWQgPSBjb25maWcuY29uZmlndXJlZDtcbiAgICAgICAgdGhpcy5hY3RpdmVDb25maWcgPSBjb25maWcuY29uZmlndXJlZDtcbiAgICAgICAgdGhpcy5yb3V0aW5nUmV3cml0ZXIgPSBuZXcgUm91dGluZ1Jld3JpdGVMb29wKHtcbiAgICAgICAgICAgIGNvbmZpZ3VyZWQ6IGNvbmZpZy5jb25maWd1cmVkLFxuICAgICAgICAgICAgZGVidWdOYW1lOiBjb25maWcuZGVidWdOYW1lLFxuICAgICAgICAgICAgbGF0ZXN0OiAoKSA9PiB0aGlzLmxhdGVzdFN0YXRlLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy51bnN1YnNjcmliZVJvdXRpbmdQdXNoID0gb25TZXJ2ZXJSb3V0aW5nQ2hhbmdlZCgoKSA9PiB7XG4gICAgICAgICAgICB2b2lkIHRoaXMucmVmcmVzaEFjdGl2ZUNvbmZpZygpLmNhdGNoKChlOiBFcnJvcikgPT4gY29uc29sZS5lcnJvcihgQ29uZmlnIHJlZnJlc2ggZmFpbGVkIGZvciAke3RoaXMuY29uZmlnLmRlYnVnTmFtZSgpfTogJHtlLnN0YWNrID8/IGV9YCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogVGhlIG5ld2VzdCBhZG9wdGVkIHN0YXRlLCBzeW5jaHJvbm91c2x5IC0gdW5kZWZpbmVkIHVudGlsIHRoZSBmaXJzdCBpbml0IGZpbmlzaGVzLiAqL1xuICAgIHB1YmxpYyBsYXRlc3QoKTogQ2hhaW5TdGF0ZSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIHJldHVybiB0aGlzLmxhdGVzdFN0YXRlO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTdGF0ZSgpOiBQcm9taXNlPENoYWluU3RhdGU+IHtcbiAgICAgICAgaWYgKHRoaXMuZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoYEFyY2hpdmVzQ2hhaW4gJHt0aGlzLmNvbmZpZy5kZWJ1Z05hbWUoKX0gaGFzIGJlZW4gZGlzcG9zZWRgKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlUHJvbWlzZSkge1xuICAgICAgICAgICAgbGV0IHByb21pc2UgPSB0aGlzLmluaXQoKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdGVQcm9taXNlID0gcHJvbWlzZTtcbiAgICAgICAgICAgIHByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0UmV0cnlEZWxheSA9IFJFVFJZX1NUQVJUX0RFTEFZO1xuICAgICAgICAgICAgfSwgKGU6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzcG9zZWQgfHwgdGhpcy5pbml0UmV0cnlUaW1lcikgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFN0b3JhZ2UgaW5pdCBmYWlsZWQgZm9yICR7dGhpcy5jb25maWcuZGVidWdOYW1lKCl9LCByZXRyeWluZyBpbiAke01hdGgucm91bmQodGhpcy5pbml0UmV0cnlEZWxheSAvIDEwMDApfXMuICR7ZS5zdGFjayA/PyBlfWApO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJldHJ5VGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0UmV0cnlUaW1lciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzcG9zZWQpIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGVQcm9taXNlID09PSBwcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlUHJvbWlzZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldFN0YXRlKCkuY2F0Y2goKCkgPT4geyB9KTtcbiAgICAgICAgICAgICAgICB9LCB0aGlzLmluaXRSZXRyeURlbGF5KTtcbiAgICAgICAgICAgICAgICAodGhpcy5pbml0UmV0cnlUaW1lciBhcyB7IHVucmVmPzogKCkgPT4gdm9pZCB9KS51bnJlZj8uKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0UmV0cnlEZWxheSA9IE1hdGgubWluKFJFVFJZX01BWF9ERUxBWSwgdGhpcy5pbml0UmV0cnlEZWxheSAqIFJFVFJZX0dST1dUSCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZVByb21pc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBpbml0KCk6IFByb21pc2U8Q2hhaW5TdGF0ZT4ge1xuICAgICAgICBsZXQgY29uZmlncyA9IHRoaXMuY29uZmlndXJlZC5zb3VyY2VzLm1hcChub3JtYWxpemVTb3VyY2UpO1xuICAgICAgICBsZXQgcmVhZE9ubHkgPSB0aGlzLmlzUmVhZE9ubHkodGhpcy5jb25maWd1cmVkKTtcbiAgICAgICAgbGV0IHByb2JlcyA9IGF3YWl0IHByb2JlU291cmNlcyhjb25maWdzLCByZWFkT25seSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsZXQgeyBhY3RpdmUsIG5lZWRzV3JpdGUsIGV4aXN0aW5nIH0gPSBjaG9vc2VTdGFydHVwQ29uZmlnKHsgY29uZmlndXJlZDogdGhpcy5jb25maWd1cmVkLCBwcm9iZXMsIGRlYnVnTmFtZTogdGhpcy5jb25maWcuZGVidWdOYW1lKCkgfSk7XG4gICAgICAgICAgICBsZXQgc291cmNlcyA9IGF3YWl0IHRoaXMuYnVpbGRTb3VyY2VzKGFjdGl2ZSk7XG4gICAgICAgICAgICBsZXQgY29uZmlnV3JpdGVGYWlsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChuZWVkc1dyaXRlKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coYFN0b3JhZ2Ugcm91dGluZyBjb25maWcgZm9yICR7dGhpcy5jb25maWcuZGVidWdOYW1lKCl9IGlzIG91dCBvZiBkYXRlIChzdG9yZWQgdmVyc2lvbiAke2V4aXN0aW5nICYmIGdldENvbmZpZ1ZlcnNpb24oZXhpc3RpbmcpIHx8IFwibm9uZVwifSwgb3VycyAke2dldENvbmZpZ1ZlcnNpb24odGhpcy5jb25maWd1cmVkKX0pYCk7XG4gICAgICAgICAgICAgICAgbGV0IHsgZmFpbHVyZXMsIHRvdGFsIH0gPSBhd2FpdCB3cml0ZVJvdXRpbmdUb0FsbFN0b3Jlcyh7IGNvbmZpZ3VyZWQ6IHRoaXMuY29uZmlndXJlZCwgc291cmNlcywgZGVidWdOYW1lOiB0aGlzLmNvbmZpZy5kZWJ1Z05hbWUoKSB9KTtcbiAgICAgICAgICAgICAgICBjb25maWdXcml0ZUZhaWxlZCA9IGZhaWx1cmVzLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICAgICAgaWYgKGZhaWx1cmVzLmxlbmd0aCAmJiBmYWlsdXJlcy5sZW5ndGggPT09IHRvdGFsKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vYm9keSBoYXMgb3VyIGNvbmZpZywgc28gcnVubmluZyBvbiBpdCB3b3VsZCBqdXN0IGRpc2FncmVlIHdpdGggZXZlcnkgc2VydmVyLiBUaGUgc3RvcmVkIG9uZSAod2hlbiB0aGVyZSBpcyBvbmUpIGlzIHdoYXQgdGhlIHNlcnZlcnMgYWN0dWFsbHkgcnVuLlxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBUaGUgc3RvcmFnZSByb3V0aW5nIGNvbmZpZyBmb3IgJHt0aGlzLmNvbmZpZy5kZWJ1Z05hbWUoKX0gKHZlcnNpb24gJHtnZXRDb25maWdWZXJzaW9uKHRoaXMuY29uZmlndXJlZCl9KSBjb3VsZCBub3QgYmUgd3JpdHRlbiB0byBBTlkgb2YgdGhlICR7dG90YWx9IHN0b3Jlcy4gJHtleGlzdGluZyAmJiBgUnVubmluZyBvbiB0aGUgc3RvcmVkIGNvbmZpZyAodmVyc2lvbiAke2dldENvbmZpZ1ZlcnNpb24oZXhpc3RpbmcpfSkgdW50aWwgYSB3cml0ZSBzdWNjZWVkcy5gIHx8IGBObyBzdG9yZWQgY29uZmlnIGV4aXN0cyBlaXRoZXIsIHNvIHNlcnZlcnMgd2lsbCByZWplY3Qgd3JpdGVzIHVudGlsIHRoaXMgc3VjY2VlZHMuYH0gUmV0cnlpbmcgaW4gJHtDT05GSUdfV1JJVEVfUkVUUllfSU5URVJWQUwgLyAxMDAwfXMuIEZhaWx1cmVzOiAke2ZhaWx1cmVzLmpvaW4oXCIgfCBcIil9YCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aXZlID0gZXhpc3Rpbmc7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBzb3VyY2Ugb2Ygc291cmNlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZS5kaXNwb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VzID0gYXdhaXQgdGhpcy5idWlsZFNvdXJjZXMoYWN0aXZlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZmFpbHVyZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFRoZSBzdG9yYWdlIHJvdXRpbmcgY29uZmlnIGZvciAke3RoaXMuY29uZmlnLmRlYnVnTmFtZSgpfSAodmVyc2lvbiAke2dldENvbmZpZ1ZlcnNpb24odGhpcy5jb25maWd1cmVkKX0pIHdhcyB3cml0dGVuIHRvICR7dG90YWwgLSBmYWlsdXJlcy5sZW5ndGh9IG9mICR7dG90YWx9IHN0b3Jlcy4gUmV0cnlpbmcgdGhlIHJlc3QgaW4gJHtDT05GSUdfV1JJVEVfUkVUUllfSU5URVJWQUwgLyAxMDAwfXMgKHRoZXkgYWxzbyBwdWxsIGl0IGZyb20gdGhlIHN0b3JlcyB0aGF0IGhhdmUgaXQpLiBGYWlsdXJlczogJHtmYWlsdXJlcy5qb2luKFwiIHwgXCIpfWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IHNvdXJjZSBvZiBzb3VyY2VzKSB7XG4gICAgICAgICAgICAgICAgbGV0IHByb2JlID0gcHJvYmVzLmZpbmQoeCA9PiB4LnJlc3BvbmRlZCAmJiB4LnNvdXJjZUNvbmZpZy51cmwgPT09IHNvdXJjZS5jb25maWcudXJsKTtcbiAgICAgICAgICAgICAgICBpZiAocHJvYmUpIHtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlLnNlZWRMYXRlbmN5KHByb2JlLmxhdGVuY3kpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYWN0aXZlQ29uZmlnID0gYWN0aXZlO1xuICAgICAgICAgICAgdGhpcy5zdGFydENvbmZpZ1BvbGwoKTtcbiAgICAgICAgICAgIGxldCBzdGF0ZTogQ2hhaW5TdGF0ZSA9IHsgY29uZmlnOiBhY3RpdmUsIHNvdXJjZXMgfTtcbiAgICAgICAgICAgIHRoaXMubGF0ZXN0U3RhdGUgPSBzdGF0ZTtcbiAgICAgICAgICAgIHRoaXMucm91dGluZ1Jld3JpdGVyLnN0YXJ0KGNvbmZpZ1dyaXRlRmFpbGVkKTtcbiAgICAgICAgICAgIHJldHVybiBzdGF0ZTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIGRpc3Bvc2VQcm9iZXMocHJvYmVzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBDbGllbnRzaWRlLCBhIGNvbmZpZyB3aXRoIHB1YmxpYyBzb3VyY2VzIGlzIHNlcnZlZCBlbnRpcmVseSBvdmVyIHBsYWluIFVSTCBkb3dubG9hZHMgLSBubyBBUEkgY29ubmVjdGlvbiwgbm8gYWNjZXNzIGdyYW50LCBhbmQgbm8gd3JpdGluZy4gZGlyZWN0Q29ubmVjdCBvcHRzIG91dCBvZiB0aGF0LiAqL1xuICAgIHByaXZhdGUgaXNSZWFkT25seShjb25maWc6IFJlbW90ZUNvbmZpZyk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAodGhpcy5jb25maWcuZGlyZWN0Q29ubmVjdCB8fCBpc05vZGUoKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gY29uZmlnLnNvdXJjZXMubWFwKG5vcm1hbGl6ZVNvdXJjZSkuc29tZSh4ID0+IHgucHVibGljKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNyZWF0ZUNoYWluU291cmNlKHNvdXJjZUNvbmZpZzogU291cmNlQ29uZmlnLCByZWFkT25seTogYm9vbGVhbik6IFByb21pc2U8U291cmNlV3JhcHBlcj4ge1xuICAgICAgICBsZXQgc291cmNlID0gYXdhaXQgU291cmNlV3JhcHBlci5jcmVhdGUoc291cmNlQ29uZmlnLCB7IHJlYWRPbmx5IH0pO1xuICAgICAgICBzb3VyY2Uuc3RhcnRQaW5naW5nKCk7XG4gICAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBidWlsZFNvdXJjZXMoY29uZmlnOiBSZW1vdGVDb25maWcpOiBQcm9taXNlPFNvdXJjZVdyYXBwZXJbXT4ge1xuICAgICAgICBsZXQgcmVhZE9ubHkgPSB0aGlzLmlzUmVhZE9ubHkoY29uZmlnKTtcbiAgICAgICAgbGV0IHNvdXJjZXM6IFNvdXJjZVdyYXBwZXJbXSA9IFtdO1xuICAgICAgICBmb3IgKGxldCBzb3VyY2VDb25maWcgb2YgY29uZmlnLnNvdXJjZXMubWFwKG5vcm1hbGl6ZVNvdXJjZSkpIHtcbiAgICAgICAgICAgIHNvdXJjZXMucHVzaChhd2FpdCB0aGlzLmNyZWF0ZUNoYWluU291cmNlKHNvdXJjZUNvbmZpZywgcmVhZE9ubHkpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc291cmNlcztcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXJ0Q29uZmlnUG9sbCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMucG9sbFRpbWVyIHx8IHRoaXMuZGlzcG9zZWQpIHJldHVybjtcbiAgICAgICAgdGhpcy5wb2xsVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICB2b2lkIHRoaXMucmVmcmVzaEFjdGl2ZUNvbmZpZygpLmNhdGNoKChlOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYENoZWNraW5nIGZvciBhIG5ldyBzdG9yYWdlIHJvdXRpbmcgY29uZmlnIGZhaWxlZCBmb3IgJHt0aGlzLmNvbmZpZy5kZWJ1Z05hbWUoKX06ICR7ZS5zdGFjayA/PyBlfWApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIENPTkZJR19QT0xMX0lOVEVSVkFMKTtcbiAgICAgICAgKHRoaXMucG9sbFRpbWVyIGFzIHsgdW5yZWY/OiAoKSA9PiB2b2lkIH0pLnVucmVmPy4oKTtcbiAgICB9XG5cbiAgICAvLyBEZWR1cGxpY2F0ZXMgY29uY3VycmVudCByZWZyZXNoZXMgKHRoZSBwb2xsIHRpbWVyIGFuZCB3cm9uZy10YXJnZXQgd3JpdGUgcmV0cmllcyBzaGFyZSB0aGlzKVxuICAgIHByaXZhdGUgY29uZmlnUmVmcmVzaEluRmxpZ2h0OiBQcm9taXNlPHZvaWQ+IHwgdW5kZWZpbmVkO1xuICAgIHB1YmxpYyByZWZyZXNoQWN0aXZlQ29uZmlnKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXRoaXMuY29uZmlnUmVmcmVzaEluRmxpZ2h0KSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZ1JlZnJlc2hJbkZsaWdodCA9IHRoaXMuY2hlY2tGb3JOZXdDb25maWcoKS5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ1JlZnJlc2hJbkZsaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZ1JlZnJlc2hJbkZsaWdodDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGZldGNoTGF0ZXN0Q29uZmlnKHN0YXRlOiBDaGFpblN0YXRlKTogUHJvbWlzZTxSZW1vdGVDb25maWcgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgbGV0IGVycm9yczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgZm9yIChsZXQgc291cmNlIG9mIHN0YXRlLnNvdXJjZXMpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IGxhdGVzdCA9IGF3YWl0IHNvdXJjZS5yZWFkUm91dGluZ0NvbmZpZygpO1xuICAgICAgICAgICAgICAgIGlmIChsYXRlc3QpIHJldHVybiBub3JtYWxpemVSZW1vdGVDb25maWcobGF0ZXN0KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBlcnJvcnMucHVzaChgJHtzb3VyY2UuY29uZmlnLnVybH06ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVycm9ycy5sZW5ndGggPT09IHN0YXRlLnNvdXJjZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHN0b3JhZ2Ugc291cmNlIGNvdWxkIGdpdmUgdXMgdGhlIHJvdXRpbmcgY29uZmlnIGZvciAke3RoaXMuY29uZmlnLmRlYnVnTmFtZSgpfTogJHtlcnJvcnMuam9pbihcIiB8IFwiKX1gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgY2hlY2tGb3JOZXdDb25maWcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLmRpc3Bvc2VkIHx8ICF0aGlzLnN0YXRlUHJvbWlzZSkgcmV0dXJuO1xuICAgICAgICBsZXQgc3RhdGU6IENoYWluU3RhdGU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzdGF0ZSA9IGF3YWl0IHRoaXMuc3RhdGVQcm9taXNlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgbGF0ZXN0ID0gYXdhaXQgdGhpcy5mZXRjaExhdGVzdENvbmZpZyhzdGF0ZSk7XG4gICAgICAgIGlmICghbGF0ZXN0KSByZXR1cm47XG4gICAgICAgIGF3YWl0IHRoaXMuYWRvcHROZXdDb25maWcoc3RhdGUsIGxhdGVzdCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBhZG9wdE5ld0NvbmZpZyhzdGF0ZTogQ2hhaW5TdGF0ZSwgbGF0ZXN0OiBSZW1vdGVDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKEpTT04uc3RyaW5naWZ5KGxhdGVzdCkgPT09IEpTT04uc3RyaW5naWZ5KHN0YXRlLmNvbmZpZykpIHJldHVybjtcbiAgICAgICAgbGV0IHJlY2VpdmVkID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuICAgICAgICBsZXQgb25seUludGVybWVkaWF0ZXNDaGFuZ2VkID0gSlNPTi5zdHJpbmdpZnkocmVzb2x2ZUludGVybWVkaWF0ZVNvdXJjZXMobGF0ZXN0KSkgPT09IEpTT04uc3RyaW5naWZ5KHJlc29sdmVJbnRlcm1lZGlhdGVTb3VyY2VzKHN0YXRlLmNvbmZpZykpO1xuICAgICAgICBpZiAob25seUludGVybWVkaWF0ZXNDaGFuZ2VkKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgU3RvcmFnZSByb3V0aW5nIHN3aXRjaG92ZXIgd2luZG93cyBjaGFuZ2VkICh2ZXJzaW9uICR7Z2V0Q29uZmlnVmVyc2lvbihzdGF0ZS5jb25maWcpfSAtPiAke2dldENvbmZpZ1ZlcnNpb24obGF0ZXN0KX0pLCByZWNlaXZlZCAke3JlY2VpdmVkfSwgcmVidWlsZGluZyBzb3VyY2VzLiBOZXcgY29uZmlnOiAke0pTT04uc3RyaW5naWZ5KGxhdGVzdCl9YCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgU3RvcmFnZSByb3V0aW5nIGNvbmZpZyBjaGFuZ2VkICh2ZXJzaW9uICR7Z2V0Q29uZmlnVmVyc2lvbihzdGF0ZS5jb25maWcpfSAtPiAke2dldENvbmZpZ1ZlcnNpb24obGF0ZXN0KX0pLCByZWNlaXZlZCAke3JlY2VpdmVkfSwgcmVidWlsZGluZyBzb3VyY2VzLiBOZXcgY29uZmlnOiAke0pTT04uc3RyaW5naWZ5KGxhdGVzdCl9YCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHN0cmlwcGVkS2V5ID0gKGNvbmZpZzogU291cmNlQ29uZmlnKSA9PiBKU09OLnN0cmluZ2lmeSh7IC4uLmNvbmZpZywgdmFsaWRXaW5kb3c6IHVuZGVmaW5lZCB9KTtcbiAgICAgICAgbGV0IG9sZEJ5Q29uZmlnID0gbmV3IE1hcDxzdHJpbmcsIFNvdXJjZVdyYXBwZXJbXT4oKTtcbiAgICAgICAgZm9yIChsZXQgc291cmNlIG9mIHN0YXRlLnNvdXJjZXMpIHtcbiAgICAgICAgICAgIGxldCBrZXkgPSBzdHJpcHBlZEtleShzb3VyY2UuY29uZmlnKTtcbiAgICAgICAgICAgIGxldCBsaXN0ID0gb2xkQnlDb25maWcuZ2V0KGtleSk7XG4gICAgICAgICAgICBpZiAoIWxpc3QpIHtcbiAgICAgICAgICAgICAgICBsaXN0ID0gW107XG4gICAgICAgICAgICAgICAgb2xkQnlDb25maWcuc2V0KGtleSwgbGlzdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsaXN0LnB1c2goc291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmVhZE9ubHkgPSB0aGlzLmlzUmVhZE9ubHkobGF0ZXN0KTtcbiAgICAgICAgbGV0IHNvdXJjZXM6IFNvdXJjZVdyYXBwZXJbXSA9IFtdO1xuICAgICAgICBmb3IgKGxldCBzb3VyY2VDb25maWcgb2YgbGF0ZXN0LnNvdXJjZXMubWFwKG5vcm1hbGl6ZVNvdXJjZSkpIHtcbiAgICAgICAgICAgIGxldCBvbGQgPSBvbGRCeUNvbmZpZy5nZXQoc3RyaXBwZWRLZXkoc291cmNlQ29uZmlnKSk/LnNoaWZ0KCk7XG4gICAgICAgICAgICBpZiAob2xkKSB7XG4gICAgICAgICAgICAgICAgb2xkLnVwZGF0ZVZhbGlkV2luZG93KHNvdXJjZUNvbmZpZy52YWxpZFdpbmRvdyk7XG4gICAgICAgICAgICAgICAgc291cmNlcy5wdXNoKG9sZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNvdXJjZXMucHVzaChhd2FpdCB0aGlzLmNyZWF0ZUNoYWluU291cmNlKHNvdXJjZUNvbmZpZywgcmVhZE9ubHkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBsZWZ0b3ZlcnMgb2Ygb2xkQnlDb25maWcudmFsdWVzKCkpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGxlZnRvdmVyIG9mIGxlZnRvdmVycykge1xuICAgICAgICAgICAgICAgIGxlZnRvdmVyLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFjdGl2ZUNvbmZpZyA9IGxhdGVzdDtcbiAgICAgICAgbGV0IG5ld1N0YXRlOiBDaGFpblN0YXRlID0geyBjb25maWc6IGxhdGVzdCwgc291cmNlcyB9O1xuICAgICAgICB0aGlzLmxhdGVzdFN0YXRlID0gbmV3U3RhdGU7XG4gICAgICAgIHRoaXMuc3RhdGVQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKG5ld1N0YXRlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxhc3RBdmFpbGFiaWxpdHlSZWNoZWNrID0gMDtcbiAgICBwcml2YXRlIGF2YWlsYWJpbGl0eVJlY2hlY2tJbkZsaWdodDogUHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZDtcbiAgICAvKiogRXZlcnkgc291cmNlIGZhaWxlZDogcmUtY29udGFjdCBhbGwgb2YgdGhlbSAocm91dGluZyByZS1yZWFkICsgY29ubmVjdGlvbiByZS1hdHRlbXB0KSBhbmQgYWRvcHQgd2hhdGV2ZXIgY29uZmlnIGNvbWVzIGJhY2suIFRocm90dGxlZCwgYW5kIGRlZHVwbGljYXRlZCBhY3Jvc3MgY29uY3VycmVudCBjYWxsZXJzLiAqL1xuICAgIHB1YmxpYyByZWNoZWNrQXZhaWxhYmlsaXR5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5hdmFpbGFiaWxpdHlSZWNoZWNrSW5GbGlnaHQpIHJldHVybiB0aGlzLmF2YWlsYWJpbGl0eVJlY2hlY2tJbkZsaWdodDtcbiAgICAgICAgaWYgKERhdGUubm93KCkgLSB0aGlzLmxhc3RBdmFpbGFiaWxpdHlSZWNoZWNrIDwgQVZBSUxBQklMSVRZX1JFQ0hFQ0tfVEhST1RUTEUpIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgdGhpcy5sYXN0QXZhaWxhYmlsaXR5UmVjaGVjayA9IERhdGUubm93KCk7XG4gICAgICAgIHRoaXMuYXZhaWxhYmlsaXR5UmVjaGVja0luRmxpZ2h0ID0gdGhpcy5yZWNoZWNrQXZhaWxhYmlsaXR5Tm93KCkuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmF2YWlsYWJpbGl0eVJlY2hlY2tJbkZsaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLmF2YWlsYWJpbGl0eVJlY2hlY2tJbkZsaWdodDtcbiAgICB9XG4gICAgcHJpdmF0ZSBhc3luYyByZWNoZWNrQXZhaWxhYmlsaXR5Tm93KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5kaXNwb3NlZCB8fCAhdGhpcy5zdGF0ZVByb21pc2UpIHJldHVybjtcbiAgICAgICAgbGV0IHN0YXRlOiBDaGFpblN0YXRlO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc3RhdGUgPSBhd2FpdCB0aGlzLnN0YXRlUHJvbWlzZTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5sb2coYEV2ZXJ5IHN0b3JhZ2Ugc291cmNlIGZhaWxlZCBmb3IgJHt0aGlzLmNvbmZpZy5kZWJ1Z05hbWUoKX07IHJlLWNvbnRhY3RpbmcgYWxsICR7c3RhdGUuc291cmNlcy5sZW5ndGh9IHNvdXJjZXMgKHJvdXRpbmcgcmUtcmVhZCArIGNvbm5lY3Rpb24gcmUtYXR0ZW1wdClgKTtcbiAgICAgICAgbGV0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChzdGF0ZS5zb3VyY2VzLm1hcChhc3luYyBzb3VyY2UgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgc291cmNlLnJlYWRSb3V0aW5nQ29uZmlnKCk7XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgICAgIGxldCBsYXRlc3QgPSByZXN1bHRzLmZpbmQoeCA9PiB4KTtcbiAgICAgICAgaWYgKCFsYXRlc3QpIHJldHVybjtcbiAgICAgICAgYXdhaXQgdGhpcy5hZG9wdE5ld0NvbmZpZyhzdGF0ZSwgbGF0ZXN0KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgICAgIHRoaXMudW5zdWJzY3JpYmVSb3V0aW5nUHVzaD8uKCk7XG4gICAgICAgIGlmICh0aGlzLnBvbGxUaW1lcikge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLnBvbGxUaW1lcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaW5pdFJldHJ5VGltZXIpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmluaXRSZXRyeVRpbWVyKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvdXRpbmdSZXdyaXRlci5kaXNwb3NlKCk7XG4gICAgICAgIGxldCBzdGF0ZVByb21pc2UgPSB0aGlzLnN0YXRlUHJvbWlzZTtcbiAgICAgICAgaWYgKHN0YXRlUHJvbWlzZSkge1xuICAgICAgICAgICAgdm9pZCBzdGF0ZVByb21pc2UudGhlbihzdGF0ZSA9PiB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgc291cmNlIG9mIHN0YXRlLnNvdXJjZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCAoKSA9PiB7IH0pO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBTb3VyY2VQcm9iZSA9IHtcbiAgICBwcm9iZTogU291cmNlV3JhcHBlcjtcbiAgICBzb3VyY2VDb25maWc6IFNvdXJjZUNvbmZpZztcbiAgICByZXNwb25kZWQ6IGJvb2xlYW47XG4gICAgbGF0ZW5jeTogbnVtYmVyO1xuICAgIGV4aXN0aW5nOiBSZW1vdGVDb25maWcgfCB1bmRlZmluZWQ7XG4gICAgZXJyb3I6IHN0cmluZztcbn07XG5cbi8qKiBPbmUgdGhyb3dhd2F5IFNvdXJjZVdyYXBwZXIgcGVyIGNvbmZpZ3VyZWQgc291cmNlLCBlYWNoIGFza2VkIGZvciBpdHMgc3RvcmVkIHJvdXRpbmcgY29uZmlnIC0gd2hpY2ggYWxzbyBtZWFzdXJlcyBmaXJzdC1jb250YWN0IGxhdGVuY3ksIHNlZWRlZCBpbnRvIHRoZSByZWFsIHNvdXJjZXMgYWZ0ZXJ3YXJkcy4gVGhlIHByb2JlcyBNVVNUIGJlIGRpc3Bvc2VkIChkaXNwb3NlUHJvYmVzKSBvbmNlIHRoZSBjYWxsZXIgaXMgZG9uZSB3aXRoIHRoZW0uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvYmVTb3VyY2VzKGNvbmZpZ3M6IFNvdXJjZUNvbmZpZ1tdLCByZWFkT25seTogYm9vbGVhbik6IFByb21pc2U8U291cmNlUHJvYmVbXT4ge1xuICAgIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChjb25maWdzLm1hcChhc3luYyBzb3VyY2VDb25maWcgPT4ge1xuICAgICAgICBsZXQgcHJvYmUgPSBhd2FpdCBTb3VyY2VXcmFwcGVyLmNyZWF0ZShzb3VyY2VDb25maWcsIHsgYmFja2dyb3VuZDogZmFsc2UsIHJlYWRPbmx5IH0pO1xuICAgICAgICBsZXQgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbGV0IGV4aXN0aW5nID0gYXdhaXQgcHJvYmUucmVhZFJvdXRpbmdDb25maWcoKTtcbiAgICAgICAgICAgIHJldHVybiB7IHByb2JlLCBzb3VyY2VDb25maWcsIHJlc3BvbmRlZDogdHJ1ZSwgbGF0ZW5jeTogRGF0ZS5ub3coKSAtIHN0YXJ0LCBleGlzdGluZywgZXJyb3I6IFwiXCIgfTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgcHJvYmUsIHNvdXJjZUNvbmZpZywgcmVzcG9uZGVkOiBmYWxzZSwgbGF0ZW5jeTogMCwgZXhpc3Rpbmc6IHVuZGVmaW5lZCwgZXJyb3I6IGAke3NvdXJjZUNvbmZpZy51cmx9OiAkeyhlIGFzIEVycm9yKS5zdGFjayA/PyBlfWAgfTtcbiAgICAgICAgfVxuICAgIH0pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRpc3Bvc2VQcm9iZXMocHJvYmVzOiBTb3VyY2VQcm9iZVtdKTogdm9pZCB7XG4gICAgZm9yIChsZXQgcHJvYmUgb2YgcHJvYmVzKSB7XG4gICAgICAgIHByb2JlLnByb2JlLmRpc3Bvc2UoKTtcbiAgICB9XG59XG5cbi8qKlxuICogV2hpY2ggcm91dGluZyBjb25maWcgdGhlIGNoYWluIHNob3VsZCBSVU46IHRoZSBuZXdlc3Qgb2Ygb3VycyBhbmQgZXZlcnkgc3RvcmVkIG9uZS4gbmVlZHNXcml0ZVxuICogd2hlbiBvdXJzIGlzIHN0cmljdGx5IHRoZSBuZXdlc3QsIG1lYW5pbmcgdGhlIHN0b3JlcyBoYXZlIHRvIGJlIHRvbGQgYWJvdXQgaXQuIEEgc3RvcmVkIGNvbmZpZ1xuICogd2l0aCBvdXIgZXhhY3QgdmVyc2lvbiBidXQgRElGRkVSRU5UIGNvbnRlbnQgd2lucyB3aXRob3V0IGEgd3JpdGUsIGxvdWRseTogY29uZmlnIHVwZGF0ZXMgbXVzdFxuICogYnVtcCB0aGUgdmVyc2lvbiwgb3IgdGhleSBhcmUgaWdub3JlZCAtIHNpbGVudGx5IHRha2luZyB0aGUgY2hhbmdlZCBvbmUgd291bGQgbWFrZSBcIndoYXQgaXMgdGhlXG4gKiBidWNrZXQgcnVubmluZ1wiIGRlcGVuZCBvbiB3aGljaCBwcm9jZXNzIHN0YXJ0ZWQgbGFzdC5cbiAqXG4gKiBUaHJvd3Mgd2hlbiBubyBzb3VyY2UgYW5zd2VyZWQgYXQgYWxsOiB3aXRoIG5vdGhpbmcgc3RvcmVkIGFuZCBub2JvZHkgdG8gd3JpdGUgdG8sIHRoZXJlIGlzIG5vXG4gKiBjb25maWcgdG8gcnVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2hvb3NlU3RhcnR1cENvbmZpZyhjb25maWc6IHsgY29uZmlndXJlZDogUmVtb3RlQ29uZmlnOyBwcm9iZXM6IFNvdXJjZVByb2JlW107IGRlYnVnTmFtZTogc3RyaW5nIH0pOiB7IGFjdGl2ZTogUmVtb3RlQ29uZmlnOyBuZWVkc1dyaXRlOiBib29sZWFuOyBleGlzdGluZzogUmVtb3RlQ29uZmlnIHwgdW5kZWZpbmVkIH0ge1xuICAgIGxldCB7IGNvbmZpZ3VyZWQsIHByb2JlcywgZGVidWdOYW1lIH0gPSBjb25maWc7XG4gICAgbGV0IGZvdW5kID0gcHJvYmVzLmZpbmQoeCA9PiB4LnJlc3BvbmRlZCk7XG4gICAgaWYgKCFmb3VuZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBpbml0aWFsaXplIHN0b3JhZ2UgZm9yICR7ZGVidWdOYW1lfTogbm8gc291cmNlIGFuc3dlcmVkLiAke3Byb2Jlcy5tYXAoeCA9PiB4LmVycm9yKS5qb2luKFwiIHwgXCIpfWApO1xuICAgIH1cbiAgICBsZXQgZXhpc3RpbmcgPSBmb3VuZC5leGlzdGluZztcbiAgICBsZXQgYWN0aXZlID0gY29uZmlndXJlZDtcbiAgICBsZXQgbmVlZHNXcml0ZSA9IHRydWU7XG4gICAgaWYgKGV4aXN0aW5nICYmIGdldENvbmZpZ1ZlcnNpb24oZXhpc3RpbmcpID49IGdldENvbmZpZ1ZlcnNpb24oY29uZmlndXJlZCkpIHtcbiAgICAgICAgaWYgKGdldENvbmZpZ1ZlcnNpb24oZXhpc3RpbmcpID09PSBnZXRDb25maWdWZXJzaW9uKGNvbmZpZ3VyZWQpICYmIEpTT04uc3RyaW5naWZ5KGV4aXN0aW5nKSAhPT0gSlNPTi5zdHJpbmdpZnkoY29uZmlndXJlZCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEFyY2hpdmVzIGNvbmZpZ3VyYXRpb24gdXBkYXRlZCB3aXRob3V0IHVwZGF0aW5nIHRoZSB2ZXJzaW9uLCBmb3IgJHtmb3VuZC5zb3VyY2VDb25maWcudXJsfS4gVXBkYXRlcyB3aWxsIGJlIGlnbm9yZWQgdW50aWwgeW91IGluY3JlYXNlIHRoZSB2ZXJzaW9uLiBVc2luZzogJHtKU09OLnN0cmluZ2lmeShleGlzdGluZyl9LCBpZ25vcmluZzogJHtKU09OLnN0cmluZ2lmeShjb25maWd1cmVkKX1gKTtcbiAgICAgICAgfVxuICAgICAgICBhY3RpdmUgPSBleGlzdGluZztcbiAgICAgICAgbmVlZHNXcml0ZSA9IGZhbHNlO1xuICAgIH1cbiAgICBpZiAobmVlZHNXcml0ZSkge1xuICAgICAgICBsZXQgYmVzdDogUmVtb3RlQ29uZmlnIHwgdW5kZWZpbmVkO1xuICAgICAgICBsZXQgY29uZmxpY3RVcmw6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgZm9yIChsZXQgcHJvYmUgb2YgcHJvYmVzKSB7XG4gICAgICAgICAgICBsZXQgc3RvcmVkID0gcHJvYmUuZXhpc3Rpbmc7XG4gICAgICAgICAgICBpZiAoIXN0b3JlZCkgY29udGludWU7XG4gICAgICAgICAgICBpZiAoIWJlc3QgfHwgZ2V0Q29uZmlnVmVyc2lvbihzdG9yZWQpID4gZ2V0Q29uZmlnVmVyc2lvbihiZXN0KSkge1xuICAgICAgICAgICAgICAgIGJlc3QgPSBzdG9yZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZ2V0Q29uZmlnVmVyc2lvbihzdG9yZWQpID09PSBnZXRDb25maWdWZXJzaW9uKGNvbmZpZ3VyZWQpICYmIEpTT04uc3RyaW5naWZ5KHN0b3JlZCkgIT09IEpTT04uc3RyaW5naWZ5KGNvbmZpZ3VyZWQpKSB7XG4gICAgICAgICAgICAgICAgY29uZmxpY3RVcmwgPSBwcm9iZS5zb3VyY2VDb25maWcudXJsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChiZXN0ICYmIGdldENvbmZpZ1ZlcnNpb24oYmVzdCkgPj0gZ2V0Q29uZmlnVmVyc2lvbihjb25maWd1cmVkKSkge1xuICAgICAgICAgICAgaWYgKGNvbmZsaWN0VXJsICYmIGdldENvbmZpZ1ZlcnNpb24oYmVzdCkgPT09IGdldENvbmZpZ1ZlcnNpb24oY29uZmlndXJlZCkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBBcmNoaXZlcyBjb25maWd1cmF0aW9uIHVwZGF0ZWQgd2l0aG91dCB1cGRhdGluZyB0aGUgdmVyc2lvbiwgZm9yICR7Y29uZmxpY3RVcmx9LiBVcGRhdGVzIHdpbGwgYmUgaWdub3JlZCB1bnRpbCB5b3UgaW5jcmVhc2UgdGhlIHZlcnNpb24uIFVzaW5nOiAke0pTT04uc3RyaW5naWZ5KGJlc3QpfSwgaWdub3Jpbmc6ICR7SlNPTi5zdHJpbmdpZnkoY29uZmlndXJlZCl9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhY3RpdmUgPSBiZXN0O1xuICAgICAgICAgICAgbmVlZHNXcml0ZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGFjdGl2ZSwgbmVlZHNXcml0ZSwgZXhpc3RpbmcgfTtcbn1cblxuLyoqXG4gKiBXcml0ZXMgdGhlIGdpdmVuIHJvdXRpbmcgY29uZmlnIHRvIGV2ZXJ5IGNvbmZpZ3VyZWQgc3RvcmUsIG9uZSB3cml0ZSBwZXIgdXJsK25hbWU6IHRoZSB3cml0ZVxuICogbGFuZHMgaW4gdGhlIHN0b3JlIHRoZSBlbnRyeSBOQU1FUywgc28gdHdvIGVudHJpZXMgc2hhcmluZyBhIFVSTCBidXQgbmFtaW5nIGRpZmZlcmVudCBzdG9yZXMgYXJlXG4gKiB0d28gc2VwYXJhdGUgZGVsaXZlcmllcyAtIGRlZHVwaW5nIGJ5IFVSTCBhbG9uZSBsZWF2ZXMgdGhlIHNlY29uZCBzdG9yZSB1bmNvbmZpZ3VyZWQgZm9yZXZlci4gQWxsXG4gKiBpbiBwYXJhbGxlbCwgZXZlcnkgZmFpbHVyZSB0b2xlcmF0ZWQgKG5vLXdyaXRlLWFjY2VzcyBpbmNsdWRlZCAtIHRoZSBhdHRlbXB0IGNsYXNzaWZpZXMgaXQsXG4gKiBub3RoaW5nIHByZS1jaGVja3MgaXQpOiBhIGRvd24gbm9kZSBtdXN0IG5vdCBzdG9wIHRoZSBvdGhlcnMgZnJvbSBnZXR0aW5nIHRoZSBjb25maWcgLSB0aGV5IHdvdWxkXG4gKiB0aGVuIHJlamVjdCB3cml0ZXMgYXMgdW5jb25maWd1cmVkIHByZWNpc2VseSBCRUNBVVNFIGl0IG5ldmVyIGFycml2ZWQgLSBhbmQgaXQgbXVzdCBuZXZlciBzdG9wXG4gKiB0aGUgY2hhaW4gZnJvbSBzdGFydGluZy4gQSBzdG9yZSB0aGF0IG1pc3NlZCBpdCBwdWxscyBpdCBvZmYgaXRzIHBlZXJzLCBhbmQgdGhlIHJld3JpdGUgbG9vcFxuICogdHJpZXMgYWdhaW4gKHNlZSBSb3V0aW5nUmV3cml0ZUxvb3ApLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVSb3V0aW5nVG9BbGxTdG9yZXMoY29uZmlnOiB7IGNvbmZpZ3VyZWQ6IFJlbW90ZUNvbmZpZzsgc291cmNlczogU291cmNlV3JhcHBlcltdOyBkZWJ1Z05hbWU6IHN0cmluZyB9KTogUHJvbWlzZTx7IGZhaWx1cmVzOiBzdHJpbmdbXTsgdG90YWw6IG51bWJlciB9PiB7XG4gICAgbGV0IHsgY29uZmlndXJlZCwgc291cmNlcywgZGVidWdOYW1lIH0gPSBjb25maWc7XG4gICAgbGV0IHJvdXRpbmdEYXRhID0gc2VyaWFsaXplUmVtb3RlQ29uZmlnKGNvbmZpZ3VyZWQpO1xuICAgIGxldCByb3V0aW5nV3JpdGVUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBsZXQgdGFyZ2V0czogU291cmNlV3JhcHBlcltdID0gW107XG4gICAgbGV0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGxldCBzb3VyY2Ugb2Ygc291cmNlcykge1xuICAgICAgICBsZXQga2V5ID0gYCR7c291cmNlLmNvbmZpZy51cmx9fCR7c291cmNlLmNvbmZpZy5uYW1lfWA7XG4gICAgICAgIGlmIChzZWVuLmhhcyhrZXkpKSBjb250aW51ZTtcbiAgICAgICAgc2Vlbi5hZGQoa2V5KTtcbiAgICAgICAgdGFyZ2V0cy5wdXNoKHNvdXJjZSk7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGBXcml0aW5nIHJvdXRpbmcgY29uZmlnIHZlcnNpb24gJHtnZXRDb25maWdWZXJzaW9uKGNvbmZpZ3VyZWQpfSBmb3IgJHtkZWJ1Z05hbWV9IHRvIGFsbCAke3RhcmdldHMubGVuZ3RofSBzdG9yZXMgKHdyaXRlIHRpbWUgJHtuZXcgRGF0ZShyb3V0aW5nV3JpdGVUaW1lKS50b0lTT1N0cmluZygpfSk6ICR7dGFyZ2V0cy5tYXAoeCA9PiBgJHt4LmNvbmZpZy51cmx9IChzdG9yZSAke0pTT04uc3RyaW5naWZ5KHguY29uZmlnLm5hbWUpfSlgKS5qb2luKFwiLCBcIil9YCk7XG4gICAgbGV0IGZhaWx1cmVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKHRhcmdldHMubWFwKGFzeW5jIHNvdXJjZSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBzb3VyY2Uud3JpdGUoYXJjaGl2ZXMgPT4gYXJjaGl2ZXMuc2V0KFJPVVRJTkdfRklMRSwgcm91dGluZ0RhdGEsIHsgbGFzdE1vZGlmaWVkOiByb3V0aW5nV3JpdGVUaW1lIH0pKTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBXcm90ZSBzdG9yYWdlIHJvdXRpbmcgY29uZmlnIHZlcnNpb24gJHtnZXRDb25maWdWZXJzaW9uKGNvbmZpZ3VyZWQpfSB0byAke3NvdXJjZS5jb25maWcudXJsfSAoc3RvcmUgJHtKU09OLnN0cmluZ2lmeShzb3VyY2UuY29uZmlnLm5hbWUpfSlgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgZmFpbHVyZXMucHVzaChgJHtzb3VyY2UuY29uZmlnLnVybH0gKHN0b3JlICR7SlNPTi5zdHJpbmdpZnkoc291cmNlLmNvbmZpZy5uYW1lKX0pOiAkeyhlIGFzIEVycm9yKS5zdGFjayA/PyBlfWApO1xuICAgICAgICB9XG4gICAgfSkpO1xuICAgIHJldHVybiB7IGZhaWx1cmVzLCB0b3RhbDogdGFyZ2V0cy5sZW5ndGggfTtcbn1cblxuLyoqXG4gKiBUaGUgcGVyaW9kaWMgcmUtd3JpdGUgb2YgdGhlIGNoYWluJ3MgaW4tY29kZSBjb25maWc6IGZhaWx1cmVzIHJldHJpZWQgb24gdGhlIHNob3J0IGludGVydmFsIC0gYVxuICogc3RvcmUgd2l0aG91dCB0aGUgY29uZmlnIHJlamVjdHMgZXZlcnkgd3JpdGUgYWltZWQgYXQgaXQsIHNvIHRoaXMgbm90IGxhbmRpbmcgaXMgYSBiaWcgZGVhbCxcbiAqIGxvZ2dlZCBvbiBldmVyeSBhdHRlbXB0IC0gYW5kIGV2ZW4gc3VjY2VzcyByZXBlYXRlZCBob3VybHksIGluIGNhc2UgYSBzdG9yZSBsb3N0IGl0LiBUaGUgZmFpbHVyZVxuICogdGhpcyBleGlzdHMgZm9yOiBhIHNlcnZlciB3aG9zZSB0cnVzdCB3YXMgb25seSBncmFudGVkIEFGVEVSIHN0YXJ0dXAsIHNvIHRoZSBzdGFydHVwIHdyaXRlIHdhc1xuICogcmVqZWN0ZWQgYW5kIG5vdGhpbmcgZWxzZSB3b3VsZCBldmVyIHJldHJ5IGl0LlxuICovXG5leHBvcnQgY2xhc3MgUm91dGluZ1Jld3JpdGVMb29wIHtcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZzoge1xuICAgICAgICBjb25maWd1cmVkOiBSZW1vdGVDb25maWc7XG4gICAgICAgIGRlYnVnTmFtZTogKCkgPT4gc3RyaW5nO1xuICAgICAgICAvKiogVGhlIGNoYWluJ3MgbmV3ZXN0IGFkb3B0ZWQgc3RhdGU6IHdoYXQgZGVjaWRlcyB3aGV0aGVyIG91cnMgaXMgc3RpbGwgdGhlIGNvbmZpZyB0byB3cml0ZSwgYW5kIHRoZSBzb3VyY2VzIGl0IGlzIHdyaXR0ZW4gdGhyb3VnaC4gVW5kZWZpbmVkIHVudGlsIHRoZSBmaXJzdCBpbml0IGZpbmlzaGVzLiAqL1xuICAgICAgICBsYXRlc3Q6ICgpID0+IHsgY29uZmlnOiBSZW1vdGVDb25maWc7IHNvdXJjZXM6IFNvdXJjZVdyYXBwZXJbXSB9IHwgdW5kZWZpbmVkO1xuICAgIH0pIHsgfVxuXG4gICAgcHJpdmF0ZSB0aW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCB1bmRlZmluZWQ7XG4gICAgcHJpdmF0ZSBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqIChSZSlhcm1zIHRoZSBsb29wIC0gY2FsbGVkIGF0IHRoZSBlbmQgb2YgZXZlcnkgaW5pdCwgd2l0aCB3aGV0aGVyIHRoYXQgaW5pdCdzIHdyaXRlIGZhaWxlZCAod2hpY2ggcGlja3MgdGhlIHNob3J0IHJldHJ5IGludGVydmFsKS4gKi9cbiAgICBwdWJsaWMgc3RhcnQoZmFpbGVkQXRTdGFydHVwOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2NoZWR1bGUoZmFpbGVkQXRTdGFydHVwICYmIENPTkZJR19XUklURV9SRVRSWV9JTlRFUlZBTCB8fCBDT05GSUdfV1JJVEVfUkVGUkVTSF9JTlRFUlZBTCk7XG4gICAgfVxuXG4gICAgcHVibGljIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuICAgICAgICBpZiAodGhpcy50aW1lcikge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMudGltZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzY2hlZHVsZShkZWxheTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmRpc3Bvc2VkKSByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLnRpbWVyKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lcik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy50aW1lciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHZvaWQgdGhpcy5yZXdyaXRlKCkuY2F0Y2goKGU6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgUmV3cml0aW5nIHRoZSBzdG9yYWdlIHJvdXRpbmcgY29uZmlnIGZvciAke3RoaXMuY29uZmlnLmRlYnVnTmFtZSgpfSBmYWlsZWQ6ICR7ZS5zdGFjayA/PyBlfWApO1xuICAgICAgICAgICAgICAgIHRoaXMuc2NoZWR1bGUoQ09ORklHX1dSSVRFX1JFVFJZX0lOVEVSVkFMKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBkZWxheSk7XG4gICAgICAgICh0aGlzLnRpbWVyIGFzIHsgdW5yZWY/OiAoKSA9PiB2b2lkIH0pLnVucmVmPy4oKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJld3JpdGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLmRpc3Bvc2VkKSByZXR1cm47XG4gICAgICAgIGxldCBjb25maWd1cmVkID0gdGhpcy5jb25maWcuY29uZmlndXJlZDtcbiAgICAgICAgbGV0IHN0YXRlID0gdGhpcy5jb25maWcubGF0ZXN0KCk7XG4gICAgICAgIGlmICghc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuc2NoZWR1bGUoQ09ORklHX1dSSVRFX1JFVFJZX0lOVEVSVkFMKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgYnVja2V0IGFkb3B0ZWQgYSBORVdFUiBjb25maWcgdGhhbiBvdXIgaW4tY29kZSBvbmUsIHNvIG91cnMgaXMgc3RhbGUgYW5kIGV2ZXJ5IHN0b3JlIHdvdWxkIChyaWdodGx5KSByZWZ1c2UgaXRcbiAgICAgICAgaWYgKGdldENvbmZpZ1ZlcnNpb24oc3RhdGUuY29uZmlnKSA+IGdldENvbmZpZ1ZlcnNpb24oY29uZmlndXJlZCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2NoZWR1bGUoQ09ORklHX1dSSVRFX1JFRlJFU0hfSU5URVJWQUwpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNhbWUgdmVyc2lvbiBidXQgZGlmZmVyZW50IGNvbnRlbnQ6IHN0YXJ0dXAgYWxyZWFkeSBkZWNpZGVkIHRoZSBzdG9yZWQgb25lIHdpbnMgdW50aWwgdGhlIHZlcnNpb24gaXMgYnVtcGVkIChzZWUgY2hvb3NlU3RhcnR1cENvbmZpZyksIGFuZCByZS13cml0aW5nIG91cnMgd291bGQgZmxpcCB0aGUgYnVja2V0IGJhY2sgYW5kIGZvcnRoIGJldHdlZW4gdGhlIHR3b1xuICAgICAgICBpZiAoZ2V0Q29uZmlnVmVyc2lvbihzdGF0ZS5jb25maWcpID09PSBnZXRDb25maWdWZXJzaW9uKGNvbmZpZ3VyZWQpICYmIEpTT04uc3RyaW5naWZ5KHN0YXRlLmNvbmZpZykgIT09IEpTT04uc3RyaW5naWZ5KGNvbmZpZ3VyZWQpKSB7XG4gICAgICAgICAgICB0aGlzLnNjaGVkdWxlKENPTkZJR19XUklURV9SRUZSRVNIX0lOVEVSVkFMKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgeyBmYWlsdXJlcywgdG90YWwgfSA9IGF3YWl0IHdyaXRlUm91dGluZ1RvQWxsU3RvcmVzKHsgY29uZmlndXJlZCwgc291cmNlczogc3RhdGUuc291cmNlcywgZGVidWdOYW1lOiB0aGlzLmNvbmZpZy5kZWJ1Z05hbWUoKSB9KTtcbiAgICAgICAgaWYgKGZhaWx1cmVzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihgVGhlIHBlcmlvZGljIHJvdXRpbmcgY29uZmlnIHdyaXRlIGZvciAke3RoaXMuY29uZmlnLmRlYnVnTmFtZSgpfSAodmVyc2lvbiAke2dldENvbmZpZ1ZlcnNpb24oY29uZmlndXJlZCl9KSBmYWlsZWQgb24gJHtmYWlsdXJlcy5sZW5ndGh9IG9mICR7dG90YWx9IHN0b3JlcyAtIHJldHJ5aW5nIGluICR7Q09ORklHX1dSSVRFX1JFVFJZX0lOVEVSVkFMIC8gMTAwMH1zOiAke2ZhaWx1cmVzLmpvaW4oXCIgfCBcIil9YCk7XG4gICAgICAgICAgICB0aGlzLnNjaGVkdWxlKENPTkZJR19XUklURV9SRVRSWV9JTlRFUlZBTCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zY2hlZHVsZShDT05GSUdfV1JJVEVfUkVGUkVTSF9JTlRFUlZBTCk7XG4gICAgfVxufVxuIl19
466
+ /* _JS_SOURCE_HASH = "d36ce7c1c47d19c7a2c75d2ec689971b811cf13f66d47cb04f742490229aa5d8"; */