sliftutils 1.7.90 → 1.7.92

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.
Files changed (37) hide show
  1. package/index.d.ts +38 -79
  2. package/misc/https/dist/cloudflareHelpers.ts.cache +2 -2
  3. package/misc/https/dist/dns.ts.cache +2 -2
  4. package/package.json +1 -1
  5. package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +2 -2
  6. package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +2 -2
  7. package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +2 -2
  8. package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +2 -2
  9. package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +2 -2
  10. package/storage/BulkDatabase2/dist/blockCache.ts.cache +2 -2
  11. package/storage/BulkDatabase2/dist/mergeLock.ts.cache +2 -2
  12. package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +2 -2
  13. package/storage/BulkDatabase2/dist/streamLog.ts.cache +2 -2
  14. package/storage/BulkDatabase2/dist/syncClient.ts.cache +2 -2
  15. package/storage/IArchives.d.ts +1 -0
  16. package/storage/IArchives.ts +3 -0
  17. package/storage/remoteStorage/accessStats.d.ts +12 -0
  18. package/storage/remoteStorage/accessStats.ts +47 -0
  19. package/storage/remoteStorage/blobStore.d.ts +6 -1
  20. package/storage/remoteStorage/blobStore.ts +34 -5
  21. package/storage/remoteStorage/createArchives.ts +13 -6
  22. package/storage/remoteStorage/dist/accessStats.ts.cache +42 -3
  23. package/storage/remoteStorage/dist/blobStore.ts.cache +6 -3
  24. package/storage/remoteStorage/dist/intermediateManagement.ts.cache +56 -50
  25. package/storage/remoteStorage/dist/storageController.ts.cache +36 -29
  26. package/storage/remoteStorage/dist/storageServerState.ts.cache +110 -233
  27. package/storage/remoteStorage/dist/storeConfig.ts.cache +2 -2
  28. package/storage/remoteStorage/dist/storePlan.ts.cache +4 -56
  29. package/storage/remoteStorage/intermediateManagement.d.ts +2 -3
  30. package/storage/remoteStorage/intermediateManagement.ts +53 -46
  31. package/storage/remoteStorage/storageController.ts +22 -14
  32. package/storage/remoteStorage/storageServerState.d.ts +15 -55
  33. package/storage/remoteStorage/storageServerState.ts +106 -268
  34. package/storage/remoteStorage/storeConfig.d.ts +2 -0
  35. package/storage/remoteStorage/storeConfig.ts +2 -0
  36. package/storage/remoteStorage/storePlan.d.ts +0 -20
  37. package/storage/remoteStorage/storePlan.ts +1 -69
@@ -48,5 +48,5 @@ class StoreConfig {
48
48
  exports.StoreConfig = StoreConfig;
49
49
  // A store nobody has configured: always valid, the whole key space, no delays and no limits. Every one of these is the answer that does the least - it holds its own data and nothing else happens to it - which is what makes a store usable before it has ever seen a config.
50
50
  const UNCONFIGURED = { validWindow: IArchives_1.FULL_VALID_WINDOW };
51
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmVDb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzdG9yZUNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtREFBZ0Q7QUFDaEQsNENBQStEO0FBRS9ELDJZQUEyWTtBQUUzWSxNQUFhLFdBQVc7SUFDcEIsWUFDb0IsSUFBWSxFQUM1QixPQUF1QjtRQURQLFNBQUksR0FBSixJQUFJLENBQVE7UUFNaEMsc0tBQXNLO1FBQzlKLFlBQU8sR0FBbUIsRUFBRSxDQUFDO1FBSmpDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUtELDJJQUEySTtJQUMzSSw2SkFBNko7SUFDdEosTUFBTSxDQUFDLE9BQXVCO1FBQ2pDLElBQUksT0FBTyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQztRQUMzQixJQUFBLFdBQUksRUFBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDM0IsQ0FBQztJQUVNLEdBQUc7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNJLE9BQU87UUFDVixJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDckIsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNGLElBQUksVUFBVTtZQUFFLE9BQU8sVUFBVSxDQUFDO1FBQ2xDLElBQUksUUFBUSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUM5RCxJQUFJLFFBQVE7WUFBRSxPQUFPLFFBQVEsQ0FBQztRQUM5QixJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2pELElBQUksSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3RCLE9BQU8sWUFBWSxDQUFDO0lBQ3hCLENBQUM7Q0FDSjtBQTNDRCxrQ0EyQ0M7QUFZRCxnUkFBZ1I7QUFDaFIsTUFBTSxZQUFZLEdBQWdCLEVBQUUsV0FBVyxFQUFFLDZCQUFpQixFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzb3J0IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuaW1wb3J0IHsgSG9zdGVkQ29uZmlnLCBGVUxMX1ZBTElEX1dJTkRPVyB9IGZyb20gXCIuLi9JQXJjaGl2ZXNcIjtcblxuLy8gVGhlIGNvbmZpZ3VyYXRpb24gb2YgT05FIHN0b3JlLCBrZXB0IGN1cnJlbnQuIEEgc3RvcmUgaXMgbmFtZWQgYnkgaXRzIGVudHJpZXMgKHNlZSBDb21tb25Db25maWcubmFtZSksIGFuZCBhdCBhbnkgaW5zdGFudCBleGFjdGx5IG9uZSBvZiB0aGVtIGlzIGluIGVmZmVjdCAtIHRoZSBjb25maWcgd3JpdGUgcGF0aCBlbmZvcmNlcyB0aGF0IC0gc28gXCJ0aGUgY29uZmlndXJhdGlvbiBvZiB0aGlzIHN0b3JlIHJpZ2h0IG5vd1wiIGlzIGEgc2luZ2xlIGVudHJ5LCBhbmQgZXZlcnl0aGluZyB0aGUgc3RvcmUgZG9lcyB3aXRoIHJvdXRlcywgZmxhZ3MgYW5kIGxpbWl0cyByZWFkcyBpdCBmcm9tIGhlcmUgcmF0aGVyIHRoYW4gYmVpbmcgaGFuZGVkIGEgc25hcHNob3QgdGhhdCBnb2VzIHN0YWxlLlxuXG5leHBvcnQgY2xhc3MgU3RvcmVDb25maWcge1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZTogc3RyaW5nLFxuICAgICAgICBlbnRyaWVzOiBIb3N0ZWRDb25maWdbXSxcbiAgICApIHtcbiAgICAgICAgdGhpcy51cGRhdGUoZW50cmllcyk7XG4gICAgfVxuXG4gICAgLy8gRXZlcnkgZW50cnkgbmFtaW5nIHRoaXMgc3RvcmUsIG9sZGVzdCB3aW5kb3cgZmlyc3QgLSBwYXN0IG9uZXMgaW5jbHVkZWQsIGJlY2F1c2UgYSBzdGFtcGVkIHdyaXRlIG9yIGEgc2NhbiBjYW4gbGVnaXRpbWF0ZWx5IGNvbmNlcm4gYSB3aW5kb3cgdGhhdCBoYXMgYWxyZWFkeSBlbmRlZFxuICAgIHByaXZhdGUgZW50cmllczogSG9zdGVkQ29uZmlnW10gPSBbXTtcblxuICAgIC8qKiBUaGUgcm91dGluZyBjb25maWcgY2hhbmdlZC4gU2FtZSBzdG9yZSBlaXRoZXIgd2F5OiBpdHMgbmFtZSBkaWQgbm90IGNoYW5nZSwgc28gbmVpdGhlciBkaWQgaXRzIGZvbGRlciwgaXRzIGluZGV4LCBvciB0aGUgZGF0YSBpbiBpdC4gKi9cbiAgICAvKiogTm8gZW50cmllcyBpcyBhIHJlYWwgc3RhdGUsIG5vdCBhbiBlcnJvcjogYSBzdG9yZSBleGlzdHMgYXMgc29vbiBhcyBpdHMgZm9sZGVyIGRvZXMsIGFuZCBpdCBtYXkgbmV2ZXIgaGF2ZSBoZWFyZCBvZiBhIGNvbmZpZ3VyYXRpb24gKHNlZSBTdG9yZVBvbGljeSkuICovXG4gICAgcHVibGljIHVwZGF0ZShlbnRyaWVzOiBIb3N0ZWRDb25maWdbXSk6IHZvaWQge1xuICAgICAgICBsZXQgb3JkZXJlZCA9IFsuLi5lbnRyaWVzXTtcbiAgICAgICAgc29ydChvcmRlcmVkLCB4ID0+IHgudmFsaWRXaW5kb3dbMF0pO1xuICAgICAgICB0aGlzLmVudHJpZXMgPSBvcmRlcmVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBhbGwoKTogSG9zdGVkQ29uZmlnW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5lbnRyaWVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoYXQgdGhpcyBzdG9yZSBpcyBjb25maWd1cmVkIHRvIGJlIHJpZ2h0IG5vdzogdGhlIGVudHJ5IHdob3NlIHdpbmRvdyBjb250YWlucyB0aGlzIG1vbWVudDtcbiAgICAgKiBmYWlsaW5nIHRoYXQgdGhlIG5leHQgb25lIGR1ZSB0byBzdGFydDsgZmFpbGluZyB0aGF0IHRoZSBsYXN0IG9uZSB0byBoYXZlIGVuZGVkLlxuICAgICAqXG4gICAgICogVGhlcmUgaXMgYWx3YXlzIGFuIGFuc3dlciwgYW5kIGl0IG1hdHRlcnMgdGhhdCB0aGVyZSBpczogYSBzdG9yZSBiZXR3ZWVuIHdpbmRvd3Mgc3RpbGwgaG9sZHNcbiAgICAgKiBkYXRhIGFuZCBzdGlsbCBoYXMgdG8gYW5zd2VyIGZvciBpdCwgc28gaXQgbmVlZHMgYSByb3V0ZSBhbmQgZmxhZ3MgZXZlbiB3aGVuIG5vdGhpbmcgaXNcbiAgICAgKiBjdXJyZW50bHkgcG9pbnRpbmcgd3JpdGVzIGF0IGl0LiBXaGljaCBvZiB0aGUgdGhyZWUgY2FzZXMgcHJvZHVjZWQgdGhlIGFuc3dlciBpcyBkZWxpYmVyYXRlbHlcbiAgICAgKiBub3QgZXhwb3NlZCAtIHRoZSB2YWxpZCB3aW5kb3cgaXRzZWxmIGlzIHdoYXQgc2F5cyB3aGV0aGVyIHdyaXRlcyBiZWxvbmcgaGVyZSwgYW5kIGV2ZXJ5IHdyaXRlXG4gICAgICogaXMgY2hlY2tlZCBhZ2FpbnN0IGl0IHNlcGFyYXRlbHkuXG4gICAgICovXG4gICAgcHVibGljIGN1cnJlbnQoKTogU3RvcmVQb2xpY3kge1xuICAgICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgbGV0IGNvbnRhaW5pbmcgPSB0aGlzLmVudHJpZXMuZmluZCh4ID0+IHgudmFsaWRXaW5kb3dbMF0gPD0gbm93ICYmIG5vdyA8IHgudmFsaWRXaW5kb3dbMV0pO1xuICAgICAgICBpZiAoY29udGFpbmluZykgcmV0dXJuIGNvbnRhaW5pbmc7XG4gICAgICAgIGxldCB1cGNvbWluZyA9IHRoaXMuZW50cmllcy5maW5kKHggPT4geC52YWxpZFdpbmRvd1swXSA+IG5vdyk7XG4gICAgICAgIGlmICh1cGNvbWluZykgcmV0dXJuIHVwY29taW5nO1xuICAgICAgICBsZXQgbGFzdCA9IHRoaXMuZW50cmllc1t0aGlzLmVudHJpZXMubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmIChsYXN0KSByZXR1cm4gbGFzdDtcbiAgICAgICAgcmV0dXJuIFVOQ09ORklHVVJFRDtcbiAgICB9XG59XG5cbi8qKiBUaGUgcGFydHMgb2YgYSBjb25maWcgZW50cnkgdGhhdCBkZXNjcmliZSB3aGF0IGEgc3RvcmUgSVMgLSBhcyBvcHBvc2VkIHRvIHdoaWNoIGVudHJ5IHNhaWQgc28uIEtlcHQgc2VwYXJhdGUgYmVjYXVzZSBhIHN0b3JlIHdpdGggbm8gZW50cmllcyBzdGlsbCBoYXMgYWxsIG9mIHRoZW0uICovXG5leHBvcnQgdHlwZSBTdG9yZVBvbGljeSA9IHtcbiAgICB2YWxpZFdpbmRvdzogW251bWJlciwgbnVtYmVyXTtcbiAgICByb3V0ZT86IFtudW1iZXIsIG51bWJlcl07XG4gICAgZmFzdD86IGJvb2xlYW47XG4gICAgd3JpdGVEZWxheT86IG51bWJlcjtcbiAgICBub0Z1bGxTeW5jPzogYm9vbGVhbjtcbiAgICByZWFkZXJEaXNrTGltaXQ/OiBudW1iZXI7XG59O1xuXG4vLyBBIHN0b3JlIG5vYm9keSBoYXMgY29uZmlndXJlZDogYWx3YXlzIHZhbGlkLCB0aGUgd2hvbGUga2V5IHNwYWNlLCBubyBkZWxheXMgYW5kIG5vIGxpbWl0cy4gRXZlcnkgb25lIG9mIHRoZXNlIGlzIHRoZSBhbnN3ZXIgdGhhdCBkb2VzIHRoZSBsZWFzdCAtIGl0IGhvbGRzIGl0cyBvd24gZGF0YSBhbmQgbm90aGluZyBlbHNlIGhhcHBlbnMgdG8gaXQgLSB3aGljaCBpcyB3aGF0IG1ha2VzIGEgc3RvcmUgdXNhYmxlIGJlZm9yZSBpdCBoYXMgZXZlciBzZWVuIGEgY29uZmlnLlxuY29uc3QgVU5DT05GSUdVUkVEOiBTdG9yZVBvbGljeSA9IHsgdmFsaWRXaW5kb3c6IEZVTExfVkFMSURfV0lORE9XIH07XG4iXX0=
52
- /* _JS_SOURCE_HASH = "696854eab64026ab54a84df68537b6018f1f3e7d4f5bceb692aa1fc72ff2e347"; */
51
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmVDb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzdG9yZUNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtREFBZ0Q7QUFDaEQsNENBQStEO0FBRS9ELDJZQUEyWTtBQUUzWSxNQUFhLFdBQVc7SUFDcEIsWUFDb0IsSUFBWSxFQUM1QixPQUF1QjtRQURQLFNBQUksR0FBSixJQUFJLENBQVE7UUFNaEMsc0tBQXNLO1FBQzlKLFlBQU8sR0FBbUIsRUFBRSxDQUFDO1FBSmpDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUtELDJJQUEySTtJQUMzSSw2SkFBNko7SUFDdEosTUFBTSxDQUFDLE9BQXVCO1FBQ2pDLElBQUksT0FBTyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQztRQUMzQixJQUFBLFdBQUksRUFBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDM0IsQ0FBQztJQUVNLEdBQUc7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNJLE9BQU87UUFDVixJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDckIsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNGLElBQUksVUFBVTtZQUFFLE9BQU8sVUFBVSxDQUFDO1FBQ2xDLElBQUksUUFBUSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUM5RCxJQUFJLFFBQVE7WUFBRSxPQUFPLFFBQVEsQ0FBQztRQUM5QixJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2pELElBQUksSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3RCLE9BQU8sWUFBWSxDQUFDO0lBQ3hCLENBQUM7Q0FDSjtBQTNDRCxrQ0EyQ0M7QUFjRCxnUkFBZ1I7QUFDaFIsTUFBTSxZQUFZLEdBQWdCLEVBQUUsV0FBVyxFQUFFLDZCQUFpQixFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzb3J0IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuaW1wb3J0IHsgSG9zdGVkQ29uZmlnLCBGVUxMX1ZBTElEX1dJTkRPVyB9IGZyb20gXCIuLi9JQXJjaGl2ZXNcIjtcblxuLy8gVGhlIGNvbmZpZ3VyYXRpb24gb2YgT05FIHN0b3JlLCBrZXB0IGN1cnJlbnQuIEEgc3RvcmUgaXMgbmFtZWQgYnkgaXRzIGVudHJpZXMgKHNlZSBDb21tb25Db25maWcubmFtZSksIGFuZCBhdCBhbnkgaW5zdGFudCBleGFjdGx5IG9uZSBvZiB0aGVtIGlzIGluIGVmZmVjdCAtIHRoZSBjb25maWcgd3JpdGUgcGF0aCBlbmZvcmNlcyB0aGF0IC0gc28gXCJ0aGUgY29uZmlndXJhdGlvbiBvZiB0aGlzIHN0b3JlIHJpZ2h0IG5vd1wiIGlzIGEgc2luZ2xlIGVudHJ5LCBhbmQgZXZlcnl0aGluZyB0aGUgc3RvcmUgZG9lcyB3aXRoIHJvdXRlcywgZmxhZ3MgYW5kIGxpbWl0cyByZWFkcyBpdCBmcm9tIGhlcmUgcmF0aGVyIHRoYW4gYmVpbmcgaGFuZGVkIGEgc25hcHNob3QgdGhhdCBnb2VzIHN0YWxlLlxuXG5leHBvcnQgY2xhc3MgU3RvcmVDb25maWcge1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZTogc3RyaW5nLFxuICAgICAgICBlbnRyaWVzOiBIb3N0ZWRDb25maWdbXSxcbiAgICApIHtcbiAgICAgICAgdGhpcy51cGRhdGUoZW50cmllcyk7XG4gICAgfVxuXG4gICAgLy8gRXZlcnkgZW50cnkgbmFtaW5nIHRoaXMgc3RvcmUsIG9sZGVzdCB3aW5kb3cgZmlyc3QgLSBwYXN0IG9uZXMgaW5jbHVkZWQsIGJlY2F1c2UgYSBzdGFtcGVkIHdyaXRlIG9yIGEgc2NhbiBjYW4gbGVnaXRpbWF0ZWx5IGNvbmNlcm4gYSB3aW5kb3cgdGhhdCBoYXMgYWxyZWFkeSBlbmRlZFxuICAgIHByaXZhdGUgZW50cmllczogSG9zdGVkQ29uZmlnW10gPSBbXTtcblxuICAgIC8qKiBUaGUgcm91dGluZyBjb25maWcgY2hhbmdlZC4gU2FtZSBzdG9yZSBlaXRoZXIgd2F5OiBpdHMgbmFtZSBkaWQgbm90IGNoYW5nZSwgc28gbmVpdGhlciBkaWQgaXRzIGZvbGRlciwgaXRzIGluZGV4LCBvciB0aGUgZGF0YSBpbiBpdC4gKi9cbiAgICAvKiogTm8gZW50cmllcyBpcyBhIHJlYWwgc3RhdGUsIG5vdCBhbiBlcnJvcjogYSBzdG9yZSBleGlzdHMgYXMgc29vbiBhcyBpdHMgZm9sZGVyIGRvZXMsIGFuZCBpdCBtYXkgbmV2ZXIgaGF2ZSBoZWFyZCBvZiBhIGNvbmZpZ3VyYXRpb24gKHNlZSBTdG9yZVBvbGljeSkuICovXG4gICAgcHVibGljIHVwZGF0ZShlbnRyaWVzOiBIb3N0ZWRDb25maWdbXSk6IHZvaWQge1xuICAgICAgICBsZXQgb3JkZXJlZCA9IFsuLi5lbnRyaWVzXTtcbiAgICAgICAgc29ydChvcmRlcmVkLCB4ID0+IHgudmFsaWRXaW5kb3dbMF0pO1xuICAgICAgICB0aGlzLmVudHJpZXMgPSBvcmRlcmVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBhbGwoKTogSG9zdGVkQ29uZmlnW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5lbnRyaWVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoYXQgdGhpcyBzdG9yZSBpcyBjb25maWd1cmVkIHRvIGJlIHJpZ2h0IG5vdzogdGhlIGVudHJ5IHdob3NlIHdpbmRvdyBjb250YWlucyB0aGlzIG1vbWVudDtcbiAgICAgKiBmYWlsaW5nIHRoYXQgdGhlIG5leHQgb25lIGR1ZSB0byBzdGFydDsgZmFpbGluZyB0aGF0IHRoZSBsYXN0IG9uZSB0byBoYXZlIGVuZGVkLlxuICAgICAqXG4gICAgICogVGhlcmUgaXMgYWx3YXlzIGFuIGFuc3dlciwgYW5kIGl0IG1hdHRlcnMgdGhhdCB0aGVyZSBpczogYSBzdG9yZSBiZXR3ZWVuIHdpbmRvd3Mgc3RpbGwgaG9sZHNcbiAgICAgKiBkYXRhIGFuZCBzdGlsbCBoYXMgdG8gYW5zd2VyIGZvciBpdCwgc28gaXQgbmVlZHMgYSByb3V0ZSBhbmQgZmxhZ3MgZXZlbiB3aGVuIG5vdGhpbmcgaXNcbiAgICAgKiBjdXJyZW50bHkgcG9pbnRpbmcgd3JpdGVzIGF0IGl0LiBXaGljaCBvZiB0aGUgdGhyZWUgY2FzZXMgcHJvZHVjZWQgdGhlIGFuc3dlciBpcyBkZWxpYmVyYXRlbHlcbiAgICAgKiBub3QgZXhwb3NlZCAtIHRoZSB2YWxpZCB3aW5kb3cgaXRzZWxmIGlzIHdoYXQgc2F5cyB3aGV0aGVyIHdyaXRlcyBiZWxvbmcgaGVyZSwgYW5kIGV2ZXJ5IHdyaXRlXG4gICAgICogaXMgY2hlY2tlZCBhZ2FpbnN0IGl0IHNlcGFyYXRlbHkuXG4gICAgICovXG4gICAgcHVibGljIGN1cnJlbnQoKTogU3RvcmVQb2xpY3kge1xuICAgICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgbGV0IGNvbnRhaW5pbmcgPSB0aGlzLmVudHJpZXMuZmluZCh4ID0+IHgudmFsaWRXaW5kb3dbMF0gPD0gbm93ICYmIG5vdyA8IHgudmFsaWRXaW5kb3dbMV0pO1xuICAgICAgICBpZiAoY29udGFpbmluZykgcmV0dXJuIGNvbnRhaW5pbmc7XG4gICAgICAgIGxldCB1cGNvbWluZyA9IHRoaXMuZW50cmllcy5maW5kKHggPT4geC52YWxpZFdpbmRvd1swXSA+IG5vdyk7XG4gICAgICAgIGlmICh1cGNvbWluZykgcmV0dXJuIHVwY29taW5nO1xuICAgICAgICBsZXQgbGFzdCA9IHRoaXMuZW50cmllc1t0aGlzLmVudHJpZXMubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmIChsYXN0KSByZXR1cm4gbGFzdDtcbiAgICAgICAgcmV0dXJuIFVOQ09ORklHVVJFRDtcbiAgICB9XG59XG5cbi8qKiBUaGUgcGFydHMgb2YgYSBjb25maWcgZW50cnkgdGhhdCBkZXNjcmliZSB3aGF0IGEgc3RvcmUgSVMgLSBhcyBvcHBvc2VkIHRvIHdoaWNoIGVudHJ5IHNhaWQgc28uIEtlcHQgc2VwYXJhdGUgYmVjYXVzZSBhIHN0b3JlIHdpdGggbm8gZW50cmllcyBzdGlsbCBoYXMgYWxsIG9mIHRoZW0uICovXG5leHBvcnQgdHlwZSBTdG9yZVBvbGljeSA9IHtcbiAgICB2YWxpZFdpbmRvdzogW251bWJlciwgbnVtYmVyXTtcbiAgICByb3V0ZT86IFtudW1iZXIsIG51bWJlcl07XG4gICAgcHVibGljPzogYm9vbGVhbjtcbiAgICBpbW11dGFibGU/OiBib29sZWFuO1xuICAgIGZhc3Q/OiBib29sZWFuO1xuICAgIHdyaXRlRGVsYXk/OiBudW1iZXI7XG4gICAgbm9GdWxsU3luYz86IGJvb2xlYW47XG4gICAgcmVhZGVyRGlza0xpbWl0PzogbnVtYmVyO1xufTtcblxuLy8gQSBzdG9yZSBub2JvZHkgaGFzIGNvbmZpZ3VyZWQ6IGFsd2F5cyB2YWxpZCwgdGhlIHdob2xlIGtleSBzcGFjZSwgbm8gZGVsYXlzIGFuZCBubyBsaW1pdHMuIEV2ZXJ5IG9uZSBvZiB0aGVzZSBpcyB0aGUgYW5zd2VyIHRoYXQgZG9lcyB0aGUgbGVhc3QgLSBpdCBob2xkcyBpdHMgb3duIGRhdGEgYW5kIG5vdGhpbmcgZWxzZSBoYXBwZW5zIHRvIGl0IC0gd2hpY2ggaXMgd2hhdCBtYWtlcyBhIHN0b3JlIHVzYWJsZSBiZWZvcmUgaXQgaGFzIGV2ZXIgc2VlbiBhIGNvbmZpZy5cbmNvbnN0IFVOQ09ORklHVVJFRDogU3RvcmVQb2xpY3kgPSB7IHZhbGlkV2luZG93OiBGVUxMX1ZBTElEX1dJTkRPVyB9O1xuIl19
52
+ /* _JS_SOURCE_HASH = "8bb3f6f96b5bcb9f85a1dc5d367811caff8fa8ab88234e66e59890d123460dba"; */
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
- //exports.planSelfStores = exports.previousWindowOwners = exports.selectEntryAt = exports.findSelfIndexes = exports.isSelfSource = void 0;
4
- const misc_1 = require("socket-function/src/misc");
3
+ //exports.previousWindowOwners = exports.selectEntryAt = exports.findSelfIndexes = exports.isSelfSource = void 0;
5
4
  const IArchives_1 = require("../IArchives");
6
5
  const remoteConfig_1 = require("./remoteConfig");
7
6
  const serverConfig_1 = require("./serverConfig");
8
- // Turns a bucket's routing config into this server's store plan: which of the entries are us, what stores (one per route) we run, and which peers each store synchronizes from.
7
+ // Pure helpers over a bucket's routing config: which entries are this server, which entry applies at a moment, and who owned what before a window boundary. Config in, answer out - nothing here reads a store, a clock, or the network (except selectEntryAt being handed a time).
9
8
  /** Whether a config entry is THIS server's copy of this bucket - the same account and bucket, at an address this process answers on. */
10
9
  function isSelfSource(source, account, bucketName) {
11
10
  if (source.type !== "remote")
@@ -132,56 +131,5 @@ function previousWindowOwners(config, windowStart, selfIndexes) {
132
131
  return [...byRoute.values()].filter(x => x.scanOwnDisk || x.remotes.size);
133
132
  }
134
133
  exports.previousWindowOwners = previousWindowOwners;
135
- function mergeRoutes(routes) {
136
- let list = routes.map(x => x || IArchives_1.FULL_ROUTE).map(x => [x[0], x[1]]);
137
- (0, misc_1.sort)(list, x => x[0]);
138
- let merged = [];
139
- for (let route of list) {
140
- let last = merged[merged.length - 1];
141
- if (last && route[0] <= last[1]) {
142
- last[1] = Math.max(last[1], route[1]);
143
- continue;
144
- }
145
- merged.push(route);
146
- }
147
- return merged;
148
- }
149
- function summarizeSelf(selfEntries, now) {
150
- var _a;
151
- let current = selfEntries.filter(x => x.validWindow[0] <= now && now < x.validWindow[1]);
152
- if (!current.length) {
153
- let nearest = selectEntryAt(selfEntries, now);
154
- current = nearest && [nearest] || [];
155
- }
156
- if (!current.length) {
157
- return undefined;
158
- }
159
- return {
160
- routes: mergeRoutes(current.map(x => x.route)),
161
- public: current.some(x => x.public),
162
- immutable: current.some(x => x.immutable),
163
- noFullSync: current.some(x => x.noFullSync),
164
- readerDiskLimit: (_a = current.find(x => x.readerDiskLimit !== undefined)) === null || _a === void 0 ? void 0 : _a.readerDiskLimit,
165
- };
166
- }
167
- /** Which stores this server runs for a bucket, by name. Nothing more: a store is found by name, and configures itself. */
168
- function planSelfStores(account, bucketName, routing) {
169
- let selfIndexes = findSelfIndexes(routing, account, bucketName);
170
- let selfEntries = selfIndexes.map(i => routing.sources[i]);
171
- let self = summarizeSelf(selfEntries, Date.now());
172
- // One store per NAME among ALL our entries - past and future windows included, so a name we no longer write to keeps serving its data and a name we are about to use exists ahead of its window
173
- let byName = new Map();
174
- for (let entry of selfEntries) {
175
- let entries = byName.get(entry.name);
176
- if (!entries) {
177
- entries = [];
178
- byName.set(entry.name, entries);
179
- }
180
- entries.push(entry);
181
- }
182
- // Not in the config at all: no name means no store here
183
- return { selfEntries, self, stores: [...byName].map(([name, entries]) => ({ name, entries })) };
184
- }
185
- exports.planSelfStores = planSelfStores;
186
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmVQbGFuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmVQbGFuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1EQUFnRDtBQUNoRCw0Q0FBb0Y7QUFDcEYsaURBQWtGO0FBQ2xGLGlEQUE4QztBQUU5QyxnTEFBZ0w7QUFFaEwsd0lBQXdJO0FBQ3hJLFNBQWdCLFlBQVksQ0FBQyxNQUFvQixFQUFFLE9BQWUsRUFBRSxVQUFrQjtJQUNsRixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQzNDLElBQUksTUFBTSxHQUFHLElBQUEsNkJBQWMsRUFBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDeEMsSUFBSSxNQUFNLENBQUMsT0FBTyxLQUFLLE9BQU8sSUFBSSxNQUFNLENBQUMsVUFBVSxLQUFLLFVBQVU7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUNqRixPQUFPLElBQUEsMkJBQVksRUFBQyxNQUFNLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUNyRCxDQUFDO0FBTEQsb0NBS0M7QUFFRCxTQUFnQixlQUFlLENBQUMsT0FBcUIsRUFBRSxPQUFlLEVBQUUsVUFBa0I7SUFDdEYsSUFBSSxPQUFPLEdBQWEsRUFBRSxDQUFDO0lBQzNCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQzlDLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEMsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRO1lBQUUsU0FBUztRQUN6QyxJQUFJLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDNUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FB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R0FBRyxFQUEwQixDQUFDO0lBQy9DLEtBQUssSUFBSSxLQUFLLElBQUksV0FBVyxFQUFFLENBQUM7UUFDNUIsSUFBSSxPQUFPLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDckMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ1gsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNwQyxDQUFDO1FBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBQ0Qsd0RBQXdEO0lBQ3hELE9BQU8sRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDcEcsQ0FBQztBQWhCRCx3Q0FnQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzb3J0IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuaW1wb3J0IHsgUmVtb3RlQ29uZmlnLCBIb3N0ZWRDb25maWcsIFNvdXJjZUNvbmZpZywgRlVMTF9ST1VURSB9IGZyb20gXCIuLi9JQXJjaGl2ZXNcIjtcbmltcG9ydCB7IHBhcnNlSG9zdGVkVXJsLCByb3V0ZUNvbnRhaW5zLCByb3V0ZUludGVyc2VjdGlvbiB9IGZyb20gXCIuL3JlbW90ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgaXNPd25BZGRyZXNzIH0gZnJvbSBcIi4vc2VydmVyQ29uZmlnXCI7XG5cbi8vIFR1cm5zIGEgYnVja2V0J3Mgcm91dGluZyBjb25maWcgaW50byB0aGlzIHNlcnZlcidzIHN0b3JlIHBsYW46IHdoaWNoIG9mIHRoZSBlbnRyaWVzIGFyZSB1cywgd2hhdCBzdG9yZXMgKG9uZSBwZXIgcm91dGUpIHdlIHJ1biwgYW5kIHdoaWNoIHBlZXJzIGVhY2ggc3RvcmUgc3luY2hyb25pemVzIGZyb20uXG5cbi8qKiBXaGV0aGVyIGEgY29uZmlnIGVudHJ5IGlzIFRISVMgc2VydmVyJ3MgY29weSBvZiB0aGlzIGJ1Y2tldCAtIHRoZSBzYW1lIGFjY291bnQgYW5kIGJ1Y2tldCwgYXQgYW4gYWRkcmVzcyB0aGlzIHByb2Nlc3MgYW5zd2VycyBvbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1NlbGZTb3VyY2Uoc291cmNlOiBTb3VyY2VDb25maWcsIGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKHNvdXJjZS50eXBlICE9PSBcInJlbW90ZVwiKSByZXR1cm4gZmFsc2U7XG4gICAgbGV0IHBhcnNlZCA9IHBhcnNlSG9zdGVkVXJsKHNvdXJjZS51cmwpO1xuICAgIGlmIChwYXJzZWQuYWNjb3VudCAhPT0gYWNjb3VudCB8fCBwYXJzZWQuYnVja2V0TmFtZSAhPT0gYnVja2V0TmFtZSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiBpc093bkFkZHJlc3MocGFyc2VkLmFkZHJlc3MsIHBhcnNlZC5wb3J0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRTZWxmSW5kZXhlcyhyb3V0aW5nOiBSZW1vdGVDb25maWcsIGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogbnVtYmVyW10ge1xuICAgIGxldCBpbmRleGVzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcm91dGluZy5zb3VyY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCBzb3VyY2UgPSByb3V0aW5nLnNvdXJjZXNbaV07XG4gICAgICAgIGlmICh0eXBlb2Ygc291cmNlID09PSBcInN0cmluZ1wiKSBjb250aW51ZTtcbiAgICAgICAgaWYgKGlzU2VsZlNvdXJjZShzb3VyY2UsIGFjY291bnQsIGJ1Y2tldE5hbWUpKSB7XG4gICAgICAgICAgICBpbmRleGVzLnB1c2goaSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGluZGV4ZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3RFbnRyeUF0KGVudHJpZXM6IEhvc3RlZENvbmZpZ1tdLCB0aW1lOiBudW1iZXIsIHJvdXRlPzogbnVtYmVyKTogSG9zdGVkQ29uZmlnIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAocm91dGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBsZXQgY292ZXJpbmcgPSBlbnRyaWVzLmZpbHRlcih4ID0+IHJvdXRlQ29udGFpbnMoeC5yb3V0ZSwgcm91dGUpKTtcbiAgICAgICAgaWYgKGNvdmVyaW5nLmxlbmd0aCkge1xuICAgICAgICAgICAgZW50cmllcyA9IGNvdmVyaW5nO1xuICAgICAgICB9XG4gICAgfVxuICAgIGxldCBjb250YWluaW5nID0gZW50cmllcy5maW5kKHggPT4geC52YWxpZFdpbmRvd1swXSA8PSB0aW1lICYmIHRpbWUgPCB4LnZhbGlkV2luZG93WzFdKTtcbiAgICBpZiAoY29udGFpbmluZykgcmV0dXJuIGNvbnRhaW5pbmc7XG4gICAgbGV0IGJlc3Q6IEhvc3RlZENvbmZpZyB8IHVuZGVmaW5lZDtcbiAgICBsZXQgYmVzdERpc3RhbmNlID0gSW5maW5pdHk7XG4gICAgZm9yIChsZXQgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICBsZXQgZGlzdGFuY2UgPSBNYXRoLm1pbihNYXRoLmFicyh0aW1lIC0gZW50cnkudmFsaWRXaW5kb3dbMF0pLCBNYXRoLmFicyh0aW1lIC0gZW50cnkudmFsaWRXaW5kb3dbMV0pKTtcbiAgICAgICAgaWYgKGRpc3RhbmNlIDwgYmVzdERpc3RhbmNlKSB7XG4gICAgICAgICAgICBiZXN0RGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICAgICAgICAgIGJlc3QgPSBlbnRyeTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYmVzdDtcbn1cblxuLyoqIFRoZSBwYXJ0cyBvZiBgcmFuZ2VzYCB0aGF0IGBjdXRgIGRvZXMgbm90IGNvdmVyLCBwbHVzIHRoZSBzaW5nbGUgcmFuZ2Ugc3Bhbm5pbmcgd2hhdCBpdCBkaWQuIFJvdXRlcyBhcmUgaGFsZi1vcGVuIFtzdGFydCwgZW5kKSwgc28gc3VidHJhY3Rpbmcgb25lIGZyb20gYW5vdGhlciBsZWF2ZXMgYXQgbW9zdCBhIHBpZWNlIG9uIGVhY2ggc2lkZS4gKi9cbmZ1bmN0aW9uIHN1YnRyYWN0Um91dGUocmFuZ2VzOiBbbnVtYmVyLCBudW1iZXJdW10sIGN1dDogW251bWJlciwgbnVtYmVyXSk6IHsgcmVtYWluaW5nOiBbbnVtYmVyLCBudW1iZXJdW107IGNsYWltZWQ/OiBbbnVtYmVyLCBudW1iZXJdIH0ge1xuICAgIGxldCByZW1haW5pbmc6IFtudW1iZXIsIG51bWJlcl1bXSA9IFtdO1xuICAgIGxldCBjbGFpbWVkOiBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkO1xuICAgIGZvciAobGV0IHJhbmdlIG9mIHJhbmdlcykge1xuICAgICAgICBsZXQgb3ZlcmxhcCA9IHJvdXRlSW50ZXJzZWN0aW9uKHJhbmdlLCBjdXQpO1xuICAgICAgICBpZiAoIW92ZXJsYXApIHtcbiAgICAgICAgICAgIHJlbWFpbmluZy5wdXNoKHJhbmdlKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNsYWltZWQgPSBjbGFpbWVkICYmIFtNYXRoLm1pbihjbGFpbWVkWzBdLCBvdmVybGFwWzBdKSwgTWF0aC5tYXgoY2xhaW1lZFsxXSwgb3ZlcmxhcFsxXSldIGFzIFtudW1iZXIsIG51bWJlcl0gfHwgb3ZlcmxhcDtcbiAgICAgICAgaWYgKHJhbmdlWzBdIDwgb3ZlcmxhcFswXSkgcmVtYWluaW5nLnB1c2goW3JhbmdlWzBdLCBvdmVybGFwWzBdXSk7XG4gICAgICAgIGlmIChvdmVybGFwWzFdIDwgcmFuZ2VbMV0pIHJlbWFpbmluZy5wdXNoKFtvdmVybGFwWzFdLCByYW5nZVsxXV0pO1xuICAgIH1cbiAgICByZXR1cm4geyByZW1haW5pbmcsIGNsYWltZWQgfTtcbn1cblxuLyoqIFdoYXQgb25lIG9mIG91ciBzdG9yZXMgaGFzIHRvIHB1bGwgaW4gYXQgYSB2YWxpZC13aW5kb3cgYm91bmRhcnksIHNvIHRoZSB3cml0ZXMgdGhhdCBsYW5kZWQganVzdCBiZWZvcmUgdGhlIGhhbmRvdmVyIGFyZSBub3QgbWlzc2VkLiAqL1xuZXhwb3J0IHR5cGUgQm91bmRhcnlIYW5kb3ZlciA9IHtcbiAgICAvLyBUaGUgc3RvcmUgdGhhdCBuZWVkcyB0aGUgZGF0YTogdGhlIG5hbWUgb2YgdGhlIHNlbGYgZW50cnkgdGFraW5nIG92ZXIgYXQgdGhlIGJvdW5kYXJ5XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIC8vIFRoZSByb3V0ZSBpdCBpcyB0YWtpbmcgb3Zlciwgd2hpY2ggaXMgdGhlIHNsaWNlIG9mIHRoZSBrZXkgc3BhY2UgdGhlIHB1bGxzIGJlbG93IGFyZSBsaW1pdGVkIHRvXG4gICAgcm91dGU6IFtudW1iZXIsIG51bWJlcl07XG4gICAgLy8gV2UgaGVsZCBwYXJ0IG9mIHRoaXMgcm91dGUgaW4gdGhlIHByZXZpb3VzIHdpbmRvdyB0b28sIHNvIHRob3NlIHdyaXRlcyBhcmUgYWxyZWFkeSBpbiBvdXIgb3duIGZvbGRlciBhbmQgYSBkaXNrIHJlc2NhbiBmaW5kcyB0aGVtXG4gICAgc2Nhbk93bkRpc2s6IGJvb2xlYW47XG4gICAgLy8gUGVyIHNvdXJjZSBpbmRleCBpbiB0aGUgY29uZmlnLCB0aGUgc2xpY2Ugb2Ygb3VyIHJvdXRlIFRIQVQgc291cmNlIGhlbGQgaW4gdGhlIHByZXZpb3VzIHdpbmRvdyAtIGEgYm91bmRhcnkgc2NhbiBwdWxscyBpdHMgcmVjZW50IGNoYW5nZXNcbiAgICByZW1vdGVzOiBNYXA8bnVtYmVyLCBbbnVtYmVyLCBudW1iZXJdPjtcbn07XG5cbi8qKlxuICogV2hvIGhlbGQgZWFjaCBzbGljZSBvZiBvdXIgcm91dGUgaW4gdGhlIHdpbmRvdyBiZWZvcmUgd2luZG93U3RhcnQsIGZvciBldmVyeSBzZWxmIGVudHJ5IHdob3NlXG4gKiB3aW5kb3cgc3RhcnRzIGV4YWN0bHkgdGhlbi4gVGhpcyBpcyB0aGUgd2hvbGUgb2YgXCJ3aG8gZG8gd2UgdGFrZSBvdmVyIGZyb21cIjogYSBzdG9yZSB0YWtpbmcgb3ZlciBhXG4gKiByb3V0ZSBtYXkgYmUgdGFraW5nIGl0IGZyb20gc2V2ZXJhbCBwcmV2aW91cyBvd25lcnMgYXQgb25jZSAodGhlaXIgc2hhcmRzIG5lZWQgbm90IGxpbmUgdXAgd2l0aFxuICogb3VycyksIGFuZCBmcm9tIGl0c2VsZiBmb3IgdGhlIHBhcnRzIGl0IGFscmVhZHkgaGVsZC5cbiAqXG4gKiBBIHNlbGYgZW50cnkgaXMgc2tpcHBlZCB3aGVuIGFuIEVBUkxJRVIgZW50cnkgdmFsaWQgYXQgdGhlIGJvdW5kYXJ5IGFscmVhZHkgY292ZXJzIGl0cyB3aG9sZSByb3V0ZTpcbiAqIGNvbmZpZyBvcmRlciBpcyBwcmlvcml0eSwgc28gdGhhdCBlbnRyeSBpcyB0aGUgd3JpdGUgdGFyZ2V0IGFuZCB3ZSBhcmUgbm90IHRoZSBvbmUgdGFraW5nIG92ZXIuXG4gKiBPd25lcnMgYXJlIHRoZW4gcmVzb2x2ZWQgaW4gY29uZmlnIG9yZGVyIHRvbywgZWFjaCBjbGFpbWluZyB0aGUgcGFydCBvZiBvdXIgcm91dGUgc3RpbGwgdW5jbGFpbWVkIC1cbiAqIHRoZSBzYW1lIGZpcnN0LW1hdGNoLXdpbnMgcnVsZSB0aGF0IHBpY2tzIGEgd3JpdGUgdGFyZ2V0IGF0IGFueSBvdGhlciBtb21lbnQuXG4gKlxuICogUHVyZTogY29uZmlnIGluLCBwbGFuIG91dC4gTm90aGluZyBoZXJlIHJlYWRzIGEgc3RvcmUsIGEgY2xvY2ssIG9yIHRoZSBuZXR3b3JrLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJldmlvdXNXaW5kb3dPd25lcnMoY29uZmlnOiBSZW1vdGVDb25maWcsIHdpbmRvd1N0YXJ0OiBudW1iZXIsIHNlbGZJbmRleGVzOiBudW1iZXJbXSk6IEJvdW5kYXJ5SGFuZG92ZXJbXSB7XG4gICAgbGV0IHNlbGZJbmRleFNldCA9IG5ldyBTZXQoc2VsZkluZGV4ZXMpO1xuICAgIGxldCBwcmV2aW91c1RpbWUgPSB3aW5kb3dTdGFydCAtIDE7XG4gICAgbGV0IHZhbGlkQXQgPSAoc291cmNlOiBTb3VyY2VDb25maWcsIHRpbWU6IG51bWJlcikgPT4gc291cmNlLnZhbGlkV2luZG93WzBdIDw9IHRpbWUgJiYgdGltZSA8IHNvdXJjZS52YWxpZFdpbmRvd1sxXTtcbiAgICBsZXQgYnlSb3V0ZSA9IG5ldyBNYXA8c3RyaW5nLCBCb3VuZGFyeUhhbmRvdmVyPigpO1xuICAgIGZvciAobGV0IHNlbGZJbmRleCBvZiBzZWxmSW5kZXhlcykge1xuICAgICAgICBsZXQgc2VsZiA9IGNvbmZpZy5zb3VyY2VzW3NlbGZJbmRleF07XG4gICAgICAgIGlmICh0eXBlb2Ygc2VsZiA9PT0gXCJzdHJpbmdcIiB8fCBzZWxmLnZhbGlkV2luZG93WzBdICE9PSB3aW5kb3dTdGFydCkgY29udGludWU7XG4gICAgICAgIGxldCBzZWxmUm91dGUgPSBzZWxmLnJvdXRlIHx8IEZVTExfUk9VVEU7XG4gICAgICAgIGxldCBzaGFkb3dlZCA9IGZhbHNlO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGZJbmRleDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgb3RoZXIgPSBjb25maWcuc291cmNlc1tpXTtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3RoZXIgPT09IFwic3RyaW5nXCIgfHwgIXZhbGlkQXQob3RoZXIsIHdpbmRvd1N0YXJ0KSkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgcm91dGUgPSBvdGhlci5yb3V0ZSB8fCBGVUxMX1JPVVRFO1xuICAgICAgICAgICAgaWYgKHJvdXRlWzBdIDw9IHNlbGZSb3V0ZVswXSAmJiBzZWxmUm91dGVbMV0gPD0gcm91dGVbMV0pIHtcbiAgICAgICAgICAgICAgICBzaGFkb3dlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNoYWRvd2VkKSBjb250aW51ZTtcbiAgICAgICAgLy8gS2V5ZWQgYnkgYm90aDogb25lIG5hbWUgY2FuIHRha2Ugb3ZlciBzZXZlcmFsIHJvdXRlcyBhdCB0aGUgc2FtZSBib3VuZGFyeSwgYW5kIGVhY2ggaXMgcHVsbGVkIHNlcGFyYXRlbHlcbiAgICAgICAgbGV0IGhhbmRvdmVyS2V5ID0gYCR7c2VsZi5uYW1lfXwke0pTT04uc3RyaW5naWZ5KHNlbGZSb3V0ZSl9YDtcbiAgICAgICAgbGV0IGhhbmRvdmVyID0gYnlSb3V0ZS5nZXQoaGFuZG92ZXJLZXkpO1xuICAgICAgICBpZiAoIWhhbmRvdmVyKSB7XG4gICAgICAgICAgICBoYW5kb3ZlciA9IHsgbmFtZTogc2VsZi5uYW1lLCByb3V0ZTogc2VsZlJvdXRlLCBzY2FuT3duRGlzazogZmFsc2UsIHJlbW90ZXM6IG5ldyBNYXAoKSB9O1xuICAgICAgICAgICAgYnlSb3V0ZS5zZXQoaGFuZG92ZXJLZXksIGhhbmRvdmVyKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgdW5jbGFpbWVkOiBbbnVtYmVyLCBudW1iZXJdW10gPSBbW3NlbGZSb3V0ZVswXSwgc2VsZlJvdXRlWzFdXV07XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29uZmlnLnNvdXJjZXMubGVuZ3RoICYmIHVuY2xhaW1lZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IG90aGVyID0gY29uZmlnLnNvdXJjZXNbaV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIG90aGVyID09PSBcInN0cmluZ1wiIHx8ICF2YWxpZEF0KG90aGVyLCBwcmV2aW91c1RpbWUpKSBjb250aW51ZTtcbiAgICAgICAgICAgIGxldCB7IHJlbWFpbmluZywgY2xhaW1lZCB9ID0gc3VidHJhY3RSb3V0ZSh1bmNsYWltZWQsIG90aGVyLnJvdXRlIHx8IEZVTExfUk9VVEUpO1xuICAgICAgICAgICAgdW5jbGFpbWVkID0gcmVtYWluaW5nO1xuICAgICAgICAgICAgaWYgKCFjbGFpbWVkKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmIChzZWxmSW5kZXhTZXQuaGFzKGkpKSB7XG4gICAgICAgICAgICAgICAgaGFuZG92ZXIuc2Nhbk93bkRpc2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGV4aXN0aW5nID0gaGFuZG92ZXIucmVtb3Rlcy5nZXQoaSk7XG4gICAgICAgICAgICBoYW5kb3Zlci5yZW1vdGVzLnNldChpLCBleGlzdGluZyAmJiBbTWF0aC5taW4oZXhpc3RpbmdbMF0sIGNsYWltZWRbMF0pLCBNYXRoLm1heChleGlzdGluZ1sxXSwgY2xhaW1lZFsxXSldIGFzIFtudW1iZXIsIG51bWJlcl0gfHwgY2xhaW1lZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFsuLi5ieVJvdXRlLnZhbHVlcygpXS5maWx0ZXIoeCA9PiB4LnNjYW5Pd25EaXNrIHx8IHgucmVtb3Rlcy5zaXplKTtcbn1cblxuLyoqIE91ciByb2xlIGluIGEgYnVja2V0J3Mgcm91dGluZyBjb25maWcsIHN1bW1hcml6ZWQgYWNyb3NzIEFMTCBjdXJyZW50bHktdmFsaWQgc2VsZiBlbnRyaWVzLiBTdG9yZWQgaW5zdGVhZCBvZiBhIHNpbmdsZSByZXByZXNlbnRhdGl2ZSBIb3N0ZWRDb25maWcsIHNvIG5vdGhpbmcgY2FuIGFjY2lkZW50YWxseSB1c2Ugb25lIGVudHJ5J3Mgcm91dGUgb3IgZmxhZ3Mgd2hlcmUgdGhlIHVuaW9uIGlzIHJlcXVpcmVkIC0gdGhlIHN0YW5kYXJkIGNvbmZpZyBoYXMgdGhlIHNhbWUgVVJMIHR3aWNlOiBhIHJvdXRlZCB3cml0ZS1zaGFyZCBlbnRyeSBwbHVzIGFuIHVucm91dGVkIHJlYWQtZXZlcnl0aGluZyBlbnRyeS4gKi9cbmV4cG9ydCB0eXBlIFNlbGZTdW1tYXJ5ID0ge1xuICAgIC8qKiBUaGUgdW5pb24gb2YgdGhlIGN1cnJlbnQgZW50cmllcycgcm91dGVzLCB3aXRoIG92ZXJsYXBwaW5nL2FkamFjZW50IHJhbmdlcyBjb21iaW5lZCAtIHdoaWNoIGNvbW1vbmx5IGNvbGxhcHNlcyB0byBhIHNpbmdsZSBmdWxsIHJhbmdlLCBtYWtpbmcgbWF0Y2hpbmcgdHJpdmlhbC4gKi9cbiAgICByb3V0ZXM6IFtudW1iZXIsIG51bWJlcl1bXTtcbiAgICBwdWJsaWM6IGJvb2xlYW47XG4gICAgaW1tdXRhYmxlOiBib29sZWFuO1xuICAgIG5vRnVsbFN5bmM6IGJvb2xlYW47XG4gICAgcmVhZGVyRGlza0xpbWl0PzogbnVtYmVyO1xufTtcblxuZnVuY3Rpb24gbWVyZ2VSb3V0ZXMocm91dGVzOiAoW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZClbXSk6IFtudW1iZXIsIG51bWJlcl1bXSB7XG4gICAgbGV0IGxpc3QgPSByb3V0ZXMubWFwKHggPT4geCB8fCBGVUxMX1JPVVRFKS5tYXAoeCA9PiBbeFswXSwgeFsxXV0gYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgc29ydChsaXN0LCB4ID0+IHhbMF0pO1xuICAgIGxldCBtZXJnZWQ6IFtudW1iZXIsIG51bWJlcl1bXSA9IFtdO1xuICAgIGZvciAobGV0IHJvdXRlIG9mIGxpc3QpIHtcbiAgICAgICAgbGV0IGxhc3QgPSBtZXJnZWRbbWVyZ2VkLmxlbmd0aCAtIDFdO1xuICAgICAgICBpZiAobGFzdCAmJiByb3V0ZVswXSA8PSBsYXN0WzFdKSB7XG4gICAgICAgICAgICBsYXN0WzFdID0gTWF0aC5tYXgobGFzdFsxXSwgcm91dGVbMV0pO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgbWVyZ2VkLnB1c2gocm91dGUpO1xuICAgIH1cbiAgICByZXR1cm4gbWVyZ2VkO1xufVxuXG5mdW5jdGlvbiBzdW1tYXJpemVTZWxmKHNlbGZFbnRyaWVzOiBIb3N0ZWRDb25maWdbXSwgbm93OiBudW1iZXIpOiBTZWxmU3VtbWFyeSB8IHVuZGVmaW5lZCB7XG4gICAgbGV0IGN1cnJlbnQgPSBzZWxmRW50cmllcy5maWx0ZXIoeCA9PiB4LnZhbGlkV2luZG93WzBdIDw9IG5vdyAmJiBub3cgPCB4LnZhbGlkV2luZG93WzFdKTtcbiAgICBpZiAoIWN1cnJlbnQubGVuZ3RoKSB7XG4gICAgICAgIGxldCBuZWFyZXN0ID0gc2VsZWN0RW50cnlBdChzZWxmRW50cmllcywgbm93KTtcbiAgICAgICAgY3VycmVudCA9IG5lYXJlc3QgJiYgW25lYXJlc3RdIHx8IFtdO1xuICAgIH1cbiAgICBpZiAoIWN1cnJlbnQubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHJvdXRlczogbWVyZ2VSb3V0ZXMoY3VycmVudC5tYXAoeCA9PiB4LnJvdXRlKSksXG4gICAgICAgIHB1YmxpYzogY3VycmVudC5zb21lKHggPT4geC5wdWJsaWMpLFxuICAgICAgICBpbW11dGFibGU6IGN1cnJlbnQuc29tZSh4ID0+IHguaW1tdXRhYmxlKSxcbiAgICAgICAgbm9GdWxsU3luYzogY3VycmVudC5zb21lKHggPT4geC5ub0Z1bGxTeW5jKSxcbiAgICAgICAgcmVhZGVyRGlza0xpbWl0OiBjdXJyZW50LmZpbmQoeCA9PiB4LnJlYWRlckRpc2tMaW1pdCAhPT0gdW5kZWZpbmVkKT8ucmVhZGVyRGlza0xpbWl0LFxuICAgIH07XG59XG5cbi8qKiBPbmUgc3RvcmUgdGhpcyBzZXJ2ZXIgcnVucyBmb3IgYSBidWNrZXQ6IHRoZSBuYW1lIHRoYXQgSVMgdGhlIHN0b3JlLCBhbmQgdGhlIGVudHJpZXMgdGhhdCBuYW1lIGl0LiBXaGF0IGl0IHN5bmNocm9uaXplcyB3aXRoIGlzIE5PVCBkZWNpZGVkIGhlcmUgLSB0aGUgc3RvcmUgcmVhZHMgaXRzIG93biBjb3B5IG9mIHRoZSBjb25maWcgYW5kIHdvcmtzIHRoYXQgb3V0IGl0c2VsZiAoc2VlIEJsb2JTdG9yZS5hcHBseVJvdXRpbmdDb25maWcpLiAqL1xuZXhwb3J0IHR5cGUgU2VsZlN0b3JlID0ge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBlbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbn07XG5cbi8qKiBXaGljaCBzdG9yZXMgdGhpcyBzZXJ2ZXIgcnVucyBmb3IgYSBidWNrZXQsIGJ5IG5hbWUuIE5vdGhpbmcgbW9yZTogYSBzdG9yZSBpcyBmb3VuZCBieSBuYW1lLCBhbmQgY29uZmlndXJlcyBpdHNlbGYuICovXG5leHBvcnQgZnVuY3Rpb24gcGxhblNlbGZTdG9yZXMoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIHJvdXRpbmc6IFJlbW90ZUNvbmZpZyk6IHsgc2VsZkVudHJpZXM6IEhvc3RlZENvbmZpZ1tdOyBzZWxmOiBTZWxmU3VtbWFyeSB8IHVuZGVmaW5lZDsgc3RvcmVzOiBTZWxmU3RvcmVbXSB9IHtcbiAgICBsZXQgc2VsZkluZGV4ZXMgPSBmaW5kU2VsZkluZGV4ZXMocm91dGluZywgYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHNlbGZFbnRyaWVzID0gc2VsZkluZGV4ZXMubWFwKGkgPT4gcm91dGluZy5zb3VyY2VzW2ldIGFzIEhvc3RlZENvbmZpZyk7XG4gICAgbGV0IHNlbGYgPSBzdW1tYXJpemVTZWxmKHNlbGZFbnRyaWVzLCBEYXRlLm5vdygpKTtcbiAgICAvLyBPbmUgc3RvcmUgcGVyIE5BTUUgYW1vbmcgQUxMIG91ciBlbnRyaWVzIC0gcGFzdCBhbmQgZnV0dXJlIHdpbmRvd3MgaW5jbHVkZWQsIHNvIGEgbmFtZSB3ZSBubyBsb25nZXIgd3JpdGUgdG8ga2VlcHMgc2VydmluZyBpdHMgZGF0YSBhbmQgYSBuYW1lIHdlIGFyZSBhYm91dCB0byB1c2UgZXhpc3RzIGFoZWFkIG9mIGl0cyB3aW5kb3dcbiAgICBsZXQgYnlOYW1lID0gbmV3IE1hcDxzdHJpbmcsIEhvc3RlZENvbmZpZ1tdPigpO1xuICAgIGZvciAobGV0IGVudHJ5IG9mIHNlbGZFbnRyaWVzKSB7XG4gICAgICAgIGxldCBlbnRyaWVzID0gYnlOYW1lLmdldChlbnRyeS5uYW1lKTtcbiAgICAgICAgaWYgKCFlbnRyaWVzKSB7XG4gICAgICAgICAgICBlbnRyaWVzID0gW107XG4gICAgICAgICAgICBieU5hbWUuc2V0KGVudHJ5Lm5hbWUsIGVudHJpZXMpO1xuICAgICAgICB9XG4gICAgICAgIGVudHJpZXMucHVzaChlbnRyeSk7XG4gICAgfVxuICAgIC8vIE5vdCBpbiB0aGUgY29uZmlnIGF0IGFsbDogbm8gbmFtZSBtZWFucyBubyBzdG9yZSBoZXJlXG4gICAgcmV0dXJuIHsgc2VsZkVudHJpZXMsIHNlbGYsIHN0b3JlczogWy4uLmJ5TmFtZV0ubWFwKChbbmFtZSwgZW50cmllc10pID0+ICh7IG5hbWUsIGVudHJpZXMgfSkpIH07XG59XG4iXX0=
187
- /* _JS_SOURCE_HASH = "34bdac815bba6b0da86e3b712610c28994f577faf6bb0acd7d09b73d2d301e81"; */
134
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmVQbGFuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmVQbGFuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDRDQUFvRjtBQUNwRixpREFBa0Y7QUFDbEYsaURBQThDO0FBRTlDLG9SQUFvUjtBQUVwUix3SUFBd0k7QUFDeEksU0FBZ0IsWUFBWSxDQUFDLE1BQW9CLEVBQUUsT0FBZSxFQUFFLFVBQWtCO0lBQ2xGLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxRQUFRO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0MsSUFBSSxNQUFNLEdBQUcsSUFBQSw2QkFBYyxFQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN4QyxJQUFJLE1BQU0sQ0FBQyxPQUFPLEtBQUssT0FBTyxJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssVUFBVTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ2pGLE9BQU8sSUFBQSwyQkFBWSxFQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3JELENBQUM7QUFMRCxvQ0FLQztBQUVELFNBQWdCLGVBQWUsQ0FBQyxPQUFxQixFQUFFLE9BQWUsRUFBRSxVQUFrQjtJQUN0RixJQUFJLE9BQU8sR0FBYSxFQUFFLENBQUM7SUFDM0IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDOUMsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoQyxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVE7WUFBRSxTQUFTO1FBQ3pDLElBQUksWUFBWSxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUM1QyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BCLENBQUM7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O2dCQUFFLFNBQVM7WUFDekUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsR0FBRyxhQUFhLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxLQUFLLElBQUksc0JBQVUsQ0FBQyxDQUFDO1lBQ2pGLFNBQVMsR0FBRyxTQUFTLENBQUM7WUFDdEIsSUFBSSxDQUFDLE9BQU87Z0JBQUUsU0FBUztZQUN2QixJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDdEIsUUFBUSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7Z0JBQzVCLFNBQVM7WUFDYixDQUFDO1lBQ0QsSUFBSSxRQUFRLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFxQixJQUFJLE9BQU8sQ0FBQyxDQUFDO1FBQy9JLENBQUM7SUFDTCxDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUEzQ0Qsb0RBMkNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUmVtb3RlQ29uZmlnLCBIb3N0ZWRDb25maWcsIFNvdXJjZUNvbmZpZywgRlVMTF9ST1VURSB9IGZyb20gXCIuLi9JQXJjaGl2ZXNcIjtcbmltcG9ydCB7IHBhcnNlSG9zdGVkVXJsLCByb3V0ZUNvbnRhaW5zLCByb3V0ZUludGVyc2VjdGlvbiB9IGZyb20gXCIuL3JlbW90ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgaXNPd25BZGRyZXNzIH0gZnJvbSBcIi4vc2VydmVyQ29uZmlnXCI7XG5cbi8vIFB1cmUgaGVscGVycyBvdmVyIGEgYnVja2V0J3Mgcm91dGluZyBjb25maWc6IHdoaWNoIGVudHJpZXMgYXJlIHRoaXMgc2VydmVyLCB3aGljaCBlbnRyeSBhcHBsaWVzIGF0IGEgbW9tZW50LCBhbmQgd2hvIG93bmVkIHdoYXQgYmVmb3JlIGEgd2luZG93IGJvdW5kYXJ5LiBDb25maWcgaW4sIGFuc3dlciBvdXQgLSBub3RoaW5nIGhlcmUgcmVhZHMgYSBzdG9yZSwgYSBjbG9jaywgb3IgdGhlIG5ldHdvcmsgKGV4Y2VwdCBzZWxlY3RFbnRyeUF0IGJlaW5nIGhhbmRlZCBhIHRpbWUpLlxuXG4vKiogV2hldGhlciBhIGNvbmZpZyBlbnRyeSBpcyBUSElTIHNlcnZlcidzIGNvcHkgb2YgdGhpcyBidWNrZXQgLSB0aGUgc2FtZSBhY2NvdW50IGFuZCBidWNrZXQsIGF0IGFuIGFkZHJlc3MgdGhpcyBwcm9jZXNzIGFuc3dlcnMgb24uICovXG5leHBvcnQgZnVuY3Rpb24gaXNTZWxmU291cmNlKHNvdXJjZTogU291cmNlQ29uZmlnLCBhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmIChzb3VyY2UudHlwZSAhPT0gXCJyZW1vdGVcIikgcmV0dXJuIGZhbHNlO1xuICAgIGxldCBwYXJzZWQgPSBwYXJzZUhvc3RlZFVybChzb3VyY2UudXJsKTtcbiAgICBpZiAocGFyc2VkLmFjY291bnQgIT09IGFjY291bnQgfHwgcGFyc2VkLmJ1Y2tldE5hbWUgIT09IGJ1Y2tldE5hbWUpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gaXNPd25BZGRyZXNzKHBhcnNlZC5hZGRyZXNzLCBwYXJzZWQucG9ydCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kU2VsZkluZGV4ZXMocm91dGluZzogUmVtb3RlQ29uZmlnLCBhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IG51bWJlcltdIHtcbiAgICBsZXQgaW5kZXhlczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvdXRpbmcuc291cmNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgc291cmNlID0gcm91dGluZy5zb3VyY2VzW2ldO1xuICAgICAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJzdHJpbmdcIikgY29udGludWU7XG4gICAgICAgIGlmIChpc1NlbGZTb3VyY2Uoc291cmNlLCBhY2NvdW50LCBidWNrZXROYW1lKSkge1xuICAgICAgICAgICAgaW5kZXhlcy5wdXNoKGkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBpbmRleGVzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2VsZWN0RW50cnlBdChlbnRyaWVzOiBIb3N0ZWRDb25maWdbXSwgdGltZTogbnVtYmVyLCByb3V0ZT86IG51bWJlcik6IEhvc3RlZENvbmZpZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHJvdXRlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbGV0IGNvdmVyaW5nID0gZW50cmllcy5maWx0ZXIoeCA9PiByb3V0ZUNvbnRhaW5zKHgucm91dGUsIHJvdXRlKSk7XG4gICAgICAgIGlmIChjb3ZlcmluZy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGVudHJpZXMgPSBjb3ZlcmluZztcbiAgICAgICAgfVxuICAgIH1cbiAgICBsZXQgY29udGFpbmluZyA9IGVudHJpZXMuZmluZCh4ID0+IHgudmFsaWRXaW5kb3dbMF0gPD0gdGltZSAmJiB0aW1lIDwgeC52YWxpZFdpbmRvd1sxXSk7XG4gICAgaWYgKGNvbnRhaW5pbmcpIHJldHVybiBjb250YWluaW5nO1xuICAgIGxldCBiZXN0OiBIb3N0ZWRDb25maWcgfCB1bmRlZmluZWQ7XG4gICAgbGV0IGJlc3REaXN0YW5jZSA9IEluZmluaXR5O1xuICAgIGZvciAobGV0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgICAgbGV0IGRpc3RhbmNlID0gTWF0aC5taW4oTWF0aC5hYnModGltZSAtIGVudHJ5LnZhbGlkV2luZG93WzBdKSwgTWF0aC5hYnModGltZSAtIGVudHJ5LnZhbGlkV2luZG93WzFdKSk7XG4gICAgICAgIGlmIChkaXN0YW5jZSA8IGJlc3REaXN0YW5jZSkge1xuICAgICAgICAgICAgYmVzdERpc3RhbmNlID0gZGlzdGFuY2U7XG4gICAgICAgICAgICBiZXN0ID0gZW50cnk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGJlc3Q7XG59XG5cbi8qKiBUaGUgcGFydHMgb2YgYHJhbmdlc2AgdGhhdCBgY3V0YCBkb2VzIG5vdCBjb3ZlciwgcGx1cyB0aGUgc2luZ2xlIHJhbmdlIHNwYW5uaW5nIHdoYXQgaXQgZGlkLiBSb3V0ZXMgYXJlIGhhbGYtb3BlbiBbc3RhcnQsIGVuZCksIHNvIHN1YnRyYWN0aW5nIG9uZSBmcm9tIGFub3RoZXIgbGVhdmVzIGF0IG1vc3QgYSBwaWVjZSBvbiBlYWNoIHNpZGUuICovXG5mdW5jdGlvbiBzdWJ0cmFjdFJvdXRlKHJhbmdlczogW251bWJlciwgbnVtYmVyXVtdLCBjdXQ6IFtudW1iZXIsIG51bWJlcl0pOiB7IHJlbWFpbmluZzogW251bWJlciwgbnVtYmVyXVtdOyBjbGFpbWVkPzogW251bWJlciwgbnVtYmVyXSB9IHtcbiAgICBsZXQgcmVtYWluaW5nOiBbbnVtYmVyLCBudW1iZXJdW10gPSBbXTtcbiAgICBsZXQgY2xhaW1lZDogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZDtcbiAgICBmb3IgKGxldCByYW5nZSBvZiByYW5nZXMpIHtcbiAgICAgICAgbGV0IG92ZXJsYXAgPSByb3V0ZUludGVyc2VjdGlvbihyYW5nZSwgY3V0KTtcbiAgICAgICAgaWYgKCFvdmVybGFwKSB7XG4gICAgICAgICAgICByZW1haW5pbmcucHVzaChyYW5nZSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjbGFpbWVkID0gY2xhaW1lZCAmJiBbTWF0aC5taW4oY2xhaW1lZFswXSwgb3ZlcmxhcFswXSksIE1hdGgubWF4KGNsYWltZWRbMV0sIG92ZXJsYXBbMV0pXSBhcyBbbnVtYmVyLCBudW1iZXJdIHx8IG92ZXJsYXA7XG4gICAgICAgIGlmIChyYW5nZVswXSA8IG92ZXJsYXBbMF0pIHJlbWFpbmluZy5wdXNoKFtyYW5nZVswXSwgb3ZlcmxhcFswXV0pO1xuICAgICAgICBpZiAob3ZlcmxhcFsxXSA8IHJhbmdlWzFdKSByZW1haW5pbmcucHVzaChbb3ZlcmxhcFsxXSwgcmFuZ2VbMV1dKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcmVtYWluaW5nLCBjbGFpbWVkIH07XG59XG5cbi8qKiBXaGF0IG9uZSBvZiBvdXIgc3RvcmVzIGhhcyB0byBwdWxsIGluIGF0IGEgdmFsaWQtd2luZG93IGJvdW5kYXJ5LCBzbyB0aGUgd3JpdGVzIHRoYXQgbGFuZGVkIGp1c3QgYmVmb3JlIHRoZSBoYW5kb3ZlciBhcmUgbm90IG1pc3NlZC4gKi9cbmV4cG9ydCB0eXBlIEJvdW5kYXJ5SGFuZG92ZXIgPSB7XG4gICAgLy8gVGhlIHN0b3JlIHRoYXQgbmVlZHMgdGhlIGRhdGE6IHRoZSBuYW1lIG9mIHRoZSBzZWxmIGVudHJ5IHRha2luZyBvdmVyIGF0IHRoZSBib3VuZGFyeVxuICAgIG5hbWU6IHN0cmluZztcbiAgICAvLyBUaGUgcm91dGUgaXQgaXMgdGFraW5nIG92ZXIsIHdoaWNoIGlzIHRoZSBzbGljZSBvZiB0aGUga2V5IHNwYWNlIHRoZSBwdWxscyBiZWxvdyBhcmUgbGltaXRlZCB0b1xuICAgIHJvdXRlOiBbbnVtYmVyLCBudW1iZXJdO1xuICAgIC8vIFdlIGhlbGQgcGFydCBvZiB0aGlzIHJvdXRlIGluIHRoZSBwcmV2aW91cyB3aW5kb3cgdG9vLCBzbyB0aG9zZSB3cml0ZXMgYXJlIGFscmVhZHkgaW4gb3VyIG93biBmb2xkZXIgYW5kIGEgZGlzayByZXNjYW4gZmluZHMgdGhlbVxuICAgIHNjYW5Pd25EaXNrOiBib29sZWFuO1xuICAgIC8vIFBlciBzb3VyY2UgaW5kZXggaW4gdGhlIGNvbmZpZywgdGhlIHNsaWNlIG9mIG91ciByb3V0ZSBUSEFUIHNvdXJjZSBoZWxkIGluIHRoZSBwcmV2aW91cyB3aW5kb3cgLSBhIGJvdW5kYXJ5IHNjYW4gcHVsbHMgaXRzIHJlY2VudCBjaGFuZ2VzXG4gICAgcmVtb3RlczogTWFwPG51bWJlciwgW251bWJlciwgbnVtYmVyXT47XG59O1xuXG4vKipcbiAqIFdobyBoZWxkIGVhY2ggc2xpY2Ugb2Ygb3VyIHJvdXRlIGluIHRoZSB3aW5kb3cgYmVmb3JlIHdpbmRvd1N0YXJ0LCBmb3IgZXZlcnkgc2VsZiBlbnRyeSB3aG9zZVxuICogd2luZG93IHN0YXJ0cyBleGFjdGx5IHRoZW4uIFRoaXMgaXMgdGhlIHdob2xlIG9mIFwid2hvIGRvIHdlIHRha2Ugb3ZlciBmcm9tXCI6IGEgc3RvcmUgdGFraW5nIG92ZXIgYVxuICogcm91dGUgbWF5IGJlIHRha2luZyBpdCBmcm9tIHNldmVyYWwgcHJldmlvdXMgb3duZXJzIGF0IG9uY2UgKHRoZWlyIHNoYXJkcyBuZWVkIG5vdCBsaW5lIHVwIHdpdGhcbiAqIG91cnMpLCBhbmQgZnJvbSBpdHNlbGYgZm9yIHRoZSBwYXJ0cyBpdCBhbHJlYWR5IGhlbGQuXG4gKlxuICogQSBzZWxmIGVudHJ5IGlzIHNraXBwZWQgd2hlbiBhbiBFQVJMSUVSIGVudHJ5IHZhbGlkIGF0IHRoZSBib3VuZGFyeSBhbHJlYWR5IGNvdmVycyBpdHMgd2hvbGUgcm91dGU6XG4gKiBjb25maWcgb3JkZXIgaXMgcHJpb3JpdHksIHNvIHRoYXQgZW50cnkgaXMgdGhlIHdyaXRlIHRhcmdldCBhbmQgd2UgYXJlIG5vdCB0aGUgb25lIHRha2luZyBvdmVyLlxuICogT3duZXJzIGFyZSB0aGVuIHJlc29sdmVkIGluIGNvbmZpZyBvcmRlciB0b28sIGVhY2ggY2xhaW1pbmcgdGhlIHBhcnQgb2Ygb3VyIHJvdXRlIHN0aWxsIHVuY2xhaW1lZCAtXG4gKiB0aGUgc2FtZSBmaXJzdC1tYXRjaC13aW5zIHJ1bGUgdGhhdCBwaWNrcyBhIHdyaXRlIHRhcmdldCBhdCBhbnkgb3RoZXIgbW9tZW50LlxuICpcbiAqIFB1cmU6IGNvbmZpZyBpbiwgcGxhbiBvdXQuIE5vdGhpbmcgaGVyZSByZWFkcyBhIHN0b3JlLCBhIGNsb2NrLCBvciB0aGUgbmV0d29yay5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZXZpb3VzV2luZG93T3duZXJzKGNvbmZpZzogUmVtb3RlQ29uZmlnLCB3aW5kb3dTdGFydDogbnVtYmVyLCBzZWxmSW5kZXhlczogbnVtYmVyW10pOiBCb3VuZGFyeUhhbmRvdmVyW10ge1xuICAgIGxldCBzZWxmSW5kZXhTZXQgPSBuZXcgU2V0KHNlbGZJbmRleGVzKTtcbiAgICBsZXQgcHJldmlvdXNUaW1lID0gd2luZG93U3RhcnQgLSAxO1xuICAgIGxldCB2YWxpZEF0ID0gKHNvdXJjZTogU291cmNlQ29uZmlnLCB0aW1lOiBudW1iZXIpID0+IHNvdXJjZS52YWxpZFdpbmRvd1swXSA8PSB0aW1lICYmIHRpbWUgPCBzb3VyY2UudmFsaWRXaW5kb3dbMV07XG4gICAgbGV0IGJ5Um91dGUgPSBuZXcgTWFwPHN0cmluZywgQm91bmRhcnlIYW5kb3Zlcj4oKTtcbiAgICBmb3IgKGxldCBzZWxmSW5kZXggb2Ygc2VsZkluZGV4ZXMpIHtcbiAgICAgICAgbGV0IHNlbGYgPSBjb25maWcuc291cmNlc1tzZWxmSW5kZXhdO1xuICAgICAgICBpZiAodHlwZW9mIHNlbGYgPT09IFwic3RyaW5nXCIgfHwgc2VsZi52YWxpZFdpbmRvd1swXSAhPT0gd2luZG93U3RhcnQpIGNvbnRpbnVlO1xuICAgICAgICBsZXQgc2VsZlJvdXRlID0gc2VsZi5yb3V0ZSB8fCBGVUxMX1JPVVRFO1xuICAgICAgICBsZXQgc2hhZG93ZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmSW5kZXg7IGkrKykge1xuICAgICAgICAgICAgbGV0IG90aGVyID0gY29uZmlnLnNvdXJjZXNbaV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIG90aGVyID09PSBcInN0cmluZ1wiIHx8ICF2YWxpZEF0KG90aGVyLCB3aW5kb3dTdGFydCkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgbGV0IHJvdXRlID0gb3RoZXIucm91dGUgfHwgRlVMTF9ST1VURTtcbiAgICAgICAgICAgIGlmIChyb3V0ZVswXSA8PSBzZWxmUm91dGVbMF0gJiYgc2VsZlJvdXRlWzFdIDw9IHJvdXRlWzFdKSB7XG4gICAgICAgICAgICAgICAgc2hhZG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzaGFkb3dlZCkgY29udGludWU7XG4gICAgICAgIC8vIEtleWVkIGJ5IGJvdGg6IG9uZSBuYW1lIGNhbiB0YWtlIG92ZXIgc2V2ZXJhbCByb3V0ZXMgYXQgdGhlIHNhbWUgYm91bmRhcnksIGFuZCBlYWNoIGlzIHB1bGxlZCBzZXBhcmF0ZWx5XG4gICAgICAgIGxldCBoYW5kb3ZlcktleSA9IGAke3NlbGYubmFtZX18JHtKU09OLnN0cmluZ2lmeShzZWxmUm91dGUpfWA7XG4gICAgICAgIGxldCBoYW5kb3ZlciA9IGJ5Um91dGUuZ2V0KGhhbmRvdmVyS2V5KTtcbiAgICAgICAgaWYgKCFoYW5kb3Zlcikge1xuICAgICAgICAgICAgaGFuZG92ZXIgPSB7IG5hbWU6IHNlbGYubmFtZSwgcm91dGU6IHNlbGZSb3V0ZSwgc2Nhbk93bkRpc2s6IGZhbHNlLCByZW1vdGVzOiBuZXcgTWFwKCkgfTtcbiAgICAgICAgICAgIGJ5Um91dGUuc2V0KGhhbmRvdmVyS2V5LCBoYW5kb3Zlcik7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHVuY2xhaW1lZDogW251bWJlciwgbnVtYmVyXVtdID0gW1tzZWxmUm91dGVbMF0sIHNlbGZSb3V0ZVsxXV1dO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbmZpZy5zb3VyY2VzLmxlbmd0aCAmJiB1bmNsYWltZWQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxldCBvdGhlciA9IGNvbmZpZy5zb3VyY2VzW2ldO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvdGhlciA9PT0gXCJzdHJpbmdcIiB8fCAhdmFsaWRBdChvdGhlciwgcHJldmlvdXNUaW1lKSkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgeyByZW1haW5pbmcsIGNsYWltZWQgfSA9IHN1YnRyYWN0Um91dGUodW5jbGFpbWVkLCBvdGhlci5yb3V0ZSB8fCBGVUxMX1JPVVRFKTtcbiAgICAgICAgICAgIHVuY2xhaW1lZCA9IHJlbWFpbmluZztcbiAgICAgICAgICAgIGlmICghY2xhaW1lZCkgY29udGludWU7XG4gICAgICAgICAgICBpZiAoc2VsZkluZGV4U2V0LmhhcyhpKSkge1xuICAgICAgICAgICAgICAgIGhhbmRvdmVyLnNjYW5Pd25EaXNrID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBleGlzdGluZyA9IGhhbmRvdmVyLnJlbW90ZXMuZ2V0KGkpO1xuICAgICAgICAgICAgaGFuZG92ZXIucmVtb3Rlcy5zZXQoaSwgZXhpc3RpbmcgJiYgW01hdGgubWluKGV4aXN0aW5nWzBdLCBjbGFpbWVkWzBdKSwgTWF0aC5tYXgoZXhpc3RpbmdbMV0sIGNsYWltZWRbMV0pXSBhcyBbbnVtYmVyLCBudW1iZXJdIHx8IGNsYWltZWQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBbLi4uYnlSb3V0ZS52YWx1ZXMoKV0uZmlsdGVyKHggPT4geC5zY2FuT3duRGlzayB8fCB4LnJlbW90ZXMuc2l6ZSk7XG59XG5cbiJdfQ==
135
+ /* _JS_SOURCE_HASH = "13281f47f964117e77880e640758502933893081f631d576b59362f111f165cd"; */
@@ -1,7 +1,6 @@
1
1
  import { RemoteConfig } from "../IArchives";
2
- import { BucketState } from "./storageServerState";
3
- /** Called whenever a bucket's state is (re)built: arms the scans its upcoming window boundaries need. Each scan is scheduled once - the key includes the boundary it is for - so re-arming on every config change is harmless. */
4
- export declare function scheduleBoundaryWork(loaded: BucketState): void;
2
+ /** Called every time a store applies a routing config to itself (see BlobStore's onRoutingApplied): arms the scans the config's upcoming window boundaries need. Each scan is scheduled once - the key includes the boundary it is for - so re-arming on every config application is harmless. */
3
+ export declare function scheduleBoundaryWork(account: string, bucketName: string, routing: RemoteConfig): void;
5
4
  /** An operator's config knows nothing about a switchover that is in flight right now, so writing it as-is would cancel one mid-handover. The in-flight windows are put back into it first. */
6
5
  export declare function reinjectIntermediates(current: RemoteConfig | undefined, incoming: RemoteConfig): RemoteConfig;
7
6
  /** Started by deployTakeover once we are actually a deploy successor listening on an alternate port. Until then there are no switchover windows to write or expire, so nothing polls. */
@@ -1,13 +1,14 @@
1
1
  import { lazy } from "socket-function/src/caching";
2
2
  import { runInfinitePoll } from "socket-function/src/batching";
3
3
  import { RemoteConfig, SourceConfig, HostedConfig } from "../IArchives";
4
- import { ROUTING_FILE, getConfigVersion, serializeRemoteConfig, parseHostedUrl, replaceHostedUrlPort } from "./remoteConfig";
4
+ import { ROUTING_FILE, getConfigVersion, serializeRemoteConfig, parseRoutingData, parseHostedUrl, replaceHostedUrlPort } from "./remoteConfig";
5
5
  import { injectIntermediateSource, expireIntermediateSources, getIntermediateSources, nextIntermediateVersion, INTERMEDIATE_EXPIRE_GRACE } from "./intermediateSources";
6
6
  import { getTakeoverIntermediate } from "./deployTakeover";
7
7
  import { getStorageServerConfig } from "./serverConfig";
8
8
  import { createApiArchives, listServerActiveBucketKeys } from "./createArchives";
9
9
  import { findSelfIndexes, previousWindowOwners } from "./storePlan";
10
- import { BucketState, getBucketStates, getLoadedBucket, writeRoutingConfig } from "./storageServerState";
10
+ import { getActiveBucketKeys, getStore, activateBucket, writeRoutingConfig } from "./storageServerState";
11
+ import { readRoutingFromDisk, readNewestRoutingFile } from "./bucketDisk";
11
12
  import { DEFAULT_FAST_WRITE_DELAY } from "./ArchivesDelayed";
12
13
  import { WINDOW_END_FLUSH_MARGIN } from "./blobStore";
13
14
 
@@ -26,19 +27,20 @@ const INTERMEDIATE_MAINTAIN_INTERVAL = 60 * 1000;
26
27
  const scheduledBoundaryScans = new Set<string>();
27
28
  const boundaryScansRunning = new Set<string>();
28
29
 
29
- /** Called whenever a bucket's state is (re)built: arms the scans its upcoming window boundaries need. Each scan is scheduled once - the key includes the boundary it is for - so re-arming on every config change is harmless. */
30
- export function scheduleBoundaryWork(loaded: BucketState): void {
31
- let key = `${loaded.account}/${loaded.bucketName}`;
30
+ /** Called every time a store applies a routing config to itself (see BlobStore's onRoutingApplied): arms the scans the config's upcoming window boundaries need. Each scan is scheduled once - the key includes the boundary it is for - so re-arming on every config application is harmless. */
31
+ export function scheduleBoundaryWork(account: string, bucketName: string, routing: RemoteConfig): void {
32
+ let key = `${account}/${bucketName}`;
33
+ let selfEntries = findSelfIndexes(routing, account, bucketName).map(i => routing.sources[i] as HostedConfig);
32
34
  let now = Date.now();
33
35
  let starts = new Set<number>();
34
- for (let self of loaded.selfEntries) {
36
+ for (let self of selfEntries) {
35
37
  let start = self.validWindow[0];
36
38
  if (start > now && start < Number.MAX_SAFE_INTEGER) {
37
39
  starts.add(start);
38
40
  }
39
41
  }
40
42
  // A window we have only just taken over, on a server that has only just started: the boundary happened while we were not running, so its scan still has to happen
41
- for (let self of loaded.selfEntries) {
43
+ for (let self of selfEntries) {
42
44
  let [start, end] = self.validWindow;
43
45
  if (!(start <= now && now < end) || start <= 0) continue;
44
46
  if (now - start > BOUNDARY_SCAN_LOOKBACK) continue;
@@ -46,7 +48,7 @@ export function scheduleBoundaryWork(loaded: BucketState): void {
46
48
  if (scheduledBoundaryScans.has(scheduleKey)) continue;
47
49
  scheduledBoundaryScans.add(scheduleKey);
48
50
  let timer = setTimeout(() => {
49
- void runBoundaryScan(loaded, start, STARTUP_BOUNDARY_SCAN_DELAY, "startup+30s").catch((e: Error) => console.error(`Boundary scan for bucket ${key} failed: ${e.stack ?? e}`));
51
+ void runBoundaryScan(account, bucketName, start, STARTUP_BOUNDARY_SCAN_DELAY, "startup+30s").catch((e: Error) => console.error(`Boundary scan for bucket ${key} failed: ${e.stack ?? e}`));
50
52
  }, STARTUP_BOUNDARY_SCAN_DELAY);
51
53
  (timer as { unref?: () => void }).unref?.();
52
54
  }
@@ -64,7 +66,7 @@ export function scheduleBoundaryWork(loaded: BucketState): void {
64
66
  arm();
65
67
  return;
66
68
  }
67
- void runBoundaryScan(loaded, start, offset).catch((e: Error) => console.error(`Boundary scan for bucket ${key} failed: ${e.stack ?? e}`));
69
+ void runBoundaryScan(account, bucketName, start, offset).catch((e: Error) => console.error(`Boundary scan for bucket ${key} failed: ${e.stack ?? e}`));
68
70
  }, Math.min(at - Date.now(), MAX_TIMER_DELAY));
69
71
  (timer as { unref?: () => void }).unref?.();
70
72
  };
@@ -73,9 +75,9 @@ export function scheduleBoundaryWork(loaded: BucketState): void {
73
75
  }
74
76
  }
75
77
 
76
- /** Collects the writes that landed on the previous window's owners just before a boundary, into the store that has just taken over. Who owned what is worked out purely from the config (see previousWindowOwners); this only does the pulling. */
77
- async function runBoundaryScan(loaded: BucketState, windowStart: number, offset: number, offsetLabel?: string): Promise<void> {
78
- let key = `${loaded.account}/${loaded.bucketName}`;
78
+ /** Collects the writes that landed on the previous window's owners just before a boundary, into the store that has just taken over. Who owned what is worked out purely from the config (see previousWindowOwners); this only does the pulling. The config is read off the disk at FIRE time, not captured when the scan was armed - it may have changed in between, and the newest copy is the one the handover actually happened under. */
79
+ async function runBoundaryScan(account: string, bucketName: string, windowStart: number, offset: number, offsetLabel?: string): Promise<void> {
80
+ let key = `${account}/${bucketName}`;
79
81
  let label = `bucket ${key}, window starting ${new Date(windowStart).toISOString()}, offset ${offsetLabel || `${offset / 1000}s`}`;
80
82
  if (boundaryScansRunning.has(key)) {
81
83
  console.log(`Skipping boundary scan (${label}): the previous boundary scan is still running`);
@@ -83,23 +85,22 @@ async function runBoundaryScan(loaded: BucketState, windowStart: number, offset:
83
85
  }
84
86
  boundaryScansRunning.add(key);
85
87
  try {
86
- let effective = loaded.routing;
88
+ let effective = await readRoutingFromDisk(account, bucketName);
87
89
  if (!effective) return;
88
- let handovers = previousWindowOwners(effective, windowStart, findSelfIndexes(effective, loaded.account, loaded.bucketName));
90
+ let handovers = previousWindowOwners(effective, windowStart, findSelfIndexes(effective, account, bucketName));
89
91
  if (!handovers.length) return;
90
92
  console.log(`Boundary scan (${label}): ${handovers.length} route(s) taking over: ${handovers.map(x => `${JSON.stringify(x.route)} from ${x.scanOwnDisk && "our own disk" || ""}${x.scanOwnDisk && x.remotes.size && " + " || ""}${[...x.remotes.keys()].map(i => `source ${i}`).join(", ")}`).join("; ")}`);
91
93
  let since = windowStart - BOUNDARY_SCAN_LOOKBACK;
92
94
  for (let handover of handovers) {
93
- let selfStore = loaded.stores.find(x => x.name === handover.name);
94
- if (!selfStore) continue;
95
+ let selfStore = getStore(account, bucketName, handover.name);
95
96
  if (handover.scanOwnDisk) {
96
- await selfStore.store.rescanBase();
97
+ await selfStore.rescanBase();
97
98
  }
98
99
  for (let [sourceIndex, route] of handover.remotes) {
99
100
  let ownerSource = effective.sources[sourceIndex];
100
101
  if (typeof ownerSource === "string") continue;
101
102
  try {
102
- await selfStore.store.boundaryScanRemote(createApiArchives(ownerSource), { since, route });
103
+ await selfStore.boundaryScanRemote(createApiArchives(ownerSource), { since, route });
103
104
  } catch (e) {
104
105
  console.error(`Boundary scan (${label}) of previous-window owner (source index ${sourceIndex}) failed: ${(e as Error).stack ?? e}`);
105
106
  }
@@ -133,66 +134,69 @@ export function reinjectIntermediates(current: RemoteConfig | undefined, incomin
133
134
  // Per bucket, not global: a switchover has to write every bucket's windows at once, and a shared throttle would let only one bucket through per interval
134
135
  const lastOwnConfigWrite = new Map<string, number>();
135
136
 
136
- async function writeOwnRoutingConfig(loaded: BucketState, updated: RemoteConfig, reason: string): Promise<void> {
137
- let key = `${loaded.account}/${loaded.bucketName}`;
137
+ async function writeOwnRoutingConfig(config: { account: string; bucketName: string; storeName: string; current: RemoteConfig; updated: RemoteConfig; reason: string }): Promise<void> {
138
+ let { account, bucketName, current, updated, reason } = config;
139
+ let key = `${account}/${bucketName}`;
138
140
  let sinceLast = Date.now() - (lastOwnConfigWrite.get(key) || 0);
139
141
  if (sinceLast < OWN_CONFIG_WRITE_THROTTLE) {
140
142
  console.log(`Not writing our own routing config update for bucket ${key} (${reason}): the last one was ${sinceLast}ms ago, under the ${OWN_CONFIG_WRITE_THROTTLE}ms throttle. Retrying on the next maintenance pass.`);
141
143
  return;
142
144
  }
143
145
  lastOwnConfigWrite.set(key, Date.now());
144
- // A switchover writes on top of whatever the bucket is running; with no config at all there is nothing to switch over
145
- if (!loaded.routing) return;
146
- let currentVersion = getConfigVersion(loaded.routing);
146
+ let currentVersion = getConfigVersion(current);
147
147
  let version = nextIntermediateVersion(currentVersion);
148
148
  let next: RemoteConfig = { ...updated, version };
149
149
  console.log(`Writing ${ROUTING_FILE} for bucket ${key} (${reason}), version ${currentVersion} -> ${version}: ${JSON.stringify(next)}`);
150
150
  let data = Buffer.from(serializeRemoteConfig(next));
151
- // Into one of our own stores - it applies it and its peers pull it - and directly to the other servers, which is what makes a switchover take effect in seconds rather than at the next poll
152
- let ourStore = loaded.stores[0];
153
- if (ourStore) {
154
- await writeRoutingConfig(loaded.account, loaded.bucketName, ourStore.name, data);
155
- }
156
- await propagateRoutingConfig(loaded, next, data);
151
+ // Into the store holding the newest copy - it applies it and its peers pull it - and directly to the other servers, which is what makes a switchover take effect in seconds rather than at the next poll
152
+ await writeRoutingConfig(account, bucketName, config.storeName, data);
153
+ await propagateRoutingConfig({ account, bucketName, current, next, data });
157
154
  }
158
155
 
159
- async function propagateRoutingConfig(loaded: BucketState, next: RemoteConfig, data: Buffer): Promise<void> {
156
+ async function propagateRoutingConfig(config: { account: string; bucketName: string; current: RemoteConfig; next: RemoteConfig; data: Buffer }): Promise<void> {
160
157
  let targets = new Map<string, SourceConfig>();
161
- for (let source of [...loaded.routing?.sources || [], ...next.sources]) {
158
+ for (let source of [...config.current.sources, ...config.next.sources]) {
162
159
  if (typeof source === "string" || source.intermediate) continue;
163
160
  if (source.type === "remote") {
164
161
  let parsed = parseHostedUrl(source.url);
165
- if (parsed.account !== loaded.account || parsed.bucketName !== loaded.bucketName) continue;
162
+ if (parsed.account !== config.account || parsed.bucketName !== config.bucketName) continue;
166
163
  }
167
164
  if (targets.has(source.url)) continue;
168
165
  targets.set(source.url, source);
169
166
  }
170
167
  for (let [url, source] of targets) {
171
168
  try {
172
- await createApiArchives(source).set(ROUTING_FILE, data);
173
- console.log(`Wrote ${ROUTING_FILE} for bucket ${loaded.account}/${loaded.bucketName} to ${url}`);
169
+ await createApiArchives(source).set(ROUTING_FILE, config.data);
170
+ console.log(`Wrote ${ROUTING_FILE} for bucket ${config.account}/${config.bucketName} to ${url}`);
174
171
  } catch (e) {
175
172
  console.error(`Propagating our routing config update to ${url} failed: ${(e as Error).stack ?? e}`);
176
173
  }
177
174
  }
178
175
  }
179
176
 
180
- /** Keeps every loaded bucket's switchover windows current: gives our alternate port its window while a takeover is in flight, and takes expired ones back out. */
177
+ /** Keeps every active bucket's switchover windows current: gives our alternate port its window while a takeover is in flight, and takes expired ones back out. */
181
178
  async function maintainIntermediates(): Promise<void> {
182
179
  let { domain, port } = getStorageServerConfig();
183
180
  let takeover = getTakeoverIntermediate();
184
181
  let written: string[] = [];
185
182
  let alreadyCorrect: string[] = [];
186
183
  let notOurs: string[] = [];
187
- // ONLY buckets already in memory. A switchover must never load a bucket: loading starts its synchronization, and buckets nothing has touched (legacy ones especially) have no writes to hand off in the first place. One that does get used mid-switchover loads on that access, and the next pass gives it its window.
188
- let states = getBucketStates();
189
- for (let loaded of states) {
190
- let key = `${loaded.account}/${loaded.bucketName}`;
191
- let routing = loaded.routing;
192
- if (!routing) continue;
184
+ // ONLY buckets already active. A switchover must never activate a bucket: that starts its synchronization, and buckets nothing has touched (legacy ones especially) have no writes to hand off in the first place. One that does get used mid-switchover activates on that access, and the next pass gives it its window.
185
+ let activeKeys = getActiveBucketKeys();
186
+ for (let { account, bucketName } of activeKeys) {
187
+ let key = `${account}/${bucketName}`;
188
+ let newest = await readNewestRoutingFile(account, bucketName);
189
+ if (!newest) continue;
190
+ let routing: RemoteConfig;
191
+ try {
192
+ routing = parseRoutingData(newest.data);
193
+ } catch (e) {
194
+ console.error(`Skipping switchover maintenance for bucket ${key}: its routing config could not be parsed (${(e as Error).message})`);
195
+ continue;
196
+ }
193
197
  let expired = expireIntermediateSources(routing, Date.now());
194
198
  if (JSON.stringify(expired) !== JSON.stringify(routing)) {
195
- await writeOwnRoutingConfig(loaded, expired, `switchover windows expired more than ${INTERMEDIATE_EXPIRE_GRACE / 1000}s ago`);
199
+ await writeOwnRoutingConfig({ account, bucketName, storeName: newest.name, current: routing, updated: expired, reason: `switchover windows expired more than ${INTERMEDIATE_EXPIRE_GRACE / 1000}s ago` });
196
200
  written.push(key);
197
201
  continue;
198
202
  }
@@ -216,16 +220,16 @@ async function maintainIntermediates(): Promise<void> {
216
220
  alreadyCorrect.push(key);
217
221
  continue;
218
222
  }
219
- await writeOwnRoutingConfig(loaded, injected, `we are a deploy successor: writes route to our alternate port ${takeover.altPort} from ${new Date(takeover.start).toISOString()} until our predecessor is killed at ${new Date(takeover.end).toISOString()}`);
223
+ await writeOwnRoutingConfig({ account, bucketName, storeName: newest.name, current: routing, updated: injected, reason: `we are a deploy successor: writes route to our alternate port ${takeover.altPort} from ${new Date(takeover.start).toISOString()} until our predecessor is killed at ${new Date(takeover.end).toISOString()}` });
220
224
  written.push(key);
221
225
  }
222
226
  if (!takeover) return;
223
- if (!states.length) {
227
+ if (!activeKeys.length) {
224
228
  console.log(`No active buckets, so no config files to write the intermediate into (a bucket is only active once something uses it)`);
225
229
  return;
226
230
  }
227
231
  if (!written.length) {
228
- console.log(`Wrote no config files: of ${states.length} active buckets, ${alreadyCorrect.length} already contain the intermediate and ${notOurs.length} are not hosted by us`);
232
+ console.log(`Wrote no config files: of ${activeKeys.length} active buckets, ${alreadyCorrect.length} already contain the intermediate and ${notOurs.length} are not hosted by us`);
229
233
  }
230
234
  }
231
235
 
@@ -247,7 +251,10 @@ async function activatePredecessorBuckets(): Promise<void> {
247
251
  console.log(`Our predecessor on ${url} has ${keys.length} active buckets, activating them here so their config files get the intermediate: ${keys.map(x => `${x.account}/${x.bucketName}`).join(", ")}`);
248
252
  for (let { account, bucketName } of keys) {
249
253
  try {
250
- await getLoadedBucket(account, bucketName);
254
+ let result = await activateBucket(account, bucketName);
255
+ if (typeof result === "string") {
256
+ console.error(`Activating bucket ${account}/${bucketName} (active on our predecessor) failed: ${result}`);
257
+ }
251
258
  } catch (e) {
252
259
  console.error(`Activating bucket ${account}/${bucketName} (active on our predecessor) failed: ${(e as Error).stack ?? e}`);
253
260
  }
@@ -9,11 +9,12 @@ import { getCommonName, getPublicIdentifier, getOwnMachineId, verify, verifyMach
9
9
  import { ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus, FindConfig, SourceConfig, IMMUTABLE_CACHE_TIME } from "../IArchives";
10
10
  import { ROUTING_FILE, getRoute, routeContains } from "./remoteConfig";
11
11
  import {
12
- getLoadedBucket, requireBucket, findBucketStore, getStore, readBucketInternal, writeRoutingConfig,
13
- getBucketConfig, bucketSyncStatus, debugBucketIndexTotals, LoadedStore, ActiveBucketInfo,
14
- debugListAccountBuckets, ServerBucketInfo, debugClearAccountWriteStats,
12
+ findBucketStore, getStore, getBucketStores, readBucketInternal, writeRoutingConfig,
13
+ getBucketArchivesConfig, bucketSyncStatus, debugBucketIndexTotals, ActiveBucketInfo,
14
+ debugListAccountBuckets, ServerBucketInfo,
15
15
  debugGetActiveBucket, activateBucket, getActiveBucketKeys,
16
16
  } from "./storageServerState";
17
+ import { debugClearAccountWriteStats } from "./accessStats";
17
18
  import { getStorageServerConfig, getTrust, getRequests, assertWritesAllowed } from "./serverConfig";
18
19
  import { BlobStore } from "./blobStore";
19
20
  import { getRoutingFileResult } from "./bucketDisk";
@@ -332,7 +333,7 @@ class RemoteStorageControllerBase {
332
333
  }
333
334
  @assertValidArgs
334
335
  async getArchivesConfig(config: { account: string; bucketName: string }): Promise<ArchivesConfig> {
335
- return getBucketConfig(await requireBucket(config.account, config.bucketName));
336
+ return await getBucketArchivesConfig(config.account, config.bucketName);
336
337
  }
337
338
  @assertValidArgs
338
339
  async listBuckets(config: { account: string }): Promise<ServerBucketInfo[]> {
@@ -372,11 +373,11 @@ class RemoteStorageControllerBase {
372
373
  }
373
374
  @assertValidArgs
374
375
  async getIndexInfo(config: { account: string; bucketName: string }): Promise<{ fileCount: number; byteCount: number; sources: { debugName: string; fileCount: number; byteCount: number }[] } | undefined> {
375
- return await debugBucketIndexTotals(await requireBucket(config.account, config.bucketName));
376
+ return await debugBucketIndexTotals(config.account, config.bucketName);
376
377
  }
377
378
  @assertValidArgs
378
379
  async getSyncStatus(config: { account: string; bucketName: string }): Promise<ArchivesSyncStatus> {
379
- return await bucketSyncStatus(await requireBucket(config.account, config.bucketName));
380
+ return await bucketSyncStatus(config.account, config.bucketName);
380
381
  }
381
382
 
382
383
  @assertValidArgs
@@ -435,20 +436,26 @@ class RemoteStorageControllerBase {
435
436
  assertValidName(account, "account");
436
437
  assertValidName(bucketName, "bucket name");
437
438
  assertValidPath(filePath);
438
- let bucket = await getLoadedBucket(account, bucketName);
439
- if (!bucket) {
439
+ let bucketStores = await getBucketStores(account, bucketName);
440
+ if (!bucketStores.length) {
440
441
  return setHTTPResultHeaders(Buffer.from(""), { status: "404" });
441
442
  }
442
- if (!bucket.self?.public) {
443
+ // Each store's policy comes from its own config, which it has only read once init ran
444
+ await Promise.all(bucketStores.map(x => x.store.init()));
445
+ let policies = bucketStores.map(x => ({ store: x.store, policy: x.store.storeConfig.current() }));
446
+ if (!policies.some(x => x.policy.public)) {
443
447
  throw new Error(`Bucket ${account}/${bucketName} is not public, so its files cannot be read over plain URLs`);
444
448
  }
445
449
  // Anonymous URL reads carry no source selection - the file's route picks the store, and a route no store here covers is simply not found (the routing file itself lives outside every store)
446
- let httpStore: LoadedStore | undefined;
450
+ let httpStore: BlobStore | undefined;
451
+ let immutable = false;
447
452
  let info: { writeTime: number; size: number } | undefined;
448
453
  if (filePath !== ROUTING_FILE) {
449
454
  let route = getRoute(filePath);
450
- httpStore = bucket.stores.find(s => s.entries.some(e => routeContains(e.route, route)));
451
- info = httpStore && await httpStore.store.getInfo({ path: filePath }) || undefined;
455
+ let serving = policies.find(x => x.policy.public && routeContains(x.policy.route, route));
456
+ httpStore = serving?.store;
457
+ immutable = !!serving?.policy.immutable;
458
+ info = httpStore && await httpStore.getInfo({ path: filePath }) || undefined;
452
459
  } else {
453
460
  info = await getRoutingFileResult(account, bucketName);
454
461
  }
@@ -462,7 +469,8 @@ class RemoteStorageControllerBase {
462
469
  "Last-Modified": new Date(info.writeTime).toUTCString(),
463
470
  "Accept-Ranges": "bytes",
464
471
  };
465
- if (bucket.self?.immutable) {
472
+ // The serving store's own policy - and never for the routing file, which changing is the whole point of
473
+ if (immutable) {
466
474
  headers["Cache-Control"] = `max-age=${IMMUTABLE_CACHE_TIME / 1000}`;
467
475
  }
468
476
  let ifModifiedSince = request?.headers["if-modified-since"];
@@ -495,7 +503,7 @@ class RemoteStorageControllerBase {
495
503
  }
496
504
  let result: { data: Buffer; writeTime: number; size: number } | undefined;
497
505
  if (httpStore) {
498
- result = await httpStore.store.get2({ path: filePath, range });
506
+ result = await httpStore.get2({ path: filePath, range });
499
507
  } else {
500
508
  result = await getRoutingFileResult(account, bucketName);
501
509
  if (result && range) {