sliftutils 1.7.85 → 1.7.87

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.
@@ -117,8 +117,10 @@ function computeStorePlan(account, bucketName, routing) {
117
117
  }
118
118
  diskWindow = [start, end];
119
119
  }
120
- let sourceSpecs = [{ validWindow: diskWindow }];
120
+ let sourceSpecs = [{ validWindows: [diskWindow] }];
121
121
  let noFullSync = group.entries.some(x => x.noFullSync);
122
+ // The same peer endpoint (url+route+flags) can appear under several windows at once (a switchover splits one window around an intermediate). It is ONE sync source that carries ALL those windows - never several sources, which would double-scan it and, worse, make matching a request depend on which window the caller happened to hold.
123
+ let peerByKey = new Map();
122
124
  for (let i = group.firstIndex + 1; i < routing.sources.length; i++) {
123
125
  let source = routing.sources[i];
124
126
  if (typeof source === "string" || ownIndexes.has(i))
@@ -126,7 +128,14 @@ function computeStorePlan(account, bucketName, routing) {
126
128
  let sharedRoute = (0, remoteConfig_1.routeIntersection)(group.route, source.route);
127
129
  if (!sharedRoute)
128
130
  continue;
129
- sourceSpecs.push({ sourceConfig: source, validWindow: source.validWindow, route: sharedRoute, noFullSync: source.noFullSync || noFullSync });
131
+ let key = JSON.stringify({ ...source, validWindow: undefined });
132
+ let spec = peerByKey.get(key);
133
+ if (!spec) {
134
+ spec = { sourceConfig: source, validWindows: [], route: sharedRoute, noFullSync: source.noFullSync || noFullSync };
135
+ peerByKey.set(key, spec);
136
+ sourceSpecs.push(spec);
137
+ }
138
+ spec.validWindows.push(source.validWindow);
130
139
  }
131
140
  stores.push({
132
141
  routeKey,
@@ -139,11 +148,11 @@ function computeStorePlan(account, bucketName, routing) {
139
148
  }
140
149
  if (!stores.length) {
141
150
  // Not in the config at all: still serve whatever the plain folder holds, through one inert full-route store
142
- stores.push({ routeKey: JSON.stringify(IArchives_1.FULL_ROUTE), route: undefined, entries: [], rawDisk: false, readerDiskLimit: undefined, sourceSpecs: [{ validWindow: [0, 0] }] });
151
+ stores.push({ routeKey: JSON.stringify(IArchives_1.FULL_ROUTE), route: undefined, entries: [], rawDisk: false, readerDiskLimit: undefined, sourceSpecs: [{ validWindows: [[0, 0]] }] });
143
152
  }
144
153
  let structureKey = JSON.stringify(stores.map(s => ({ routeKey: s.routeKey, rawDisk: s.rawDisk, readerDiskLimit: s.readerDiskLimit })));
145
154
  return { selfEntries, self, stores, structureKey };
146
155
  }
147
156
  exports.computeStorePlan = computeStorePlan;
148
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmVQbGFuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmVQbGFuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1EQUFnRDtBQUNoRCw0Q0FBb0Y7QUFDcEYsaURBQWtGO0FBQ2xGLGlEQUE4QztBQUU5QyxnTEFBZ0w7QUFFaEwsU0FBZ0IsZUFBZSxDQUFDLE9BQXFCLEVBQUUsT0FBZSxFQUFFLFVBQWtCO0lBQ3RGLElBQUksT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUMzQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM5QyxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUTtZQUFFLFNBQVM7UUFDckUsSUFBSSxNQUFNLEdBQUcsSUFBQSw2QkFBYyxFQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QyxJQUFJLE1BQU0sQ0FBQyxPQUFPLEtBQUssT0FBTyxJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssVUFBVTtZQUFFLFNBQVM7UUFDN0UsSUFBSSxJQUFBLDJCQUFZLEVBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUM1QyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BCLENBQUM7SUFDTCxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDbkIsQ0FBQztBQVpELDBDQVlDO0FBRUQsU0FBZ0IsYUFBYSxDQUFDLE9BQXVCLEVBQUUsSUFBWSxFQUFFLEtBQWM7SUFDL0UsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDdEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxD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QUFLLEVBQUUsZUFBZSxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdLLENBQUM7SUFDRCxJQUFJLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2SSxPQUFPLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUM7QUFDdkQsQ0FBQztBQTlERCw0Q0E4REMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzb3J0IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuaW1wb3J0IHsgUmVtb3RlQ29uZmlnLCBIb3N0ZWRDb25maWcsIFNvdXJjZUNvbmZpZywgRlVMTF9ST1VURSB9IGZyb20gXCIuLi9JQXJjaGl2ZXNcIjtcbmltcG9ydCB7IHBhcnNlSG9zdGVkVXJsLCByb3V0ZUNvbnRhaW5zLCByb3V0ZUludGVyc2VjdGlvbiB9IGZyb20gXCIuL3JlbW90ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgaXNPd25BZGRyZXNzIH0gZnJvbSBcIi4vc2VydmVyQ29uZmlnXCI7XG5cbi8vIFR1cm5zIGEgYnVja2V0J3Mgcm91dGluZyBjb25maWcgaW50byB0aGlzIHNlcnZlcidzIHN0b3JlIHBsYW46IHdoaWNoIG9mIHRoZSBlbnRyaWVzIGFyZSB1cywgd2hhdCBzdG9yZXMgKG9uZSBwZXIgcm91dGUpIHdlIHJ1biwgYW5kIHdoaWNoIHBlZXJzIGVhY2ggc3RvcmUgc3luY2hyb25pemVzIGZyb20uXG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kU2VsZkluZGV4ZXMocm91dGluZzogUmVtb3RlQ29uZmlnLCBhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IG51bWJlcltdIHtcbiAgICBsZXQgaW5kZXhlczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvdXRpbmcuc291cmNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgc291cmNlID0gcm91dGluZy5zb3VyY2VzW2ldO1xuICAgICAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJzdHJpbmdcIiB8fCBzb3VyY2UudHlwZSAhPT0gXCJyZW1vdGVcIikgY29udGludWU7XG4gICAgICAgIGxldCBwYXJzZWQgPSBwYXJzZUhvc3RlZFVybChzb3VyY2UudXJsKTtcbiAgICAgICAgaWYgKHBhcnNlZC5hY2NvdW50ICE9PSBhY2NvdW50IHx8IHBhcnNlZC5idWNrZXROYW1lICE9PSBidWNrZXROYW1lKSBjb250aW51ZTtcbiAgICAgICAgaWYgKGlzT3duQWRkcmVzcyhwYXJzZWQuYWRkcmVzcywgcGFyc2VkLnBvcnQpKSB7XG4gICAgICAgICAgICBpbmRleGVzLnB1c2goaSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGluZGV4ZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3RFbnRyeUF0KGVudHJpZXM6IEhvc3RlZENvbmZpZ1tdLCB0aW1lOiBudW1iZXIsIHJvdXRlPzogbnVtYmVyKTogSG9zdGVkQ29uZmlnIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAocm91dGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBsZXQgY292ZXJpbmcgPSBlbnRyaWVzLmZpbHRlcih4ID0+IHJvdXRlQ29udGFpbnMoeC5yb3V0ZSwgcm91dGUpKTtcbiAgICAgICAgaWYgKGNvdmVyaW5nLmxlbmd0aCkge1xuICAgICAgICAgICAgZW50cmllcyA9IGNvdmVyaW5nO1xuICAgICAgICB9XG4gICAgfVxuICAgIGxldCBjb250YWluaW5nID0gZW50cmllcy5maW5kKHggPT4geC52YWxpZFdpbmRvd1swXSA8PSB0aW1lICYmIHRpbWUgPCB4LnZhbGlkV2luZG93WzFdKTtcbiAgICBpZiAoY29udGFpbmluZykgcmV0dXJuIGNvbnRhaW5pbmc7XG4gICAgbGV0IGJlc3Q6IEhvc3RlZENvbmZpZyB8IHVuZGVmaW5lZDtcbiAgICBsZXQgYmVzdERpc3RhbmNlID0gSW5maW5pdHk7XG4gICAgZm9yIChsZXQgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICBsZXQgZGlzdGFuY2UgPSBNYXRoLm1pbihNYXRoLmFicyh0aW1lIC0gZW50cnkudmFsaWRXaW5kb3dbMF0pLCBNYXRoLmFicyh0aW1lIC0gZW50cnkudmFsaWRXaW5kb3dbMV0pKTtcbiAgICAgICAgaWYgKGRpc3RhbmNlIDwgYmVzdERpc3RhbmNlKSB7XG4gICAgICAgICAgICBiZXN0RGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICAgICAgICAgIGJlc3QgPSBlbnRyeTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYmVzdDtcbn1cblxuLyoqIE91ciByb2xlIGluIGEgYnVja2V0J3Mgcm91dGluZyBjb25maWcsIHN1bW1hcml6ZWQgYWNyb3NzIEFMTCBjdXJyZW50bHktdmFsaWQgc2VsZiBlbnRyaWVzLiBTdG9yZWQgaW5zdGVhZCBvZiBhIHNpbmdsZSByZXByZXNlbnRhdGl2ZSBIb3N0ZWRDb25maWcsIHNvIG5vdGhpbmcgY2FuIGFjY2lkZW50YWxseSB1c2Ugb25lIGVudHJ5J3Mgcm91dGUgb3IgZmxhZ3Mgd2hlcmUgdGhlIHVuaW9uIGlzIHJlcXVpcmVkIC0gdGhlIHN0YW5kYXJkIGNvbmZpZyBoYXMgdGhlIHNhbWUgVVJMIHR3aWNlOiBhIHJvdXRlZCB3cml0ZS1zaGFyZCBlbnRyeSBwbHVzIGFuIHVucm91dGVkIHJlYWQtZXZlcnl0aGluZyBlbnRyeS4gKi9cbmV4cG9ydCB0eXBlIFNlbGZTdW1tYXJ5ID0ge1xuICAgIC8qKiBUaGUgdW5pb24gb2YgdGhlIGN1cnJlbnQgZW50cmllcycgcm91dGVzLCB3aXRoIG92ZXJsYXBwaW5nL2FkamFjZW50IHJhbmdlcyBjb21iaW5lZCAtIHdoaWNoIGNvbW1vbmx5IGNvbGxhcHNlcyB0byBhIHNpbmdsZSBmdWxsIHJhbmdlLCBtYWtpbmcgbWF0Y2hpbmcgdHJpdmlhbC4gKi9cbiAgICByb3V0ZXM6IFtudW1iZXIsIG51bWJlcl1bXTtcbiAgICBwdWJsaWM6IGJvb2xlYW47XG4gICAgaW1tdXRhYmxlOiBib29sZWFuO1xuICAgIG5vRnVsbFN5bmM6IGJvb2xlYW47XG4gICAgcmF3RGlzazogYm9vbGVhbjtcbiAgICByZWFkZXJEaXNrTGltaXQ/OiBudW1iZXI7XG59O1xuXG5mdW5jdGlvbiBtZXJnZVJvdXRlcyhyb3V0ZXM6IChbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkKVtdKTogW251bWJlciwgbnVtYmVyXVtdIHtcbiAgICBsZXQgbGlzdCA9IHJvdXRlcy5tYXAoeCA9PiB4IHx8IEZVTExfUk9VVEUpLm1hcCh4ID0+IFt4WzBdLCB4WzFdXSBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgICBzb3J0KGxpc3QsIHggPT4geFswXSk7XG4gICAgbGV0IG1lcmdlZDogW251bWJlciwgbnVtYmVyXVtdID0gW107XG4gICAgZm9yIChsZXQgcm91dGUgb2YgbGlzdCkge1xuICAgICAgICBsZXQgbGFzdCA9IG1lcmdlZFttZXJnZWQubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmIChsYXN0ICYmIHJvdXRlWzBdIDw9IGxhc3RbMV0pIHtcbiAgICAgICAgICAgIGxhc3RbMV0gPSBNYXRoLm1heChsYXN0WzFdLCByb3V0ZVsxXSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBtZXJnZWQucHVzaChyb3V0ZSk7XG4gICAgfVxuICAgIHJldHVybiBtZXJnZWQ7XG59XG5cbmZ1bmN0aW9uIHN1bW1hcml6ZVNlbGYoc2VsZkVudHJpZXM6IEhvc3RlZENvbmZpZ1tdLCBub3c6IG51bWJlcik6IFNlbGZTdW1tYXJ5IHwgdW5kZWZpbmVkIHtcbiAgICBsZXQgY3VycmVudCA9IHNlbGZFbnRyaWVzLmZpbHRlcih4ID0+IHgudmFsaWRXaW5kb3dbMF0gPD0gbm93ICYmIG5vdyA8IHgudmFsaWRXaW5kb3dbMV0pO1xuICAgIGlmICghY3VycmVudC5sZW5ndGgpIHtcbiAgICAgICAgbGV0IG5lYXJlc3QgPSBzZWxlY3RFbnRyeUF0KHNlbGZFbnRyaWVzLCBub3cpO1xuICAgICAgICBjdXJyZW50ID0gbmVhcmVzdCAmJiBbbmVhcmVzdF0gfHwgW107XG4gICAgfVxuICAgIGlmICghY3VycmVudC5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcm91dGVzOiBtZXJnZVJvdXRlcyhjdXJyZW50Lm1hcCh4ID0+IHgucm91dGUpKSxcbiAgICAgICAgcHVibGljOiBjdXJyZW50LnNvbWUoeCA9PiB4LnB1YmxpYyksXG4gICAgICAgIGltbXV0YWJsZTogY3VycmVudC5zb21lKHggPT4geC5pbW11dGFibGUpLFxuICAgICAgICBub0Z1bGxTeW5jOiBjdXJyZW50LnNvbWUoeCA9PiB4Lm5vRnVsbFN5bmMpLFxuICAgICAgICByYXdEaXNrOiBjdXJyZW50LnNvbWUoeCA9PiB4LnJhd0Rpc2spLFxuICAgICAgICByZWFkZXJEaXNrTGltaXQ6IGN1cnJlbnQuZmluZCh4ID0+IHgucmVhZGVyRGlza0xpbWl0ICE9PSB1bmRlZmluZWQpPy5yZWFkZXJEaXNrTGltaXQsXG4gICAgfTtcbn1cblxuZXhwb3J0IHR5cGUgU3RvcmVTb3VyY2VTcGVjID0geyBzb3VyY2VDb25maWc/OiBTb3VyY2VDb25maWc7IHZhbGlkV2luZG93OiBbbnVtYmVyLCBudW1iZXJdOyByb3V0ZT86IFtudW1iZXIsIG51bWJlcl07IG5vRnVsbFN5bmM/OiBib29sZWFuIH07XG5leHBvcnQgdHlwZSBTdG9yZVBsYW5TdG9yZSA9IHtcbiAgICByb3V0ZUtleTogc3RyaW5nO1xuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICBlbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICByYXdEaXNrOiBib29sZWFuO1xuICAgIHJlYWRlckRpc2tMaW1pdD86IG51bWJlcjtcbiAgICBzb3VyY2VTcGVjczogU3RvcmVTb3VyY2VTcGVjW107XG59O1xuZXhwb3J0IHR5cGUgU3RvcmVQbGFuID0ge1xuICAgIHNlbGZFbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICBzZWxmOiBTZWxmU3VtbWFyeSB8IHVuZGVmaW5lZDtcbiAgICBzdG9yZXM6IFN0b3JlUGxhblN0b3JlW107XG4gICAgc3RydWN0dXJlS2V5OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZVN0b3JlUGxhbihhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgcm91dGluZzogUmVtb3RlQ29uZmlnKTogU3RvcmVQbGFuIHtcbiAgICBsZXQgc2VsZkluZGV4ZXMgPSBmaW5kU2VsZkluZGV4ZXMocm91dGluZywgYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHNlbGZFbnRyaWVzID0gc2VsZkluZGV4ZXMubWFwKGkgPT4gcm91dGluZy5zb3VyY2VzW2ldIGFzIEhvc3RlZENvbmZpZyk7XG4gICAgbGV0IHNlbGYgPSBzdW1tYXJpemVTZWxmKHNlbGZFbnRyaWVzLCBEYXRlLm5vdygpKTtcbiAgICBsZXQgb3duSW5kZXhlcyA9IG5ldyBTZXQoc2VsZkluZGV4ZXMpO1xuICAgIC8vIE9uZSBzdG9yZSBwZXIgZGlzdGluY3Qgcm91dGUgYW1vbmcgQUxMIG91ciBlbnRyaWVzIC0gcGFzdCBhbmQgZnV0dXJlIHdpbmRvd3MgaW5jbHVkZWQsIHNvIGhpc3RvcmljYWwgcm91dGUgZm9sZGVycyBrZWVwIHNlcnZpbmcgdGhlaXIgZGF0YSBhbmQgdXBjb21pbmcgcm91dGVzIHN5bmMgYWhlYWQgb2YgdGhlaXIgd2luZG93XG4gICAgbGV0IGdyb3VwcyA9IG5ldyBNYXA8c3RyaW5nLCB7IHJvdXRlPzogW251bWJlciwgbnVtYmVyXTsgZW50cmllczogSG9zdGVkQ29uZmlnW107IGZpcnN0SW5kZXg6IG51bWJlciB9PigpO1xuICAgIGZvciAobGV0IGkgb2Ygc2VsZkluZGV4ZXMpIHtcbiAgICAgICAgbGV0IGVudHJ5ID0gcm91dGluZy5zb3VyY2VzW2ldIGFzIEhvc3RlZENvbmZpZztcbiAgICAgICAgbGV0IHJvdXRlS2V5ID0gSlNPTi5zdHJpbmdpZnkoZW50cnkucm91dGUgfHwgRlVMTF9ST1VURSk7XG4gICAgICAgIGxldCBncm91cCA9IGdyb3Vwcy5nZXQocm91dGVLZXkpO1xuICAgICAgICBpZiAoIWdyb3VwKSB7XG4gICAgICAgICAgICBncm91cCA9IHsgcm91dGU6IGVudHJ5LnJvdXRlLCBlbnRyaWVzOiBbXSwgZmlyc3RJbmRleDogaSB9O1xuICAgICAgICAgICAgZ3JvdXBzLnNldChyb3V0ZUtleSwgZ3JvdXApO1xuICAgICAgICB9XG4gICAgICAgIGdyb3VwLmVudHJpZXMucHVzaChlbnRyeSk7XG4gICAgfVxuICAgIGxldCBzdG9yZXM6IFN0b3JlUGxhblN0b3JlW10gPSBbXTtcbiAgICBmb3IgKGxldCBbcm91dGVLZXksIGdyb3VwXSBvZiBncm91cHMpIHtcbiAgICAgICAgbGV0IGFuY2hvciA9IHNlbGVjdEVudHJ5QXQoZ3JvdXAuZW50cmllcywgRGF0ZS5ub3coKSk7XG4gICAgICAgIGxldCBkaXNrV2luZG93OiBbbnVtYmVyLCBudW1iZXJdID0gWzAsIDBdO1xuICAgICAgICBpZiAoYW5jaG9yKSB7XG4gICAgICAgICAgICBsZXQgW3N0YXJ0LCBlbmRdID0gYW5jaG9yLnZhbGlkV2luZG93O1xuICAgICAgICAgICAgbGV0IG1lcmdlZCA9IHRydWU7XG4gICAgICAgICAgICB3aGlsZSAobWVyZ2VkKSB7XG4gICAgICAgICAgICAgICAgbWVyZ2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgZW50cnkgb2YgZ3JvdXAuZW50cmllcykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgW2VudHJ5U3RhcnQsIGVudHJ5RW5kXSA9IGVudHJ5LnZhbGlkV2luZG93O1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnlTdGFydCA+IGVuZCB8fCBlbnRyeUVuZCA8IHN0YXJ0KSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVudHJ5U3RhcnQgPCBzdGFydCB8fCBlbnRyeUVuZCA+IGVuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQgPSBNYXRoLm1pbihzdGFydCwgZW50cnlTdGFydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBNYXRoLm1heChlbmQsIGVudHJ5RW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXNrV2luZG93ID0gW3N0YXJ0LCBlbmRdO1xuICAgICAgICB9XG4gICAgICAgIGxldCBzb3VyY2VTcGVjczogU3RvcmVTb3VyY2VTcGVjW10gPSBbeyB2YWxpZFdpbmRvdzogZGlza1dpbmRvdyB9XTtcbiAgICAgICAgbGV0IG5vRnVsbFN5bmMgPSBncm91cC5lbnRyaWVzLnNvbWUoeCA9PiB4Lm5vRnVsbFN5bmMpO1xuICAgICAgICBmb3IgKGxldCBpID0gZ3JvdXAuZmlyc3RJbmRleCArIDE7IGkgPCByb3V0aW5nLnNvdXJjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxldCBzb3VyY2UgPSByb3V0aW5nLnNvdXJjZXNbaV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJzdHJpbmdcIiB8fCBvd25JbmRleGVzLmhhcyhpKSkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgc2hhcmVkUm91dGUgPSByb3V0ZUludGVyc2VjdGlvbihncm91cC5yb3V0ZSwgc291cmNlLnJvdXRlKTtcbiAgICAgICAgICAgIGlmICghc2hhcmVkUm91dGUpIGNvbnRpbnVlO1xuICAgICAgICAgICAgc291cmNlU3BlY3MucHVzaCh7IHNvdXJjZUNvbmZpZzogc291cmNlLCB2YWxpZFdpbmRvdzogc291cmNlLnZhbGlkV2luZG93LCByb3V0ZTogc2hhcmVkUm91dGUsIG5vRnVsbFN5bmM6IHNvdXJjZS5ub0Z1bGxTeW5jIHx8IG5vRnVsbFN5bmMgfSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RvcmVzLnB1c2goe1xuICAgICAgICAgICAgcm91dGVLZXksXG4gICAgICAgICAgICByb3V0ZTogZ3JvdXAucm91dGUsXG4gICAgICAgICAgICBlbnRyaWVzOiBncm91cC5lbnRyaWVzLFxuICAgICAgICAgICAgcmF3RGlzazogZ3JvdXAuZW50cmllcy5zb21lKHggPT4geC5yYXdEaXNrKSxcbiAgICAgICAgICAgIHJlYWRlckRpc2tMaW1pdDogZ3JvdXAuZW50cmllcy5maW5kKHggPT4geC5yZWFkZXJEaXNrTGltaXQgIT09IHVuZGVmaW5lZCk/LnJlYWRlckRpc2tMaW1pdCxcbiAgICAgICAgICAgIHNvdXJjZVNwZWNzLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYgKCFzdG9yZXMubGVuZ3RoKSB7XG4gICAgICAgIC8vIE5vdCBpbiB0aGUgY29uZmlnIGF0IGFsbDogc3RpbGwgc2VydmUgd2hhdGV2ZXIgdGhlIHBsYWluIGZvbGRlciBob2xkcywgdGhyb3VnaCBvbmUgaW5lcnQgZnVsbC1yb3V0ZSBzdG9yZVxuICAgICAgICBzdG9yZXMucHVzaCh7IHJvdXRlS2V5OiBKU09OLnN0cmluZ2lmeShGVUxMX1JPVVRFKSwgcm91dGU6IHVuZGVmaW5lZCwgZW50cmllczogW10sIHJhd0Rpc2s6IGZhbHNlLCByZWFkZXJEaXNrTGltaXQ6IHVuZGVmaW5lZCwgc291cmNlU3BlY3M6IFt7IHZhbGlkV2luZG93OiBbMCwgMF0gfV0gfSk7XG4gICAgfVxuICAgIGxldCBzdHJ1Y3R1cmVLZXkgPSBKU09OLnN0cmluZ2lmeShzdG9yZXMubWFwKHMgPT4gKHsgcm91dGVLZXk6IHMucm91dGVLZXksIHJhd0Rpc2s6IHMucmF3RGlzaywgcmVhZGVyRGlza0xpbWl0OiBzLnJlYWRlckRpc2tMaW1pdCB9KSkpO1xuICAgIHJldHVybiB7IHNlbGZFbnRyaWVzLCBzZWxmLCBzdG9yZXMsIHN0cnVjdHVyZUtleSB9O1xufVxuIl19
149
- /* _JS_SOURCE_HASH = "9bef0980db5b25c667b14368838cb733860e13722b222e7c53ddcfb8e53ba4fb"; */
157
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmVQbGFuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmVQbGFuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1EQUFnRDtBQUNoRCw0Q0FBb0Y7QUFDcEYsaURBQWtGO0FBQ2xGLGlEQUE4QztBQUU5QyxnTEFBZ0w7QUFFaEwsU0FBZ0IsZUFBZSxDQUFDLE9BQXFCLEVBQUUsT0FBZSxFQUFFLFVBQWtCO0lBQ3RGLElBQUksT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUMzQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM5QyxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUTtZQUFFLFNBQVM7UUFDckUsSUFBSSxNQUFNLEdBQUcsSUFBQSw2QkFBYyxFQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QyxJQUFJLE1BQU0sQ0FBQyxPQUFPLEtBQUssT0FBTyxJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssVUFBVTtZQUFFLFNBQVM7UUFDN0UsSUFBSSxJQUFBLDJCQUFZLEVBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUM1QyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BCLENBQUM7SUFDTCxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDbkIsQ0FBQztBQVpELDBDQVlDO0FBRUQsU0FBZ0IsYUFBYSxDQUFDLE9BQXVCLEVBQUUsSUFBWSxFQUFFLEtBQWM7SUFDL0UsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDdEIsSUFBSSxRQUFRLEdBQUcsT0FBTyxD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QUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDM0MsZUFBZSxFQUFFLE1BQUEsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsZUFBZSxLQUFLLFNBQVMsQ0FBQywwQ0FBRSxlQUFlO1lBQzFGLFdBQVc7U0FDZCxDQUFDLENBQUM7SUFDUCxDQUFDO0lBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNqQiw0R0FBNEc7UUFDNUcsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLHNCQUFVLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2hMLENBQUM7SUFDRCxJQUFJLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2SSxPQUFPLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUM7QUFDdkQsQ0FBQztBQXZFRCw0Q0F1RUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzb3J0IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuaW1wb3J0IHsgUmVtb3RlQ29uZmlnLCBIb3N0ZWRDb25maWcsIFNvdXJjZUNvbmZpZywgRlVMTF9ST1VURSB9IGZyb20gXCIuLi9JQXJjaGl2ZXNcIjtcbmltcG9ydCB7IHBhcnNlSG9zdGVkVXJsLCByb3V0ZUNvbnRhaW5zLCByb3V0ZUludGVyc2VjdGlvbiB9IGZyb20gXCIuL3JlbW90ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgaXNPd25BZGRyZXNzIH0gZnJvbSBcIi4vc2VydmVyQ29uZmlnXCI7XG5cbi8vIFR1cm5zIGEgYnVja2V0J3Mgcm91dGluZyBjb25maWcgaW50byB0aGlzIHNlcnZlcidzIHN0b3JlIHBsYW46IHdoaWNoIG9mIHRoZSBlbnRyaWVzIGFyZSB1cywgd2hhdCBzdG9yZXMgKG9uZSBwZXIgcm91dGUpIHdlIHJ1biwgYW5kIHdoaWNoIHBlZXJzIGVhY2ggc3RvcmUgc3luY2hyb25pemVzIGZyb20uXG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kU2VsZkluZGV4ZXMocm91dGluZzogUmVtb3RlQ29uZmlnLCBhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IG51bWJlcltdIHtcbiAgICBsZXQgaW5kZXhlczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvdXRpbmcuc291cmNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgc291cmNlID0gcm91dGluZy5zb3VyY2VzW2ldO1xuICAgICAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJzdHJpbmdcIiB8fCBzb3VyY2UudHlwZSAhPT0gXCJyZW1vdGVcIikgY29udGludWU7XG4gICAgICAgIGxldCBwYXJzZWQgPSBwYXJzZUhvc3RlZFVybChzb3VyY2UudXJsKTtcbiAgICAgICAgaWYgKHBhcnNlZC5hY2NvdW50ICE9PSBhY2NvdW50IHx8IHBhcnNlZC5idWNrZXROYW1lICE9PSBidWNrZXROYW1lKSBjb250aW51ZTtcbiAgICAgICAgaWYgKGlzT3duQWRkcmVzcyhwYXJzZWQuYWRkcmVzcywgcGFyc2VkLnBvcnQpKSB7XG4gICAgICAgICAgICBpbmRleGVzLnB1c2goaSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGluZGV4ZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3RFbnRyeUF0KGVudHJpZXM6IEhvc3RlZENvbmZpZ1tdLCB0aW1lOiBudW1iZXIsIHJvdXRlPzogbnVtYmVyKTogSG9zdGVkQ29uZmlnIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAocm91dGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBsZXQgY292ZXJpbmcgPSBlbnRyaWVzLmZpbHRlcih4ID0+IHJvdXRlQ29udGFpbnMoeC5yb3V0ZSwgcm91dGUpKTtcbiAgICAgICAgaWYgKGNvdmVyaW5nLmxlbmd0aCkge1xuICAgICAgICAgICAgZW50cmllcyA9IGNvdmVyaW5nO1xuICAgICAgICB9XG4gICAgfVxuICAgIGxldCBjb250YWluaW5nID0gZW50cmllcy5maW5kKHggPT4geC52YWxpZFdpbmRvd1swXSA8PSB0aW1lICYmIHRpbWUgPCB4LnZhbGlkV2luZG93WzFdKTtcbiAgICBpZiAoY29udGFpbmluZykgcmV0dXJuIGNvbnRhaW5pbmc7XG4gICAgbGV0IGJlc3Q6IEhvc3RlZENvbmZpZyB8IHVuZGVmaW5lZDtcbiAgICBsZXQgYmVzdERpc3RhbmNlID0gSW5maW5pdHk7XG4gICAgZm9yIChsZXQgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICBsZXQgZGlzdGFuY2UgPSBNYXRoLm1pbihNYXRoLmFicyh0aW1lIC0gZW50cnkudmFsaWRXaW5kb3dbMF0pLCBNYXRoLmFicyh0aW1lIC0gZW50cnkudmFsaWRXaW5kb3dbMV0pKTtcbiAgICAgICAgaWYgKGRpc3RhbmNlIDwgYmVzdERpc3RhbmNlKSB7XG4gICAgICAgICAgICBiZXN0RGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICAgICAgICAgIGJlc3QgPSBlbnRyeTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYmVzdDtcbn1cblxuLyoqIE91ciByb2xlIGluIGEgYnVja2V0J3Mgcm91dGluZyBjb25maWcsIHN1bW1hcml6ZWQgYWNyb3NzIEFMTCBjdXJyZW50bHktdmFsaWQgc2VsZiBlbnRyaWVzLiBTdG9yZWQgaW5zdGVhZCBvZiBhIHNpbmdsZSByZXByZXNlbnRhdGl2ZSBIb3N0ZWRDb25maWcsIHNvIG5vdGhpbmcgY2FuIGFjY2lkZW50YWxseSB1c2Ugb25lIGVudHJ5J3Mgcm91dGUgb3IgZmxhZ3Mgd2hlcmUgdGhlIHVuaW9uIGlzIHJlcXVpcmVkIC0gdGhlIHN0YW5kYXJkIGNvbmZpZyBoYXMgdGhlIHNhbWUgVVJMIHR3aWNlOiBhIHJvdXRlZCB3cml0ZS1zaGFyZCBlbnRyeSBwbHVzIGFuIHVucm91dGVkIHJlYWQtZXZlcnl0aGluZyBlbnRyeS4gKi9cbmV4cG9ydCB0eXBlIFNlbGZTdW1tYXJ5ID0ge1xuICAgIC8qKiBUaGUgdW5pb24gb2YgdGhlIGN1cnJlbnQgZW50cmllcycgcm91dGVzLCB3aXRoIG92ZXJsYXBwaW5nL2FkamFjZW50IHJhbmdlcyBjb21iaW5lZCAtIHdoaWNoIGNvbW1vbmx5IGNvbGxhcHNlcyB0byBhIHNpbmdsZSBmdWxsIHJhbmdlLCBtYWtpbmcgbWF0Y2hpbmcgdHJpdmlhbC4gKi9cbiAgICByb3V0ZXM6IFtudW1iZXIsIG51bWJlcl1bXTtcbiAgICBwdWJsaWM6IGJvb2xlYW47XG4gICAgaW1tdXRhYmxlOiBib29sZWFuO1xuICAgIG5vRnVsbFN5bmM6IGJvb2xlYW47XG4gICAgcmF3RGlzazogYm9vbGVhbjtcbiAgICByZWFkZXJEaXNrTGltaXQ/OiBudW1iZXI7XG59O1xuXG5mdW5jdGlvbiBtZXJnZVJvdXRlcyhyb3V0ZXM6IChbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkKVtdKTogW251bWJlciwgbnVtYmVyXVtdIHtcbiAgICBsZXQgbGlzdCA9IHJvdXRlcy5tYXAoeCA9PiB4IHx8IEZVTExfUk9VVEUpLm1hcCh4ID0+IFt4WzBdLCB4WzFdXSBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgICBzb3J0KGxpc3QsIHggPT4geFswXSk7XG4gICAgbGV0IG1lcmdlZDogW251bWJlciwgbnVtYmVyXVtdID0gW107XG4gICAgZm9yIChsZXQgcm91dGUgb2YgbGlzdCkge1xuICAgICAgICBsZXQgbGFzdCA9IG1lcmdlZFttZXJnZWQubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmIChsYXN0ICYmIHJvdXRlWzBdIDw9IGxhc3RbMV0pIHtcbiAgICAgICAgICAgIGxhc3RbMV0gPSBNYXRoLm1heChsYXN0WzFdLCByb3V0ZVsxXSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBtZXJnZWQucHVzaChyb3V0ZSk7XG4gICAgfVxuICAgIHJldHVybiBtZXJnZWQ7XG59XG5cbmZ1bmN0aW9uIHN1bW1hcml6ZVNlbGYoc2VsZkVudHJpZXM6IEhvc3RlZENvbmZpZ1tdLCBub3c6IG51bWJlcik6IFNlbGZTdW1tYXJ5IHwgdW5kZWZpbmVkIHtcbiAgICBsZXQgY3VycmVudCA9IHNlbGZFbnRyaWVzLmZpbHRlcih4ID0+IHgudmFsaWRXaW5kb3dbMF0gPD0gbm93ICYmIG5vdyA8IHgudmFsaWRXaW5kb3dbMV0pO1xuICAgIGlmICghY3VycmVudC5sZW5ndGgpIHtcbiAgICAgICAgbGV0IG5lYXJlc3QgPSBzZWxlY3RFbnRyeUF0KHNlbGZFbnRyaWVzLCBub3cpO1xuICAgICAgICBjdXJyZW50ID0gbmVhcmVzdCAmJiBbbmVhcmVzdF0gfHwgW107XG4gICAgfVxuICAgIGlmICghY3VycmVudC5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcm91dGVzOiBtZXJnZVJvdXRlcyhjdXJyZW50Lm1hcCh4ID0+IHgucm91dGUpKSxcbiAgICAgICAgcHVibGljOiBjdXJyZW50LnNvbWUoeCA9PiB4LnB1YmxpYyksXG4gICAgICAgIGltbXV0YWJsZTogY3VycmVudC5zb21lKHggPT4geC5pbW11dGFibGUpLFxuICAgICAgICBub0Z1bGxTeW5jOiBjdXJyZW50LnNvbWUoeCA9PiB4Lm5vRnVsbFN5bmMpLFxuICAgICAgICByYXdEaXNrOiBjdXJyZW50LnNvbWUoeCA9PiB4LnJhd0Rpc2spLFxuICAgICAgICByZWFkZXJEaXNrTGltaXQ6IGN1cnJlbnQuZmluZCh4ID0+IHgucmVhZGVyRGlza0xpbWl0ICE9PSB1bmRlZmluZWQpPy5yZWFkZXJEaXNrTGltaXQsXG4gICAgfTtcbn1cblxuZXhwb3J0IHR5cGUgU3RvcmVTb3VyY2VTcGVjID0geyBzb3VyY2VDb25maWc/OiBTb3VyY2VDb25maWc7IHZhbGlkV2luZG93czogW251bWJlciwgbnVtYmVyXVtdOyByb3V0ZT86IFtudW1iZXIsIG51bWJlcl07IG5vRnVsbFN5bmM/OiBib29sZWFuIH07XG5leHBvcnQgdHlwZSBTdG9yZVBsYW5TdG9yZSA9IHtcbiAgICByb3V0ZUtleTogc3RyaW5nO1xuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICBlbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICByYXdEaXNrOiBib29sZWFuO1xuICAgIHJlYWRlckRpc2tMaW1pdD86IG51bWJlcjtcbiAgICBzb3VyY2VTcGVjczogU3RvcmVTb3VyY2VTcGVjW107XG59O1xuZXhwb3J0IHR5cGUgU3RvcmVQbGFuID0ge1xuICAgIHNlbGZFbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICBzZWxmOiBTZWxmU3VtbWFyeSB8IHVuZGVmaW5lZDtcbiAgICBzdG9yZXM6IFN0b3JlUGxhblN0b3JlW107XG4gICAgc3RydWN0dXJlS2V5OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZVN0b3JlUGxhbihhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgcm91dGluZzogUmVtb3RlQ29uZmlnKTogU3RvcmVQbGFuIHtcbiAgICBsZXQgc2VsZkluZGV4ZXMgPSBmaW5kU2VsZkluZGV4ZXMocm91dGluZywgYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHNlbGZFbnRyaWVzID0gc2VsZkluZGV4ZXMubWFwKGkgPT4gcm91dGluZy5zb3VyY2VzW2ldIGFzIEhvc3RlZENvbmZpZyk7XG4gICAgbGV0IHNlbGYgPSBzdW1tYXJpemVTZWxmKHNlbGZFbnRyaWVzLCBEYXRlLm5vdygpKTtcbiAgICBsZXQgb3duSW5kZXhlcyA9IG5ldyBTZXQoc2VsZkluZGV4ZXMpO1xuICAgIC8vIE9uZSBzdG9yZSBwZXIgZGlzdGluY3Qgcm91dGUgYW1vbmcgQUxMIG91ciBlbnRyaWVzIC0gcGFzdCBhbmQgZnV0dXJlIHdpbmRvd3MgaW5jbHVkZWQsIHNvIGhpc3RvcmljYWwgcm91dGUgZm9sZGVycyBrZWVwIHNlcnZpbmcgdGhlaXIgZGF0YSBhbmQgdXBjb21pbmcgcm91dGVzIHN5bmMgYWhlYWQgb2YgdGhlaXIgd2luZG93XG4gICAgbGV0IGdyb3VwcyA9IG5ldyBNYXA8c3RyaW5nLCB7IHJvdXRlPzogW251bWJlciwgbnVtYmVyXTsgZW50cmllczogSG9zdGVkQ29uZmlnW107IGZpcnN0SW5kZXg6IG51bWJlciB9PigpO1xuICAgIGZvciAobGV0IGkgb2Ygc2VsZkluZGV4ZXMpIHtcbiAgICAgICAgbGV0IGVudHJ5ID0gcm91dGluZy5zb3VyY2VzW2ldIGFzIEhvc3RlZENvbmZpZztcbiAgICAgICAgbGV0IHJvdXRlS2V5ID0gSlNPTi5zdHJpbmdpZnkoZW50cnkucm91dGUgfHwgRlVMTF9ST1VURSk7XG4gICAgICAgIGxldCBncm91cCA9IGdyb3Vwcy5nZXQocm91dGVLZXkpO1xuICAgICAgICBpZiAoIWdyb3VwKSB7XG4gICAgICAgICAgICBncm91cCA9IHsgcm91dGU6IGVudHJ5LnJvdXRlLCBlbnRyaWVzOiBbXSwgZmlyc3RJbmRleDogaSB9O1xuICAgICAgICAgICAgZ3JvdXBzLnNldChyb3V0ZUtleSwgZ3JvdXApO1xuICAgICAgICB9XG4gICAgICAgIGdyb3VwLmVudHJpZXMucHVzaChlbnRyeSk7XG4gICAgfVxuICAgIGxldCBzdG9yZXM6IFN0b3JlUGxhblN0b3JlW10gPSBbXTtcbiAgICBmb3IgKGxldCBbcm91dGVLZXksIGdyb3VwXSBvZiBncm91cHMpIHtcbiAgICAgICAgbGV0IGFuY2hvciA9IHNlbGVjdEVudHJ5QXQoZ3JvdXAuZW50cmllcywgRGF0ZS5ub3coKSk7XG4gICAgICAgIGxldCBkaXNrV2luZG93OiBbbnVtYmVyLCBudW1iZXJdID0gWzAsIDBdO1xuICAgICAgICBpZiAoYW5jaG9yKSB7XG4gICAgICAgICAgICBsZXQgW3N0YXJ0LCBlbmRdID0gYW5jaG9yLnZhbGlkV2luZG93O1xuICAgICAgICAgICAgbGV0IG1lcmdlZCA9IHRydWU7XG4gICAgICAgICAgICB3aGlsZSAobWVyZ2VkKSB7XG4gICAgICAgICAgICAgICAgbWVyZ2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgZW50cnkgb2YgZ3JvdXAuZW50cmllcykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgW2VudHJ5U3RhcnQsIGVudHJ5RW5kXSA9IGVudHJ5LnZhbGlkV2luZG93O1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnlTdGFydCA+IGVuZCB8fCBlbnRyeUVuZCA8IHN0YXJ0KSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVudHJ5U3RhcnQgPCBzdGFydCB8fCBlbnRyeUVuZCA+IGVuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQgPSBNYXRoLm1pbihzdGFydCwgZW50cnlTdGFydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBNYXRoLm1heChlbmQsIGVudHJ5RW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXNrV2luZG93ID0gW3N0YXJ0LCBlbmRdO1xuICAgICAgICB9XG4gICAgICAgIGxldCBzb3VyY2VTcGVjczogU3RvcmVTb3VyY2VTcGVjW10gPSBbeyB2YWxpZFdpbmRvd3M6IFtkaXNrV2luZG93XSB9XTtcbiAgICAgICAgbGV0IG5vRnVsbFN5bmMgPSBncm91cC5lbnRyaWVzLnNvbWUoeCA9PiB4Lm5vRnVsbFN5bmMpO1xuICAgICAgICAvLyBUaGUgc2FtZSBwZWVyIGVuZHBvaW50ICh1cmwrcm91dGUrZmxhZ3MpIGNhbiBhcHBlYXIgdW5kZXIgc2V2ZXJhbCB3aW5kb3dzIGF0IG9uY2UgKGEgc3dpdGNob3ZlciBzcGxpdHMgb25lIHdpbmRvdyBhcm91bmQgYW4gaW50ZXJtZWRpYXRlKS4gSXQgaXMgT05FIHN5bmMgc291cmNlIHRoYXQgY2FycmllcyBBTEwgdGhvc2Ugd2luZG93cyAtIG5ldmVyIHNldmVyYWwgc291cmNlcywgd2hpY2ggd291bGQgZG91YmxlLXNjYW4gaXQgYW5kLCB3b3JzZSwgbWFrZSBtYXRjaGluZyBhIHJlcXVlc3QgZGVwZW5kIG9uIHdoaWNoIHdpbmRvdyB0aGUgY2FsbGVyIGhhcHBlbmVkIHRvIGhvbGQuXG4gICAgICAgIGxldCBwZWVyQnlLZXkgPSBuZXcgTWFwPHN0cmluZywgU3RvcmVTb3VyY2VTcGVjPigpO1xuICAgICAgICBmb3IgKGxldCBpID0gZ3JvdXAuZmlyc3RJbmRleCArIDE7IGkgPCByb3V0aW5nLnNvdXJjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxldCBzb3VyY2UgPSByb3V0aW5nLnNvdXJjZXNbaV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJzdHJpbmdcIiB8fCBvd25JbmRleGVzLmhhcyhpKSkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgc2hhcmVkUm91dGUgPSByb3V0ZUludGVyc2VjdGlvbihncm91cC5yb3V0ZSwgc291cmNlLnJvdXRlKTtcbiAgICAgICAgICAgIGlmICghc2hhcmVkUm91dGUpIGNvbnRpbnVlO1xuICAgICAgICAgICAgbGV0IGtleSA9IEpTT04uc3RyaW5naWZ5KHsgLi4uc291cmNlLCB2YWxpZFdpbmRvdzogdW5kZWZpbmVkIH0pO1xuICAgICAgICAgICAgbGV0IHNwZWMgPSBwZWVyQnlLZXkuZ2V0KGtleSk7XG4gICAgICAgICAgICBpZiAoIXNwZWMpIHtcbiAgICAgICAgICAgICAgICBzcGVjID0geyBzb3VyY2VDb25maWc6IHNvdXJjZSwgdmFsaWRXaW5kb3dzOiBbXSwgcm91dGU6IHNoYXJlZFJvdXRlLCBub0Z1bGxTeW5jOiBzb3VyY2Uubm9GdWxsU3luYyB8fCBub0Z1bGxTeW5jIH07XG4gICAgICAgICAgICAgICAgcGVlckJ5S2V5LnNldChrZXksIHNwZWMpO1xuICAgICAgICAgICAgICAgIHNvdXJjZVNwZWNzLnB1c2goc3BlYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzcGVjLnZhbGlkV2luZG93cy5wdXNoKHNvdXJjZS52YWxpZFdpbmRvdyk7XG4gICAgICAgIH1cbiAgICAgICAgc3RvcmVzLnB1c2goe1xuICAgICAgICAgICAgcm91dGVLZXksXG4gICAgICAgICAgICByb3V0ZTogZ3JvdXAucm91dGUsXG4gICAgICAgICAgICBlbnRyaWVzOiBncm91cC5lbnRyaWVzLFxuICAgICAgICAgICAgcmF3RGlzazogZ3JvdXAuZW50cmllcy5zb21lKHggPT4geC5yYXdEaXNrKSxcbiAgICAgICAgICAgIHJlYWRlckRpc2tMaW1pdDogZ3JvdXAuZW50cmllcy5maW5kKHggPT4geC5yZWFkZXJEaXNrTGltaXQgIT09IHVuZGVmaW5lZCk/LnJlYWRlckRpc2tMaW1pdCxcbiAgICAgICAgICAgIHNvdXJjZVNwZWNzLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYgKCFzdG9yZXMubGVuZ3RoKSB7XG4gICAgICAgIC8vIE5vdCBpbiB0aGUgY29uZmlnIGF0IGFsbDogc3RpbGwgc2VydmUgd2hhdGV2ZXIgdGhlIHBsYWluIGZvbGRlciBob2xkcywgdGhyb3VnaCBvbmUgaW5lcnQgZnVsbC1yb3V0ZSBzdG9yZVxuICAgICAgICBzdG9yZXMucHVzaCh7IHJvdXRlS2V5OiBKU09OLnN0cmluZ2lmeShGVUxMX1JPVVRFKSwgcm91dGU6IHVuZGVmaW5lZCwgZW50cmllczogW10sIHJhd0Rpc2s6IGZhbHNlLCByZWFkZXJEaXNrTGltaXQ6IHVuZGVmaW5lZCwgc291cmNlU3BlY3M6IFt7IHZhbGlkV2luZG93czogW1swLCAwXV0gfV0gfSk7XG4gICAgfVxuICAgIGxldCBzdHJ1Y3R1cmVLZXkgPSBKU09OLnN0cmluZ2lmeShzdG9yZXMubWFwKHMgPT4gKHsgcm91dGVLZXk6IHMucm91dGVLZXksIHJhd0Rpc2s6IHMucmF3RGlzaywgcmVhZGVyRGlza0xpbWl0OiBzLnJlYWRlckRpc2tMaW1pdCB9KSkpO1xuICAgIHJldHVybiB7IHNlbGZFbnRyaWVzLCBzZWxmLCBzdG9yZXMsIHN0cnVjdHVyZUtleSB9O1xufVxuIl19
158
+ /* _JS_SOURCE_HASH = "de02e6db6f6d1447f4a3b26c37f95ce8a86b8f1d3dd558e60fca94e7a7974c9f"; */
@@ -15,5 +15,3 @@ export declare function injectIntermediateSource(config: RemoteConfig, inject: {
15
15
  }): RemoteConfig;
16
16
  /** Intermediates whose window ended more than INTERMEDIATE_EXPIRE_GRACE ago are removed, and the windows they split are rejoined. */
17
17
  export declare function expireIntermediateSources(config: RemoteConfig, now: number): RemoteConfig;
18
- /** The url of the entry an intermediate was split out of - the neighbour it touches. */
19
- export declare function findSplitUrl(config: RemoteConfig, intermediate: SourceConfig): string | undefined;
@@ -81,7 +81,8 @@ export function injectIntermediateSource(config: RemoteConfig, inject: { splitUr
81
81
  if (middleStart > windowStart) {
82
82
  sources.push({ ...source, validWindow: [windowStart, middleStart] });
83
83
  }
84
- sources.push({ ...source, url: intermediateUrl, validWindow: [middleStart, middleEnd], intermediate: true });
84
+ // intermediate = the url this entry was split out of, so a request naming the intermediate still resolves to the original source
85
+ sources.push({ ...source, url: intermediateUrl, validWindow: [middleStart, middleEnd], intermediate: splitUrl });
85
86
  if (windowEnd > middleEnd) {
86
87
  sources.push({ ...source, validWindow: [middleEnd, windowEnd] });
87
88
  }
@@ -98,7 +99,8 @@ export function expireIntermediateSources(config: RemoteConfig, now: number): Re
98
99
  let result = resolved;
99
100
  for (let keep of keptIntermediates) {
100
101
  result = injectIntermediateSource(result, {
101
- splitUrl: findSplitUrl(config, keep) || keep.url,
102
+ // The intermediate carries the url it was split out of; fall back to its own url only for a legacy entry that predates that
103
+ splitUrl: keep.intermediate || keep.url,
102
104
  intermediateUrl: keep.url,
103
105
  start: keep.validWindow[0],
104
106
  end: keep.validWindow[1],
@@ -106,10 +108,3 @@ export function expireIntermediateSources(config: RemoteConfig, now: number): Re
106
108
  }
107
109
  return result;
108
110
  }
109
-
110
- /** The url of the entry an intermediate was split out of - the neighbour it touches. */
111
- export function findSplitUrl(config: RemoteConfig, intermediate: SourceConfig): string | undefined {
112
- let [start, end] = intermediate.validWindow;
113
- let neighbour = config.sources.find(x => isSourceConfig(x) && !x.intermediate && (x.validWindow[1] === start || x.validWindow[0] === end)) as SourceConfig | undefined;
114
- return neighbour?.url;
115
- }
@@ -23,7 +23,7 @@ export type BucketState = {
23
23
  };
24
24
  /** The loaded bucket, loading it (which instantiates its stores and starts their synchronization) if needed. A bucket that does not exist on this server throws - callers never see undefined buckets. */
25
25
  export declare function requireBucket(account: string, bucketName: string): Promise<BucketState>;
26
- /** The store serving a request: the exact config entry the CLIENT selected, matched by equality (key order ignored) against the bucket's own entries. A match is honored even when its window has passed - the selection never validates, the store's own validation throws instead. Throws when nothing matches, listing what is available. */
26
+ /** The store serving a request: the config entry the CLIENT selected, matched against the bucket's own entries by identity EXCLUDING the valid window (see sourceMatchKey). The selection never validates - the store's own window/route checks throw if the caller is stale - so honoring a window mismatch here is exactly right. Throws when nothing matches, listing what is available. */
27
27
  export declare function findBucketStore(account: string, bucketName: string, sourceConfig: SourceConfig | undefined): Promise<LoadedStore>;
28
28
  /** Internal (store-to-store) reads skip store selection entirely: the caller is another store whose index says this MACHINE holds the bytes - the persisted holder identity is just a URL, which cannot name a store. Whichever store's folder has the newest copy answers. */
29
29
  export declare function readBucketInternal(account: string, bucketName: string, config: {
@@ -10,7 +10,7 @@ import {
10
10
  ArchiveFileInfo, ChangesAfterConfig, DelConfig, FindConfig, GetConfig, GetInfoConfig, SetConfig, SyncActivity, FULL_ROUTE,
11
11
  } from "../IArchives";
12
12
  import { ROUTING_FILE, parseRoutingData, serializeRemoteConfig, parseHostedUrl, replaceHostedUrlPort, buildFileUrl, getConfigVersion, routeIntersection, normalizeSource } from "./remoteConfig";
13
- import { injectIntermediateSource, expireIntermediateSources, getIntermediateSources, findSplitUrl, nextIntermediateVersion, INTERMEDIATE_EXPIRE_GRACE } from "./intermediateSources";
13
+ import { injectIntermediateSource, expireIntermediateSources, getIntermediateSources, nextIntermediateVersion, INTERMEDIATE_EXPIRE_GRACE } from "./intermediateSources";
14
14
  import { getTakeoverIntermediate } from "./deployTakeover";
15
15
  import { createApiArchives, listServerActiveBucketKeys } from "./createArchives";
16
16
  import { broadcastRoutingChanged } from "./storageController";
@@ -62,15 +62,21 @@ export async function requireBucket(account: string, bucketName: string): Promis
62
62
  return bucket;
63
63
  }
64
64
 
65
- /** The store serving a request: the exact config entry the CLIENT selected, matched by equality (key order ignored) against the bucket's own entries. A match is honored even when its window has passed - the selection never validates, the store's own validation throws instead. Throws when nothing matches, listing what is available. */
65
+ /** The stable identity of a source config for matching: everything EXCEPT the valid window, and with an intermediate resolved back to the source it was split out of. The window drifts (a switchover splits one window in two around an intermediate, then rejoins it), so a caller and this server routinely disagree on it - matching on it would wrongly reject the request. An intermediate is a transient alt-port view of another source, so it must resolve to THAT source (config.intermediate holds its url + the intermediate flag is dropped), or a request naming the intermediate would fail to match once the intermediate has rejoined and its entry is gone. The route stays in the identity (it selects the store/folder). */
66
+ function sourceMatchKey(config: SourceConfig): string {
67
+ let url = config.intermediate || config.url;
68
+ return stableStringify({ ...config, url, intermediate: undefined, validWindow: undefined });
69
+ }
70
+
71
+ /** The store serving a request: the config entry the CLIENT selected, matched against the bucket's own entries by identity EXCLUDING the valid window (see sourceMatchKey). The selection never validates - the store's own window/route checks throw if the caller is stale - so honoring a window mismatch here is exactly right. Throws when nothing matches, listing what is available. */
66
72
  export async function findBucketStore(account: string, bucketName: string, sourceConfig: SourceConfig | undefined): Promise<LoadedStore> {
67
73
  let bucket = await requireBucket(account, bucketName);
68
74
  if (!sourceConfig) {
69
75
  throw new Error(`No remote source configuration was provided for bucket ${account}/${bucketName}: every request must say which configured source it selected. Available: ${JSON.stringify(bucket.selfEntries)}`);
70
76
  }
71
- let wanted = stableStringify(sourceConfig);
77
+ let wanted = sourceMatchKey(sourceConfig);
72
78
  for (let s of bucket.stores) {
73
- if (s.entries.some(e => stableStringify(e) === wanted)) return s;
79
+ if (s.entries.some(e => sourceMatchKey(e) === wanted)) return s;
74
80
  }
75
81
  throw new Error(`No source on this server matches the requested remote configuration for bucket ${account}/${bucketName}. Requested: ${JSON.stringify(sourceConfig)}. Available: ${JSON.stringify(bucket.selfEntries)}`);
76
82
  }
@@ -350,7 +356,7 @@ function buildStore(account: string, bucketName: string, planStore: StorePlanSto
350
356
  let sources: ArchivesSource[] = planStore.sourceSpecs.map(spec => ({
351
357
  source: spec.sourceConfig && createApiArchives(spec.sourceConfig) || new ArchivesDisk(folder),
352
358
  url: spec.sourceConfig?.url || folder,
353
- validWindow: spec.validWindow,
359
+ validWindows: spec.validWindows,
354
360
  route: spec.route,
355
361
  noFullSync: spec.noFullSync,
356
362
  intermediate: spec.sourceConfig?.intermediate,
@@ -447,12 +453,12 @@ async function checkRoutingChanged(account: string, bucketName: string, config?:
447
453
  live.store.updateSources(planStore.sourceSpecs.map(spec => {
448
454
  const sourceConfig = spec.sourceConfig;
449
455
  if (!sourceConfig) {
450
- return { identity: sourceIdentity(undefined), url: storeFolder, validWindow: spec.validWindow, create: (): IArchives => new ArchivesDisk(storeFolder) };
456
+ return { identity: sourceIdentity(undefined), url: storeFolder, validWindows: spec.validWindows, create: (): IArchives => new ArchivesDisk(storeFolder) };
451
457
  }
452
458
  return {
453
459
  identity: sourceIdentity(sourceConfig),
454
460
  url: sourceConfig.url,
455
- validWindow: spec.validWindow,
461
+ validWindows: spec.validWindows,
456
462
  route: spec.route,
457
463
  noFullSync: spec.noFullSync,
458
464
  intermediate: sourceConfig.intermediate,
@@ -512,7 +518,7 @@ async function writeRoutingConfig(account: string, bucketName: string, data: Buf
512
518
  let reinjected = 0;
513
519
  for (let intermediate of getIntermediateSources(expireIntermediateSources(loaded.routing, Date.now()))) {
514
520
  stored = injectIntermediateSource(stored, {
515
- splitUrl: findSplitUrl(loaded.routing, intermediate) || intermediate.url,
521
+ splitUrl: intermediate.intermediate || intermediate.url,
516
522
  intermediateUrl: intermediate.url,
517
523
  start: intermediate.validWindow[0],
518
524
  end: intermediate.validWindow[1],
@@ -13,7 +13,7 @@ export type SelfSummary = {
13
13
  };
14
14
  export type StoreSourceSpec = {
15
15
  sourceConfig?: SourceConfig;
16
- validWindow: [number, number];
16
+ validWindows: [number, number][];
17
17
  route?: [number, number];
18
18
  noFullSync?: boolean;
19
19
  };
@@ -85,7 +85,7 @@ function summarizeSelf(selfEntries: HostedConfig[], now: number): SelfSummary |
85
85
  };
86
86
  }
87
87
 
88
- export type StoreSourceSpec = { sourceConfig?: SourceConfig; validWindow: [number, number]; route?: [number, number]; noFullSync?: boolean };
88
+ export type StoreSourceSpec = { sourceConfig?: SourceConfig; validWindows: [number, number][]; route?: [number, number]; noFullSync?: boolean };
89
89
  export type StorePlanStore = {
90
90
  routeKey: string;
91
91
  route?: [number, number];
@@ -139,14 +139,23 @@ export function computeStorePlan(account: string, bucketName: string, routing: R
139
139
  }
140
140
  diskWindow = [start, end];
141
141
  }
142
- let sourceSpecs: StoreSourceSpec[] = [{ validWindow: diskWindow }];
142
+ let sourceSpecs: StoreSourceSpec[] = [{ validWindows: [diskWindow] }];
143
143
  let noFullSync = group.entries.some(x => x.noFullSync);
144
+ // The same peer endpoint (url+route+flags) can appear under several windows at once (a switchover splits one window around an intermediate). It is ONE sync source that carries ALL those windows - never several sources, which would double-scan it and, worse, make matching a request depend on which window the caller happened to hold.
145
+ let peerByKey = new Map<string, StoreSourceSpec>();
144
146
  for (let i = group.firstIndex + 1; i < routing.sources.length; i++) {
145
147
  let source = routing.sources[i];
146
148
  if (typeof source === "string" || ownIndexes.has(i)) continue;
147
149
  let sharedRoute = routeIntersection(group.route, source.route);
148
150
  if (!sharedRoute) continue;
149
- sourceSpecs.push({ sourceConfig: source, validWindow: source.validWindow, route: sharedRoute, noFullSync: source.noFullSync || noFullSync });
151
+ let key = JSON.stringify({ ...source, validWindow: undefined });
152
+ let spec = peerByKey.get(key);
153
+ if (!spec) {
154
+ spec = { sourceConfig: source, validWindows: [], route: sharedRoute, noFullSync: source.noFullSync || noFullSync };
155
+ peerByKey.set(key, spec);
156
+ sourceSpecs.push(spec);
157
+ }
158
+ spec.validWindows.push(source.validWindow);
150
159
  }
151
160
  stores.push({
152
161
  routeKey,
@@ -159,7 +168,7 @@ export function computeStorePlan(account: string, bucketName: string, routing: R
159
168
  }
160
169
  if (!stores.length) {
161
170
  // Not in the config at all: still serve whatever the plain folder holds, through one inert full-route store
162
- stores.push({ routeKey: JSON.stringify(FULL_ROUTE), route: undefined, entries: [], rawDisk: false, readerDiskLimit: undefined, sourceSpecs: [{ validWindow: [0, 0] }] });
171
+ stores.push({ routeKey: JSON.stringify(FULL_ROUTE), route: undefined, entries: [], rawDisk: false, readerDiskLimit: undefined, sourceSpecs: [{ validWindows: [[0, 0]] }] });
163
172
  }
164
173
  let structureKey = JSON.stringify(stores.map(s => ({ routeKey: s.routeKey, rawDisk: s.rawDisk, readerDiskLimit: s.readerDiskLimit })));
165
174
  return { selfEntries, self, stores, structureKey };