UNPKG

urbi-exhibitions

Version:
2,404 lines 83.5 kB
import { g as getRouteKey } from "./getRouteKey-BSdUqT6h.js";
import { t as toChunks } from "./toChunks-DRfoi4L8.js";
import { g as getDefaultExportFromCjs } from "./_commonjsHelpers-DaMA6jEr.js";
var parser = {}, hasRequiredParser;
function requireParser() {
  return hasRequiredParser || (hasRequiredParser = 1, parser.load = function(t, c, n = {}) {
    var a, e, i;
    for (a in c)
      i = c[a], n[a] = (e = t[a]) != null ? e : i;
    return n;
  }, parser.overwrite = function(t, c, n = {}) {
    var a, e;
    for (a in t)
      e = t[a], c[a] !== void 0 && (n[a] = e);
    return n;
  }), parser;
}
var DLList_1, hasRequiredDLList;
function requireDLList() {
  if (hasRequiredDLList) return DLList_1;
  hasRequiredDLList = 1;
  var t;
  return t = class {
    constructor(n, a) {
      this.incr = n, this.decr = a, this._first = null, this._last = null, this.length = 0;
    }
    push(n) {
      var a;
      this.length++, typeof this.incr == "function" && this.incr(), a = {
        value: n,
        prev: this._last,
        next: null
      }, this._last != null ? (this._last.next = a, this._last = a) : this._first = this._last = a;
    }
    shift() {
      var n;
      if (this._first != null)
        return this.length--, typeof this.decr == "function" && this.decr(), n = this._first.value, (this._first = this._first.next) != null ? this._first.prev = null : this._last = null, n;
    }
    first() {
      if (this._first != null)
        return this._first.value;
    }
    getArray() {
      var n, a, e;
      for (n = this._first, e = []; n != null; )
        e.push((a = n, n = n.next, a.value));
      return e;
    }
    forEachShift(n) {
      var a;
      for (a = this.shift(); a != null; )
        n(a), a = this.shift();
    }
    debug() {
      var n, a, e, i, r;
      for (n = this._first, r = []; n != null; )
        r.push((a = n, n = n.next, {
          value: a.value,
          prev: (e = a.prev) != null ? e.value : void 0,
          next: (i = a.next) != null ? i.value : void 0
        }));
      return r;
    }
  }, DLList_1 = t, DLList_1;
}
var Events_1, hasRequiredEvents;
function requireEvents() {
  if (hasRequiredEvents) return Events_1;
  hasRequiredEvents = 1;
  function t(a, e, i, r, u, l, v) {
    try {
      var m = a[l](v), p = m.value;
    } catch (s) {
      i(s);
      return;
    }
    m.done ? e(p) : Promise.resolve(p).then(r, u);
  }
  function c(a) {
    return function() {
      var e = this, i = arguments;
      return new Promise(function(r, u) {
        var l = a.apply(e, i);
        function v(p) {
          t(l, r, u, v, m, "next", p);
        }
        function m(p) {
          t(l, r, u, v, m, "throw", p);
        }
        v(void 0);
      });
    };
  }
  var n;
  return n = class {
    constructor(e) {
      if (this.instance = e, this._events = {}, this.instance.on != null || this.instance.once != null || this.instance.removeAllListeners != null)
        throw new Error("An Emitter already exists for this object");
      this.instance.on = (i, r) => this._addListener(i, "many", r), this.instance.once = (i, r) => this._addListener(i, "once", r), this.instance.removeAllListeners = (i = null) => i != null ? delete this._events[i] : this._events = {};
    }
    _addListener(e, i, r) {
      var u;
      return (u = this._events)[e] == null && (u[e] = []), this._events[e].push({
        cb: r,
        status: i
      }), this.instance;
    }
    listenerCount(e) {
      return this._events[e] != null ? this._events[e].length : 0;
    }
    trigger(e, ...i) {
      var r = this;
      return c(function* () {
        var u, l;
        try {
          return e !== "debug" && r.trigger("debug", `Event triggered: ${e}`, i), r._events[e] == null ? void 0 : (r._events[e] = r._events[e].filter(function(v) {
            return v.status !== "none";
          }), l = r._events[e].map(
            /* @__PURE__ */ function() {
              var v = c(function* (m) {
                var p, s;
                if (m.status !== "none") {
                  m.status === "once" && (m.status = "none");
                  try {
                    return s = typeof m.cb == "function" ? m.cb(...i) : void 0, typeof (s != null ? s.then : void 0) == "function" ? yield s : s;
                  } catch (d) {
                    return p = d, r.trigger("error", p), null;
                  }
                }
              });
              return function(m) {
                return v.apply(this, arguments);
              };
            }()
          ), (yield Promise.all(l)).find(function(v) {
            return v != null;
          }));
        } catch (v) {
          return u = v, r.trigger("error", u), null;
        }
      })();
    }
  }, Events_1 = n, Events_1;
}
var Queues_1, hasRequiredQueues;
function requireQueues() {
  if (hasRequiredQueues) return Queues_1;
  hasRequiredQueues = 1;
  var t, c, n;
  return t = requireDLList(), c = requireEvents(), n = class {
    constructor(e) {
      this.Events = new c(this), this._length = 0, this._lists = (function() {
        var i, r, u;
        for (u = [], i = 1, r = e; 1 <= r ? i <= r : i >= r; 1 <= r ? ++i : --i)
          u.push(new t(() => this.incr(), () => this.decr()));
        return u;
      }).call(this);
    }
    incr() {
      if (this._length++ === 0)
        return this.Events.trigger("leftzero");
    }
    decr() {
      if (--this._length === 0)
        return this.Events.trigger("zero");
    }
    push(e) {
      return this._lists[e.options.priority].push(e);
    }
    queued(e) {
      return e != null ? this._lists[e].length : this._length;
    }
    shiftAll(e) {
      return this._lists.forEach(function(i) {
        return i.forEachShift(e);
      });
    }
    getFirst(e = this._lists) {
      var i, r, u;
      for (i = 0, r = e.length; i < r; i++)
        if (u = e[i], u.length > 0)
          return u;
      return [];
    }
    shiftLastFrom(e) {
      return this.getFirst(this._lists.slice(e).reverse()).shift();
    }
  }, Queues_1 = n, Queues_1;
}
var BottleneckError_1, hasRequiredBottleneckError;
function requireBottleneckError() {
  if (hasRequiredBottleneckError) return BottleneckError_1;
  hasRequiredBottleneckError = 1;
  var t;
  return t = class extends Error {
  }, BottleneckError_1 = t, BottleneckError_1;
}
var Job_1, hasRequiredJob;
function requireJob() {
  if (hasRequiredJob) return Job_1;
  hasRequiredJob = 1;
  function t(u, l, v, m, p, s, d) {
    try {
      var o = u[s](d), _ = o.value;
    } catch (b) {
      v(b);
      return;
    }
    o.done ? l(_) : Promise.resolve(_).then(m, p);
  }
  function c(u) {
    return function() {
      var l = this, v = arguments;
      return new Promise(function(m, p) {
        var s = u.apply(l, v);
        function d(_) {
          t(s, m, p, d, o, "next", _);
        }
        function o(_) {
          t(s, m, p, d, o, "throw", _);
        }
        d(void 0);
      });
    };
  }
  var n, a, e, i, r;
  return i = 10, a = 5, r = requireParser(), n = requireBottleneckError(), e = class {
    constructor(l, v, m, p, s, d, o, _) {
      this.task = l, this.args = v, this.rejectOnDrop = s, this.Events = d, this._states = o, this.Promise = _, this.options = r.load(m, p), this.options.priority = this._sanitizePriority(this.options.priority), this.options.id === p.id && (this.options.id = `${this.options.id}-${this._randomIndex()}`), this.promise = new this.Promise((b, R) => {
        this._resolve = b, this._reject = R;
      }), this.retryCount = 0;
    }
    _sanitizePriority(l) {
      var v;
      return v = ~~l !== l ? a : l, v < 0 ? 0 : v > i - 1 ? i - 1 : v;
    }
    _randomIndex() {
      return Math.random().toString(36).slice(2);
    }
    doDrop({
      error: l,
      message: v = "This job has been dropped by Bottleneck"
    } = {}) {
      return this._states.remove(this.options.id) ? (this.rejectOnDrop && this._reject(l ?? new n(v)), this.Events.trigger("dropped", {
        args: this.args,
        options: this.options,
        task: this.task,
        promise: this.promise
      }), !0) : !1;
    }
    _assertStatus(l) {
      var v;
      if (v = this._states.jobStatus(this.options.id), !(v === l || l === "DONE" && v === null))
        throw new n(`Invalid job status ${v}, expected ${l}. Please open an issue at https://github.com/SGrondin/bottleneck/issues`);
    }
    doReceive() {
      return this._states.start(this.options.id), this.Events.trigger("received", {
        args: this.args,
        options: this.options
      });
    }
    doQueue(l, v) {
      return this._assertStatus("RECEIVED"), this._states.next(this.options.id), this.Events.trigger("queued", {
        args: this.args,
        options: this.options,
        reachedHWM: l,
        blocked: v
      });
    }
    doRun() {
      return this.retryCount === 0 ? (this._assertStatus("QUEUED"), this._states.next(this.options.id)) : this._assertStatus("EXECUTING"), this.Events.trigger("scheduled", {
        args: this.args,
        options: this.options
      });
    }
    doExecute(l, v, m, p) {
      var s = this;
      return c(function* () {
        var d, o, _;
        s.retryCount === 0 ? (s._assertStatus("RUNNING"), s._states.next(s.options.id)) : s._assertStatus("EXECUTING"), o = {
          args: s.args,
          options: s.options,
          retryCount: s.retryCount
        }, s.Events.trigger("executing", o);
        try {
          if (_ = yield l != null ? l.schedule(s.options, s.task, ...s.args) : s.task(...s.args), v())
            return s.doDone(o), yield p(s.options, o), s._assertStatus("DONE"), s._resolve(_);
        } catch (b) {
          return d = b, s._onFailure(d, o, v, m, p);
        }
      })();
    }
    doExpire(l, v, m) {
      var p, s;
      return this._states.jobStatus(this.options.id === "RUNNING") && this._states.next(this.options.id), this._assertStatus("EXECUTING"), s = {
        args: this.args,
        options: this.options,
        retryCount: this.retryCount
      }, p = new n(`This job timed out after ${this.options.expiration} ms.`), this._onFailure(p, s, l, v, m);
    }
    _onFailure(l, v, m, p, s) {
      var d = this;
      return c(function* () {
        var o, _;
        if (m())
          return o = yield d.Events.trigger("failed", l, v), o != null ? (_ = ~~o, d.Events.trigger("retry", `Retrying ${d.options.id} after ${_} ms`, v), d.retryCount++, p(_)) : (d.doDone(v), yield s(d.options, v), d._assertStatus("DONE"), d._reject(l));
      })();
    }
    doDone(l) {
      return this._assertStatus("EXECUTING"), this._states.next(this.options.id), this.Events.trigger("done", l);
    }
  }, Job_1 = e, Job_1;
}
var LocalDatastore_1, hasRequiredLocalDatastore;
function requireLocalDatastore() {
  if (hasRequiredLocalDatastore) return LocalDatastore_1;
  hasRequiredLocalDatastore = 1;
  function t(i, r, u, l, v, m, p) {
    try {
      var s = i[m](p), d = s.value;
    } catch (o) {
      u(o);
      return;
    }
    s.done ? r(d) : Promise.resolve(d).then(l, v);
  }
  function c(i) {
    return function() {
      var r = this, u = arguments;
      return new Promise(function(l, v) {
        var m = i.apply(r, u);
        function p(d) {
          t(m, l, v, p, s, "next", d);
        }
        function s(d) {
          t(m, l, v, p, s, "throw", d);
        }
        p(void 0);
      });
    };
  }
  var n, a, e;
  return e = requireParser(), n = requireBottleneckError(), a = class {
    constructor(r, u, l) {
      this.instance = r, this.storeOptions = u, this.clientId = this.instance._randomIndex(), e.load(l, l, this), this._nextRequest = this._lastReservoirRefresh = this._lastReservoirIncrease = Date.now(), this._running = 0, this._done = 0, this._unblockTime = 0, this.ready = this.Promise.resolve(), this.clients = {}, this._startHeartbeat();
    }
    _startHeartbeat() {
      var r;
      return this.heartbeat == null && (this.storeOptions.reservoirRefreshInterval != null && this.storeOptions.reservoirRefreshAmount != null || this.storeOptions.reservoirIncreaseInterval != null && this.storeOptions.reservoirIncreaseAmount != null) ? typeof (r = this.heartbeat = setInterval(() => {
        var u, l, v, m, p;
        if (m = Date.now(), this.storeOptions.reservoirRefreshInterval != null && m >= this._lastReservoirRefresh + this.storeOptions.reservoirRefreshInterval && (this._lastReservoirRefresh = m, this.storeOptions.reservoir = this.storeOptions.reservoirRefreshAmount, this.instance._drainAll(this.computeCapacity())), this.storeOptions.reservoirIncreaseInterval != null && m >= this._lastReservoirIncrease + this.storeOptions.reservoirIncreaseInterval) {
          var s = this.storeOptions;
          if (u = s.reservoirIncreaseAmount, v = s.reservoirIncreaseMaximum, p = s.reservoir, this._lastReservoirIncrease = m, l = v != null ? Math.min(u, v - p) : u, l > 0)
            return this.storeOptions.reservoir += l, this.instance._drainAll(this.computeCapacity());
        }
      }, this.heartbeatInterval)).unref == "function" ? r.unref() : void 0 : clearInterval(this.heartbeat);
    }
    __publish__(r) {
      var u = this;
      return c(function* () {
        return yield u.yieldLoop(), u.instance.Events.trigger("message", r.toString());
      })();
    }
    __disconnect__(r) {
      var u = this;
      return c(function* () {
        return yield u.yieldLoop(), clearInterval(u.heartbeat), u.Promise.resolve();
      })();
    }
    yieldLoop(r = 0) {
      return new this.Promise(function(u, l) {
        return setTimeout(u, r);
      });
    }
    computePenalty() {
      var r;
      return (r = this.storeOptions.penalty) != null ? r : 15 * this.storeOptions.minTime || 5e3;
    }
    __updateSettings__(r) {
      var u = this;
      return c(function* () {
        return yield u.yieldLoop(), e.overwrite(r, r, u.storeOptions), u._startHeartbeat(), u.instance._drainAll(u.computeCapacity()), !0;
      })();
    }
    __running__() {
      var r = this;
      return c(function* () {
        return yield r.yieldLoop(), r._running;
      })();
    }
    __queued__() {
      var r = this;
      return c(function* () {
        return yield r.yieldLoop(), r.instance.queued();
      })();
    }
    __done__() {
      var r = this;
      return c(function* () {
        return yield r.yieldLoop(), r._done;
      })();
    }
    __groupCheck__(r) {
      var u = this;
      return c(function* () {
        return yield u.yieldLoop(), u._nextRequest + u.timeout < r;
      })();
    }
    computeCapacity() {
      var r, u, l = this.storeOptions;
      return r = l.maxConcurrent, u = l.reservoir, r != null && u != null ? Math.min(r - this._running, u) : r != null ? r - this._running : u ?? null;
    }
    conditionsCheck(r) {
      var u;
      return u = this.computeCapacity(), u == null || r <= u;
    }
    __incrementReservoir__(r) {
      var u = this;
      return c(function* () {
        var l;
        return yield u.yieldLoop(), l = u.storeOptions.reservoir += r, u.instance._drainAll(u.computeCapacity()), l;
      })();
    }
    __currentReservoir__() {
      var r = this;
      return c(function* () {
        return yield r.yieldLoop(), r.storeOptions.reservoir;
      })();
    }
    isBlocked(r) {
      return this._unblockTime >= r;
    }
    check(r, u) {
      return this.conditionsCheck(r) && this._nextRequest - u <= 0;
    }
    __check__(r) {
      var u = this;
      return c(function* () {
        var l;
        return yield u.yieldLoop(), l = Date.now(), u.check(r, l);
      })();
    }
    __register__(r, u, l) {
      var v = this;
      return c(function* () {
        var m, p;
        return yield v.yieldLoop(), m = Date.now(), v.conditionsCheck(u) ? (v._running += u, v.storeOptions.reservoir != null && (v.storeOptions.reservoir -= u), p = Math.max(v._nextRequest - m, 0), v._nextRequest = m + p + v.storeOptions.minTime, {
          success: !0,
          wait: p,
          reservoir: v.storeOptions.reservoir
        }) : {
          success: !1
        };
      })();
    }
    strategyIsBlock() {
      return this.storeOptions.strategy === 3;
    }
    __submit__(r, u) {
      var l = this;
      return c(function* () {
        var v, m, p;
        if (yield l.yieldLoop(), l.storeOptions.maxConcurrent != null && u > l.storeOptions.maxConcurrent)
          throw new n(`Impossible to add a job having a weight of ${u} to a limiter having a maxConcurrent setting of ${l.storeOptions.maxConcurrent}`);
        return m = Date.now(), p = l.storeOptions.highWater != null && r === l.storeOptions.highWater && !l.check(u, m), v = l.strategyIsBlock() && (p || l.isBlocked(m)), v && (l._unblockTime = m + l.computePenalty(), l._nextRequest = l._unblockTime + l.storeOptions.minTime, l.instance._dropAllQueued()), {
          reachedHWM: p,
          blocked: v,
          strategy: l.storeOptions.strategy
        };
      })();
    }
    __free__(r, u) {
      var l = this;
      return c(function* () {
        return yield l.yieldLoop(), l._running -= u, l._done += u, l.instance._drainAll(l.computeCapacity()), {
          running: l._running
        };
      })();
    }
  }, LocalDatastore_1 = a, LocalDatastore_1;
}
var Scripts = {};
const require$$0 = {
  "blacklist_client.lua": `local blacklist = ARGV[num_static_argv + 1]

if redis.call('zscore', client_last_seen_key, blacklist) then
  redis.call('zadd', client_last_seen_key, 0, blacklist)
end


return {}
`,
  "check.lua": `local weight = tonumber(ARGV[num_static_argv + 1])

local capacity = process_tick(now, false)['capacity']
local nextRequest = tonumber(redis.call('hget', settings_key, 'nextRequest'))

return conditions_check(capacity, weight) and nextRequest - now <= 0
`,
  "conditions_check.lua": `local conditions_check = function (capacity, weight)
  return capacity == nil or weight <= capacity
end
`,
  "current_reservoir.lua": `return process_tick(now, false)['reservoir']
`,
  "done.lua": `process_tick(now, false)

return tonumber(redis.call('hget', settings_key, 'done'))
`,
  "free.lua": `local index = ARGV[num_static_argv + 1]

redis.call('zadd', job_expirations_key, 0, index)

return process_tick(now, false)['running']
`,
  "get_time.lua": `redis.replicate_commands()

local get_time = function ()
  local time = redis.call('time')

  return tonumber(time[1]..string.sub(time[2], 1, 3))
end
`,
  "group_check.lua": `return not (redis.call('exists', settings_key) == 1)
`,
  "heartbeat.lua": `process_tick(now, true)
`,
  "increment_reservoir.lua": `local incr = tonumber(ARGV[num_static_argv + 1])

redis.call('hincrby', settings_key, 'reservoir', incr)

local reservoir = process_tick(now, true)['reservoir']

local groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout'))
refresh_expiration(0, 0, groupTimeout)

return reservoir
`,
  "init.lua": `local clear = tonumber(ARGV[num_static_argv + 1])
local limiter_version = ARGV[num_static_argv + 2]
local num_local_argv = num_static_argv + 2

if clear == 1 then
  redis.call('del', unpack(KEYS))
end

if redis.call('exists', settings_key) == 0 then
  -- Create
  local args = {'hmset', settings_key}

  for i = num_local_argv + 1, #ARGV do
    table.insert(args, ARGV[i])
  end

  redis.call(unpack(args))
  redis.call('hmset', settings_key,
    'nextRequest', now,
    'lastReservoirRefresh', now,
    'lastReservoirIncrease', now,
    'running', 0,
    'done', 0,
    'unblockTime', 0,
    'capacityPriorityCounter', 0
  )

else
  -- Apply migrations
  local settings = redis.call('hmget', settings_key,
    'id',
    'version'
  )
  local id = settings[1]
  local current_version = settings[2]

  if current_version ~= limiter_version then
    local version_digits = {}
    for k, v in string.gmatch(current_version, "([^.]+)") do
      table.insert(version_digits, tonumber(k))
    end

    -- 2.10.0
    if version_digits[2] < 10 then
      redis.call('hsetnx', settings_key, 'reservoirRefreshInterval', '')
      redis.call('hsetnx', settings_key, 'reservoirRefreshAmount', '')
      redis.call('hsetnx', settings_key, 'lastReservoirRefresh', '')
      redis.call('hsetnx', settings_key, 'done', 0)
      redis.call('hset', settings_key, 'version', '2.10.0')
    end

    -- 2.11.1
    if version_digits[2] < 11 or (version_digits[2] == 11 and version_digits[3] < 1) then
      if redis.call('hstrlen', settings_key, 'lastReservoirRefresh') == 0 then
        redis.call('hmset', settings_key,
          'lastReservoirRefresh', now,
          'version', '2.11.1'
        )
      end
    end

    -- 2.14.0
    if version_digits[2] < 14 then
      local old_running_key = 'b_'..id..'_running'
      local old_executing_key = 'b_'..id..'_executing'

      if redis.call('exists', old_running_key) == 1 then
        redis.call('rename', old_running_key, job_weights_key)
      end
      if redis.call('exists', old_executing_key) == 1 then
        redis.call('rename', old_executing_key, job_expirations_key)
      end
      redis.call('hset', settings_key, 'version', '2.14.0')
    end

    -- 2.15.2
    if version_digits[2] < 15 or (version_digits[2] == 15 and version_digits[3] < 2) then
      redis.call('hsetnx', settings_key, 'capacityPriorityCounter', 0)
      redis.call('hset', settings_key, 'version', '2.15.2')
    end

    -- 2.17.0
    if version_digits[2] < 17 then
      redis.call('hsetnx', settings_key, 'clientTimeout', 10000)
      redis.call('hset', settings_key, 'version', '2.17.0')
    end

    -- 2.18.0
    if version_digits[2] < 18 then
      redis.call('hsetnx', settings_key, 'reservoirIncreaseInterval', '')
      redis.call('hsetnx', settings_key, 'reservoirIncreaseAmount', '')
      redis.call('hsetnx', settings_key, 'reservoirIncreaseMaximum', '')
      redis.call('hsetnx', settings_key, 'lastReservoirIncrease', now)
      redis.call('hset', settings_key, 'version', '2.18.0')
    end

  end

  process_tick(now, false)
end

local groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout'))
refresh_expiration(0, 0, groupTimeout)

return {}
`,
  "process_tick.lua": `local process_tick = function (now, always_publish)

  local compute_capacity = function (maxConcurrent, running, reservoir)
    if maxConcurrent ~= nil and reservoir ~= nil then
      return math.min((maxConcurrent - running), reservoir)
    elseif maxConcurrent ~= nil then
      return maxConcurrent - running
    elseif reservoir ~= nil then
      return reservoir
    else
      return nil
    end
  end

  local settings = redis.call('hmget', settings_key,
    'id',
    'maxConcurrent',
    'running',
    'reservoir',
    'reservoirRefreshInterval',
    'reservoirRefreshAmount',
    'lastReservoirRefresh',
    'reservoirIncreaseInterval',
    'reservoirIncreaseAmount',
    'reservoirIncreaseMaximum',
    'lastReservoirIncrease',
    'capacityPriorityCounter',
    'clientTimeout'
  )
  local id = settings[1]
  local maxConcurrent = tonumber(settings[2])
  local running = tonumber(settings[3])
  local reservoir = tonumber(settings[4])
  local reservoirRefreshInterval = tonumber(settings[5])
  local reservoirRefreshAmount = tonumber(settings[6])
  local lastReservoirRefresh = tonumber(settings[7])
  local reservoirIncreaseInterval = tonumber(settings[8])
  local reservoirIncreaseAmount = tonumber(settings[9])
  local reservoirIncreaseMaximum = tonumber(settings[10])
  local lastReservoirIncrease = tonumber(settings[11])
  local capacityPriorityCounter = tonumber(settings[12])
  local clientTimeout = tonumber(settings[13])

  local initial_capacity = compute_capacity(maxConcurrent, running, reservoir)

  --
  -- Process 'running' changes
  --
  local expired = redis.call('zrangebyscore', job_expirations_key, '-inf', '('..now)

  if #expired > 0 then
    redis.call('zremrangebyscore', job_expirations_key, '-inf', '('..now)

    local flush_batch = function (batch, acc)
      local weights = redis.call('hmget', job_weights_key, unpack(batch))
                      redis.call('hdel',  job_weights_key, unpack(batch))
      local clients = redis.call('hmget', job_clients_key, unpack(batch))
                      redis.call('hdel',  job_clients_key, unpack(batch))

      -- Calculate sum of removed weights
      for i = 1, #weights do
        acc['total'] = acc['total'] + (tonumber(weights[i]) or 0)
      end

      -- Calculate sum of removed weights by client
      local client_weights = {}
      for i = 1, #clients do
        local removed = tonumber(weights[i]) or 0
        if removed > 0 then
          acc['client_weights'][clients[i]] = (acc['client_weights'][clients[i]] or 0) + removed
        end
      end
    end

    local acc = {
      ['total'] = 0,
      ['client_weights'] = {}
    }
    local batch_size = 1000

    -- Compute changes to Zsets and apply changes to Hashes
    for i = 1, #expired, batch_size do
      local batch = {}
      for j = i, math.min(i + batch_size - 1, #expired) do
        table.insert(batch, expired[j])
      end

      flush_batch(batch, acc)
    end

    -- Apply changes to Zsets
    if acc['total'] > 0 then
      redis.call('hincrby', settings_key, 'done', acc['total'])
      running = tonumber(redis.call('hincrby', settings_key, 'running', -acc['total']))
    end

    for client, weight in pairs(acc['client_weights']) do
      redis.call('zincrby', client_running_key, -weight, client)
    end
  end

  --
  -- Process 'reservoir' changes
  --
  local reservoirRefreshActive = reservoirRefreshInterval ~= nil and reservoirRefreshAmount ~= nil
  if reservoirRefreshActive and now >= lastReservoirRefresh + reservoirRefreshInterval then
    reservoir = reservoirRefreshAmount
    redis.call('hmset', settings_key,
      'reservoir', reservoir,
      'lastReservoirRefresh', now
    )
  end

  local reservoirIncreaseActive = reservoirIncreaseInterval ~= nil and reservoirIncreaseAmount ~= nil
  if reservoirIncreaseActive and now >= lastReservoirIncrease + reservoirIncreaseInterval then
    local num_intervals = math.floor((now - lastReservoirIncrease) / reservoirIncreaseInterval)
    local incr = reservoirIncreaseAmount * num_intervals
    if reservoirIncreaseMaximum ~= nil then
      incr = math.min(incr, reservoirIncreaseMaximum - (reservoir or 0))
    end
    if incr > 0 then
      reservoir = (reservoir or 0) + incr
    end
    redis.call('hmset', settings_key,
      'reservoir', reservoir,
      'lastReservoirIncrease', lastReservoirIncrease + (num_intervals * reservoirIncreaseInterval)
    )
  end

  --
  -- Clear unresponsive clients
  --
  local unresponsive = redis.call('zrangebyscore', client_last_seen_key, '-inf', (now - clientTimeout))
  local unresponsive_lookup = {}
  local terminated_clients = {}
  for i = 1, #unresponsive do
    unresponsive_lookup[unresponsive[i]] = true
    if tonumber(redis.call('zscore', client_running_key, unresponsive[i])) == 0 then
      table.insert(terminated_clients, unresponsive[i])
    end
  end
  if #terminated_clients > 0 then
    redis.call('zrem', client_running_key,         unpack(terminated_clients))
    redis.call('hdel', client_num_queued_key,      unpack(terminated_clients))
    redis.call('zrem', client_last_registered_key, unpack(terminated_clients))
    redis.call('zrem', client_last_seen_key,       unpack(terminated_clients))
  end

  --
  -- Broadcast capacity changes
  --
  local final_capacity = compute_capacity(maxConcurrent, running, reservoir)

  if always_publish or (initial_capacity ~= nil and final_capacity == nil) then
    -- always_publish or was not unlimited, now unlimited
    redis.call('publish', 'b_'..id, 'capacity:'..(final_capacity or ''))

  elseif initial_capacity ~= nil and final_capacity ~= nil and final_capacity > initial_capacity then
    -- capacity was increased
    -- send the capacity message to the limiter having the lowest number of running jobs
    -- the tiebreaker is the limiter having not registered a job in the longest time

    local lowest_concurrency_value = nil
    local lowest_concurrency_clients = {}
    local lowest_concurrency_last_registered = {}
    local client_concurrencies = redis.call('zrange', client_running_key, 0, -1, 'withscores')

    for i = 1, #client_concurrencies, 2 do
      local client = client_concurrencies[i]
      local concurrency = tonumber(client_concurrencies[i+1])

      if (
        lowest_concurrency_value == nil or lowest_concurrency_value == concurrency
      ) and (
        not unresponsive_lookup[client]
      ) and (
        tonumber(redis.call('hget', client_num_queued_key, client)) > 0
      ) then
        lowest_concurrency_value = concurrency
        table.insert(lowest_concurrency_clients, client)
        local last_registered = tonumber(redis.call('zscore', client_last_registered_key, client))
        table.insert(lowest_concurrency_last_registered, last_registered)
      end
    end

    if #lowest_concurrency_clients > 0 then
      local position = 1
      local earliest = lowest_concurrency_last_registered[1]

      for i,v in ipairs(lowest_concurrency_last_registered) do
        if v < earliest then
          position = i
          earliest = v
        end
      end

      local next_client = lowest_concurrency_clients[position]
      redis.call('publish', 'b_'..id,
        'capacity-priority:'..(final_capacity or '')..
        ':'..next_client..
        ':'..capacityPriorityCounter
      )
      redis.call('hincrby', settings_key, 'capacityPriorityCounter', '1')
    else
      redis.call('publish', 'b_'..id, 'capacity:'..(final_capacity or ''))
    end
  end

  return {
    ['capacity'] = final_capacity,
    ['running'] = running,
    ['reservoir'] = reservoir
  }
end
`,
  "queued.lua": `local clientTimeout = tonumber(redis.call('hget', settings_key, 'clientTimeout'))
local valid_clients = redis.call('zrangebyscore', client_last_seen_key, (now - clientTimeout), 'inf')
local client_queued = redis.call('hmget', client_num_queued_key, unpack(valid_clients))

local sum = 0
for i = 1, #client_queued do
  sum = sum + tonumber(client_queued[i])
end

return sum
`,
  "refresh_expiration.lua": `local refresh_expiration = function (now, nextRequest, groupTimeout)

  if groupTimeout ~= nil then
    local ttl = (nextRequest + groupTimeout) - now

    for i = 1, #KEYS do
      redis.call('pexpire', KEYS[i], ttl)
    end
  end

end
`,
  "refs.lua": `local settings_key = KEYS[1]
local job_weights_key = KEYS[2]
local job_expirations_key = KEYS[3]
local job_clients_key = KEYS[4]
local client_running_key = KEYS[5]
local client_num_queued_key = KEYS[6]
local client_last_registered_key = KEYS[7]
local client_last_seen_key = KEYS[8]

local now = tonumber(ARGV[1])
local client = ARGV[2]

local num_static_argv = 2
`,
  "register.lua": `local index = ARGV[num_static_argv + 1]
local weight = tonumber(ARGV[num_static_argv + 2])
local expiration = tonumber(ARGV[num_static_argv + 3])

local state = process_tick(now, false)
local capacity = state['capacity']
local reservoir = state['reservoir']

local settings = redis.call('hmget', settings_key,
  'nextRequest',
  'minTime',
  'groupTimeout'
)
local nextRequest = tonumber(settings[1])
local minTime = tonumber(settings[2])
local groupTimeout = tonumber(settings[3])

if conditions_check(capacity, weight) then

  redis.call('hincrby', settings_key, 'running', weight)
  redis.call('hset', job_weights_key, index, weight)
  if expiration ~= nil then
    redis.call('zadd', job_expirations_key, now + expiration, index)
  end
  redis.call('hset', job_clients_key, index, client)
  redis.call('zincrby', client_running_key, weight, client)
  redis.call('hincrby', client_num_queued_key, client, -1)
  redis.call('zadd', client_last_registered_key, now, client)

  local wait = math.max(nextRequest - now, 0)
  local newNextRequest = now + wait + minTime

  if reservoir == nil then
    redis.call('hset', settings_key,
      'nextRequest', newNextRequest
    )
  else
    reservoir = reservoir - weight
    redis.call('hmset', settings_key,
      'reservoir', reservoir,
      'nextRequest', newNextRequest
    )
  end

  refresh_expiration(now, newNextRequest, groupTimeout)

  return {true, wait, reservoir}

else
  return {false}
end
`,
  "register_client.lua": `local queued = tonumber(ARGV[num_static_argv + 1])

-- Could have been re-registered concurrently
if not redis.call('zscore', client_last_seen_key, client) then
  redis.call('zadd', client_running_key, 0, client)
  redis.call('hset', client_num_queued_key, client, queued)
  redis.call('zadd', client_last_registered_key, 0, client)
end

redis.call('zadd', client_last_seen_key, now, client)

return {}
`,
  "running.lua": `return process_tick(now, false)['running']
`,
  "submit.lua": `local queueLength = tonumber(ARGV[num_static_argv + 1])
local weight = tonumber(ARGV[num_static_argv + 2])

local capacity = process_tick(now, false)['capacity']

local settings = redis.call('hmget', settings_key,
  'id',
  'maxConcurrent',
  'highWater',
  'nextRequest',
  'strategy',
  'unblockTime',
  'penalty',
  'minTime',
  'groupTimeout'
)
local id = settings[1]
local maxConcurrent = tonumber(settings[2])
local highWater = tonumber(settings[3])
local nextRequest = tonumber(settings[4])
local strategy = tonumber(settings[5])
local unblockTime = tonumber(settings[6])
local penalty = tonumber(settings[7])
local minTime = tonumber(settings[8])
local groupTimeout = tonumber(settings[9])

if maxConcurrent ~= nil and weight > maxConcurrent then
  return redis.error_reply('OVERWEIGHT:'..weight..':'..maxConcurrent)
end

local reachedHWM = (highWater ~= nil and queueLength == highWater
  and not (
    conditions_check(capacity, weight)
    and nextRequest - now <= 0
  )
)

local blocked = strategy == 3 and (reachedHWM or unblockTime >= now)

if blocked then
  local computedPenalty = penalty
  if computedPenalty == nil then
    if minTime == 0 then
      computedPenalty = 5000
    else
      computedPenalty = 15 * minTime
    end
  end

  local newNextRequest = now + computedPenalty + minTime

  redis.call('hmset', settings_key,
    'unblockTime', now + computedPenalty,
    'nextRequest', newNextRequest
  )

  local clients_queued_reset = redis.call('hkeys', client_num_queued_key)
  local queued_reset = {}
  for i = 1, #clients_queued_reset do
    table.insert(queued_reset, clients_queued_reset[i])
    table.insert(queued_reset, 0)
  end
  redis.call('hmset', client_num_queued_key, unpack(queued_reset))

  redis.call('publish', 'b_'..id, 'blocked:')

  refresh_expiration(now, newNextRequest, groupTimeout)
end

if not blocked and not reachedHWM then
  redis.call('hincrby', client_num_queued_key, client, 1)
end

return {reachedHWM, blocked, strategy}
`,
  "update_settings.lua": `local args = {'hmset', settings_key}

for i = num_static_argv + 1, #ARGV do
  table.insert(args, ARGV[i])
end

redis.call(unpack(args))

process_tick(now, true)

local groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout'))
refresh_expiration(0, 0, groupTimeout)

return {}
`,
  "validate_client.lua": `if not redis.call('zscore', client_last_seen_key, client) then
  return redis.error_reply('UNKNOWN_CLIENT')
end

redis.call('zadd', client_last_seen_key, now, client)
`,
  "validate_keys.lua": `if not (redis.call('exists', settings_key) == 1) then
  return redis.error_reply('SETTINGS_KEY_NOT_FOUND')
end
`
};
var hasRequiredScripts;
function requireScripts() {
  return hasRequiredScripts || (hasRequiredScripts = 1, function(t) {
    var c, n, a;
    n = require$$0, c = {
      refs: n["refs.lua"],
      validate_keys: n["validate_keys.lua"],
      validate_client: n["validate_client.lua"],
      refresh_expiration: n["refresh_expiration.lua"],
      process_tick: n["process_tick.lua"],
      conditions_check: n["conditions_check.lua"],
      get_time: n["get_time.lua"]
    }, t.allKeys = function(e) {
      return [
        /*
        HASH
        */
        `b_${e}_settings`,
        /*
        HASH
        job index -> weight
        */
        `b_${e}_job_weights`,
        /*
        ZSET
        job index -> expiration
        */
        `b_${e}_job_expirations`,
        /*
        HASH
        job index -> client
        */
        `b_${e}_job_clients`,
        /*
        ZSET
        client -> sum running
        */
        `b_${e}_client_running`,
        /*
        HASH
        client -> num queued
        */
        `b_${e}_client_num_queued`,
        /*
        ZSET
        client -> last job registered
        */
        `b_${e}_client_last_registered`,
        /*
        ZSET
        client -> last seen
        */
        `b_${e}_client_last_seen`
      ];
    }, a = {
      init: {
        keys: t.allKeys,
        headers: ["process_tick"],
        refresh_expiration: !0,
        code: n["init.lua"]
      },
      group_check: {
        keys: t.allKeys,
        headers: [],
        refresh_expiration: !1,
        code: n["group_check.lua"]
      },
      register_client: {
        keys: t.allKeys,
        headers: ["validate_keys"],
        refresh_expiration: !1,
        code: n["register_client.lua"]
      },
      blacklist_client: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client"],
        refresh_expiration: !1,
        code: n["blacklist_client.lua"]
      },
      heartbeat: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick"],
        refresh_expiration: !1,
        code: n["heartbeat.lua"]
      },
      update_settings: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick"],
        refresh_expiration: !0,
        code: n["update_settings.lua"]
      },
      running: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick"],
        refresh_expiration: !1,
        code: n["running.lua"]
      },
      queued: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client"],
        refresh_expiration: !1,
        code: n["queued.lua"]
      },
      done: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick"],
        refresh_expiration: !1,
        code: n["done.lua"]
      },
      check: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"],
        refresh_expiration: !1,
        code: n["check.lua"]
      },
      submit: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"],
        refresh_expiration: !0,
        code: n["submit.lua"]
      },
      register: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"],
        refresh_expiration: !0,
        code: n["register.lua"]
      },
      free: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick"],
        refresh_expiration: !0,
        code: n["free.lua"]
      },
      current_reservoir: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick"],
        refresh_expiration: !1,
        code: n["current_reservoir.lua"]
      },
      increment_reservoir: {
        keys: t.allKeys,
        headers: ["validate_keys", "validate_client", "process_tick"],
        refresh_expiration: !0,
        code: n["increment_reservoir.lua"]
      }
    }, t.names = Object.keys(a), t.keys = function(e, i) {
      return a[e].keys(i);
    }, t.payload = function(e) {
      var i;
      return i = a[e], Array.prototype.concat(c.refs, i.headers.map(function(r) {
        return c[r];
      }), i.refresh_expiration ? c.refresh_expiration : "", i.code).join(`
`);
    };
  }(Scripts)), Scripts;
}
var RedisConnection_1, hasRequiredRedisConnection;
function requireRedisConnection() {
  if (hasRequiredRedisConnection) return RedisConnection_1;
  hasRequiredRedisConnection = 1;
  function asyncGeneratorStep(t, c, n, a, e, i, r) {
    try {
      var u = t[i](r), l = u.value;
    } catch (v) {
      n(v);
      return;
    }
    u.done ? c(l) : Promise.resolve(l).then(a, e);
  }
  function _asyncToGenerator(t) {
    return function() {
      var c = this, n = arguments;
      return new Promise(function(a, e) {
        var i = t.apply(c, n);
        function r(l) {
          asyncGeneratorStep(i, a, e, r, u, "next", l);
        }
        function u(l) {
          asyncGeneratorStep(i, a, e, r, u, "throw", l);
        }
        r(void 0);
      });
    };
  }
  var Events, RedisConnection, Scripts, parser;
  return parser = requireParser(), Events = requireEvents(), Scripts = requireScripts(), RedisConnection = (function() {
    class RedisConnection {
      constructor(options = {}) {
        parser.load(options, this.defaults, this), this.Redis == null && (this.Redis = eval("require")("redis")), this.Events == null && (this.Events = new Events(this)), this.terminated = !1, this.client == null && (this.client = this.Redis.createClient(this.clientOptions)), this.subscriber = this.client.duplicate(), this.limiters = {}, this.shas = {}, this.ready = this.Promise.all([this._setup(this.client, !1), this._setup(this.subscriber, !0)]).then(() => this._loadScripts()).then(() => ({
          client: this.client,
          subscriber: this.subscriber
        }));
      }
      _setup(t, c) {
        return t.setMaxListeners(0), new this.Promise((n, a) => (t.on("error", (e) => this.Events.trigger("error", e)), c && t.on("message", (e, i) => {
          var r;
          return (r = this.limiters[e]) != null ? r._store.onMessage(e, i) : void 0;
        }), t.ready ? n() : t.once("ready", n)));
      }
      _loadScript(t) {
        return new this.Promise((c, n) => {
          var a;
          return a = Scripts.payload(t), this.client.multi([["script", "load", a]]).exec((e, i) => e != null ? n(e) : (this.shas[t] = i[0], c(i[0])));
        });
      }
      _loadScripts() {
        return this.Promise.all(Scripts.names.map((t) => this._loadScript(t)));
      }
      __runCommand__(t) {
        var c = this;
        return _asyncToGenerator(function* () {
          return yield c.ready, new c.Promise((n, a) => c.client.multi([t]).exec_atomic(function(e, i) {
            return e != null ? a(e) : n(i[0]);
          }));
        })();
      }
      __addLimiter__(t) {
        return this.Promise.all([t.channel(), t.channel_client()].map((c) => new this.Promise((n, a) => {
          var e;
          return e = (i) => {
            if (i === c)
              return this.subscriber.removeListener("subscribe", e), this.limiters[c] = t, n();
          }, this.subscriber.on("subscribe", e), this.subscriber.subscribe(c);
        })));
      }
      __removeLimiter__(t) {
        var c = this;
        return this.Promise.all([t.channel(), t.channel_client()].map(
          /* @__PURE__ */ function() {
            var n = _asyncToGenerator(function* (a) {
              return c.terminated || (yield new c.Promise((e, i) => c.subscriber.unsubscribe(a, function(r, u) {
                if (r != null)
                  return i(r);
                if (u === a)
                  return e();
              }))), delete c.limiters[a];
            });
            return function(a) {
              return n.apply(this, arguments);
            };
          }()
        ));
      }
      __scriptArgs__(t, c, n, a) {
        var e;
        return e = Scripts.keys(t, c), [this.shas[t], e.length].concat(e, n, a);
      }
      __scriptFn__(t) {
        return this.client.evalsha.bind(this.client);
      }
      disconnect(t = !0) {
        var c, n, a, e;
        for (e = Object.keys(this.limiters), c = 0, a = e.length; c < a; c++)
          n = e[c], clearInterval(this.limiters[n]._store.heartbeat);
        return this.limiters = {}, this.terminated = !0, this.client.end(t), this.subscriber.end(t), this.Promise.resolve();
      }
    }
    return RedisConnection.prototype.datastore = "redis", RedisConnection.prototype.defaults = {
      Redis: null,
      clientOptions: {},
      client: null,
      Promise,
      Events: null
    }, RedisConnection;
  }).call(void 0), RedisConnection_1 = RedisConnection, RedisConnection_1;
}
var IORedisConnection_1, hasRequiredIORedisConnection;
function requireIORedisConnection() {
  if (hasRequiredIORedisConnection) return IORedisConnection_1;
  hasRequiredIORedisConnection = 1;
  function _slicedToArray(t, c) {
    return _arrayWithHoles(t) || _iterableToArrayLimit(t, c) || _nonIterableRest();
  }
  function _nonIterableRest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance");
  }
  function _iterableToArrayLimit(t, c) {
    var n = [], a = !0, e = !1, i = void 0;
    try {
      for (var r = t[Symbol.iterator](), u; !(a = (u = r.next()).done) && (n.push(u.value), !(c && n.length === c)); a = !0)
        ;
    } catch (l) {
      e = !0, i = l;
    } finally {
      try {
        !a && r.return != null && r.return();
      } finally {
        if (e) throw i;
      }
    }
    return n;
  }
  function _arrayWithHoles(t) {
    if (Array.isArray(t)) return t;
  }
  function asyncGeneratorStep(t, c, n, a, e, i, r) {
    try {
      var u = t[i](r), l = u.value;
    } catch (v) {
      n(v);
      return;
    }
    u.done ? c(l) : Promise.resolve(l).then(a, e);
  }
  function _asyncToGenerator(t) {
    return function() {
      var c = this, n = arguments;
      return new Promise(function(a, e) {
        var i = t.apply(c, n);
        function r(l) {
          asyncGeneratorStep(i, a, e, r, u, "next", l);
        }
        function u(l) {
          asyncGeneratorStep(i, a, e, r, u, "throw", l);
        }
        r(void 0);
      });
    };
  }
  var Events, IORedisConnection, Scripts, parser;
  return parser = requireParser(), Events = requireEvents(), Scripts = requireScripts(), IORedisConnection = (function() {
    class IORedisConnection {
      constructor(options = {}) {
        parser.load(options, this.defaults, this), this.Redis == null && (this.Redis = eval("require")("ioredis")), this.Events == null && (this.Events = new Events(this)), this.terminated = !1, this.clusterNodes != null ? (this.client = new this.Redis.Cluster(this.clusterNodes, this.clientOptions), this.subscriber = new this.Redis.Cluster(this.clusterNodes, this.clientOptions)) : this.client != null && this.client.duplicate == null ? this.subscriber = new this.Redis.Cluster(this.client.startupNodes, this.client.options) : (this.client == null && (this.client = new this.Redis(this.clientOptions)), this.subscriber = this.client.duplicate()), this.limiters = {}, this.ready = this.Promise.all([this._setup(this.client, !1), this._setup(this.subscriber, !0)]).then(() => (this._loadScripts(), {
          client: this.client,
          subscriber: this.subscriber
        }));
      }
      _setup(t, c) {
        return t.setMaxListeners(0), new this.Promise((n, a) => (t.on("error", (e) => this.Events.trigger("error", e)), c && t.on("message", (e, i) => {
          var r;
          return (r = this.limiters[e]) != null ? r._store.onMessage(e, i) : void 0;
        }), t.status === "ready" ? n() : t.once("ready", n)));
      }
      _loadScripts() {
        return Scripts.names.forEach((t) => this.client.defineCommand(t, {
          lua: Scripts.payload(t)
        }));
      }
      __runCommand__(t) {
        var c = this;
        return _asyncToGenerator(function* () {
          var n;
          yield c.ready;
          var a = yield c.client.pipeline([t]).exec(), e = _slicedToArray(a, 1), i = _slicedToArray(e[0], 2);
          return i[0], n = i[1], n;
        })();
      }
      __addLimiter__(t) {
        return this.Promise.all([t.channel(), t.channel_client()].map((c) => new this.Promise((n, a) => this.subscriber.subscribe(c, () => (this.limiters[c] = t, n())))));
      }
      __removeLimiter__(t) {
        var c = this;
        return [t.channel(), t.channel_client()].forEach(
          /* @__PURE__ */ function() {
            var n = _asyncToGenerator(function* (a) {
              return c.terminated || (yield c.subscriber.unsubscribe(a)), delete c.limiters[a];
            });
            return function(a) {
              return n.apply(this, arguments);
            };
          }()
        );
      }
      __scriptArgs__(t, c, n, a) {
        var e;
        return e = Scripts.keys(t, c), [e.length].concat(e, n, a);
      }
      __scriptFn__(t) {
        return this.client[t].bind(this.client);
      }
      disconnect(t = !0) {
        var c, n, a, e;
        for (e = Object.keys(this.limiters), c = 0, a = e.length; c < a; c++)
          n = e[c], clearInterval(this.limiters[n]._store.heartbeat);
        return this.limiters = {}, this.terminated = !0, t ? this.Promise.all([this.client.quit(), this.subscriber.quit()]) : (this.client.disconnect(), this.subscriber.disconnect(), this.Promise.resolve());
      }
    }
    return IORedisConnection.prototype.datastore = "ioredis", IORedisConnection.prototype.defaults = {
      Redis: null,
      clientOptions: {},
      clusterNodes: null,
      client: null,
      Promise,
      Events: null
    }, IORedisConnection;
  }).call(void 0), IORedisConnection_1 = IORedisConnection, IORedisConnection_1;
}
var RedisDatastore_1, hasRequiredRedisDatastore;
function requireRedisDatastore() {
  if (hasRequiredRedisDatastore) return RedisDatastore_1;
  hasRequiredRedisDatastore = 1;
  function t(p, s) {
    return a(p) || n(p, s) || c();
  }
  function c() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance");
  }
  function n(p, s) {
    var d = [], o = !0, _ = !1, b = void 0;
    try {
      for (var R = p[Symbol.iterator](), x; !(o = (x = R.next()).done) && (d.push(x.value), !(s && d.length === s)); o = !0)
        ;
    } catch (E) {
      _ = !0, b = E;
    } finally {
      try {
        !o && R.return != null && R.return();
      } finally {
        if (_) throw b;
      }
    }
    return d;
  }
  function a(p) {
    if (Array.isArray(p)) return p;
  }
  function e(p, s, d, o, _, b, R) {
    try {
      var x = p[b](R), E = x.value;
    } catch (f) {
      d(f);
      return;
    }
    x.done ? s(E) : Promise.resolve(E).then(o, _);
  }
  function i(p) {
    return function() {
      var s = this, d = arguments;
      return new Promise(function(o, _) {
        var b = p.apply(s, d);
        function R(E) {
          e(b, o, _, R, x, "next", E);
        }
        function x(E) {
          e(b, o, _, R, x, "throw", E);
        }
        R(void 0);
      });
    };
  }
  var r, u, l, v, m;
  return m = requireParser(), r = requireBottleneckError(), l = requireRedisConnection(), u = requireIORedisConnection(), v = class {
    constructor(s, d, o) {
      this.instance = s, this.storeOptions = d, this.originalId = this.instance.id, this.clientId = this.instance._randomIndex(), m.load(o, o, this), this.clients = {}, this.capacityPriorityCounters = {}, this.sharedConnection = this.connection != null, this.connection == null && (this.connection = this.instance.datastore === "redis" ? new l({
        Redis: this.Redis,
        clientOptions: this.clientOptions,
        Promise: this.Promise,
        Events: this.instance.Events
      }) : this.instance.datastore === "ioredis" ? new u({
        Redis: this.Redis,
        clientOptions: this.clientOptions,
        clusterNodes: this.clusterNodes,
        Promise: this.Promise,
        Events: this.instance.Events
      }) : void 0), this.instance.connection = this.connection, this.instance.datastore = this.connection.datastore, this.ready = this.connection.ready.then((_) => (this.clients = _, this.runScript("init", this.prepareInitSettings(this.clearDatastore)))).then(() => this.connection.__addLimiter__(this.instance)).then(() => this.runScript("register_client", [this.instance.queued()])).then(() => {
        var _;
        return typeof (_ = this.heartbeat = setInterval(() => this.runScript("heartbeat", []).catch((b) => this.instance.Events.trigger("error", b)), this.heartbeatInterval)).unref == "function" && _.unref(), this.clients;
      });
    }
    __publish__(s) {
      var d = this;
      return i(function* () {
        var o, _ = yield d.ready;
        return o = _.client, o.publish(d.instance.channel(), `message:${s.toString()}`);
      })();
    }
    onMessage(s, d) {
      var o = this;
      return i(function* () {
        var _, b, R, x, E, f, I, h, y, k;
        try {
          I = d.indexOf(":");
          var w = [d.slice(0, I), d.slice(I + 1)];
          if (k = w[0], R = w[1], k === "capacity")
            return yield o.instance._drainAll(R.length > 0 ? ~~R : void 0);
          if (k === "capacity-priority") {
            var g = R.split(":"), q = t(g, 3);
            return y = q[0], h = q[1], b = q[2], _ = y.length > 0 ? ~~y : void 0, h === o.clientId ? (x = yield o.instance._drainAll(_), f = _ != null ? _ - (x || 0) : "", yield o.clients.client.publish(o.instance.channel(), `capacity-priority:${f}::${b}`)) : h === "" ? (clearTimeout(o.capacityPriorityCounters[b]), delete o.capacityPriorityCounters[b], o.instance._drainAll(_)) : o.capacityPriorityCounters[b] = setTimeout(
              /* @__PURE__ */ i(function* () {
                var S;
                try {
                  return delete o.capacityPriorityCounters[b], yield o.runScript("blacklist_client", [h]), yield o.instance._drainAll(_);
                } catch (C) {
                  return S = C, o.instance.Events.trigger("error", S);
                }
              }),
              1e3
            );
          } else {
            if (k === "message")
              return o.instance.Events.trigger("message", R);
            if (k === "blocked")
              return yield o.instance._dropAllQueued();
          }
        } catch (S) {
          return E = S, o.instance.Events.trigger("error", E);
        }
      })();
    }
    __disconnect__(s) {
      return clearInterval(this.heartbeat), this.sharedConnection ? this.connection.__removeLimiter__(this.instance) : this.connection.disconnect(s);
    }
    runScript(s, d) {
      var o = this;
      return i(function* () {
        return s === "init" || s === "register_client" || (yield o.ready), new o.Promise((_, b) => {
          var R, x;
          return R = [Date.now(), o.clientId].concat(d), o.instance.Events.trigger("debug", `Calling Redis script: ${s}.lua`, R), x = o.connection.__scriptArgs__(s, o.originalId, R, function(E, f) {
            return E != null ? b(E) : _(f);
          }), o.connection.__scriptFn__(s)(...x);
        }).catch((_) => _.message === "SETTINGS_KEY_NOT_FOUND" ? s === "heartbeat" ? o.Promise.resolve() : o.runScript("init", o.prepareInitSettings(!1)).then(() => o.runScript(s, d)) : _.message === "UNKNOWN_CLIENT" ? o.runScript("register_client", [o.instance.queued()]).then(() => o.runScript(s, d)) : o.Promise.reject(_));
      })();
    }
    prepareArray(s) {
      var d, o, _, b;
      for (_ = [], d = 0, o = s.length; d < o; d++)
        b = s[d], _.push(b != null ? b.toString() : "");
      return _;
    }
    prepareObject(s) {
      var d, o, _;
      d = [];
      for (o in s)
        _ = s[o], d.push(o, _ != null ? _.toString() : "");
      return d;
    }
    prepareInitSettings(s) {
      var d;
      return d = this.prepareObject(Object.assign({}, this.storeOptions, {
        id: this.originalId,
        version: this.instance.version,
        groupTimeout: this.timeout,
        clientTimeout: this.clientTimeout
      })), d.unshift(s ? 1 : 0, this.instance.version), d;
    }
    convertBool(s) {
      return !!s;
    }
    __updateSettings__(s) {
      var d = this;
      return i(function* () {
        return yield d.runScript("update_settings", d.prepareObject(s)), m.overwrite(s, s, d.storeOptions);
      })();
    }
    __running__() {
      return this.runScript("running", []);
    }
    __queued__() {
      return this.runScript("queued", []);
    }
    __done__() {
      return this.runScript("done", []);
    }
    __groupCheck__() {
      var s = this;
      return i(function* () {
        return s.convertBool(yield s.runScript("group_check", []));
      })();
    }
    __incrementReservoir__(s) {
      return this.runScript("increment_reservoir", [s]);
    }
    __currentReservoir__() {
      return this.runScript("current_reservoir", []);
    }
    __check__(s) {
      var d = this;
      return i(function* () {
        return d.convertBool(yield d.runScript("check", d.prepareArray([s])));
      })();
    }
    __register__(s, d, o) {
      var _ = this;
      return i(function* () {
        var b, R, x, E = yield _.runScript("register", _.prepareArray([s, d, o])), f = t(E, 3);
        return R = f[0], x = f[1], b = f[2], {
          success: _.convertBool(R),
          wait: x,
          reservoir: b
        };
      })();
    }
    __submit__(s, d) {
      var o = this;
      return i(function* () {
        var _, b, R, x, E;
        try {
          var f = yield o.runScript("submit", o.prepareArray([s, d])), I = t(f, 3);
          return x = I[0], _ = I[1], E = I[2], {
            reachedHWM: o.convertBool(x),
            blocked: o.convertBool(_),
            strategy: E
          };
        } catch (k) {
          if (b = k, b.message.indexOf("OVERWEIGHT") === 0) {
            var h = b.message.split(":"), y = t(h, 3);
            throw y[0], d = y[1], R = y[2], new r(`Impossible to add a job having a weight of ${d} to a limiter having a maxConcurrent setting of ${R}`);
          } else
            throw b;
        }
      })();
    }
    __free__(s, d) {
      var o = this;
      return i(function* () {
        var _;
        return _ = yield o.runScript("free", o.prepareArray([s])), {
          running: _
        };
      })();
    }
  }, RedisDatastore_1 = v, RedisDatastore_1;
}
var States_1, hasRequiredStates;
function requireStates() {
  if (hasRequiredStates) return States_1;
  hasRequiredStates = 1;
  var t, c;
  return t = requireBottleneckError(), c = class {
    constructor(a) {
      this.status = a, this._jobs = {}, this.counts = this.status.map(function() {
        return 0;
      });
    }
    next(a) {
      var e, i;
      if (e = this._jobs[a], i = e + 1, e != null && i < this.status.length)
        return this.counts[e]--, this.counts[i]++, this._jobs[a]++;
      if (e != null)
        return this.counts[e]--, delete this._jobs[a];
    }
    start(a) {
      var e;
      return e = 0, this._jobs[a] = e, this.counts[e]++;
    }
    remove(a) {
      var e;
      return e = this._jobs[a], e != null && (this.counts[e]--, delete this._jobs[a]), e != null;
    }
    jobStatus(a) {
      var e;
      return (e = this.status[this._jobs[a]]) != null ? e : null;
    }
    statusJobs(a) {
      var e, i, r, u, l;
      if (a != null) {
        if (i = this.status.indexOf(a), i < 0)
          throw new t(`status must be one of ${this.status.join(", ")}`);
        r = this._jobs, u = [];
        for (e in r)
          l = r[e], l === i && u.push(e);
        return u;
      } else
        return Object.keys(this._jobs);
    }
    statusCounts() {
      return this.counts.reduce((a, e, i) => (a[this.status[i]] = e, a), {});
    }
  }, States_1 = c, States_1;
}
var Sync_1, hasRequiredSync;
function requireSync() {
  if (hasRequiredSync) return Sync_1;
  hasRequiredSync = 1;
  function t(e, i, r, u, l, v, m) {
    try {
      var p = e[v](m), s = p.value;
    } catch (d) {
      r(d);
      return;
    }
    p.done ? i(s) : Promise.resolve(s).then(u, l);
  }
  function c(e) {
    return function() {
      var i = this, r = arguments;
      return new Promise(function(u, l) {
        var v = e.apply(i, r);
        function m(s) {
          t(v, u, l, m, p, "next", s);
        }
        function p(s) {
          t(v, u, l, m, p, "throw", s);
        }
        m(void 0);
      });
    };
  }
  var n, a;
  return n = requireDLList(), a = class {
    constructor(i, r) {
      this.schedule = this.schedule.bind(this), this.name = i, this.Promise = r, this._running = 0, this._queue = new n();
    }
    isEmpty() {
      return this._queue.length === 0;
    }
    _tryToRun() {
      var i = this;
      return c(function* () {
        var r, u, l, v, m, p, s;
        if (i._running < 1 && i._queue.length > 0) {
          i._running++;
          var d = i._queue.shift();
          return s = d.task, r = d.args, m = d.resolve, v = d.reject, u = yield c(function* () {
            try {
              return p = yield s(...r), function() {
                return m(p);
              };
            } catch (o) {
              return l = o, function() {
                return v(l);
              };
            }
          })(), i._running--, i._tryToRun(), u();
        }
      })();
    }
    schedule(i, ...r) {
      var u, l, v;
      return v = l = null, u = new this.Promise(function(m, p) {
        return v = m, l = p;
      }), this._queue.push({
        task: i,
        args: r,
        resolve: v,
        reject: l
      }), this._tryToRun(), u;
    }
  }, Sync_1 = a, Sync_1;
}
const version = "2.19.5", require$$8 = {
  version
};
var Group_1, hasRequiredGroup;
function requireGroup() {
  if (hasRequiredGroup) return Group_1;
  hasRequiredGroup = 1;
  function t(s, d) {
    return a(s) || n(s, d) || c();
  }
  function c() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance");
  }
  function n(s, d) {
    var o = [], _ = !0, b = !1, R = void 0;
    try {
      for (var x = s[Symbol.iterator](), E; !(_ = (E = x.next()).done) && (o.push(E.value), !(d && o.length === d)); _ = !0)
        ;
    } catch (f) {
      b = !0, R = f;
    } finally {
      try {
        !_ && x.return != null && x.return();
      } finally {
        if (b) throw R;
      }
    }
    return o;
  }
  function a(s) {
    if (Array.isArray(s)) return s;
  }
  function e(s, d, o, _, b, R, x) {
    try {
      var E = s[R](x), f = E.value;
    } catch (I) {
      o(I);
      return;
    }
    E.done ? d(f) : Promise.resolve(f).then(_, b);
  }
  function i(s) {
    return function() {
      var d = this, o = arguments;
      return new Promise(function(_, b) {
        var R = s.apply(d, o);
        function x(f) {
          e(R, _, b, x, E, "next", f);
        }
        function E(f) {
          e(R, _, b, x, E, "throw", f);
        }
        x(void 0);
      });
    };
  }
  var r, u, l, v, m, p;
  return p = requireParser(), r = requireEvents(), v = requireRedisConnection(), l = requireIORedisConnection(), m = requireScripts(), u = (function() {
    class s {
      constructor(o = {}) {
        this.deleteKey = this.deleteKey.bind(this), this.limiterOptions = o, p.load(this.limiterOptions, this.defaults, this), this.Events = new r(this), this.instances = {}, this.Bottleneck = requireBottleneck(), this._startAutoCleanup(), this.sharedConnection = this.connection != null, this.connection == null && (this.limiterOptions.datastore === "redis" ? this.connection = new v(Object.assign({}, this.limiterOptions, {
          Events: this.Events
        })) : this.limiterOptions.datastore === "ioredis" && (this.connection = new l(Object.assign({}, this.limiterOptions, {
          Events: this.Events
        }))));
      }
      key(o = "") {
        var _;
        return (_ = this.instances[o]) != null ? _ : (() => {
          var b;
          return b = this.instances[o] = new this.Bottleneck(Object.assign(this.limiterOptions, {
            id: `${this.id}-${o}`,
            timeout: this.timeout,
            connection: this.connection
          })), this.Events.trigger("created", b, o), b;
        })();
      }
      deleteKey(o = "") {
        var _ = this;
        return i(function* () {
          var b, R;
          return R = _.instances[o], _.connection && (b = yield _.connection.__runCommand__(["del", ...m.allKeys(`${_.id}-${o}`)])), R != null && (delete _.instances[o], yield R.disconnect()), R != null || b > 0;
        })();
      }
      limiters() {
        var o, _, b, R;
        _ = this.instances, b = [];
        for (o in _)
          R = _[o], b.push({
            key: o,
            limiter: R
          });
        return b;
      }
      keys() {
        return Object.keys(this.instances);
      }
      clusterKeys() {
        var o = this;
        return i(function* () {
          var _, b, R, x, E, f, I, h, y;
          if (o.connection == null)
            return o.Promise.resolve(o.keys());
          for (f = [], _ = null, y = `b_${o.id}-`.length, b = 9; _ !== 0; ) {
            var k = yield o.connection.__runCommand__(["scan", _ ?? 0, "match", `b_${o.id}-*_settings`, "count", 1e4]), w = t(k, 2);
            for (h = w[0], R = w[1], _ = ~~h, x = 0, I = R.length; x < I; x++)
              E = R[x], f.push(E.slice(y, -b));
          }
          return f;
        })();
      }
      _startAutoCleanup() {
        var o = this, _;
        return clearInterval(this.interval), typeof (_ = this.interval = setInterval(
          /* @__PURE__ */ i(function* () {
            var b, R, x, E, f, I;
            f = Date.now(), x = o.instances, E = [];
            for (R in x) {
              I = x[R];
              try {
                (yield I._store.__groupCheck__(f)) ? E.push(o.deleteKey(R)) : E.push(void 0);
              } catch (h) {
                b = h, E.push(I.Events.trigger("error", b));
              }
            }
            return E;
          }),
          this.timeout / 2
        )).unref == "function" ? _.unref() : void 0;
      }
      updateSettings(o = {}) {
        if (p.overwrite(o, this.defaults, this), p.overwrite(o, o, this.limiterOptions), o.timeout != null)
          return this._startAutoCleanup();
      }
      disconnect(o = !0) {
        var _;
        if (!this.sharedConnection)
          return (_ = this.connection) != null ? _.disconnect(o) : void 0;
      }
    }
    return s.prototype.defaults = {
      timeout: 1e3 * 60 * 5,
      connection: null,
      Promise,
      id: "group-key"
    }, s;
  }).call(void 0), Group_1 = u, Group_1;
}
var Batcher_1, hasRequiredBatcher;
function requireBatcher() {
  if (hasRequiredBatcher) return Batcher_1;
  hasRequiredBatcher = 1;
  var t, c, n;
  return n = requireParser(), c = requireEvents(), t = (function() {
    class a {
      constructor(i = {}) {
        this.options = i, n.load(this.options, this.defaults, this), this.Events = new c(this), this._arr = [], this._resetPromise(), this._lastFlush = Date.now();
      }
      _resetPromise() {
        return this._promise = new this.Promise((i, r) => this._resolve = i);
      }
      _flush() {
        return clearTimeout(this._timeout), this._lastFlush = Date.now(), this._resolve(), this.Events.trigger("batch", this._arr), this._arr = [], this._resetPromise();
      }
      add(i) {
        var r;
        return this._arr.push(i), r = this._promise, this._arr.length === this.maxSize ? this._flush() : this.maxTime != null && this._arr.length === 1 && (this._timeout = setTimeout(() => this._flush(), this.maxTime)), r;
      }
    }
    return a.prototype.defaults = {
      maxTime: null,
      maxSize: null,
      Promise
    }, a;
  }).call(void 0), Batcher_1 = t, Batcher_1;
}
var Bottleneck_1, hasRequiredBottleneck;
function requireBottleneck() {
  if (hasRequiredBottleneck) return Bottleneck_1;
  hasRequiredBottleneck = 1;
  function t(f, I) {
    return i(f) || c(f, I) || a();
  }
  function c(f, I) {
    var h = [], y = !0, k = !1, w = void 0;
    try {
      for (var g = f[Symbol.iterator](), q; !(y = (q = g.next()).done) && (h.push(q.value), !(I && h.length === I)); y = !0)
        ;
    } catch (S) {
      k = !0, w = S;
    } finally {
      try {
        !y && g.return != null && g.return();
      } finally {
        if (k) throw w;
      }
    }
    return h;
  }
  function n(f) {
    return i(f) || e(f) || a();
  }
  function a() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance");
  }
  function e(f) {
    if (Symbol.iterator in Object(f) || Object.prototype.toString.call(f) === "[object Arguments]") return Array.from(f);
  }
  function i(f) {
    if (Array.isArray(f)) return f;
  }
  function r(f, I, h, y, k, w, g) {
    try {
      var q = f[w](g), S = q.value;
    } catch (C) {
      h(C);
      return;
    }
    q.done ? I(S) : Promise.resolve(S).then(y, k);
  }
  function u(f) {
    return function() {
      var I = this, h = arguments;
      return new Promise(function(y, k) {
        var w = f.apply(I, h);
        function g(S) {
          r(w, y, k, g, q, "next", S);
        }
        function q(S) {
          r(w, y, k, g, q, "throw", S);
        }
        g(void 0);
      });
    };
  }
  var l, v, m, p, s, d, o, _, b, R, x, E = [].splice;
  return d = 10, v = 5, x = requireParser(), o = requireQueues(), p = requireJob(), s = requireLocalDatastore(), _ = requireRedisDatastore(), m = requireEvents(), b = requireStates(), R = requireSync(), l = (function() {
    class f {
      constructor(h = {}, ...y) {
        var k, w;
        this._addToQueue = this._addToQueue.bind(this), this._validateOptions(h, y), x.load(h, this.instanceDefaults, this), this._queues = new o(d), this._scheduled = {}, this._states = new b(["RECEIVED", "QUEUED", "RUNNING", "EXECUTING"].concat(this.trackDoneStatus ? ["DONE"] : [])), this._limiter = null, this.Events = new m(this), this._submitLock = new R("submit", this.Promise), this._registerLock = new R("register", this.Promise), w = x.load(h, this.storeDefaults, {}), this._store = (function() {
          if (this.datastore === "redis" || this.datastore === "ioredis" || this.connection != null)
            return k = x.load(h, this.redisStoreDefaults, {}), new _(this, w, k);
          if (this.datastore === "local")
            return k = x.load(h, this.localStoreDefaults, {}), new s(this, w, k);
          throw new f.prototype.BottleneckError(`Invalid datastore type: ${this.datastore}`);
        }).call(this), this._queues.on("leftzero", () => {
          var g;
          return (g = this._store.heartbeat) != null && typeof g.ref == "function" ? g.ref() : void 0;
        }), this._queues.on("zero", () => {
          var g;
          return (g = this._store.heartbeat) != null && typeof g.unref == "function" ? g.unref() : void 0;
        });
      }
      _validateOptions(h, y) {
        if (!(h != null && typeof h == "object" && y.length === 0))
          throw new f.prototype.BottleneckError("Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you're upgrading from Bottleneck v1.");
      }
      ready() {
        return this._store.ready;
      }
      clients() {
        return this._store.clients;
      }
      channel() {
        return `b_${this.id}`;
      }
      channel_client() {
        return `b_${this.id}_${this._store.clientId}`;
      }
      publish(h) {
        return this._store.__publish__(h);
      }
      disconnect(h = !0) {
        return this._store.__disconnect__(h);
      }
      chain(h) {
        return this._limiter = h, this;
      }
      queued(h) {
        return this._queues.queued(h);
      }
      clusterQueued() {
        return this._store.__queued__();
      }
      empty() {
        return this.queued() === 0 && this._submitLock.isEmpty();
      }
      running() {
        return this._store.__running__();
      }
      done() {
        return this._store.__done__();
      }
      jobStatus(h) {
        return this._states.jobStatus(h);
      }
      jobs(h) {
        return this._states.statusJobs(h);
      }
      counts() {
        return this._states.statusCounts();
      }
      _randomIndex() {
        return Math.random().toString(36).slice(2);
      }
      check(h = 1) {
        return this._store.__check__(h);
      }
      _clearGlobalState(h) {
        return this._scheduled[h] != null ? (clearTimeout(this._scheduled[h].expiration), delete this._scheduled[h], !0) : !1;
      }
      _free(h, y, k, w) {
        var g = this;
        return u(function* () {
          var q, S;
          try {
            var C = yield g._store.__free__(h, k.weight);
            if (S = C.running, g.Events.trigger("debug", `Freed ${k.id}`, w), S === 0 && g.empty())
              return g.Events.trigger("idle");
          } catch (O) {
            return q = O, g.Events.trigger("error", q);
          }
        })();
      }
      _run(h, y, k) {
        var w, g, q;
        return y.doRun(), w = this._clearGlobalState.bind(this, h), q = this._run.bind(this, h, y), g = this._free.bind(this, h, y), this._scheduled[h] = {
          timeout: setTimeout(() => y.doExecute(this._limiter, w, q, g), k),
          expiration: y.options.expiration != null ? setTimeout(function() {
            return y.doExpire(w, q, g);
          }, k + y.options.expiration) : void 0,
          job: y
        };
      }
      _drainOne(h) {
        return this._registerLock.schedule(() => {
          var y, k, w, g, q;
          if (this.queued() === 0)
            return this.Promise.resolve(null);
          q = this._queues.getFirst();
          var S = w = q.first();
          return g = S.options, y = S.args, h != null && g.weight > h ? this.Promise.resolve(null) : (this.Events.trigger("debug", `Draining ${g.id}`, {
            args: y,
            options: g
          }), k = this._randomIndex(), this._store.__register__(k, g.weight, g.expiration).then(({
            success: C,
            wait: O,
            reservoir: P
          }) => {
            var T;
            return this.Events.trigger("debug", `Drained ${g.id}`, {
              success: C,
              args: y,
              options: g
            }), C ? (q.shift(), T = this.empty(), T && this.Events.trigger("empty"), P === 0 && this.Events.trigger("depleted", T), this._run(k, w, O), this.Promise.resolve(g.weight)) : this.Promise.resolve(null);
          }));
        });
      }
      _drainAll(h, y = 0) {
        return this._drainOne(h).then((k) => {
          var w;
          return k != null ? (w = h != null ? h - k : h, this._drainAll(w, y + k)) : this.Promise.resolve(y);
        }).catch((k) => this.Events.trigger("error", k));
      }
      _dropAllQueued(h) {
        return this._queues.shiftAll(function(y) {
          return y.doDrop({
            message: h
          });
        });
      }
      stop(h = {}) {
        var y, k;
        return h = x.load(h, this.stopDefaults), k = (w) => {
          var g;
          return g = () => {
            var q;
            return q = this._states.counts, q[0] + q[1] + q[2] + q[3] === w;
          }, new this.Promise((q, S) => g() ? q() : this.on("done", () => {
            if (g())
              return this.removeAllListeners("done"), q();
          }));
        }, y = h.dropWaitingJobs ? (this._run = function(w, g) {
          return g.doDrop({
            message: h.dropErrorMessage
          });
        }, this._drainOne = () => this.Promise.resolve(null), this._registerLock.schedule(() => this._submitLock.schedule(() => {
          var w, g, q;
          g = this._scheduled;
          for (w in g)
            q = g[w], this.jobStatus(q.job.options.id) === "RUNNING" && (clearTimeout(q.timeout), clearTimeout(q.expiration), q.job.doDrop({
              message: h.dropErrorMessage
            }));
          return this._dropAllQueued(h.dropErrorMessage), k(0);
        }))) : this.schedule({
          priority: d - 1,
          weight: 0
        }, () => k(1)), this._receive = function(w) {
          return w._reject(new f.prototype.BottleneckError(h.enqueueErrorMessage));
        }, this.stop = () => this.Promise.reject(new f.prototype.BottleneckError("stop() has already been called")), y;
      }
      _addToQueue(h) {
        var y = this;
        return u(function* () {
          var k, w, g, q, S, C, O;
          k = h.args, q = h.options;
          try {
            var P = yield y._store.__submit__(y.queued(), q.weight);
            S = P.reachedHWM, w = P.blocked, O = P.strategy;
          } catch (T) {
            return g = T, y.Events.trigger("debug", `Could not queue ${q.id}`, {
              args: k,
              options: q,
              error: g
            }), h.doDrop({
              error: g
            }), !1;
          }
          return w ? (h.doDrop(), !0) : S && (C = O === f.prototype.strategy.LEAK ? y._queues.shiftLastFrom(q.priority) : O === f.prototype.strategy.OVERFLOW_PRIORITY ? y._queues.shiftLastFrom(q.priority + 1) : O === f.prototype.strategy.OVERFLOW ? h : void 0, C != null && C.doDrop(), C == null || O === f.prototype.strategy.OVERFLOW) ? (C == null && h.doDrop(), S) : (h.doQueue(S, w), y._queues.push(h), yield y._drainAll(), S);
        })();
      }
      _receive(h) {
        return this._states.jobStatus(h.options.id) != null ? (h._reject(new f.prototype.BottleneckError(`A job with the same id already exists (id=${h.options.id})`)), !1) : (h.doReceive(), this._submitLock.schedule(this._addToQueue, h));
      }
      submit(...h) {
        var y, k, w, g, q, S, C;
        if (typeof h[0] == "function") {
          var O, P, T, j;
          q = h, O = q, P = n(O), k = P[0], h = P.slice(1), T = E.call(h, -1), j = t(T, 1), y = j[0], g = x.load({}, this.jobDefaults);
        } else {
          var D, L, G, B;
          S = h, D = S, L = n(D), g = L[0], k = L[1], h = L.slice(2), G = E.call(h, -1), B = t(G, 1), y = B[0], g = x.load(g, this.jobDefaults);
        }
        return C = (...A) => new this.Promise(function(K, M) {
          return k(...A, function(...N) {
            return (N[0] != null ? M : K)(N);
          });
        }), w = new p(C, h, g, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise), w.promise.then(function(A) {
          return typeof y == "function" ? y(...A) : void 0;
        }).catch(function(A) {
          return Array.isArray(A) ? typeof y == "function" ? y(...A) : void 0 : typeof y == "function" ? y(A) : void 0;
        }), this._receive(w);
      }
      schedule(...h) {
        var y, k, w;
        if (typeof h[0] == "function") {
          var g = h, q = n(g);
          w = q[0], h = q.slice(1), k = {};
        } else {
          var S = h, C = n(S);
          k = C[0], w = C[1], h = C.slice(2);
        }
        return y = new p(w, h, k, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise), this._receive(y), y.promise;
      }
      wrap(h) {
        var y, k;
        return y = this.schedule.bind(this), k = function(...g) {
          return y(h.bind(this), ...g);
        }, k.withOptions = function(w, ...g) {
          return y(w, h, ...g);
        }, k;
      }
      updateSettings(h = {}) {
        var y = this;
        return u(function* () {
          return yield y._store.__updateSettings__(x.overwrite(h, y.storeDefaults)), x.overwrite(h, y.instanceDefaults, y), y;
        })();
      }
      currentReservoir() {
        return this._store.__currentReservoir__();
      }
      incrementReservoir(h = 0) {
        return this._store.__incrementReservoir__(h);
      }
    }
    return f.default = f, f.Events = m, f.version = f.prototype.version = require$$8.version, f.strategy = f.prototype.strategy = {
      LEAK: 1,
      OVERFLOW: 2,
      OVERFLOW_PRIORITY: 4,
      BLOCK: 3
    }, f.BottleneckError = f.prototype.BottleneckError = requireBottleneckError(), f.Group = f.prototype.Group = requireGroup(), f.RedisConnection = f.prototype.RedisConnection = requireRedisConnection(), f.IORedisConnection = f.prototype.IORedisConnection = requireIORedisConnection(), f.Batcher = f.prototype.Batcher = requireBatcher(), f.prototype.jobDefaults = {
      priority: v,
      weight: 1,
      expiration: null,
      id: "<no-id>"
    }, f.prototype.storeDefaults = {
      maxConcurrent: null,
      minTime: 0,
      highWater: null,
      strategy: f.prototype.strategy.LEAK,
      penalty: null,
      reservoir: null,
      reservoirRefreshInterval: null,
      reservoirRefreshAmount: null,
      reservoirIncreaseInterval: null,
      reservoirIncreaseAmount: null,
      reservoirIncreaseMaximum: null
    }, f.prototype.localStoreDefaults = {
      Promise,
      timeout: null,
      heartbeatInterval: 250
    }, f.prototype.redisStoreDefaults = {
      Promise,
      timeout: null,
      heartbeatInterval: 5e3,
      clientTimeout: 1e4,
      Redis: null,
      clientOptions: {},
      clusterNodes: null,
      clearDatastore: !1,
      connection: null
    }, f.prototype.instanceDefaults = {
      datastore: "local",
      connection: null,
      id: "<no-id>",
      rejectOnDrop: !0,
      trackDoneStatus: !1,
      Promise
    }, f.prototype.stopDefaults = {
      enqueueErrorMessage: "This limiter has been stopped and cannot accept new jobs.",
      dropWaitingJobs: !0,
      dropErrorMessage: "This limiter has been stopped."
    }, f;
  }).call(void 0), Bottleneck_1 = l, Bottleneck_1;
}
var lib, hasRequiredLib;
function requireLib() {
  return hasRequiredLib || (hasRequiredLib = 1, lib = requireBottleneck()), lib;
}
var libExports = requireLib();
const Bottleneck = /* @__PURE__ */ getDefaultExportFromCjs(libExports);
function promisifyRequest(t) {
  return new Promise((c, n) => {
    t.oncomplete = t.onsuccess = () => c(t.result), t.onabort = t.onerror = () => n(t.error);
  });
}
function createStore(t, c) {
  const n = indexedDB.open(t);
  n.onupgradeneeded = () => n.result.createObjectStore(c);
  const a = promisifyRequest(n);
  return (e, i) => a.then((r) => i(r.transaction(c, e).objectStore(c)));
}
let defaultGetStoreFunc;
function defaultGetStore() {
  return defaultGetStoreFunc || (defaultGetStoreFunc = createStore("keyval-store", "keyval")), defaultGetStoreFunc;
}
function get(t, c = defaultGetStore()) {
  return c("readonly", (n) => promisifyRequest(n.get(t)));
}
function set(t, c, n = defaultGetStore()) {
  return n("readwrite", (a) => (a.put(c, t), promisifyRequest(a.transaction)));
}
function clear(t = defaultGetStore()) {
  return t("readwrite", (c) => (c.clear(), promisifyRequest(c.transaction)));
}
const routesCache = createStore("navigation-db", "routes-cache"), getRouteStringKey = (t) => `route_${JSON.stringify(t)}`, prefetchRoutes = async (t) => {
  const {
    routes: c,
    chunkSize: n = 100,
    maxConcurrent: a = 10,
    maxRequestsPerMinute: e = 2e3,
    maxRequestsPerSecond: i,
    onProgress: r,
    getRoute: u
  } = t, l = new Bottleneck({
    reservoir: e,
    reservoirRefreshAmount: e,
    reservoirRefreshInterval: 60 * 1e3,
    maxConcurrent: a
  });
  if (i) {
    const s = new Bottleneck({
      reservoir: i,
      reservoirRefreshInterval: 1e3,
      reservoirRefreshAmount: i,
      maxConcurrent: a
    });
    l.chain(s);
  }
  const v = c.length;
  let m = 0;
  const p = toChunks(c, n);
  await Promise.all(
    p.map(async (s) => {
      await Promise.all(
        s.map(
          (d) => l.schedule(async () => {
            const o = await u(d);
            if (o) {
              const _ = getRouteStringKey(getRouteKey(d));
              await set(_, o, routesCache);
            }
            m += 1, r == null || r(m, v);
          })
        )
      );
    })
  );
}, clearRoutesCache = async () => clear(routesCache), getRouteCache = async (t) => get(getRouteStringKey(t), routesCache);
export {
  getRouteCache as a,
  clearRoutesCache as c,
  getRouteStringKey as g,
  prefetchRoutes as p,
  routesCache as r
};