@trigger.dev/redis-worker 4.7.3 → 4.7.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["assert","util","process","os","tty","net_1","events_1","events_1","net_1","tls_1","Buffer","Logger","Redis","scopedUrlAlphabet","Logger","#registerCommands","API_NAME","API_NAME","API_NAME","#head","#tail","#size","z","Logger","#updateQueueSizeMetric","#updateDeadLetterQueueSizeMetric","#updateConcurrencyLimitActiveMetric","#updateConcurrencyLimitPendingMetric","#updateOldestMessageAgeMetric","cronParser","#registerCommands","#assertPipelineSucceeded","#registerCommands","#hashToShard","#initializeMetrics","#registerCommands","#getShardForQueue","#removeFromInflight","#makeMember","#parseMember","#registerCommands","#buildKey","#registerCommands","#getQueuesFromShard","#addQuantumToTenants","#getTenantsFromDispatch","#decrementDeficit","#decrementDeficitBatch","#deficitKey","#getOrCreateSnapshot","#shuffleTenantsByWeight","#orderQueuesForTenant","#createSnapshot","#getQueuesFromShard","#selectTopTenantQueues","#shuffle","#weightedShuffle","#getQueuesFromShard","#getLastServedIndex","#rotateArray","#setLastServedIndex","#lastServedKey","Logger","#registerCommands","#runMasterQueueConsumerLoop","#runReclaimLoop","#runReconcileLoop","#processShardIteration","#processDispatchShard","#drainLegacyMasterQueueShard","#createSchedulerContext","#fallbackDispatchToLegacyScheduler","#processSelectedQueues","#isInCooloff","#claimAndPushToWorkerQueue","#updateAllIndexesAfterDequeue","#resetCooloff","#releaseConcurrencySafely","#releaseOrphanedConcurrency","#handleMessageFailure","#moveToDeadLetterQueue","#reclaimTimedOutMessages","#releaseReclaimedConcurrency","#reconcileConcurrency","z","Logger","#registerCommands","Logger"],"sources":["../../../node_modules/.pnpm/@ioredis+commands@1.2.0/node_modules/@ioredis/commands/built/commands.json","../../../node_modules/.pnpm/@ioredis+commands@1.2.0/node_modules/@ioredis/commands/built/index.js","../../../node_modules/.pnpm/standard-as-callback@2.1.0/node_modules/standard-as-callback/built/utils.js","../../../node_modules/.pnpm/standard-as-callback@2.1.0/node_modules/standard-as-callback/built/index.js","../../../node_modules/.pnpm/redis-errors@1.2.0/node_modules/redis-errors/lib/old.js","../../../node_modules/.pnpm/redis-errors@1.2.0/node_modules/redis-errors/lib/modern.js","../../../node_modules/.pnpm/redis-errors@1.2.0/node_modules/redis-errors/index.js","../../../node_modules/.pnpm/cluster-key-slot@1.1.2/node_modules/cluster-key-slot/lib/index.js","../../../node_modules/.pnpm/lodash.defaults@4.2.0/node_modules/lodash.defaults/index.js","../../../node_modules/.pnpm/lodash.isarguments@3.1.0/node_modules/lodash.isarguments/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/lodash.js","../../../node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js","../../../node_modules/.pnpm/debug@4.4.3_supports-color@10.0.0/node_modules/debug/src/common.js","../../../node_modules/.pnpm/debug@4.4.3_supports-color@10.0.0/node_modules/debug/src/browser.js","../../../node_modules/.pnpm/supports-color@10.0.0/node_modules/supports-color/index.js","../../../node_modules/.pnpm/debug@4.4.3_supports-color@10.0.0/node_modules/debug/src/node.js","../../../node_modules/.pnpm/debug@4.4.3_supports-color@10.0.0/node_modules/debug/src/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/debug.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/constants/TLSProfiles.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/Command.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/errors/ClusterAllFailedError.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/ScanStream.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/autoPipelining.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/Script.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/Commander.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/Pipeline.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/transaction.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/applyMixin.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/ClusterOptions.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/util.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/ClusterSubscriber.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/ConnectionPool.js","../../../node_modules/.pnpm/denque@2.1.0/node_modules/denque/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/DelayQueue.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/AbstractConnector.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/StandaloneConnector.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/SentinelConnector/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/errors/index.js","../../../node_modules/.pnpm/redis-parser@3.0.0/node_modules/redis-parser/lib/parser.js","../../../node_modules/.pnpm/redis-parser@3.0.0/node_modules/redis-parser/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/SubscriptionSet.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/DataHandler.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/redis/event_handler.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/redis/RedisOptions.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/Redis.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/index.js","../../../internal-packages/redis/src/index.ts","../../../node_modules/.pnpm/nanoid@5.1.16/node_modules/nanoid/url-alphabet/index.js","../../../node_modules/.pnpm/nanoid@5.1.16/node_modules/nanoid/index.js","../src/queue.ts","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/version.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/internal/semver.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/diag/ComponentLogger.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/diag/types.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/diag/internal/logLevelLogger.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/api/diag.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/context/context.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics/Metric.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/api/context.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/trace_flags.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/invalid-span-constants.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/NonRecordingSpan.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/context-utils.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/spancontext-utils.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/NoopTracer.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracer.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracerProvider.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/span_kind.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/status.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/context-api.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/api/metrics.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics-api.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/api/trace.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace-api.js","../../../internal-packages/tracing/src/index.ts","../../../node_modules/.pnpm/yocto-queue@1.1.1/node_modules/yocto-queue/index.js","../../../node_modules/.pnpm/p-limit@6.2.0/node_modules/p-limit/index.js","../src/worker.ts","../src/utils.ts","../src/fair-queue/concurrency.ts","../src/fair-queue/masterQueue.ts","../src/fair-queue/telemetry.ts","../src/fair-queue/tenantDispatch.ts","../src/fair-queue/visibility.ts","../src/fair-queue/workerQueue.ts","../src/fair-queue/keyProducer.ts","../src/fair-queue/retry.ts","../src/fair-queue/scheduler.ts","../src/fair-queue/schedulers/drr.ts","../src/fair-queue/schedulers/weighted.ts","../src/fair-queue/schedulers/roundRobin.ts","../src/fair-queue/index.ts","../src/mollifier/schemas.ts","../src/mollifier/buffer.ts","../src/mollifier/drainer.ts"],"sourcesContent":["","\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getKeyIndexes = exports.hasFlag = exports.exists = exports.list = void 0;\nconst commands_json_1 = __importDefault(require(\"./commands.json\"));\n/**\n * Redis command list\n *\n * All commands are lowercased.\n */\nexports.list = Object.keys(commands_json_1.default);\nconst flags = {};\nexports.list.forEach((commandName) => {\n flags[commandName] = commands_json_1.default[commandName].flags.reduce(function (flags, flag) {\n flags[flag] = true;\n return flags;\n }, {});\n});\n/**\n * Check if the command exists\n */\nfunction exists(commandName) {\n return Boolean(commands_json_1.default[commandName]);\n}\nexports.exists = exists;\n/**\n * Check if the command has the flag\n *\n * Some of possible flags: readonly, noscript, loading\n */\nfunction hasFlag(commandName, flag) {\n if (!flags[commandName]) {\n throw new Error(\"Unknown command \" + commandName);\n }\n return Boolean(flags[commandName][flag]);\n}\nexports.hasFlag = hasFlag;\n/**\n * Get indexes of keys in the command arguments\n *\n * @example\n * ```javascript\n * getKeyIndexes('set', ['key', 'value']) // [0]\n * getKeyIndexes('mget', ['key1', 'key2']) // [0, 1]\n * ```\n */\nfunction getKeyIndexes(commandName, args, options) {\n const command = commands_json_1.default[commandName];\n if (!command) {\n throw new Error(\"Unknown command \" + commandName);\n }\n if (!Array.isArray(args)) {\n throw new Error(\"Expect args to be an array\");\n }\n const keys = [];\n const parseExternalKey = Boolean(options && options.parseExternalKey);\n const takeDynamicKeys = (args, startIndex) => {\n const keys = [];\n const keyStop = Number(args[startIndex]);\n for (let i = 0; i < keyStop; i++) {\n keys.push(i + startIndex + 1);\n }\n return keys;\n };\n const takeKeyAfterToken = (args, startIndex, token) => {\n for (let i = startIndex; i < args.length - 1; i += 1) {\n if (String(args[i]).toLowerCase() === token.toLowerCase()) {\n return i + 1;\n }\n }\n return null;\n };\n switch (commandName) {\n case \"zunionstore\":\n case \"zinterstore\":\n case \"zdiffstore\":\n keys.push(0, ...takeDynamicKeys(args, 1));\n break;\n case \"eval\":\n case \"evalsha\":\n case \"eval_ro\":\n case \"evalsha_ro\":\n case \"fcall\":\n case \"fcall_ro\":\n case \"blmpop\":\n case \"bzmpop\":\n keys.push(...takeDynamicKeys(args, 1));\n break;\n case \"sintercard\":\n case \"lmpop\":\n case \"zunion\":\n case \"zinter\":\n case \"zmpop\":\n case \"zintercard\":\n case \"zdiff\": {\n keys.push(...takeDynamicKeys(args, 0));\n break;\n }\n case \"georadius\": {\n keys.push(0);\n const storeKey = takeKeyAfterToken(args, 5, \"STORE\");\n if (storeKey)\n keys.push(storeKey);\n const distKey = takeKeyAfterToken(args, 5, \"STOREDIST\");\n if (distKey)\n keys.push(distKey);\n break;\n }\n case \"georadiusbymember\": {\n keys.push(0);\n const storeKey = takeKeyAfterToken(args, 4, \"STORE\");\n if (storeKey)\n keys.push(storeKey);\n const distKey = takeKeyAfterToken(args, 4, \"STOREDIST\");\n if (distKey)\n keys.push(distKey);\n break;\n }\n case \"sort\":\n case \"sort_ro\":\n keys.push(0);\n for (let i = 1; i < args.length - 1; i++) {\n let arg = args[i];\n if (typeof arg !== \"string\") {\n continue;\n }\n const directive = arg.toUpperCase();\n if (directive === \"GET\") {\n i += 1;\n arg = args[i];\n if (arg !== \"#\") {\n if (parseExternalKey) {\n keys.push([i, getExternalKeyNameLength(arg)]);\n }\n else {\n keys.push(i);\n }\n }\n }\n else if (directive === \"BY\") {\n i += 1;\n if (parseExternalKey) {\n keys.push([i, getExternalKeyNameLength(args[i])]);\n }\n else {\n keys.push(i);\n }\n }\n else if (directive === \"STORE\") {\n i += 1;\n keys.push(i);\n }\n }\n break;\n case \"migrate\":\n if (args[2] === \"\") {\n for (let i = 5; i < args.length - 1; i++) {\n const arg = args[i];\n if (typeof arg === \"string\" && arg.toUpperCase() === \"KEYS\") {\n for (let j = i + 1; j < args.length; j++) {\n keys.push(j);\n }\n break;\n }\n }\n }\n else {\n keys.push(2);\n }\n break;\n case \"xreadgroup\":\n case \"xread\":\n // Keys are 1st half of the args after STREAMS argument.\n for (let i = commandName === \"xread\" ? 0 : 3; i < args.length - 1; i++) {\n if (String(args[i]).toUpperCase() === \"STREAMS\") {\n for (let j = i + 1; j <= i + (args.length - 1 - i) / 2; j++) {\n keys.push(j);\n }\n break;\n }\n }\n break;\n default:\n // Step has to be at least one in this case, otherwise the command does\n // not contain a key.\n if (command.step > 0) {\n const keyStart = command.keyStart - 1;\n const keyStop = command.keyStop > 0\n ? command.keyStop\n : args.length + command.keyStop + 1;\n for (let i = keyStart; i < keyStop; i += command.step) {\n keys.push(i);\n }\n }\n break;\n }\n return keys;\n}\nexports.getKeyIndexes = getKeyIndexes;\nfunction getExternalKeyNameLength(key) {\n if (typeof key !== \"string\") {\n key = String(key);\n }\n const hashPos = key.indexOf(\"->\");\n return hashPos === -1 ? key.length : hashPos;\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.tryCatch = exports.errorObj = void 0;\n//Try catch is not supported in optimizing\n//compiler, so it is isolated\nexports.errorObj = { e: {} };\nlet tryCatchTarget;\nfunction tryCatcher(err, val) {\n try {\n const target = tryCatchTarget;\n tryCatchTarget = null;\n return target.apply(this, arguments);\n }\n catch (e) {\n exports.errorObj.e = e;\n return exports.errorObj;\n }\n}\nfunction tryCatch(fn) {\n tryCatchTarget = fn;\n return tryCatcher;\n}\nexports.tryCatch = tryCatch;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst utils_1 = require(\"./utils\");\nfunction throwLater(e) {\n setTimeout(function () {\n throw e;\n }, 0);\n}\nfunction asCallback(promise, nodeback, options) {\n if (typeof nodeback === \"function\") {\n promise.then((val) => {\n let ret;\n if (options !== undefined &&\n Object(options).spread &&\n Array.isArray(val)) {\n ret = utils_1.tryCatch(nodeback).apply(undefined, [null].concat(val));\n }\n else {\n ret =\n val === undefined\n ? utils_1.tryCatch(nodeback)(null)\n : utils_1.tryCatch(nodeback)(null, val);\n }\n if (ret === utils_1.errorObj) {\n throwLater(ret.e);\n }\n }, (cause) => {\n if (!cause) {\n const newReason = new Error(cause + \"\");\n Object.assign(newReason, { cause });\n cause = newReason;\n }\n const ret = utils_1.tryCatch(nodeback)(cause);\n if (ret === utils_1.errorObj) {\n throwLater(ret.e);\n }\n });\n }\n return promise;\n}\nexports.default = asCallback;\n","'use strict'\n\nconst assert = require('assert')\nconst util = require('util')\n\n// RedisError\n\nfunction RedisError (message) {\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n Error.captureStackTrace(this, this.constructor)\n}\n\nutil.inherits(RedisError, Error)\n\nObject.defineProperty(RedisError.prototype, 'name', {\n value: 'RedisError',\n configurable: true,\n writable: true\n})\n\n// ParserError\n\nfunction ParserError (message, buffer, offset) {\n assert(buffer)\n assert.strictEqual(typeof offset, 'number')\n\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n\n const tmp = Error.stackTraceLimit\n Error.stackTraceLimit = 2\n Error.captureStackTrace(this, this.constructor)\n Error.stackTraceLimit = tmp\n this.offset = offset\n this.buffer = buffer\n}\n\nutil.inherits(ParserError, RedisError)\n\nObject.defineProperty(ParserError.prototype, 'name', {\n value: 'ParserError',\n configurable: true,\n writable: true\n})\n\n// ReplyError\n\nfunction ReplyError (message) {\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n const tmp = Error.stackTraceLimit\n Error.stackTraceLimit = 2\n Error.captureStackTrace(this, this.constructor)\n Error.stackTraceLimit = tmp\n}\n\nutil.inherits(ReplyError, RedisError)\n\nObject.defineProperty(ReplyError.prototype, 'name', {\n value: 'ReplyError',\n configurable: true,\n writable: true\n})\n\n// AbortError\n\nfunction AbortError (message) {\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n Error.captureStackTrace(this, this.constructor)\n}\n\nutil.inherits(AbortError, RedisError)\n\nObject.defineProperty(AbortError.prototype, 'name', {\n value: 'AbortError',\n configurable: true,\n writable: true\n})\n\n// InterruptError\n\nfunction InterruptError (message) {\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n Error.captureStackTrace(this, this.constructor)\n}\n\nutil.inherits(InterruptError, AbortError)\n\nObject.defineProperty(InterruptError.prototype, 'name', {\n value: 'InterruptError',\n configurable: true,\n writable: true\n})\n\nmodule.exports = {\n RedisError,\n ParserError,\n ReplyError,\n AbortError,\n InterruptError\n}\n","'use strict'\n\nconst assert = require('assert')\n\nclass RedisError extends Error {\n get name () {\n return this.constructor.name\n }\n}\n\nclass ParserError extends RedisError {\n constructor (message, buffer, offset) {\n assert(buffer)\n assert.strictEqual(typeof offset, 'number')\n\n const tmp = Error.stackTraceLimit\n Error.stackTraceLimit = 2\n super(message)\n Error.stackTraceLimit = tmp\n this.offset = offset\n this.buffer = buffer\n }\n\n get name () {\n return this.constructor.name\n }\n}\n\nclass ReplyError extends RedisError {\n constructor (message) {\n const tmp = Error.stackTraceLimit\n Error.stackTraceLimit = 2\n super(message)\n Error.stackTraceLimit = tmp\n }\n get name () {\n return this.constructor.name\n }\n}\n\nclass AbortError extends RedisError {\n get name () {\n return this.constructor.name\n }\n}\n\nclass InterruptError extends AbortError {\n get name () {\n return this.constructor.name\n }\n}\n\nmodule.exports = {\n RedisError,\n ParserError,\n ReplyError,\n AbortError,\n InterruptError\n}\n","'use strict'\n\nconst Errors = process.version.charCodeAt(1) < 55 && process.version.charCodeAt(2) === 46\n ? require('./lib/old') // Node.js < 7\n : require('./lib/modern')\n\nmodule.exports = Errors\n","/*\n * Copyright 2001-2010 Georges Menie (www.menie.org)\n * Copyright 2010 Salvatore Sanfilippo (adapted to Redis coding style)\n * Copyright 2015 Zihua Li (http://zihua.li) (ported to JavaScript)\n * Copyright 2016 Mike Diarmid (http://github.com/salakar) (re-write for performance, ~700% perf inc)\n * All rights reserved.\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * * Neither the name of the University of California, Berkeley nor the\n * names of its contributors may be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* CRC16 implementation according to CCITT standards.\n *\n * Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the\n * following parameters:\n *\n * Name : \"XMODEM\", also known as \"ZMODEM\", \"CRC-16/ACORN\"\n * Width : 16 bit\n * Poly : 1021 (That is actually x^16 + x^12 + x^5 + 1)\n * Initialization : 0000\n * Reflect Input byte : False\n * Reflect Output CRC : False\n * Xor constant to output CRC : 0000\n * Output for \"123456789\" : 31C3\n */\n\nvar lookup = [\n 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,\n 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,\n 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,\n 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,\n 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,\n 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,\n 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,\n 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,\n 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,\n 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,\n 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,\n 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,\n 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,\n 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,\n 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,\n 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,\n 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,\n 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,\n 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,\n 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,\n 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,\n 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,\n 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,\n 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,\n 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,\n 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,\n 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,\n 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,\n 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,\n 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,\n 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,\n 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0\n];\n\n/**\n * Convert a string to a UTF8 array - faster than via buffer\n * @param str\n * @returns {Array}\n */\nvar toUTF8Array = function toUTF8Array(str) {\n var char;\n var i = 0;\n var p = 0;\n var utf8 = [];\n var len = str.length;\n\n for (; i < len; i++) {\n char = str.charCodeAt(i);\n if (char < 128) {\n utf8[p++] = char;\n } else if (char < 2048) {\n utf8[p++] = (char >> 6) | 192;\n utf8[p++] = (char & 63) | 128;\n } else if (\n ((char & 0xFC00) === 0xD800) && (i + 1) < str.length &&\n ((str.charCodeAt(i + 1) & 0xFC00) === 0xDC00)) {\n char = 0x10000 + ((char & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);\n utf8[p++] = (char >> 18) | 240;\n utf8[p++] = ((char >> 12) & 63) | 128;\n utf8[p++] = ((char >> 6) & 63) | 128;\n utf8[p++] = (char & 63) | 128;\n } else {\n utf8[p++] = (char >> 12) | 224;\n utf8[p++] = ((char >> 6) & 63) | 128;\n utf8[p++] = (char & 63) | 128;\n }\n }\n\n return utf8;\n};\n\n/**\n * Convert a string into a redis slot hash.\n * @param str\n * @returns {number}\n */\nvar generate = module.exports = function generate(str) {\n var char;\n var i = 0;\n var start = -1;\n var result = 0;\n var resultHash = 0;\n var utf8 = typeof str === 'string' ? toUTF8Array(str) : str;\n var len = utf8.length;\n\n while (i < len) {\n char = utf8[i++];\n if (start === -1) {\n if (char === 0x7B) {\n start = i;\n }\n } else if (char !== 0x7D) {\n resultHash = lookup[(char ^ (resultHash >> 8)) & 0xFF] ^ (resultHash << 8);\n } else if (i - 1 !== start) {\n return resultHash & 0x3FFF;\n }\n\n result = lookup[(char ^ (result >> 8)) & 0xFF] ^ (result << 8);\n }\n\n return result & 0x3FFF;\n};\n\n/**\n * Convert an array of multiple strings into a redis slot hash.\n * Returns -1 if one of the keys is not for the same slot as the others\n * @param keys\n * @returns {number}\n */\nmodule.exports.generateMulti = function generateMulti(keys) {\n var i = 1;\n var len = keys.length;\n var base = generate(keys[0]);\n\n while (i < len) {\n if (generate(keys[i++]) !== base) return -1;\n }\n\n return base;\n};\n","/**\n * lodash (Custom Build) <https://lodash.com/>\n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors <https://jquery.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]';\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\n/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n // Safari 9 makes `arguments.length` enumerable in strict mode.\n var result = (isArray(value) || isArguments(value))\n ? baseTimes(value.length, String)\n : [];\n\n var length = result.length,\n skipIndexes = !!length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (key == 'length' || isIndex(key, length)))) {\n result.push(key);\n }\n }\n return result;\n}\n\n/**\n * Used by `_.defaults` to customize its `_.assignIn` use.\n *\n * @private\n * @param {*} objValue The destination value.\n * @param {*} srcValue The source value.\n * @param {string} key The key of the property to assign.\n * @param {Object} object The parent object of `objValue`.\n * @returns {*} Returns the value to assign.\n */\nfunction assignInDefaults(objValue, srcValue, key, object) {\n if (objValue === undefined ||\n (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n return srcValue;\n }\n return objValue;\n}\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n object[key] = value;\n }\n}\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n}\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = array;\n return apply(func, this, otherArgs);\n };\n}\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n assignValue(object, key, newValue === undefined ? source[key] : newValue);\n }\n return object;\n}\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n length = length == null ? MAX_SAFE_INTEGER : length;\n return !!length &&\n (typeof value == 'number' || reIsUint.test(value)) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\n/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\n/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nfunction isArguments(value) {\n // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&\n (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);\n}\n\n/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 8-9 which returns 'object' for typed array and other constructors.\n var tag = isObject(value) ? objectToString.call(value) : '';\n return tag == funcTag || tag == genTag;\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/**\n * This method is like `_.assignIn` except that it accepts `customizer`\n * which is invoked to produce the assigned values. If `customizer` returns\n * `undefined`, assignment is handled by the method instead. The `customizer`\n * is invoked with five arguments: (objValue, srcValue, key, object, source).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extendWith\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @see _.assignWith\n * @example\n *\n * function customizer(objValue, srcValue) {\n * return _.isUndefined(objValue) ? srcValue : objValue;\n * }\n *\n * var defaults = _.partialRight(_.assignInWith, customizer);\n *\n * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\nvar assignInWith = createAssigner(function(object, source, srcIndex, customizer) {\n copyObject(source, keysIn(source), object, customizer);\n});\n\n/**\n * Assigns own and inherited enumerable string keyed properties of source\n * objects to the destination object for all destination properties that\n * resolve to `undefined`. Source objects are applied from left to right.\n * Once a property is set, additional values of the same property are ignored.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaultsDeep\n * @example\n *\n * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\nvar defaults = baseRest(function(args) {\n args.push(undefined, assignInDefaults);\n return apply(assignInWith, undefined, args);\n});\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nmodule.exports = defaults;\n","/**\n * lodash (Custom Build) <https://lodash.com/>\n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors <https://jquery.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nfunction isArguments(value) {\n // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&\n (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);\n}\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 8-9 which returns 'object' for typed array and other constructors.\n var tag = isObject(value) ? objectToString.call(value) : '';\n return tag == funcTag || tag == genTag;\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\nmodule.exports = isArguments;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.isArguments = exports.defaults = exports.noop = void 0;\nconst defaults = require(\"lodash.defaults\");\nexports.defaults = defaults;\nconst isArguments = require(\"lodash.isarguments\");\nexports.isArguments = isArguments;\nfunction noop() { }\nexports.noop = noop;\n","/**\n * Helpers.\n */\n\nvar s = 1000;\nvar m = s * 60;\nvar h = m * 60;\nvar d = h * 24;\nvar w = d * 7;\nvar y = d * 365.25;\n\n/**\n * Parse or format the given `val`.\n *\n * Options:\n *\n * - `long` verbose formatting [false]\n *\n * @param {String|Number} val\n * @param {Object} [options]\n * @throws {Error} throw an error if val is not a non-empty string or a number\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function (val, options) {\n options = options || {};\n var type = typeof val;\n if (type === 'string' && val.length > 0) {\n return parse(val);\n } else if (type === 'number' && isFinite(val)) {\n return options.long ? fmtLong(val) : fmtShort(val);\n }\n throw new Error(\n 'val is not a non-empty string or a valid number. val=' +\n JSON.stringify(val)\n );\n};\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n str = String(str);\n if (str.length > 100) {\n return;\n }\n var match = /^(-?(?:\\d+)?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(\n str\n );\n if (!match) {\n return;\n }\n var n = parseFloat(match[1]);\n var type = (match[2] || 'ms').toLowerCase();\n switch (type) {\n case 'years':\n case 'year':\n case 'yrs':\n case 'yr':\n case 'y':\n return n * y;\n case 'weeks':\n case 'week':\n case 'w':\n return n * w;\n case 'days':\n case 'day':\n case 'd':\n return n * d;\n case 'hours':\n case 'hour':\n case 'hrs':\n case 'hr':\n case 'h':\n return n * h;\n case 'minutes':\n case 'minute':\n case 'mins':\n case 'min':\n case 'm':\n return n * m;\n case 'seconds':\n case 'second':\n case 'secs':\n case 'sec':\n case 's':\n return n * s;\n case 'milliseconds':\n case 'millisecond':\n case 'msecs':\n case 'msec':\n case 'ms':\n return n;\n default:\n return undefined;\n }\n}\n\n/**\n * Short format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtShort(ms) {\n var msAbs = Math.abs(ms);\n if (msAbs >= d) {\n return Math.round(ms / d) + 'd';\n }\n if (msAbs >= h) {\n return Math.round(ms / h) + 'h';\n }\n if (msAbs >= m) {\n return Math.round(ms / m) + 'm';\n }\n if (msAbs >= s) {\n return Math.round(ms / s) + 's';\n }\n return ms + 'ms';\n}\n\n/**\n * Long format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtLong(ms) {\n var msAbs = Math.abs(ms);\n if (msAbs >= d) {\n return plural(ms, msAbs, d, 'day');\n }\n if (msAbs >= h) {\n return plural(ms, msAbs, h, 'hour');\n }\n if (msAbs >= m) {\n return plural(ms, msAbs, m, 'minute');\n }\n if (msAbs >= s) {\n return plural(ms, msAbs, s, 'second');\n }\n return ms + ' ms';\n}\n\n/**\n * Pluralization helper.\n */\n\nfunction plural(ms, msAbs, n, name) {\n var isPlural = msAbs >= n * 1.5;\n return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\n}\n","\n/**\n * This is the common logic for both the Node.js and web browser\n * implementations of `debug()`.\n */\n\nfunction setup(env) {\n\tcreateDebug.debug = createDebug;\n\tcreateDebug.default = createDebug;\n\tcreateDebug.coerce = coerce;\n\tcreateDebug.disable = disable;\n\tcreateDebug.enable = enable;\n\tcreateDebug.enabled = enabled;\n\tcreateDebug.humanize = require('ms');\n\tcreateDebug.destroy = destroy;\n\n\tObject.keys(env).forEach(key => {\n\t\tcreateDebug[key] = env[key];\n\t});\n\n\t/**\n\t* The currently active debug mode names, and names to skip.\n\t*/\n\n\tcreateDebug.names = [];\n\tcreateDebug.skips = [];\n\n\t/**\n\t* Map of special \"%n\" handling functions, for the debug \"format\" argument.\n\t*\n\t* Valid key names are a single, lower or upper-case letter, i.e. \"n\" and \"N\".\n\t*/\n\tcreateDebug.formatters = {};\n\n\t/**\n\t* Selects a color for a debug namespace\n\t* @param {String} namespace The namespace string for the debug instance to be colored\n\t* @return {Number|String} An ANSI color code for the given namespace\n\t* @api private\n\t*/\n\tfunction selectColor(namespace) {\n\t\tlet hash = 0;\n\n\t\tfor (let i = 0; i < namespace.length; i++) {\n\t\t\thash = ((hash << 5) - hash) + namespace.charCodeAt(i);\n\t\t\thash |= 0; // Convert to 32bit integer\n\t\t}\n\n\t\treturn createDebug.colors[Math.abs(hash) % createDebug.colors.length];\n\t}\n\tcreateDebug.selectColor = selectColor;\n\n\t/**\n\t* Create a debugger with the given `namespace`.\n\t*\n\t* @param {String} namespace\n\t* @return {Function}\n\t* @api public\n\t*/\n\tfunction createDebug(namespace) {\n\t\tlet prevTime;\n\t\tlet enableOverride = null;\n\t\tlet namespacesCache;\n\t\tlet enabledCache;\n\n\t\tfunction debug(...args) {\n\t\t\t// Disabled?\n\t\t\tif (!debug.enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst self = debug;\n\n\t\t\t// Set `diff` timestamp\n\t\t\tconst curr = Number(new Date());\n\t\t\tconst ms = curr - (prevTime || curr);\n\t\t\tself.diff = ms;\n\t\t\tself.prev = prevTime;\n\t\t\tself.curr = curr;\n\t\t\tprevTime = curr;\n\n\t\t\targs[0] = createDebug.coerce(args[0]);\n\n\t\t\tif (typeof args[0] !== 'string') {\n\t\t\t\t// Anything else let's inspect with %O\n\t\t\t\targs.unshift('%O');\n\t\t\t}\n\n\t\t\t// Apply any `formatters` transformations\n\t\t\tlet index = 0;\n\t\t\targs[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {\n\t\t\t\t// If we encounter an escaped % then don't increase the array index\n\t\t\t\tif (match === '%%') {\n\t\t\t\t\treturn '%';\n\t\t\t\t}\n\t\t\t\tindex++;\n\t\t\t\tconst formatter = createDebug.formatters[format];\n\t\t\t\tif (typeof formatter === 'function') {\n\t\t\t\t\tconst val = args[index];\n\t\t\t\t\tmatch = formatter.call(self, val);\n\n\t\t\t\t\t// Now we need to remove `args[index]` since it's inlined in the `format`\n\t\t\t\t\targs.splice(index, 1);\n\t\t\t\t\tindex--;\n\t\t\t\t}\n\t\t\t\treturn match;\n\t\t\t});\n\n\t\t\t// Apply env-specific formatting (colors, etc.)\n\t\t\tcreateDebug.formatArgs.call(self, args);\n\n\t\t\tconst logFn = self.log || createDebug.log;\n\t\t\tlogFn.apply(self, args);\n\t\t}\n\n\t\tdebug.namespace = namespace;\n\t\tdebug.useColors = createDebug.useColors();\n\t\tdebug.color = createDebug.selectColor(namespace);\n\t\tdebug.extend = extend;\n\t\tdebug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.\n\n\t\tObject.defineProperty(debug, 'enabled', {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: false,\n\t\t\tget: () => {\n\t\t\t\tif (enableOverride !== null) {\n\t\t\t\t\treturn enableOverride;\n\t\t\t\t}\n\t\t\t\tif (namespacesCache !== createDebug.namespaces) {\n\t\t\t\t\tnamespacesCache = createDebug.namespaces;\n\t\t\t\t\tenabledCache = createDebug.enabled(namespace);\n\t\t\t\t}\n\n\t\t\t\treturn enabledCache;\n\t\t\t},\n\t\t\tset: v => {\n\t\t\t\tenableOverride = v;\n\t\t\t}\n\t\t});\n\n\t\t// Env-specific initialization logic for debug instances\n\t\tif (typeof createDebug.init === 'function') {\n\t\t\tcreateDebug.init(debug);\n\t\t}\n\n\t\treturn debug;\n\t}\n\n\tfunction extend(namespace, delimiter) {\n\t\tconst newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);\n\t\tnewDebug.log = this.log;\n\t\treturn newDebug;\n\t}\n\n\t/**\n\t* Enables a debug mode by namespaces. This can include modes\n\t* separated by a colon and wildcards.\n\t*\n\t* @param {String} namespaces\n\t* @api public\n\t*/\n\tfunction enable(namespaces) {\n\t\tcreateDebug.save(namespaces);\n\t\tcreateDebug.namespaces = namespaces;\n\n\t\tcreateDebug.names = [];\n\t\tcreateDebug.skips = [];\n\n\t\tconst split = (typeof namespaces === 'string' ? namespaces : '')\n\t\t\t.trim()\n\t\t\t.replace(/\\s+/g, ',')\n\t\t\t.split(',')\n\t\t\t.filter(Boolean);\n\n\t\tfor (const ns of split) {\n\t\t\tif (ns[0] === '-') {\n\t\t\t\tcreateDebug.skips.push(ns.slice(1));\n\t\t\t} else {\n\t\t\t\tcreateDebug.names.push(ns);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given string matches a namespace template, honoring\n\t * asterisks as wildcards.\n\t *\n\t * @param {String} search\n\t * @param {String} template\n\t * @return {Boolean}\n\t */\n\tfunction matchesTemplate(search, template) {\n\t\tlet searchIndex = 0;\n\t\tlet templateIndex = 0;\n\t\tlet starIndex = -1;\n\t\tlet matchIndex = 0;\n\n\t\twhile (searchIndex < search.length) {\n\t\t\tif (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {\n\t\t\t\t// Match character or proceed with wildcard\n\t\t\t\tif (template[templateIndex] === '*') {\n\t\t\t\t\tstarIndex = templateIndex;\n\t\t\t\t\tmatchIndex = searchIndex;\n\t\t\t\t\ttemplateIndex++; // Skip the '*'\n\t\t\t\t} else {\n\t\t\t\t\tsearchIndex++;\n\t\t\t\t\ttemplateIndex++;\n\t\t\t\t}\n\t\t\t} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition\n\t\t\t\t// Backtrack to the last '*' and try to match more characters\n\t\t\t\ttemplateIndex = starIndex + 1;\n\t\t\t\tmatchIndex++;\n\t\t\t\tsearchIndex = matchIndex;\n\t\t\t} else {\n\t\t\t\treturn false; // No match\n\t\t\t}\n\t\t}\n\n\t\t// Handle trailing '*' in template\n\t\twhile (templateIndex < template.length && template[templateIndex] === '*') {\n\t\t\ttemplateIndex++;\n\t\t}\n\n\t\treturn templateIndex === template.length;\n\t}\n\n\t/**\n\t* Disable debug output.\n\t*\n\t* @return {String} namespaces\n\t* @api public\n\t*/\n\tfunction disable() {\n\t\tconst namespaces = [\n\t\t\t...createDebug.names,\n\t\t\t...createDebug.skips.map(namespace => '-' + namespace)\n\t\t].join(',');\n\t\tcreateDebug.enable('');\n\t\treturn namespaces;\n\t}\n\n\t/**\n\t* Returns true if the given mode name is enabled, false otherwise.\n\t*\n\t* @param {String} name\n\t* @return {Boolean}\n\t* @api public\n\t*/\n\tfunction enabled(name) {\n\t\tfor (const skip of createDebug.skips) {\n\t\t\tif (matchesTemplate(name, skip)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfor (const ns of createDebug.names) {\n\t\t\tif (matchesTemplate(name, ns)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t* Coerce `val`.\n\t*\n\t* @param {Mixed} val\n\t* @return {Mixed}\n\t* @api private\n\t*/\n\tfunction coerce(val) {\n\t\tif (val instanceof Error) {\n\t\t\treturn val.stack || val.message;\n\t\t}\n\t\treturn val;\n\t}\n\n\t/**\n\t* XXX DO NOT USE. This is a temporary stub function.\n\t* XXX It WILL be removed in the next major release.\n\t*/\n\tfunction destroy() {\n\t\tconsole.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');\n\t}\n\n\tcreateDebug.enable(createDebug.load());\n\n\treturn createDebug;\n}\n\nmodule.exports = setup;\n","/* eslint-env browser */\n\n/**\n * This is the web browser implementation of `debug()`.\n */\n\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\nexports.storage = localstorage();\nexports.destroy = (() => {\n\tlet warned = false;\n\n\treturn () => {\n\t\tif (!warned) {\n\t\t\twarned = true;\n\t\t\tconsole.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');\n\t\t}\n\t};\n})();\n\n/**\n * Colors.\n */\n\nexports.colors = [\n\t'#0000CC',\n\t'#0000FF',\n\t'#0033CC',\n\t'#0033FF',\n\t'#0066CC',\n\t'#0066FF',\n\t'#0099CC',\n\t'#0099FF',\n\t'#00CC00',\n\t'#00CC33',\n\t'#00CC66',\n\t'#00CC99',\n\t'#00CCCC',\n\t'#00CCFF',\n\t'#3300CC',\n\t'#3300FF',\n\t'#3333CC',\n\t'#3333FF',\n\t'#3366CC',\n\t'#3366FF',\n\t'#3399CC',\n\t'#3399FF',\n\t'#33CC00',\n\t'#33CC33',\n\t'#33CC66',\n\t'#33CC99',\n\t'#33CCCC',\n\t'#33CCFF',\n\t'#6600CC',\n\t'#6600FF',\n\t'#6633CC',\n\t'#6633FF',\n\t'#66CC00',\n\t'#66CC33',\n\t'#9900CC',\n\t'#9900FF',\n\t'#9933CC',\n\t'#9933FF',\n\t'#99CC00',\n\t'#99CC33',\n\t'#CC0000',\n\t'#CC0033',\n\t'#CC0066',\n\t'#CC0099',\n\t'#CC00CC',\n\t'#CC00FF',\n\t'#CC3300',\n\t'#CC3333',\n\t'#CC3366',\n\t'#CC3399',\n\t'#CC33CC',\n\t'#CC33FF',\n\t'#CC6600',\n\t'#CC6633',\n\t'#CC9900',\n\t'#CC9933',\n\t'#CCCC00',\n\t'#CCCC33',\n\t'#FF0000',\n\t'#FF0033',\n\t'#FF0066',\n\t'#FF0099',\n\t'#FF00CC',\n\t'#FF00FF',\n\t'#FF3300',\n\t'#FF3333',\n\t'#FF3366',\n\t'#FF3399',\n\t'#FF33CC',\n\t'#FF33FF',\n\t'#FF6600',\n\t'#FF6633',\n\t'#FF9900',\n\t'#FF9933',\n\t'#FFCC00',\n\t'#FFCC33'\n];\n\n/**\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\n * and the Firebug extension (any Firefox version) are known\n * to support \"%c\" CSS customizations.\n *\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\n */\n\n// eslint-disable-next-line complexity\nfunction useColors() {\n\t// NB: In an Electron preload script, document will be defined but not fully\n\t// initialized. Since we know we're in Chrome, we'll just detect this case\n\t// explicitly\n\tif (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {\n\t\treturn true;\n\t}\n\n\t// Internet Explorer and Edge do not support colors.\n\tif (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\\/(\\d+)/)) {\n\t\treturn false;\n\t}\n\n\tlet m;\n\n\t// Is webkit? http://stackoverflow.com/a/16459606/376773\n\t// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\n\t// eslint-disable-next-line no-return-assign\n\treturn (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||\n\t\t// Is firebug? http://stackoverflow.com/a/398120/376773\n\t\t(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||\n\t\t// Is firefox >= v31?\n\t\t// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\n\t\t(typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/)) && parseInt(m[1], 10) >= 31) ||\n\t\t// Double check webkit in userAgent just in case we are in a worker\n\t\t(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\/(\\d+)/));\n}\n\n/**\n * Colorize log arguments if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n\targs[0] = (this.useColors ? '%c' : '') +\n\t\tthis.namespace +\n\t\t(this.useColors ? ' %c' : ' ') +\n\t\targs[0] +\n\t\t(this.useColors ? '%c ' : ' ') +\n\t\t'+' + module.exports.humanize(this.diff);\n\n\tif (!this.useColors) {\n\t\treturn;\n\t}\n\n\tconst c = 'color: ' + this.color;\n\targs.splice(1, 0, c, 'color: inherit');\n\n\t// The final \"%c\" is somewhat tricky, because there could be other\n\t// arguments passed either before or after the %c, so we need to\n\t// figure out the correct index to insert the CSS into\n\tlet index = 0;\n\tlet lastC = 0;\n\targs[0].replace(/%[a-zA-Z%]/g, match => {\n\t\tif (match === '%%') {\n\t\t\treturn;\n\t\t}\n\t\tindex++;\n\t\tif (match === '%c') {\n\t\t\t// We only are interested in the *last* %c\n\t\t\t// (the user may have provided their own)\n\t\t\tlastC = index;\n\t\t}\n\t});\n\n\targs.splice(lastC, 0, c);\n}\n\n/**\n * Invokes `console.debug()` when available.\n * No-op when `console.debug` is not a \"function\".\n * If `console.debug` is not available, falls back\n * to `console.log`.\n *\n * @api public\n */\nexports.log = console.debug || console.log || (() => {});\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\nfunction save(namespaces) {\n\ttry {\n\t\tif (namespaces) {\n\t\t\texports.storage.setItem('debug', namespaces);\n\t\t} else {\n\t\t\texports.storage.removeItem('debug');\n\t\t}\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\nfunction load() {\n\tlet r;\n\ttry {\n\t\tr = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n\n\t// If debug isn't set in LS, and we're in Electron, try to load $DEBUG\n\tif (!r && typeof process !== 'undefined' && 'env' in process) {\n\t\tr = process.env.DEBUG;\n\t}\n\n\treturn r;\n}\n\n/**\n * Localstorage attempts to return the localstorage.\n *\n * This is necessary because safari throws\n * when a user disables cookies/localstorage\n * and you attempt to access it.\n *\n * @return {LocalStorage}\n * @api private\n */\n\nfunction localstorage() {\n\ttry {\n\t\t// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\n\t\t// The Browser also has localStorage in the global context.\n\t\treturn localStorage;\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n}\n\nmodule.exports = require('./common')(exports);\n\nconst {formatters} = module.exports;\n\n/**\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\n */\n\nformatters.j = function (v) {\n\ttry {\n\t\treturn JSON.stringify(v);\n\t} catch (error) {\n\t\treturn '[UnexpectedJSONParseError]: ' + error.message;\n\t}\n};\n","import process from 'node:process';\nimport os from 'node:os';\nimport tty from 'node:tty';\n\n// From: https://github.com/sindresorhus/has-flag/blob/main/index.js\n/// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {\nfunction hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {\n\tconst prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');\n\tconst position = argv.indexOf(prefix + flag);\n\tconst terminatorPosition = argv.indexOf('--');\n\treturn position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);\n}\n\nconst {env} = process;\n\nlet flagForceColor;\nif (\n\thasFlag('no-color')\n\t|| hasFlag('no-colors')\n\t|| hasFlag('color=false')\n\t|| hasFlag('color=never')\n) {\n\tflagForceColor = 0;\n} else if (\n\thasFlag('color')\n\t|| hasFlag('colors')\n\t|| hasFlag('color=true')\n\t|| hasFlag('color=always')\n) {\n\tflagForceColor = 1;\n}\n\nfunction envForceColor() {\n\tif (!('FORCE_COLOR' in env)) {\n\t\treturn;\n\t}\n\n\tif (env.FORCE_COLOR === 'true') {\n\t\treturn 1;\n\t}\n\n\tif (env.FORCE_COLOR === 'false') {\n\t\treturn 0;\n\t}\n\n\tif (env.FORCE_COLOR.length === 0) {\n\t\treturn 1;\n\t}\n\n\tconst level = Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);\n\n\tif (![0, 1, 2, 3].includes(level)) {\n\t\treturn;\n\t}\n\n\treturn level;\n}\n\nfunction translateLevel(level) {\n\tif (level === 0) {\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tlevel,\n\t\thasBasic: true,\n\t\thas256: level >= 2,\n\t\thas16m: level >= 3,\n\t};\n}\n\nfunction _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {\n\tconst noFlagForceColor = envForceColor();\n\tif (noFlagForceColor !== undefined) {\n\t\tflagForceColor = noFlagForceColor;\n\t}\n\n\tconst forceColor = sniffFlags ? flagForceColor : noFlagForceColor;\n\n\tif (forceColor === 0) {\n\t\treturn 0;\n\t}\n\n\tif (sniffFlags) {\n\t\tif (hasFlag('color=16m')\n\t\t\t|| hasFlag('color=full')\n\t\t\t|| hasFlag('color=truecolor')) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (hasFlag('color=256')) {\n\t\t\treturn 2;\n\t\t}\n\t}\n\n\t// Check for Azure DevOps pipelines.\n\t// Has to be above the `!streamIsTTY` check.\n\tif ('TF_BUILD' in env && 'AGENT_NAME' in env) {\n\t\treturn 1;\n\t}\n\n\tif (haveStream && !streamIsTTY && forceColor === undefined) {\n\t\treturn 0;\n\t}\n\n\tconst min = forceColor || 0;\n\n\tif (env.TERM === 'dumb') {\n\t\treturn min;\n\t}\n\n\tif (process.platform === 'win32') {\n\t\t// Windows 10 build 10586 is the first Windows release that supports 256 colors.\n\t\t// Windows 10 build 14931 is the first release that supports 16m/TrueColor.\n\t\tconst osRelease = os.release().split('.');\n\t\tif (\n\t\t\tNumber(osRelease[0]) >= 10\n\t\t\t&& Number(osRelease[2]) >= 10_586\n\t\t) {\n\t\t\treturn Number(osRelease[2]) >= 14_931 ? 3 : 2;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\tif ('CI' in env) {\n\t\tif (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn min;\n\t}\n\n\tif ('TEAMCITY_VERSION' in env) {\n\t\treturn /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;\n\t}\n\n\tif (env.COLORTERM === 'truecolor') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-kitty') {\n\t\treturn 3;\n\t}\n\n\tif ('TERM_PROGRAM' in env) {\n\t\tconst version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);\n\n\t\tswitch (env.TERM_PROGRAM) {\n\t\t\tcase 'iTerm.app': {\n\t\t\t\treturn version >= 3 ? 3 : 2;\n\t\t\t}\n\n\t\t\tcase 'Apple_Terminal': {\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t}\n\n\tif (/-256(color)?$/i.test(env.TERM)) {\n\t\treturn 2;\n\t}\n\n\tif (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {\n\t\treturn 1;\n\t}\n\n\tif ('COLORTERM' in env) {\n\t\treturn 1;\n\t}\n\n\treturn min;\n}\n\nexport function createSupportsColor(stream, options = {}) {\n\tconst level = _supportsColor(stream, {\n\t\tstreamIsTTY: stream && stream.isTTY,\n\t\t...options,\n\t});\n\n\treturn translateLevel(level);\n}\n\nconst supportsColor = {\n\tstdout: createSupportsColor({isTTY: tty.isatty(1)}),\n\tstderr: createSupportsColor({isTTY: tty.isatty(2)}),\n};\n\nexport default supportsColor;\n","/**\n * Module dependencies.\n */\n\nconst tty = require('tty');\nconst util = require('util');\n\n/**\n * This is the Node.js implementation of `debug()`.\n */\n\nexports.init = init;\nexports.log = log;\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\nexports.destroy = util.deprecate(\n\t() => {},\n\t'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'\n);\n\n/**\n * Colors.\n */\n\nexports.colors = [6, 2, 3, 4, 5, 1];\n\ntry {\n\t// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)\n\t// eslint-disable-next-line import/no-extraneous-dependencies\n\tconst supportsColor = require('supports-color');\n\n\tif (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {\n\t\texports.colors = [\n\t\t\t20,\n\t\t\t21,\n\t\t\t26,\n\t\t\t27,\n\t\t\t32,\n\t\t\t33,\n\t\t\t38,\n\t\t\t39,\n\t\t\t40,\n\t\t\t41,\n\t\t\t42,\n\t\t\t43,\n\t\t\t44,\n\t\t\t45,\n\t\t\t56,\n\t\t\t57,\n\t\t\t62,\n\t\t\t63,\n\t\t\t68,\n\t\t\t69,\n\t\t\t74,\n\t\t\t75,\n\t\t\t76,\n\t\t\t77,\n\t\t\t78,\n\t\t\t79,\n\t\t\t80,\n\t\t\t81,\n\t\t\t92,\n\t\t\t93,\n\t\t\t98,\n\t\t\t99,\n\t\t\t112,\n\t\t\t113,\n\t\t\t128,\n\t\t\t129,\n\t\t\t134,\n\t\t\t135,\n\t\t\t148,\n\t\t\t149,\n\t\t\t160,\n\t\t\t161,\n\t\t\t162,\n\t\t\t163,\n\t\t\t164,\n\t\t\t165,\n\t\t\t166,\n\t\t\t167,\n\t\t\t168,\n\t\t\t169,\n\t\t\t170,\n\t\t\t171,\n\t\t\t172,\n\t\t\t173,\n\t\t\t178,\n\t\t\t179,\n\t\t\t184,\n\t\t\t185,\n\t\t\t196,\n\t\t\t197,\n\t\t\t198,\n\t\t\t199,\n\t\t\t200,\n\t\t\t201,\n\t\t\t202,\n\t\t\t203,\n\t\t\t204,\n\t\t\t205,\n\t\t\t206,\n\t\t\t207,\n\t\t\t208,\n\t\t\t209,\n\t\t\t214,\n\t\t\t215,\n\t\t\t220,\n\t\t\t221\n\t\t];\n\t}\n} catch (error) {\n\t// Swallow - we only care if `supports-color` is available; it doesn't have to be.\n}\n\n/**\n * Build up the default `inspectOpts` object from the environment variables.\n *\n * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js\n */\n\nexports.inspectOpts = Object.keys(process.env).filter(key => {\n\treturn /^debug_/i.test(key);\n}).reduce((obj, key) => {\n\t// Camel-case\n\tconst prop = key\n\t\t.substring(6)\n\t\t.toLowerCase()\n\t\t.replace(/_([a-z])/g, (_, k) => {\n\t\t\treturn k.toUpperCase();\n\t\t});\n\n\t// Coerce string value into JS value\n\tlet val = process.env[key];\n\tif (/^(yes|on|true|enabled)$/i.test(val)) {\n\t\tval = true;\n\t} else if (/^(no|off|false|disabled)$/i.test(val)) {\n\t\tval = false;\n\t} else if (val === 'null') {\n\t\tval = null;\n\t} else {\n\t\tval = Number(val);\n\t}\n\n\tobj[prop] = val;\n\treturn obj;\n}, {});\n\n/**\n * Is stdout a TTY? Colored output is enabled when `true`.\n */\n\nfunction useColors() {\n\treturn 'colors' in exports.inspectOpts ?\n\t\tBoolean(exports.inspectOpts.colors) :\n\t\ttty.isatty(process.stderr.fd);\n}\n\n/**\n * Adds ANSI color escape codes if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n\tconst {namespace: name, useColors} = this;\n\n\tif (useColors) {\n\t\tconst c = this.color;\n\t\tconst colorCode = '\\u001B[3' + (c < 8 ? c : '8;5;' + c);\n\t\tconst prefix = ` ${colorCode};1m${name} \\u001B[0m`;\n\n\t\targs[0] = prefix + args[0].split('\\n').join('\\n' + prefix);\n\t\targs.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\\u001B[0m');\n\t} else {\n\t\targs[0] = getDate() + name + ' ' + args[0];\n\t}\n}\n\nfunction getDate() {\n\tif (exports.inspectOpts.hideDate) {\n\t\treturn '';\n\t}\n\treturn new Date().toISOString() + ' ';\n}\n\n/**\n * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr.\n */\n\nfunction log(...args) {\n\treturn process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\\n');\n}\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\nfunction save(namespaces) {\n\tif (namespaces) {\n\t\tprocess.env.DEBUG = namespaces;\n\t} else {\n\t\t// If you set a process.env field to null or undefined, it gets cast to the\n\t\t// string 'null' or 'undefined'. Just delete instead.\n\t\tdelete process.env.DEBUG;\n\t}\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\n\nfunction load() {\n\treturn process.env.DEBUG;\n}\n\n/**\n * Init logic for `debug` instances.\n *\n * Create a new `inspectOpts` object in case `useColors` is set\n * differently for a particular `debug` instance.\n */\n\nfunction init(debug) {\n\tdebug.inspectOpts = {};\n\n\tconst keys = Object.keys(exports.inspectOpts);\n\tfor (let i = 0; i < keys.length; i++) {\n\t\tdebug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];\n\t}\n}\n\nmodule.exports = require('./common')(exports);\n\nconst {formatters} = module.exports;\n\n/**\n * Map %o to `util.inspect()`, all on a single line.\n */\n\nformatters.o = function (v) {\n\tthis.inspectOpts.colors = this.useColors;\n\treturn util.inspect(v, this.inspectOpts)\n\t\t.split('\\n')\n\t\t.map(str => str.trim())\n\t\t.join(' ');\n};\n\n/**\n * Map %O to `util.inspect()`, allowing multiple lines if needed.\n */\n\nformatters.O = function (v) {\n\tthis.inspectOpts.colors = this.useColors;\n\treturn util.inspect(v, this.inspectOpts);\n};\n","/**\n * Detect Electron renderer / nwjs process, which is node, but we should\n * treat as a browser.\n */\n\nif (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {\n\tmodule.exports = require('./browser.js');\n} else {\n\tmodule.exports = require('./node.js');\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.genRedactedString = exports.getStringValue = exports.MAX_ARGUMENT_LENGTH = void 0;\nconst debug_1 = require(\"debug\");\nconst MAX_ARGUMENT_LENGTH = 200;\nexports.MAX_ARGUMENT_LENGTH = MAX_ARGUMENT_LENGTH;\nconst NAMESPACE_PREFIX = \"ioredis\";\n/**\n * helper function that tried to get a string value for\n * arbitrary \"debug\" arg\n */\nfunction getStringValue(v) {\n if (v === null) {\n return;\n }\n switch (typeof v) {\n case \"boolean\":\n return;\n case \"number\":\n return;\n case \"object\":\n if (Buffer.isBuffer(v)) {\n return v.toString(\"hex\");\n }\n if (Array.isArray(v)) {\n return v.join(\",\");\n }\n try {\n return JSON.stringify(v);\n }\n catch (e) {\n return;\n }\n case \"string\":\n return v;\n }\n}\nexports.getStringValue = getStringValue;\n/**\n * helper function that redacts a string representation of a \"debug\" arg\n */\nfunction genRedactedString(str, maxLen) {\n const { length } = str;\n return length <= maxLen\n ? str\n : str.slice(0, maxLen) + ' ... <REDACTED full-length=\"' + length + '\">';\n}\nexports.genRedactedString = genRedactedString;\n/**\n * a wrapper for the `debug` module, used to generate\n * \"debug functions\" that trim the values in their output\n */\nfunction genDebugFunction(namespace) {\n const fn = (0, debug_1.default)(`${NAMESPACE_PREFIX}:${namespace}`);\n function wrappedDebug(...args) {\n if (!fn.enabled) {\n return; // no-op\n }\n // we skip the first arg because that is the message\n for (let i = 1; i < args.length; i++) {\n const str = getStringValue(args[i]);\n if (typeof str === \"string\" && str.length > MAX_ARGUMENT_LENGTH) {\n args[i] = genRedactedString(str, MAX_ARGUMENT_LENGTH);\n }\n }\n return fn.apply(null, args);\n }\n Object.defineProperties(wrappedDebug, {\n namespace: {\n get() {\n return fn.namespace;\n },\n },\n enabled: {\n get() {\n return fn.enabled;\n },\n },\n destroy: {\n get() {\n return fn.destroy;\n },\n },\n log: {\n get() {\n return fn.log;\n },\n set(l) {\n fn.log = l;\n },\n },\n });\n return wrappedDebug;\n}\nexports.default = genDebugFunction;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n/**\n * TLS settings for Redis Cloud. Updated on 2022-08-19.\n */\nconst RedisCloudCA = `-----BEGIN CERTIFICATE-----\nMIIDTzCCAjegAwIBAgIJAKSVpiDswLcwMA0GCSqGSIb3DQEBBQUAMD4xFjAUBgNV\nBAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTAeFw0xMzEwMDExMjE0NTVaFw0yMzA5MjkxMjE0NTVaMD4xFjAUBgNV\nBAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZqkh/DczWP\nJnxnHLQ7QL0T4B4CDKWBKCcisriGbA6ZePWVNo4hfKQC6JrzfR+081NeD6VcWUiz\nrmd+jtPhIY4c+WVQYm5PKaN6DT1imYdxQw7aqO5j2KUCEh/cznpLxeSHoTxlR34E\nQwF28Wl3eg2vc5ct8LjU3eozWVk3gb7alx9mSA2SgmuX5lEQawl++rSjsBStemY2\nBDwOpAMXIrdEyP/cVn8mkvi/BDs5M5G+09j0gfhyCzRWMQ7Hn71u1eolRxwVxgi3\nTMn+/vTaFSqxKjgck6zuAYjBRPaHe7qLxHNr1So/Mc9nPy+3wHebFwbIcnUojwbp\n4nctkWbjb2cCAwEAAaNQME4wHQYDVR0OBBYEFP1whtcrydmW3ZJeuSoKZIKjze3w\nMB8GA1UdIwQYMBaAFP1whtcrydmW3ZJeuSoKZIKjze3wMAwGA1UdEwQFMAMBAf8w\nDQYJKoZIhvcNAQEFBQADggEBAG2erXhwRAa7+ZOBs0B6X57Hwyd1R4kfmXcs0rta\nlbPpvgULSiB+TCbf3EbhJnHGyvdCY1tvlffLjdA7HJ0PCOn+YYLBA0pTU/dyvrN6\nSu8NuS5yubnt9mb13nDGYo1rnt0YRfxN+8DM3fXIVr038A30UlPX2Ou1ExFJT0MZ\nuFKY6ZvLdI6/1cbgmguMlAhM+DhKyV6Sr5699LM3zqeI816pZmlREETYkGr91q7k\nBpXJu/dtHaGxg1ZGu6w/PCsYGUcECWENYD4VQPd8N32JjOfu6vEgoEAwfPP+3oGp\nZ4m3ewACcWOAenqflb+cQYC4PsF7qbXDmRaWrbKntOlZ3n0=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIGMTCCBBmgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCVVMx\nCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJDQTESMBAGA1UECgwJUmVkaXNMYWJzMS0w\nKwYDVQQDDCRSZWRpc0xhYnMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN\nMTgwMjI1MTUzNzM3WhcNMjgwMjIzMTUzNzM3WjBfMQswCQYDVQQGEwJVUzELMAkG\nA1UECAwCQ0ExEjAQBgNVBAoMCVJlZGlzTGFiczEvMC0GA1UEAwwmUkNQIEludGVy\nbWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA\nA4ICDwAwggIKAoICAQDf9dqbxc8Bq7Ctq9rWcxrGNKKHivqLAFpPq02yLPx6fsOv\nTq7GsDChAYBBc4v7Y2Ap9RD5Vs3dIhEANcnolf27QwrG9RMnnvzk8pCvp1o6zSU4\nVuOE1W66/O1/7e2rVxyrnTcP7UgK43zNIXu7+tiAqWsO92uSnuMoGPGpeaUm1jym\nhjWKtkAwDFSqvHY+XL5qDVBEjeUe+WHkYUg40cAXjusAqgm2hZt29c2wnVrxW25W\nP0meNlzHGFdA2AC5z54iRiqj57dTfBTkHoBczQxcyw6hhzxZQ4e5I5zOKjXXEhZN\nr0tA3YC14CTabKRus/JmZieyZzRgEy2oti64tmLYTqSlAD78pRL40VNoaSYetXLw\nhhNsXCHgWaY6d5bLOc/aIQMAV5oLvZQKvuXAF1IDmhPA+bZbpWipp0zagf1P1H3s\nUzsMdn2KM0ejzgotbtNlj5TcrVwpmvE3ktvUAuA+hi3FkVx1US+2Gsp5x4YOzJ7u\nP1WPk6ShF0JgnJH2ILdj6kttTWwFzH17keSFICWDfH/+kM+k7Y1v3EXMQXE7y0T9\nMjvJskz6d/nv+sQhY04xt64xFMGTnZjlJMzfQNi7zWFLTZnDD0lPowq7l3YiPoTT\nt5Xky83lu0KZsZBo0WlWaDG00gLVdtRgVbcuSWxpi5BdLb1kRab66JptWjxwXQID\nAQABo4HrMIHoMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHBzOi8vcmwtY2Etc2VydmVy\nLnJlZGlzbGFicy5jb20vdjEvY3JsMEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcw\nAYYqaHR0cHM6Ly9ybC1jYS1zZXJ2ZXIucmVkaXNsYWJzLmNvbS92MS9vY3NwMB0G\nA1UdDgQWBBQHar5OKvQUpP2qWt6mckzToeCOHDAfBgNVHSMEGDAWgBQi42wH6hM4\nL2sujEvLM0/u8lRXTzASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIB\nhjANBgkqhkiG9w0BAQsFAAOCAgEAirEn/iTsAKyhd+pu2W3Z5NjCko4NPU0EYUbr\nAP7+POK2rzjIrJO3nFYQ/LLuC7KCXG+2qwan2SAOGmqWst13Y+WHp44Kae0kaChW\nvcYLXXSoGQGC8QuFSNUdaeg3RbMDYFT04dOkqufeWVccoHVxyTSg9eD8LZuHn5jw\n7QDLiEECBmIJHk5Eeo2TAZrx4Yx6ufSUX5HeVjlAzqwtAqdt99uCJ/EL8bgpWbe+\nXoSpvUv0SEC1I1dCAhCKAvRlIOA6VBcmzg5Am12KzkqTul12/VEFIgzqu0Zy2Jbc\nAUPrYVu/+tOGXQaijy7YgwH8P8n3s7ZeUa1VABJHcxrxYduDDJBLZi+MjheUDaZ1\njQRHYevI2tlqeSBqdPKG4zBY5lS0GiAlmuze5oENt0P3XboHoZPHiqcK3VECgTVh\n/BkJcuudETSJcZDmQ8YfoKfBzRQNg2sv/hwvUv73Ss51Sco8GEt2lD8uEdib1Q6z\nzDT5lXJowSzOD5ZA9OGDjnSRL+2riNtKWKEqvtEG3VBJoBzu9GoxbAc7wIZLxmli\niF5a/Zf5X+UXD3s4TMmy6C4QZJpAA2egsSQCnraWO2ULhh7iXMysSkF/nzVfZn43\niqpaB8++9a37hWq14ZmOv0TJIDz//b2+KC4VFXWQ5W5QC6whsjT+OlG4p5ZYG0jo\n616pxqo=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n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\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIEjzCCA3egAwIBAgIQe55B/ALCKJDZtdNT8kD6hTANBgkqhkiG9w0BAQsFADBM\nMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv\nYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMjAxMjYxMjAwMDBaFw0y\nNTAxMjYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu\nIG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIE9WIFRMUyBDQSAy\nMDIyIFEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmGmg1LW9b7Lf\n8zDD83yBDTEkt+FOxKJZqF4veWc5KZsQj9HfnUS2e5nj/E+JImlGPsQuoiosLuXD\nBVBNAMcUFa11buFMGMeEMwiTmCXoXRrXQmH0qjpOfKgYc5gHG3BsRGaRrf7VR4eg\nofNMG9wUBw4/g/TT7+bQJdA4NfE7Y4d5gEryZiBGB/swaX6Jp/8MF4TgUmOWmalK\ndZCKyb4sPGQFRTtElk67F7vU+wdGcrcOx1tDcIB0ncjLPMnaFicagl+daWGsKqTh\ncounQb6QJtYHa91KvCfKWocMxQ7OIbB5UARLPmC4CJ1/f8YFm35ebfzAeULYdGXu\njE9CLor0OwIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG\nCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW\nBBSH5Zq7a7B/t95GfJWkDBpA8HHqdjAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj\nmove4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw\nMi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1\ncmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w\nK6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwIQYD\nVR0gBBowGDAIBgZngQwBAgIwDAYKKwYBBAGgMgoBAjANBgkqhkiG9w0BAQsFAAOC\nAQEAKRic9/f+nmhQU/wz04APZLjgG5OgsuUOyUEZjKVhNGDwxGTvKhyXGGAMW2B/\n3bRi+aElpXwoxu3pL6fkElbX3B0BeS5LoDtxkyiVEBMZ8m+sXbocwlPyxrPbX6mY\n0rVIvnuUeBH8X0L5IwfpNVvKnBIilTbcebfHyXkPezGwz7E1yhUULjJFm2bt0SdX\ny+4X/WeiiYIv+fTVgZZgl+/2MKIsu/qdBJc3f3TvJ8nz+Eax1zgZmww+RSQWeOj3\n15Iw6Z5FX+NwzY/Ab+9PosR5UosSeq+9HhtaxZttXG1nVh+avYPGYddWmiMT90J5\nZgKnO/Fx2hBgTxhOTMYaD312kg==\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\nA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\nZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\nMTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\nA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\nRgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\ngHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\nKPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\nQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\nXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\nDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\nLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\nRUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\njjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\n6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\nmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\nMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\nWD9f\n-----END CERTIFICATE-----`;\nconst TLSProfiles = {\n RedisCloudFixed: { ca: RedisCloudCA },\n RedisCloudFlexible: { ca: RedisCloudCA },\n};\nexports.default = TLSProfiles;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.noop = exports.defaults = exports.Debug = exports.zipMap = exports.CONNECTION_CLOSED_ERROR_MSG = exports.shuffle = exports.sample = exports.resolveTLSProfile = exports.parseURL = exports.optimizeErrorStack = exports.toArg = exports.convertMapToArray = exports.convertObjectToArray = exports.timeout = exports.packObject = exports.isInt = exports.wrapMultiResult = exports.convertBufferToString = void 0;\nconst url_1 = require(\"url\");\nconst lodash_1 = require(\"./lodash\");\nObject.defineProperty(exports, \"defaults\", { enumerable: true, get: function () { return lodash_1.defaults; } });\nObject.defineProperty(exports, \"noop\", { enumerable: true, get: function () { return lodash_1.noop; } });\nconst debug_1 = require(\"./debug\");\nexports.Debug = debug_1.default;\nconst TLSProfiles_1 = require(\"../constants/TLSProfiles\");\n/**\n * Convert a buffer to string, supports buffer array\n *\n * @example\n * ```js\n * const input = [Buffer.from('foo'), [Buffer.from('bar')]]\n * const res = convertBufferToString(input, 'utf8')\n * expect(res).to.eql(['foo', ['bar']])\n * ```\n */\nfunction convertBufferToString(value, encoding) {\n if (value instanceof Buffer) {\n return value.toString(encoding);\n }\n if (Array.isArray(value)) {\n const length = value.length;\n const res = Array(length);\n for (let i = 0; i < length; ++i) {\n res[i] =\n value[i] instanceof Buffer && encoding === \"utf8\"\n ? value[i].toString()\n : convertBufferToString(value[i], encoding);\n }\n return res;\n }\n return value;\n}\nexports.convertBufferToString = convertBufferToString;\n/**\n * Convert a list of results to node-style\n *\n * @example\n * ```js\n * const input = ['a', 'b', new Error('c'), 'd']\n * const output = exports.wrapMultiResult(input)\n * expect(output).to.eql([[null, 'a'], [null, 'b'], [new Error('c')], [null, 'd'])\n * ```\n */\nfunction wrapMultiResult(arr) {\n // When using WATCH/EXEC transactions, the EXEC will return\n // a null instead of an array\n if (!arr) {\n return null;\n }\n const result = [];\n const length = arr.length;\n for (let i = 0; i < length; ++i) {\n const item = arr[i];\n if (item instanceof Error) {\n result.push([item]);\n }\n else {\n result.push([null, item]);\n }\n }\n return result;\n}\nexports.wrapMultiResult = wrapMultiResult;\n/**\n * Detect if the argument is a int\n * @example\n * ```js\n * > isInt('123')\n * true\n * > isInt('123.3')\n * false\n * > isInt('1x')\n * false\n * > isInt(123)\n * true\n * > isInt(true)\n * false\n * ```\n */\nfunction isInt(value) {\n const x = parseFloat(value);\n return !isNaN(value) && (x | 0) === x;\n}\nexports.isInt = isInt;\n/**\n * Pack an array to an Object\n *\n * @example\n * ```js\n * > packObject(['a', 'b', 'c', 'd'])\n * { a: 'b', c: 'd' }\n * ```\n */\nfunction packObject(array) {\n const result = {};\n const length = array.length;\n for (let i = 1; i < length; i += 2) {\n result[array[i - 1]] = array[i];\n }\n return result;\n}\nexports.packObject = packObject;\n/**\n * Return a callback with timeout\n */\nfunction timeout(callback, timeout) {\n let timer = null;\n const run = function () {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n callback.apply(this, arguments);\n }\n };\n timer = setTimeout(run, timeout, new Error(\"timeout\"));\n return run;\n}\nexports.timeout = timeout;\n/**\n * Convert an object to an array\n * @example\n * ```js\n * > convertObjectToArray({ a: '1' })\n * ['a', '1']\n * ```\n */\nfunction convertObjectToArray(obj) {\n const result = [];\n const keys = Object.keys(obj); // Object.entries requires node 7+\n for (let i = 0, l = keys.length; i < l; i++) {\n result.push(keys[i], obj[keys[i]]);\n }\n return result;\n}\nexports.convertObjectToArray = convertObjectToArray;\n/**\n * Convert a map to an array\n * @example\n * ```js\n * > convertMapToArray(new Map([[1, '2']]))\n * [1, '2']\n * ```\n */\nfunction convertMapToArray(map) {\n const result = [];\n let pos = 0;\n map.forEach(function (value, key) {\n result[pos] = key;\n result[pos + 1] = value;\n pos += 2;\n });\n return result;\n}\nexports.convertMapToArray = convertMapToArray;\n/**\n * Convert a non-string arg to a string\n */\nfunction toArg(arg) {\n if (arg === null || typeof arg === \"undefined\") {\n return \"\";\n }\n return String(arg);\n}\nexports.toArg = toArg;\n/**\n * Optimize error stack\n *\n * @param error actually error\n * @param friendlyStack the stack that more meaningful\n * @param filterPath only show stacks with the specified path\n */\nfunction optimizeErrorStack(error, friendlyStack, filterPath) {\n const stacks = friendlyStack.split(\"\\n\");\n let lines = \"\";\n let i;\n for (i = 1; i < stacks.length; ++i) {\n if (stacks[i].indexOf(filterPath) === -1) {\n break;\n }\n }\n for (let j = i; j < stacks.length; ++j) {\n lines += \"\\n\" + stacks[j];\n }\n if (error.stack) {\n const pos = error.stack.indexOf(\"\\n\");\n error.stack = error.stack.slice(0, pos) + lines;\n }\n return error;\n}\nexports.optimizeErrorStack = optimizeErrorStack;\n/**\n * Parse the redis protocol url\n */\nfunction parseURL(url) {\n if (isInt(url)) {\n return { port: url };\n }\n let parsed = (0, url_1.parse)(url, true, true);\n if (!parsed.slashes && url[0] !== \"/\") {\n url = \"//\" + url;\n parsed = (0, url_1.parse)(url, true, true);\n }\n const options = parsed.query || {};\n const result = {};\n if (parsed.auth) {\n const index = parsed.auth.indexOf(\":\");\n result.username = index === -1 ? parsed.auth : parsed.auth.slice(0, index);\n result.password = index === -1 ? \"\" : parsed.auth.slice(index + 1);\n }\n if (parsed.pathname) {\n if (parsed.protocol === \"redis:\" || parsed.protocol === \"rediss:\") {\n if (parsed.pathname.length > 1) {\n result.db = parsed.pathname.slice(1);\n }\n }\n else {\n result.path = parsed.pathname;\n }\n }\n if (parsed.host) {\n result.host = parsed.hostname;\n }\n if (parsed.port) {\n result.port = parsed.port;\n }\n if (typeof options.family === \"string\") {\n const intFamily = Number.parseInt(options.family, 10);\n if (!Number.isNaN(intFamily)) {\n result.family = intFamily;\n }\n }\n (0, lodash_1.defaults)(result, options);\n return result;\n}\nexports.parseURL = parseURL;\n/**\n * Resolve TLS profile shortcut in connection options\n */\nfunction resolveTLSProfile(options) {\n let tls = options === null || options === void 0 ? void 0 : options.tls;\n if (typeof tls === \"string\")\n tls = { profile: tls };\n const profile = TLSProfiles_1.default[tls === null || tls === void 0 ? void 0 : tls.profile];\n if (profile) {\n tls = Object.assign({}, profile, tls);\n delete tls.profile;\n options = Object.assign({}, options, { tls });\n }\n return options;\n}\nexports.resolveTLSProfile = resolveTLSProfile;\n/**\n * Get a random element from `array`\n */\nfunction sample(array, from = 0) {\n const length = array.length;\n if (from >= length) {\n return null;\n }\n return array[from + Math.floor(Math.random() * (length - from))];\n}\nexports.sample = sample;\n/**\n * Shuffle the array using the Fisher-Yates Shuffle.\n * This method will mutate the original array.\n */\nfunction shuffle(array) {\n let counter = array.length;\n // While there are elements in the array\n while (counter > 0) {\n // Pick a random index\n const index = Math.floor(Math.random() * counter);\n // Decrease counter by 1\n counter--;\n // And swap the last element with it\n [array[counter], array[index]] = [array[index], array[counter]];\n }\n return array;\n}\nexports.shuffle = shuffle;\n/**\n * Error message for connection being disconnected\n */\nexports.CONNECTION_CLOSED_ERROR_MSG = \"Connection is closed.\";\nfunction zipMap(keys, values) {\n const map = new Map();\n keys.forEach((key, index) => {\n map.set(key, values[index]);\n });\n return map;\n}\nexports.zipMap = zipMap;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst commands_1 = require(\"@ioredis/commands\");\nconst calculateSlot = require(\"cluster-key-slot\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst utils_1 = require(\"./utils\");\n/**\n * Command instance\n *\n * It's rare that you need to create a Command instance yourself.\n *\n * ```js\n * var infoCommand = new Command('info', null, function (err, result) {\n * console.log('result', result);\n * });\n *\n * redis.sendCommand(infoCommand);\n *\n * // When no callback provided, Command instance will have a `promise` property,\n * // which will resolve/reject with the result of the command.\n * var getCommand = new Command('get', ['foo']);\n * getCommand.promise.then(function (result) {\n * console.log('result', result);\n * });\n * ```\n */\nclass Command {\n /**\n * Creates an instance of Command.\n * @param name Command name\n * @param args An array of command arguments\n * @param options\n * @param callback The callback that handles the response.\n * If omit, the response will be handled via Promise\n */\n constructor(name, args = [], options = {}, callback) {\n this.name = name;\n this.inTransaction = false;\n this.isResolved = false;\n this.transformed = false;\n this.replyEncoding = options.replyEncoding;\n this.errorStack = options.errorStack;\n this.args = args.flat();\n this.callback = callback;\n this.initPromise();\n if (options.keyPrefix) {\n // @ts-expect-error\n const isBufferKeyPrefix = options.keyPrefix instanceof Buffer;\n // @ts-expect-error\n let keyPrefixBuffer = isBufferKeyPrefix\n ? options.keyPrefix\n : null;\n this._iterateKeys((key) => {\n if (key instanceof Buffer) {\n if (keyPrefixBuffer === null) {\n keyPrefixBuffer = Buffer.from(options.keyPrefix);\n }\n return Buffer.concat([keyPrefixBuffer, key]);\n }\n else if (isBufferKeyPrefix) {\n // @ts-expect-error\n return Buffer.concat([options.keyPrefix, Buffer.from(String(key))]);\n }\n return options.keyPrefix + key;\n });\n }\n if (options.readOnly) {\n this.isReadOnly = true;\n }\n }\n /**\n * Check whether the command has the flag\n */\n static checkFlag(flagName, commandName) {\n return !!this.getFlagMap()[flagName][commandName];\n }\n static setArgumentTransformer(name, func) {\n this._transformer.argument[name] = func;\n }\n static setReplyTransformer(name, func) {\n this._transformer.reply[name] = func;\n }\n static getFlagMap() {\n if (!this.flagMap) {\n this.flagMap = Object.keys(Command.FLAGS).reduce((map, flagName) => {\n map[flagName] = {};\n Command.FLAGS[flagName].forEach((commandName) => {\n map[flagName][commandName] = true;\n });\n return map;\n }, {});\n }\n return this.flagMap;\n }\n getSlot() {\n if (typeof this.slot === \"undefined\") {\n const key = this.getKeys()[0];\n this.slot = key == null ? null : calculateSlot(key);\n }\n return this.slot;\n }\n getKeys() {\n return this._iterateKeys();\n }\n /**\n * Convert command to writable buffer or string\n */\n toWritable(_socket) {\n let result;\n const commandStr = \"*\" +\n (this.args.length + 1) +\n \"\\r\\n$\" +\n Buffer.byteLength(this.name) +\n \"\\r\\n\" +\n this.name +\n \"\\r\\n\";\n if (this.bufferMode) {\n const buffers = new MixedBuffers();\n buffers.push(commandStr);\n for (let i = 0; i < this.args.length; ++i) {\n const arg = this.args[i];\n if (arg instanceof Buffer) {\n if (arg.length === 0) {\n buffers.push(\"$0\\r\\n\\r\\n\");\n }\n else {\n buffers.push(\"$\" + arg.length + \"\\r\\n\");\n buffers.push(arg);\n buffers.push(\"\\r\\n\");\n }\n }\n else {\n buffers.push(\"$\" +\n Buffer.byteLength(arg) +\n \"\\r\\n\" +\n arg +\n \"\\r\\n\");\n }\n }\n result = buffers.toBuffer();\n }\n else {\n result = commandStr;\n for (let i = 0; i < this.args.length; ++i) {\n const arg = this.args[i];\n result +=\n \"$\" +\n Buffer.byteLength(arg) +\n \"\\r\\n\" +\n arg +\n \"\\r\\n\";\n }\n }\n return result;\n }\n stringifyArguments() {\n for (let i = 0; i < this.args.length; ++i) {\n const arg = this.args[i];\n if (typeof arg === \"string\") {\n // buffers and strings don't need any transformation\n }\n else if (arg instanceof Buffer) {\n this.bufferMode = true;\n }\n else {\n this.args[i] = (0, utils_1.toArg)(arg);\n }\n }\n }\n /**\n * Convert buffer/buffer[] to string/string[],\n * and apply reply transformer.\n */\n transformReply(result) {\n if (this.replyEncoding) {\n result = (0, utils_1.convertBufferToString)(result, this.replyEncoding);\n }\n const transformer = Command._transformer.reply[this.name];\n if (transformer) {\n result = transformer(result);\n }\n return result;\n }\n /**\n * Set the wait time before terminating the attempt to execute a command\n * and generating an error.\n */\n setTimeout(ms) {\n if (!this._commandTimeoutTimer) {\n this._commandTimeoutTimer = setTimeout(() => {\n if (!this.isResolved) {\n this.reject(new Error(\"Command timed out\"));\n }\n }, ms);\n }\n }\n initPromise() {\n const promise = new Promise((resolve, reject) => {\n if (!this.transformed) {\n this.transformed = true;\n const transformer = Command._transformer.argument[this.name];\n if (transformer) {\n this.args = transformer(this.args);\n }\n this.stringifyArguments();\n }\n this.resolve = this._convertValue(resolve);\n if (this.errorStack) {\n this.reject = (err) => {\n reject((0, utils_1.optimizeErrorStack)(err, this.errorStack.stack, __dirname));\n };\n }\n else {\n this.reject = reject;\n }\n });\n this.promise = (0, standard_as_callback_1.default)(promise, this.callback);\n }\n /**\n * Iterate through the command arguments that are considered keys.\n */\n _iterateKeys(transform = (key) => key) {\n if (typeof this.keys === \"undefined\") {\n this.keys = [];\n if ((0, commands_1.exists)(this.name)) {\n // @ts-expect-error\n const keyIndexes = (0, commands_1.getKeyIndexes)(this.name, this.args);\n for (const index of keyIndexes) {\n this.args[index] = transform(this.args[index]);\n this.keys.push(this.args[index]);\n }\n }\n }\n return this.keys;\n }\n /**\n * Convert the value from buffer to the target encoding.\n */\n _convertValue(resolve) {\n return (value) => {\n try {\n const existingTimer = this._commandTimeoutTimer;\n if (existingTimer) {\n clearTimeout(existingTimer);\n delete this._commandTimeoutTimer;\n }\n resolve(this.transformReply(value));\n this.isResolved = true;\n }\n catch (err) {\n this.reject(err);\n }\n return this.promise;\n };\n }\n}\nexports.default = Command;\nCommand.FLAGS = {\n VALID_IN_SUBSCRIBER_MODE: [\n \"subscribe\",\n \"psubscribe\",\n \"unsubscribe\",\n \"punsubscribe\",\n \"ssubscribe\",\n \"sunsubscribe\",\n \"ping\",\n \"quit\",\n ],\n VALID_IN_MONITOR_MODE: [\"monitor\", \"auth\"],\n ENTER_SUBSCRIBER_MODE: [\"subscribe\", \"psubscribe\", \"ssubscribe\"],\n EXIT_SUBSCRIBER_MODE: [\"unsubscribe\", \"punsubscribe\", \"sunsubscribe\"],\n WILL_DISCONNECT: [\"quit\"],\n};\nCommand._transformer = {\n argument: {},\n reply: {},\n};\nconst msetArgumentTransformer = function (args) {\n if (args.length === 1) {\n if (args[0] instanceof Map) {\n return (0, utils_1.convertMapToArray)(args[0]);\n }\n if (typeof args[0] === \"object\" && args[0] !== null) {\n return (0, utils_1.convertObjectToArray)(args[0]);\n }\n }\n return args;\n};\nconst hsetArgumentTransformer = function (args) {\n if (args.length === 2) {\n if (args[1] instanceof Map) {\n return [args[0]].concat((0, utils_1.convertMapToArray)(args[1]));\n }\n if (typeof args[1] === \"object\" && args[1] !== null) {\n return [args[0]].concat((0, utils_1.convertObjectToArray)(args[1]));\n }\n }\n return args;\n};\nCommand.setArgumentTransformer(\"mset\", msetArgumentTransformer);\nCommand.setArgumentTransformer(\"msetnx\", msetArgumentTransformer);\nCommand.setArgumentTransformer(\"hset\", hsetArgumentTransformer);\nCommand.setArgumentTransformer(\"hmset\", hsetArgumentTransformer);\nCommand.setReplyTransformer(\"hgetall\", function (result) {\n if (Array.isArray(result)) {\n const obj = {};\n for (let i = 0; i < result.length; i += 2) {\n const key = result[i];\n const value = result[i + 1];\n if (key in obj) {\n // can only be truthy if the property is special somehow, like '__proto__' or 'constructor'\n // https://github.com/luin/ioredis/issues/1267\n Object.defineProperty(obj, key, {\n value,\n configurable: true,\n enumerable: true,\n writable: true,\n });\n }\n else {\n obj[key] = value;\n }\n }\n return obj;\n }\n return result;\n});\nclass MixedBuffers {\n constructor() {\n this.length = 0;\n this.items = [];\n }\n push(x) {\n this.length += Buffer.byteLength(x);\n this.items.push(x);\n }\n toBuffer() {\n const result = Buffer.allocUnsafe(this.length);\n let offset = 0;\n for (const item of this.items) {\n const length = Buffer.byteLength(item);\n Buffer.isBuffer(item)\n ? item.copy(result, offset)\n : result.write(item, offset, length);\n offset += length;\n }\n return result;\n }\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst redis_errors_1 = require(\"redis-errors\");\nclass ClusterAllFailedError extends redis_errors_1.RedisError {\n constructor(message, lastNodeError) {\n super(message);\n this.lastNodeError = lastNodeError;\n Error.captureStackTrace(this, this.constructor);\n }\n get name() {\n return this.constructor.name;\n }\n}\nexports.default = ClusterAllFailedError;\nClusterAllFailedError.defaultMessage = \"Failed to refresh slots cache.\";\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst stream_1 = require(\"stream\");\n/**\n * Convenient class to convert the process of scanning keys to a readable stream.\n */\nclass ScanStream extends stream_1.Readable {\n constructor(opt) {\n super(opt);\n this.opt = opt;\n this._redisCursor = \"0\";\n this._redisDrained = false;\n }\n _read() {\n if (this._redisDrained) {\n this.push(null);\n return;\n }\n const args = [this._redisCursor];\n if (this.opt.key) {\n args.unshift(this.opt.key);\n }\n if (this.opt.match) {\n args.push(\"MATCH\", this.opt.match);\n }\n if (this.opt.type) {\n args.push(\"TYPE\", this.opt.type);\n }\n if (this.opt.count) {\n args.push(\"COUNT\", String(this.opt.count));\n }\n if (this.opt.noValues) {\n args.push(\"NOVALUES\");\n }\n this.opt.redis[this.opt.command](args, (err, res) => {\n if (err) {\n this.emit(\"error\", err);\n return;\n }\n this._redisCursor = res[0] instanceof Buffer ? res[0].toString() : res[0];\n if (this._redisCursor === \"0\") {\n this._redisDrained = true;\n }\n this.push(res[1]);\n });\n }\n close() {\n this._redisDrained = true;\n }\n}\nexports.default = ScanStream;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.executeWithAutoPipelining = exports.getFirstValueInFlattenedArray = exports.shouldUseAutoPipelining = exports.notAllowedAutoPipelineCommands = exports.kCallbacks = exports.kExec = void 0;\nconst lodash_1 = require(\"./utils/lodash\");\nconst calculateSlot = require(\"cluster-key-slot\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nexports.kExec = Symbol(\"exec\");\nexports.kCallbacks = Symbol(\"callbacks\");\nexports.notAllowedAutoPipelineCommands = [\n \"auth\",\n \"info\",\n \"script\",\n \"quit\",\n \"cluster\",\n \"pipeline\",\n \"multi\",\n \"subscribe\",\n \"psubscribe\",\n \"unsubscribe\",\n \"unpsubscribe\",\n \"select\",\n];\nfunction executeAutoPipeline(client, slotKey) {\n /*\n If a pipeline is already executing, keep queueing up commands\n since ioredis won't serve two pipelines at the same time\n */\n if (client._runningAutoPipelines.has(slotKey)) {\n return;\n }\n if (!client._autoPipelines.has(slotKey)) {\n /*\n Rare edge case. Somehow, something has deleted this running autopipeline in an immediate\n call to executeAutoPipeline.\n \n Maybe the callback in the pipeline.exec is sometimes called in the same tick,\n e.g. if redis is disconnected?\n */\n return;\n }\n client._runningAutoPipelines.add(slotKey);\n // Get the pipeline and immediately delete it so that new commands are queued on a new pipeline\n const pipeline = client._autoPipelines.get(slotKey);\n client._autoPipelines.delete(slotKey);\n const callbacks = pipeline[exports.kCallbacks];\n // Stop keeping a reference to callbacks immediately after the callbacks stop being used.\n // This allows the GC to reclaim objects referenced by callbacks, especially with 16384 slots\n // in Redis.Cluster\n pipeline[exports.kCallbacks] = null;\n // Perform the call\n pipeline.exec(function (err, results) {\n client._runningAutoPipelines.delete(slotKey);\n /*\n Invoke all callback in nextTick so the stack is cleared\n and callbacks can throw errors without affecting other callbacks.\n */\n if (err) {\n for (let i = 0; i < callbacks.length; i++) {\n process.nextTick(callbacks[i], err);\n }\n }\n else {\n for (let i = 0; i < callbacks.length; i++) {\n process.nextTick(callbacks[i], ...results[i]);\n }\n }\n // If there is another pipeline on the same node, immediately execute it without waiting for nextTick\n if (client._autoPipelines.has(slotKey)) {\n executeAutoPipeline(client, slotKey);\n }\n });\n}\nfunction shouldUseAutoPipelining(client, functionName, commandName) {\n return (functionName &&\n client.options.enableAutoPipelining &&\n !client.isPipeline &&\n !exports.notAllowedAutoPipelineCommands.includes(commandName) &&\n !client.options.autoPipeliningIgnoredCommands.includes(commandName));\n}\nexports.shouldUseAutoPipelining = shouldUseAutoPipelining;\nfunction getFirstValueInFlattenedArray(args) {\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (typeof arg === \"string\") {\n return arg;\n }\n else if (Array.isArray(arg) || (0, lodash_1.isArguments)(arg)) {\n if (arg.length === 0) {\n continue;\n }\n return arg[0];\n }\n const flattened = [arg].flat();\n if (flattened.length > 0) {\n return flattened[0];\n }\n }\n return undefined;\n}\nexports.getFirstValueInFlattenedArray = getFirstValueInFlattenedArray;\nfunction executeWithAutoPipelining(client, functionName, commandName, args, callback) {\n // On cluster mode let's wait for slots to be available\n if (client.isCluster && !client.slots.length) {\n if (client.status === \"wait\")\n client.connect().catch(lodash_1.noop);\n return (0, standard_as_callback_1.default)(new Promise(function (resolve, reject) {\n client.delayUntilReady((err) => {\n if (err) {\n reject(err);\n return;\n }\n executeWithAutoPipelining(client, functionName, commandName, args, null).then(resolve, reject);\n });\n }), callback);\n }\n // If we have slot information, we can improve routing by grouping slots served by the same subset of nodes\n // Note that the first value in args may be a (possibly empty) array.\n // ioredis will only flatten one level of the array, in the Command constructor.\n const prefix = client.options.keyPrefix || \"\";\n const slotKey = client.isCluster\n ? client.slots[calculateSlot(`${prefix}${getFirstValueInFlattenedArray(args)}`)].join(\",\")\n : \"main\";\n if (!client._autoPipelines.has(slotKey)) {\n const pipeline = client.pipeline();\n pipeline[exports.kExec] = false;\n pipeline[exports.kCallbacks] = [];\n client._autoPipelines.set(slotKey, pipeline);\n }\n const pipeline = client._autoPipelines.get(slotKey);\n /*\n Mark the pipeline as scheduled.\n The symbol will make sure that the pipeline is only scheduled once per tick.\n New commands are appended to an already scheduled pipeline.\n */\n if (!pipeline[exports.kExec]) {\n pipeline[exports.kExec] = true;\n /*\n Deferring with setImmediate so we have a chance to capture multiple\n commands that can be scheduled by I/O events already in the event loop queue.\n */\n setImmediate(executeAutoPipeline, client, slotKey);\n }\n // Create the promise which will execute the command in the pipeline.\n const autoPipelinePromise = new Promise(function (resolve, reject) {\n pipeline[exports.kCallbacks].push(function (err, value) {\n if (err) {\n reject(err);\n return;\n }\n resolve(value);\n });\n if (functionName === \"call\") {\n args.unshift(commandName);\n }\n pipeline[functionName](...args);\n });\n return (0, standard_as_callback_1.default)(autoPipelinePromise, callback);\n}\nexports.executeWithAutoPipelining = executeWithAutoPipelining;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst crypto_1 = require(\"crypto\");\nconst Command_1 = require(\"./Command\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nclass Script {\n constructor(lua, numberOfKeys = null, keyPrefix = \"\", readOnly = false) {\n this.lua = lua;\n this.numberOfKeys = numberOfKeys;\n this.keyPrefix = keyPrefix;\n this.readOnly = readOnly;\n this.sha = (0, crypto_1.createHash)(\"sha1\").update(lua).digest(\"hex\");\n const sha = this.sha;\n const socketHasScriptLoaded = new WeakSet();\n this.Command = class CustomScriptCommand extends Command_1.default {\n toWritable(socket) {\n const origReject = this.reject;\n this.reject = (err) => {\n if (err.message.indexOf(\"NOSCRIPT\") !== -1) {\n socketHasScriptLoaded.delete(socket);\n }\n origReject.call(this, err);\n };\n if (!socketHasScriptLoaded.has(socket)) {\n socketHasScriptLoaded.add(socket);\n this.name = \"eval\";\n this.args[0] = lua;\n }\n else if (this.name === \"eval\") {\n this.name = \"evalsha\";\n this.args[0] = sha;\n }\n return super.toWritable(socket);\n }\n };\n }\n execute(container, args, options, callback) {\n if (typeof this.numberOfKeys === \"number\") {\n args.unshift(this.numberOfKeys);\n }\n if (this.keyPrefix) {\n options.keyPrefix = this.keyPrefix;\n }\n if (this.readOnly) {\n options.readOnly = true;\n }\n const evalsha = new this.Command(\"evalsha\", [this.sha, ...args], options);\n evalsha.promise = evalsha.promise.catch((err) => {\n if (err.message.indexOf(\"NOSCRIPT\") === -1) {\n throw err;\n }\n // Resend the same custom evalsha command that gets transformed\n // to an eval in case it's not loaded yet on the connection.\n const resend = new this.Command(\"evalsha\", [this.sha, ...args], options);\n const client = container.isPipeline ? container.redis : container;\n return client.sendCommand(resend);\n });\n (0, standard_as_callback_1.default)(evalsha.promise, callback);\n return container.sendCommand(evalsha);\n }\n}\nexports.default = Script;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst commands_1 = require(\"@ioredis/commands\");\nconst autoPipelining_1 = require(\"../autoPipelining\");\nconst Command_1 = require(\"../Command\");\nconst Script_1 = require(\"../Script\");\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nclass Commander {\n constructor() {\n this.options = {};\n /**\n * @ignore\n */\n this.scriptsSet = {};\n /**\n * @ignore\n */\n this.addedBuiltinSet = new Set();\n }\n /**\n * Return supported builtin commands\n */\n getBuiltinCommands() {\n return commands.slice(0);\n }\n /**\n * Create a builtin command\n */\n createBuiltinCommand(commandName) {\n return {\n string: generateFunction(null, commandName, \"utf8\"),\n buffer: generateFunction(null, commandName, null),\n };\n }\n /**\n * Create add builtin command\n */\n addBuiltinCommand(commandName) {\n this.addedBuiltinSet.add(commandName);\n this[commandName] = generateFunction(commandName, commandName, \"utf8\");\n this[commandName + \"Buffer\"] = generateFunction(commandName + \"Buffer\", commandName, null);\n }\n /**\n * Define a custom command using lua script\n */\n defineCommand(name, definition) {\n const script = new Script_1.default(definition.lua, definition.numberOfKeys, this.options.keyPrefix, definition.readOnly);\n this.scriptsSet[name] = script;\n this[name] = generateScriptingFunction(name, name, script, \"utf8\");\n this[name + \"Buffer\"] = generateScriptingFunction(name + \"Buffer\", name, script, null);\n }\n /**\n * @ignore\n */\n sendCommand(command, stream, node) {\n throw new Error('\"sendCommand\" is not implemented');\n }\n}\nconst commands = commands_1.list.filter((command) => command !== \"monitor\");\ncommands.push(\"sentinel\");\ncommands.forEach(function (commandName) {\n Commander.prototype[commandName] = generateFunction(commandName, commandName, \"utf8\");\n Commander.prototype[commandName + \"Buffer\"] = generateFunction(commandName + \"Buffer\", commandName, null);\n});\nCommander.prototype.call = generateFunction(\"call\", \"utf8\");\nCommander.prototype.callBuffer = generateFunction(\"callBuffer\", null);\n// @ts-expect-error\nCommander.prototype.send_command = Commander.prototype.call;\nfunction generateFunction(functionName, _commandName, _encoding) {\n if (typeof _encoding === \"undefined\") {\n _encoding = _commandName;\n _commandName = null;\n }\n return function (...args) {\n const commandName = (_commandName || args.shift());\n let callback = args[args.length - 1];\n if (typeof callback === \"function\") {\n args.pop();\n }\n else {\n callback = undefined;\n }\n const options = {\n errorStack: this.options.showFriendlyErrorStack ? new Error() : undefined,\n keyPrefix: this.options.keyPrefix,\n replyEncoding: _encoding,\n };\n // No auto pipeline, use regular command sending\n if (!(0, autoPipelining_1.shouldUseAutoPipelining)(this, functionName, commandName)) {\n return this.sendCommand(\n // @ts-expect-error\n new Command_1.default(commandName, args, options, callback));\n }\n // Create a new pipeline and make sure it's scheduled\n return (0, autoPipelining_1.executeWithAutoPipelining)(this, functionName, commandName, \n // @ts-expect-error\n args, callback);\n };\n}\nfunction generateScriptingFunction(functionName, commandName, script, encoding) {\n return function (...args) {\n const callback = typeof args[args.length - 1] === \"function\" ? args.pop() : undefined;\n const options = {\n replyEncoding: encoding,\n };\n if (this.options.showFriendlyErrorStack) {\n options.errorStack = new Error();\n }\n // No auto pipeline, use regular command sending\n if (!(0, autoPipelining_1.shouldUseAutoPipelining)(this, functionName, commandName)) {\n return script.execute(this, args, options, callback);\n }\n // Create a new pipeline and make sure it's scheduled\n return (0, autoPipelining_1.executeWithAutoPipelining)(this, functionName, commandName, args, callback);\n };\n}\nexports.default = Commander;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst calculateSlot = require(\"cluster-key-slot\");\nconst commands_1 = require(\"@ioredis/commands\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst util_1 = require(\"util\");\nconst Command_1 = require(\"./Command\");\nconst utils_1 = require(\"./utils\");\nconst Commander_1 = require(\"./utils/Commander\");\n/*\n This function derives from the cluster-key-slot implementation.\n Instead of checking that all keys have the same slot, it checks that all slots are served by the same set of nodes.\n If this is satisfied, it returns the first key's slot.\n*/\nfunction generateMultiWithNodes(redis, keys) {\n const slot = calculateSlot(keys[0]);\n const target = redis._groupsBySlot[slot];\n for (let i = 1; i < keys.length; i++) {\n if (redis._groupsBySlot[calculateSlot(keys[i])] !== target) {\n return -1;\n }\n }\n return slot;\n}\nclass Pipeline extends Commander_1.default {\n constructor(redis) {\n super();\n this.redis = redis;\n this.isPipeline = true;\n this.replyPending = 0;\n this._queue = [];\n this._result = [];\n this._transactions = 0;\n this._shaToScript = {};\n this.isCluster =\n this.redis.constructor.name === \"Cluster\" || this.redis.isCluster;\n this.options = redis.options;\n Object.keys(redis.scriptsSet).forEach((name) => {\n const script = redis.scriptsSet[name];\n this._shaToScript[script.sha] = script;\n this[name] = redis[name];\n this[name + \"Buffer\"] = redis[name + \"Buffer\"];\n });\n redis.addedBuiltinSet.forEach((name) => {\n this[name] = redis[name];\n this[name + \"Buffer\"] = redis[name + \"Buffer\"];\n });\n this.promise = new Promise((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n const _this = this;\n Object.defineProperty(this, \"length\", {\n get: function () {\n return _this._queue.length;\n },\n });\n }\n fillResult(value, position) {\n if (this._queue[position].name === \"exec\" && Array.isArray(value[1])) {\n const execLength = value[1].length;\n for (let i = 0; i < execLength; i++) {\n if (value[1][i] instanceof Error) {\n continue;\n }\n const cmd = this._queue[position - (execLength - i)];\n try {\n value[1][i] = cmd.transformReply(value[1][i]);\n }\n catch (err) {\n value[1][i] = err;\n }\n }\n }\n this._result[position] = value;\n if (--this.replyPending) {\n return;\n }\n if (this.isCluster) {\n let retriable = true;\n let commonError;\n for (let i = 0; i < this._result.length; ++i) {\n const error = this._result[i][0];\n const command = this._queue[i];\n if (error) {\n if (command.name === \"exec\" &&\n error.message ===\n \"EXECABORT Transaction discarded because of previous errors.\") {\n continue;\n }\n if (!commonError) {\n commonError = {\n name: error.name,\n message: error.message,\n };\n }\n else if (commonError.name !== error.name ||\n commonError.message !== error.message) {\n retriable = false;\n break;\n }\n }\n else if (!command.inTransaction) {\n const isReadOnly = (0, commands_1.exists)(command.name) && (0, commands_1.hasFlag)(command.name, \"readonly\");\n if (!isReadOnly) {\n retriable = false;\n break;\n }\n }\n }\n if (commonError && retriable) {\n const _this = this;\n const errv = commonError.message.split(\" \");\n const queue = this._queue;\n let inTransaction = false;\n this._queue = [];\n for (let i = 0; i < queue.length; ++i) {\n if (errv[0] === \"ASK\" &&\n !inTransaction &&\n queue[i].name !== \"asking\" &&\n (!queue[i - 1] || queue[i - 1].name !== \"asking\")) {\n const asking = new Command_1.default(\"asking\");\n asking.ignore = true;\n this.sendCommand(asking);\n }\n queue[i].initPromise();\n this.sendCommand(queue[i]);\n inTransaction = queue[i].inTransaction;\n }\n let matched = true;\n if (typeof this.leftRedirections === \"undefined\") {\n this.leftRedirections = {};\n }\n const exec = function () {\n _this.exec();\n };\n const cluster = this.redis;\n cluster.handleError(commonError, this.leftRedirections, {\n moved: function (_slot, key) {\n _this.preferKey = key;\n cluster.slots[errv[1]] = [key];\n cluster._groupsBySlot[errv[1]] =\n cluster._groupsIds[cluster.slots[errv[1]].join(\";\")];\n cluster.refreshSlotsCache();\n _this.exec();\n },\n ask: function (_slot, key) {\n _this.preferKey = key;\n _this.exec();\n },\n tryagain: exec,\n clusterDown: exec,\n connectionClosed: exec,\n maxRedirections: () => {\n matched = false;\n },\n defaults: () => {\n matched = false;\n },\n });\n if (matched) {\n return;\n }\n }\n }\n let ignoredCount = 0;\n for (let i = 0; i < this._queue.length - ignoredCount; ++i) {\n if (this._queue[i + ignoredCount].ignore) {\n ignoredCount += 1;\n }\n this._result[i] = this._result[i + ignoredCount];\n }\n this.resolve(this._result.slice(0, this._result.length - ignoredCount));\n }\n sendCommand(command) {\n if (this._transactions > 0) {\n command.inTransaction = true;\n }\n const position = this._queue.length;\n command.pipelineIndex = position;\n command.promise\n .then((result) => {\n this.fillResult([null, result], position);\n })\n .catch((error) => {\n this.fillResult([error], position);\n });\n this._queue.push(command);\n return this;\n }\n addBatch(commands) {\n let command, commandName, args;\n for (let i = 0; i < commands.length; ++i) {\n command = commands[i];\n commandName = command[0];\n args = command.slice(1);\n this[commandName].apply(this, args);\n }\n return this;\n }\n}\nexports.default = Pipeline;\n// @ts-expect-error\nconst multi = Pipeline.prototype.multi;\n// @ts-expect-error\nPipeline.prototype.multi = function () {\n this._transactions += 1;\n return multi.apply(this, arguments);\n};\n// @ts-expect-error\nconst execBuffer = Pipeline.prototype.execBuffer;\n// @ts-expect-error\nPipeline.prototype.execBuffer = (0, util_1.deprecate)(function () {\n if (this._transactions > 0) {\n this._transactions -= 1;\n }\n return execBuffer.apply(this, arguments);\n}, \"Pipeline#execBuffer: Use Pipeline#exec instead\");\n// NOTE: To avoid an unhandled promise rejection, this will unconditionally always return this.promise,\n// which always has the rejection handled by standard-as-callback\n// adding the provided rejection callback.\n//\n// If a different promise instance were returned, that promise would cause its own unhandled promise rejection\n// errors, even if that promise unconditionally resolved to **the resolved value of** this.promise.\nPipeline.prototype.exec = function (callback) {\n // Wait for the cluster to be connected, since we need nodes information before continuing\n if (this.isCluster && !this.redis.slots.length) {\n if (this.redis.status === \"wait\")\n this.redis.connect().catch(utils_1.noop);\n if (callback && !this.nodeifiedPromise) {\n this.nodeifiedPromise = true;\n (0, standard_as_callback_1.default)(this.promise, callback);\n }\n this.redis.delayUntilReady((err) => {\n if (err) {\n this.reject(err);\n return;\n }\n this.exec(callback);\n });\n return this.promise;\n }\n if (this._transactions > 0) {\n this._transactions -= 1;\n return execBuffer.apply(this, arguments);\n }\n if (!this.nodeifiedPromise) {\n this.nodeifiedPromise = true;\n (0, standard_as_callback_1.default)(this.promise, callback);\n }\n if (!this._queue.length) {\n this.resolve([]);\n }\n let pipelineSlot;\n if (this.isCluster) {\n // List of the first key for each command\n const sampleKeys = [];\n for (let i = 0; i < this._queue.length; i++) {\n const keys = this._queue[i].getKeys();\n if (keys.length) {\n sampleKeys.push(keys[0]);\n }\n // For each command, check that the keys belong to the same slot\n if (keys.length && calculateSlot.generateMulti(keys) < 0) {\n this.reject(new Error(\"All the keys in a pipeline command should belong to the same slot\"));\n return this.promise;\n }\n }\n if (sampleKeys.length) {\n pipelineSlot = generateMultiWithNodes(this.redis, sampleKeys);\n if (pipelineSlot < 0) {\n this.reject(new Error(\"All keys in the pipeline should belong to the same slots allocation group\"));\n return this.promise;\n }\n }\n else {\n // Send the pipeline to a random node\n pipelineSlot = (Math.random() * 16384) | 0;\n }\n }\n const _this = this;\n execPipeline();\n return this.promise;\n function execPipeline() {\n let writePending = (_this.replyPending = _this._queue.length);\n let node;\n if (_this.isCluster) {\n node = {\n slot: pipelineSlot,\n redis: _this.redis.connectionPool.nodes.all[_this.preferKey],\n };\n }\n let data = \"\";\n let buffers;\n const stream = {\n isPipeline: true,\n destination: _this.isCluster ? node : { redis: _this.redis },\n write(writable) {\n if (typeof writable !== \"string\") {\n if (!buffers) {\n buffers = [];\n }\n if (data) {\n buffers.push(Buffer.from(data, \"utf8\"));\n data = \"\";\n }\n buffers.push(writable);\n }\n else {\n data += writable;\n }\n if (!--writePending) {\n if (buffers) {\n if (data) {\n buffers.push(Buffer.from(data, \"utf8\"));\n }\n stream.destination.redis.stream.write(Buffer.concat(buffers));\n }\n else {\n stream.destination.redis.stream.write(data);\n }\n // Reset writePending for resending\n writePending = _this._queue.length;\n data = \"\";\n buffers = undefined;\n }\n },\n };\n for (let i = 0; i < _this._queue.length; ++i) {\n _this.redis.sendCommand(_this._queue[i], stream, node);\n }\n return _this.promise;\n }\n};\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.addTransactionSupport = void 0;\nconst utils_1 = require(\"./utils\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst Pipeline_1 = require(\"./Pipeline\");\nfunction addTransactionSupport(redis) {\n redis.pipeline = function (commands) {\n const pipeline = new Pipeline_1.default(this);\n if (Array.isArray(commands)) {\n pipeline.addBatch(commands);\n }\n return pipeline;\n };\n const { multi } = redis;\n redis.multi = function (commands, options) {\n if (typeof options === \"undefined\" && !Array.isArray(commands)) {\n options = commands;\n commands = null;\n }\n if (options && options.pipeline === false) {\n return multi.call(this);\n }\n const pipeline = new Pipeline_1.default(this);\n // @ts-expect-error\n pipeline.multi();\n if (Array.isArray(commands)) {\n pipeline.addBatch(commands);\n }\n const exec = pipeline.exec;\n pipeline.exec = function (callback) {\n // Wait for the cluster to be connected, since we need nodes information before continuing\n if (this.isCluster && !this.redis.slots.length) {\n if (this.redis.status === \"wait\")\n this.redis.connect().catch(utils_1.noop);\n return (0, standard_as_callback_1.default)(new Promise((resolve, reject) => {\n this.redis.delayUntilReady((err) => {\n if (err) {\n reject(err);\n return;\n }\n this.exec(pipeline).then(resolve, reject);\n });\n }), callback);\n }\n if (this._transactions > 0) {\n exec.call(pipeline);\n }\n // Returns directly when the pipeline\n // has been called multiple times (retries).\n if (this.nodeifiedPromise) {\n return exec.call(pipeline);\n }\n const promise = exec.call(pipeline);\n return (0, standard_as_callback_1.default)(promise.then(function (result) {\n const execResult = result[result.length - 1];\n if (typeof execResult === \"undefined\") {\n throw new Error(\"Pipeline cannot be used to send any commands when the `exec()` has been called on it.\");\n }\n if (execResult[0]) {\n execResult[0].previousErrors = [];\n for (let i = 0; i < result.length - 1; ++i) {\n if (result[i][0]) {\n execResult[0].previousErrors.push(result[i][0]);\n }\n }\n throw execResult[0];\n }\n return (0, utils_1.wrapMultiResult)(execResult[1]);\n }), callback);\n };\n // @ts-expect-error\n const { execBuffer } = pipeline;\n // @ts-expect-error\n pipeline.execBuffer = function (callback) {\n if (this._transactions > 0) {\n execBuffer.call(pipeline);\n }\n return pipeline.exec(callback);\n };\n return pipeline;\n };\n const { exec } = redis;\n redis.exec = function (callback) {\n return (0, standard_as_callback_1.default)(exec.call(this).then(function (results) {\n if (Array.isArray(results)) {\n results = (0, utils_1.wrapMultiResult)(results);\n }\n return results;\n }), callback);\n };\n}\nexports.addTransactionSupport = addTransactionSupport;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction applyMixin(derivedConstructor, mixinConstructor) {\n Object.getOwnPropertyNames(mixinConstructor.prototype).forEach((name) => {\n Object.defineProperty(derivedConstructor.prototype, name, Object.getOwnPropertyDescriptor(mixinConstructor.prototype, name));\n });\n}\nexports.default = applyMixin;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.DEFAULT_CLUSTER_OPTIONS = void 0;\nconst dns_1 = require(\"dns\");\nexports.DEFAULT_CLUSTER_OPTIONS = {\n clusterRetryStrategy: (times) => Math.min(100 + times * 2, 2000),\n enableOfflineQueue: true,\n enableReadyCheck: true,\n scaleReads: \"master\",\n maxRedirections: 16,\n retryDelayOnMoved: 0,\n retryDelayOnFailover: 100,\n retryDelayOnClusterDown: 100,\n retryDelayOnTryAgain: 100,\n slotsRefreshTimeout: 1000,\n useSRVRecords: false,\n resolveSrv: dns_1.resolveSrv,\n dnsLookup: dns_1.lookup,\n enableAutoPipelining: false,\n autoPipeliningIgnoredCommands: [],\n shardedSubscribers: false,\n};\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getConnectionName = exports.weightSrvRecords = exports.groupSrvRecords = exports.getUniqueHostnamesFromOptions = exports.normalizeNodeOptions = exports.nodeKeyToRedisOptions = exports.getNodeKey = void 0;\nconst utils_1 = require(\"../utils\");\nconst net_1 = require(\"net\");\nfunction getNodeKey(node) {\n node.port = node.port || 6379;\n node.host = node.host || \"127.0.0.1\";\n return node.host + \":\" + node.port;\n}\nexports.getNodeKey = getNodeKey;\nfunction nodeKeyToRedisOptions(nodeKey) {\n const portIndex = nodeKey.lastIndexOf(\":\");\n if (portIndex === -1) {\n throw new Error(`Invalid node key ${nodeKey}`);\n }\n return {\n host: nodeKey.slice(0, portIndex),\n port: Number(nodeKey.slice(portIndex + 1)),\n };\n}\nexports.nodeKeyToRedisOptions = nodeKeyToRedisOptions;\nfunction normalizeNodeOptions(nodes) {\n return nodes.map((node) => {\n const options = {};\n if (typeof node === \"object\") {\n Object.assign(options, node);\n }\n else if (typeof node === \"string\") {\n Object.assign(options, (0, utils_1.parseURL)(node));\n }\n else if (typeof node === \"number\") {\n options.port = node;\n }\n else {\n throw new Error(\"Invalid argument \" + node);\n }\n if (typeof options.port === \"string\") {\n options.port = parseInt(options.port, 10);\n }\n // Cluster mode only support db 0\n delete options.db;\n if (!options.port) {\n options.port = 6379;\n }\n if (!options.host) {\n options.host = \"127.0.0.1\";\n }\n return (0, utils_1.resolveTLSProfile)(options);\n });\n}\nexports.normalizeNodeOptions = normalizeNodeOptions;\nfunction getUniqueHostnamesFromOptions(nodes) {\n const uniqueHostsMap = {};\n nodes.forEach((node) => {\n uniqueHostsMap[node.host] = true;\n });\n return Object.keys(uniqueHostsMap).filter((host) => !(0, net_1.isIP)(host));\n}\nexports.getUniqueHostnamesFromOptions = getUniqueHostnamesFromOptions;\nfunction groupSrvRecords(records) {\n const recordsByPriority = {};\n for (const record of records) {\n if (!recordsByPriority.hasOwnProperty(record.priority)) {\n recordsByPriority[record.priority] = {\n totalWeight: record.weight,\n records: [record],\n };\n }\n else {\n recordsByPriority[record.priority].totalWeight += record.weight;\n recordsByPriority[record.priority].records.push(record);\n }\n }\n return recordsByPriority;\n}\nexports.groupSrvRecords = groupSrvRecords;\nfunction weightSrvRecords(recordsGroup) {\n if (recordsGroup.records.length === 1) {\n recordsGroup.totalWeight = 0;\n return recordsGroup.records.shift();\n }\n // + `recordsGroup.records.length` to support `weight` 0\n const random = Math.floor(Math.random() * (recordsGroup.totalWeight + recordsGroup.records.length));\n let total = 0;\n for (const [i, record] of recordsGroup.records.entries()) {\n total += 1 + record.weight;\n if (total > random) {\n recordsGroup.totalWeight -= record.weight;\n recordsGroup.records.splice(i, 1);\n return record;\n }\n }\n}\nexports.weightSrvRecords = weightSrvRecords;\nfunction getConnectionName(component, nodeConnectionName) {\n const prefix = `ioredis-cluster(${component})`;\n return nodeConnectionName ? `${prefix}:${nodeConnectionName}` : prefix;\n}\nexports.getConnectionName = getConnectionName;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst util_1 = require(\"./util\");\nconst utils_1 = require(\"../utils\");\nconst Redis_1 = require(\"../Redis\");\nconst debug = (0, utils_1.Debug)(\"cluster:subscriber\");\nclass ClusterSubscriber {\n constructor(connectionPool, emitter, isSharded = false) {\n this.connectionPool = connectionPool;\n this.emitter = emitter;\n this.isSharded = isSharded;\n this.started = false;\n //There is only one connection for the entire pool\n this.subscriber = null;\n //The slot range for which this subscriber is responsible\n this.slotRange = [];\n this.onSubscriberEnd = () => {\n if (!this.started) {\n debug(\"subscriber has disconnected, but ClusterSubscriber is not started, so not reconnecting.\");\n return;\n }\n // If the subscriber closes whilst it's still the active connection,\n // we might as well try to connecting to a new node if possible to\n // minimise the number of missed publishes.\n debug(\"subscriber has disconnected, selecting a new one...\");\n this.selectSubscriber();\n };\n // If the current node we're using as the subscriber disappears\n // from the node pool for some reason, we will select a new one\n // to connect to.\n // Note that this event is only triggered if the connection to\n // the node has been used; cluster subscriptions are setup with\n // lazyConnect = true. It's possible for the subscriber node to\n // disappear without this method being called!\n // See https://github.com/luin/ioredis/pull/1589\n this.connectionPool.on(\"-node\", (_, key) => {\n if (!this.started || !this.subscriber) {\n return;\n }\n if ((0, util_1.getNodeKey)(this.subscriber.options) === key) {\n debug(\"subscriber has left, selecting a new one...\");\n this.selectSubscriber();\n }\n });\n this.connectionPool.on(\"+node\", () => {\n if (!this.started || this.subscriber) {\n return;\n }\n debug(\"a new node is discovered and there is no subscriber, selecting a new one...\");\n this.selectSubscriber();\n });\n }\n getInstance() {\n return this.subscriber;\n }\n /**\n * Associate this subscriber to a specific slot range.\n *\n * Returns the range or an empty array if the slot range couldn't be associated.\n *\n * BTW: This is more for debugging and testing purposes.\n *\n * @param range\n */\n associateSlotRange(range) {\n if (this.isSharded) {\n this.slotRange = range;\n }\n return this.slotRange;\n }\n start() {\n this.started = true;\n this.selectSubscriber();\n debug(\"started\");\n }\n stop() {\n this.started = false;\n if (this.subscriber) {\n this.subscriber.disconnect();\n this.subscriber = null;\n }\n }\n isStarted() {\n return this.started;\n }\n selectSubscriber() {\n const lastActiveSubscriber = this.lastActiveSubscriber;\n // Disconnect the previous subscriber even if there\n // will not be a new one.\n if (lastActiveSubscriber) {\n lastActiveSubscriber.off(\"end\", this.onSubscriberEnd);\n lastActiveSubscriber.disconnect();\n }\n if (this.subscriber) {\n this.subscriber.off(\"end\", this.onSubscriberEnd);\n this.subscriber.disconnect();\n }\n const sampleNode = (0, utils_1.sample)(this.connectionPool.getNodes());\n if (!sampleNode) {\n debug(\"selecting subscriber failed since there is no node discovered in the cluster yet\");\n this.subscriber = null;\n return;\n }\n const { options } = sampleNode;\n debug(\"selected a subscriber %s:%s\", options.host, options.port);\n /*\n * Create a specialized Redis connection for the subscription.\n * Note that auto reconnection is enabled here.\n *\n * `enableReadyCheck` is also enabled because although subscription is allowed\n * while redis is loading data from the disk, we can check if the password\n * provided for the subscriber is correct, and if not, the current subscriber\n * will be disconnected and a new subscriber will be selected.\n */\n let connectionPrefix = \"subscriber\";\n if (this.isSharded)\n connectionPrefix = \"ssubscriber\";\n this.subscriber = new Redis_1.default({\n port: options.port,\n host: options.host,\n username: options.username,\n password: options.password,\n enableReadyCheck: true,\n connectionName: (0, util_1.getConnectionName)(connectionPrefix, options.connectionName),\n lazyConnect: true,\n tls: options.tls,\n // Don't try to reconnect the subscriber connection. If the connection fails\n // we will get an end event (handled below), at which point we'll pick a new\n // node from the pool and try to connect to that as the subscriber connection.\n retryStrategy: null,\n });\n // Ignore the errors since they're handled in the connection pool.\n this.subscriber.on(\"error\", utils_1.noop);\n // The node we lost connection to may not come back up in a\n // reasonable amount of time (e.g. a slave that's taken down\n // for maintainence), we could potentially miss many published\n // messages so we should reconnect as quickly as possible, to\n // a different node if needed.\n this.subscriber.once(\"end\", this.onSubscriberEnd);\n // Re-subscribe previous channels\n const previousChannels = { subscribe: [], psubscribe: [], ssubscribe: [] };\n if (lastActiveSubscriber) {\n const condition = lastActiveSubscriber.condition || lastActiveSubscriber.prevCondition;\n if (condition && condition.subscriber) {\n previousChannels.subscribe = condition.subscriber.channels(\"subscribe\");\n previousChannels.psubscribe =\n condition.subscriber.channels(\"psubscribe\");\n previousChannels.ssubscribe =\n condition.subscriber.channels(\"ssubscribe\");\n }\n }\n if (previousChannels.subscribe.length ||\n previousChannels.psubscribe.length ||\n previousChannels.ssubscribe.length) {\n let pending = 0;\n for (const type of [\"subscribe\", \"psubscribe\", \"ssubscribe\"]) {\n const channels = previousChannels[type];\n if (channels.length) {\n pending += 1;\n debug(\"%s %d channels\", type, channels.length);\n this.subscriber[type](channels)\n .then(() => {\n if (!--pending) {\n this.lastActiveSubscriber = this.subscriber;\n }\n })\n .catch(() => {\n // TODO: should probably disconnect the subscriber and try again.\n debug(\"failed to %s %d channels\", type, channels.length);\n });\n }\n }\n }\n else {\n this.lastActiveSubscriber = this.subscriber;\n }\n for (const event of [\n \"message\",\n \"messageBuffer\",\n ]) {\n this.subscriber.on(event, (arg1, arg2) => {\n this.emitter.emit(event, arg1, arg2);\n });\n }\n for (const event of [\"pmessage\", \"pmessageBuffer\"]) {\n this.subscriber.on(event, (arg1, arg2, arg3) => {\n this.emitter.emit(event, arg1, arg2, arg3);\n });\n }\n if (this.isSharded == true) {\n for (const event of [\n \"smessage\",\n \"smessageBuffer\",\n ]) {\n this.subscriber.on(event, (arg1, arg2) => {\n this.emitter.emit(event, arg1, arg2);\n });\n }\n }\n }\n}\nexports.default = ClusterSubscriber;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst events_1 = require(\"events\");\nconst utils_1 = require(\"../utils\");\nconst util_1 = require(\"./util\");\nconst Redis_1 = require(\"../Redis\");\nconst debug = (0, utils_1.Debug)(\"cluster:connectionPool\");\nclass ConnectionPool extends events_1.EventEmitter {\n constructor(redisOptions) {\n super();\n this.redisOptions = redisOptions;\n // master + slave = all\n this.nodes = {\n all: {},\n master: {},\n slave: {},\n };\n this.specifiedOptions = {};\n }\n getNodes(role = \"all\") {\n const nodes = this.nodes[role];\n return Object.keys(nodes).map((key) => nodes[key]);\n }\n getInstanceByKey(key) {\n return this.nodes.all[key];\n }\n getSampleInstance(role) {\n const keys = Object.keys(this.nodes[role]);\n const sampleKey = (0, utils_1.sample)(keys);\n return this.nodes[role][sampleKey];\n }\n /**\n * Add a master node to the pool\n * @param node\n */\n addMasterNode(node) {\n const key = (0, util_1.getNodeKey)(node.options);\n const redis = this.createRedisFromOptions(node, node.options.readOnly);\n //Master nodes aren't read-only\n if (!node.options.readOnly) {\n this.nodes.all[key] = redis;\n this.nodes.master[key] = redis;\n return true;\n }\n return false;\n }\n /**\n * Creates a Redis connection instance from the node options\n * @param node\n * @param readOnly\n */\n createRedisFromOptions(node, readOnly) {\n const redis = new Redis_1.default((0, utils_1.defaults)({\n // Never try to reconnect when a node is lose,\n // instead, waiting for a `MOVED` error and\n // fetch the slots again.\n retryStrategy: null,\n // Offline queue should be enabled so that\n // we don't need to wait for the `ready` event\n // before sending commands to the node.\n enableOfflineQueue: true,\n readOnly: readOnly,\n }, node, this.redisOptions, { lazyConnect: true }));\n return redis;\n }\n /**\n * Find or create a connection to the node\n */\n findOrCreate(node, readOnly = false) {\n const key = (0, util_1.getNodeKey)(node);\n readOnly = Boolean(readOnly);\n if (this.specifiedOptions[key]) {\n Object.assign(node, this.specifiedOptions[key]);\n }\n else {\n this.specifiedOptions[key] = node;\n }\n let redis;\n if (this.nodes.all[key]) {\n redis = this.nodes.all[key];\n if (redis.options.readOnly !== readOnly) {\n redis.options.readOnly = readOnly;\n debug(\"Change role of %s to %s\", key, readOnly ? \"slave\" : \"master\");\n redis[readOnly ? \"readonly\" : \"readwrite\"]().catch(utils_1.noop);\n if (readOnly) {\n delete this.nodes.master[key];\n this.nodes.slave[key] = redis;\n }\n else {\n delete this.nodes.slave[key];\n this.nodes.master[key] = redis;\n }\n }\n }\n else {\n debug(\"Connecting to %s as %s\", key, readOnly ? \"slave\" : \"master\");\n redis = this.createRedisFromOptions(node, readOnly);\n this.nodes.all[key] = redis;\n this.nodes[readOnly ? \"slave\" : \"master\"][key] = redis;\n redis.once(\"end\", () => {\n this.removeNode(key);\n this.emit(\"-node\", redis, key);\n if (!Object.keys(this.nodes.all).length) {\n this.emit(\"drain\");\n }\n });\n this.emit(\"+node\", redis, key);\n redis.on(\"error\", function (error) {\n this.emit(\"nodeError\", error, key);\n });\n }\n return redis;\n }\n /**\n * Reset the pool with a set of nodes.\n * The old node will be removed.\n */\n reset(nodes) {\n debug(\"Reset with %O\", nodes);\n const newNodes = {};\n nodes.forEach((node) => {\n const key = (0, util_1.getNodeKey)(node);\n // Don't override the existing (master) node\n // when the current one is slave.\n if (!(node.readOnly && newNodes[key])) {\n newNodes[key] = node;\n }\n });\n Object.keys(this.nodes.all).forEach((key) => {\n if (!newNodes[key]) {\n debug(\"Disconnect %s because the node does not hold any slot\", key);\n this.nodes.all[key].disconnect();\n this.removeNode(key);\n }\n });\n Object.keys(newNodes).forEach((key) => {\n const node = newNodes[key];\n this.findOrCreate(node, node.readOnly);\n });\n }\n /**\n * Remove a node from the pool.\n */\n removeNode(key) {\n const { nodes } = this;\n if (nodes.all[key]) {\n debug(\"Remove %s from the pool\", key);\n delete nodes.all[key];\n }\n delete nodes.master[key];\n delete nodes.slave[key];\n }\n}\nexports.default = ConnectionPool;\n","'use strict';\n\n/**\n * Custom implementation of a double ended queue.\n */\nfunction Denque(array, options) {\n var options = options || {};\n this._capacity = options.capacity;\n\n this._head = 0;\n this._tail = 0;\n\n if (Array.isArray(array)) {\n this._fromArray(array);\n } else {\n this._capacityMask = 0x3;\n this._list = new Array(4);\n }\n}\n\n/**\n * --------------\n * PUBLIC API\n * -------------\n */\n\n/**\n * Returns the item at the specified index from the list.\n * 0 is the first element, 1 is the second, and so on...\n * Elements at negative values are that many from the end: -1 is one before the end\n * (the last element), -2 is two before the end (one before last), etc.\n * @param index\n * @returns {*}\n */\nDenque.prototype.peekAt = function peekAt(index) {\n var i = index;\n // expect a number or return undefined\n if ((i !== (i | 0))) {\n return void 0;\n }\n var len = this.size();\n if (i >= len || i < -len) return undefined;\n if (i < 0) i += len;\n i = (this._head + i) & this._capacityMask;\n return this._list[i];\n};\n\n/**\n * Alias for peekAt()\n * @param i\n * @returns {*}\n */\nDenque.prototype.get = function get(i) {\n return this.peekAt(i);\n};\n\n/**\n * Returns the first item in the list without removing it.\n * @returns {*}\n */\nDenque.prototype.peek = function peek() {\n if (this._head === this._tail) return undefined;\n return this._list[this._head];\n};\n\n/**\n * Alias for peek()\n * @returns {*}\n */\nDenque.prototype.peekFront = function peekFront() {\n return this.peek();\n};\n\n/**\n * Returns the item that is at the back of the queue without removing it.\n * Uses peekAt(-1)\n */\nDenque.prototype.peekBack = function peekBack() {\n return this.peekAt(-1);\n};\n\n/**\n * Returns the current length of the queue\n * @return {Number}\n */\nObject.defineProperty(Denque.prototype, 'length', {\n get: function length() {\n return this.size();\n }\n});\n\n/**\n * Return the number of items on the list, or 0 if empty.\n * @returns {number}\n */\nDenque.prototype.size = function size() {\n if (this._head === this._tail) return 0;\n if (this._head < this._tail) return this._tail - this._head;\n else return this._capacityMask + 1 - (this._head - this._tail);\n};\n\n/**\n * Add an item at the beginning of the list.\n * @param item\n */\nDenque.prototype.unshift = function unshift(item) {\n if (arguments.length === 0) return this.size();\n var len = this._list.length;\n this._head = (this._head - 1 + len) & this._capacityMask;\n this._list[this._head] = item;\n if (this._tail === this._head) this._growArray();\n if (this._capacity && this.size() > this._capacity) this.pop();\n if (this._head < this._tail) return this._tail - this._head;\n else return this._capacityMask + 1 - (this._head - this._tail);\n};\n\n/**\n * Remove and return the first item on the list,\n * Returns undefined if the list is empty.\n * @returns {*}\n */\nDenque.prototype.shift = function shift() {\n var head = this._head;\n if (head === this._tail) return undefined;\n var item = this._list[head];\n this._list[head] = undefined;\n this._head = (head + 1) & this._capacityMask;\n if (head < 2 && this._tail > 10000 && this._tail <= this._list.length >>> 2) this._shrinkArray();\n return item;\n};\n\n/**\n * Add an item to the bottom of the list.\n * @param item\n */\nDenque.prototype.push = function push(item) {\n if (arguments.length === 0) return this.size();\n var tail = this._tail;\n this._list[tail] = item;\n this._tail = (tail + 1) & this._capacityMask;\n if (this._tail === this._head) {\n this._growArray();\n }\n if (this._capacity && this.size() > this._capacity) {\n this.shift();\n }\n if (this._head < this._tail) return this._tail - this._head;\n else return this._capacityMask + 1 - (this._head - this._tail);\n};\n\n/**\n * Remove and return the last item on the list.\n * Returns undefined if the list is empty.\n * @returns {*}\n */\nDenque.prototype.pop = function pop() {\n var tail = this._tail;\n if (tail === this._head) return undefined;\n var len = this._list.length;\n this._tail = (tail - 1 + len) & this._capacityMask;\n var item = this._list[this._tail];\n this._list[this._tail] = undefined;\n if (this._head < 2 && tail > 10000 && tail <= len >>> 2) this._shrinkArray();\n return item;\n};\n\n/**\n * Remove and return the item at the specified index from the list.\n * Returns undefined if the list is empty.\n * @param index\n * @returns {*}\n */\nDenque.prototype.removeOne = function removeOne(index) {\n var i = index;\n // expect a number or return undefined\n if ((i !== (i | 0))) {\n return void 0;\n }\n if (this._head === this._tail) return void 0;\n var size = this.size();\n var len = this._list.length;\n if (i >= size || i < -size) return void 0;\n if (i < 0) i += size;\n i = (this._head + i) & this._capacityMask;\n var item = this._list[i];\n var k;\n if (index < size / 2) {\n for (k = index; k > 0; k--) {\n this._list[i] = this._list[i = (i - 1 + len) & this._capacityMask];\n }\n this._list[i] = void 0;\n this._head = (this._head + 1 + len) & this._capacityMask;\n } else {\n for (k = size - 1 - index; k > 0; k--) {\n this._list[i] = this._list[i = (i + 1 + len) & this._capacityMask];\n }\n this._list[i] = void 0;\n this._tail = (this._tail - 1 + len) & this._capacityMask;\n }\n return item;\n};\n\n/**\n * Remove number of items from the specified index from the list.\n * Returns array of removed items.\n * Returns undefined if the list is empty.\n * @param index\n * @param count\n * @returns {array}\n */\nDenque.prototype.remove = function remove(index, count) {\n var i = index;\n var removed;\n var del_count = count;\n // expect a number or return undefined\n if ((i !== (i | 0))) {\n return void 0;\n }\n if (this._head === this._tail) return void 0;\n var size = this.size();\n var len = this._list.length;\n if (i >= size || i < -size || count < 1) return void 0;\n if (i < 0) i += size;\n if (count === 1 || !count) {\n removed = new Array(1);\n removed[0] = this.removeOne(i);\n return removed;\n }\n if (i === 0 && i + count >= size) {\n removed = this.toArray();\n this.clear();\n return removed;\n }\n if (i + count > size) count = size - i;\n var k;\n removed = new Array(count);\n for (k = 0; k < count; k++) {\n removed[k] = this._list[(this._head + i + k) & this._capacityMask];\n }\n i = (this._head + i) & this._capacityMask;\n if (index + count === size) {\n this._tail = (this._tail - count + len) & this._capacityMask;\n for (k = count; k > 0; k--) {\n this._list[i = (i + 1 + len) & this._capacityMask] = void 0;\n }\n return removed;\n }\n if (index === 0) {\n this._head = (this._head + count + len) & this._capacityMask;\n for (k = count - 1; k > 0; k--) {\n this._list[i = (i + 1 + len) & this._capacityMask] = void 0;\n }\n return removed;\n }\n if (i < size / 2) {\n this._head = (this._head + index + count + len) & this._capacityMask;\n for (k = index; k > 0; k--) {\n this.unshift(this._list[i = (i - 1 + len) & this._capacityMask]);\n }\n i = (this._head - 1 + len) & this._capacityMask;\n while (del_count > 0) {\n this._list[i = (i - 1 + len) & this._capacityMask] = void 0;\n del_count--;\n }\n if (index < 0) this._tail = i;\n } else {\n this._tail = i;\n i = (i + count + len) & this._capacityMask;\n for (k = size - (count + index); k > 0; k--) {\n this.push(this._list[i++]);\n }\n i = this._tail;\n while (del_count > 0) {\n this._list[i = (i + 1 + len) & this._capacityMask] = void 0;\n del_count--;\n }\n }\n if (this._head < 2 && this._tail > 10000 && this._tail <= len >>> 2) this._shrinkArray();\n return removed;\n};\n\n/**\n * Native splice implementation.\n * Remove number of items from the specified index from the list and/or add new elements.\n * Returns array of removed items or empty array if count == 0.\n * Returns undefined if the list is empty.\n *\n * @param index\n * @param count\n * @param {...*} [elements]\n * @returns {array}\n */\nDenque.prototype.splice = function splice(index, count) {\n var i = index;\n // expect a number or return undefined\n if ((i !== (i | 0))) {\n return void 0;\n }\n var size = this.size();\n if (i < 0) i += size;\n if (i > size) return void 0;\n if (arguments.length > 2) {\n var k;\n var temp;\n var removed;\n var arg_len = arguments.length;\n var len = this._list.length;\n var arguments_index = 2;\n if (!size || i < size / 2) {\n temp = new Array(i);\n for (k = 0; k < i; k++) {\n temp[k] = this._list[(this._head + k) & this._capacityMask];\n }\n if (count === 0) {\n removed = [];\n if (i > 0) {\n this._head = (this._head + i + len) & this._capacityMask;\n }\n } else {\n removed = this.remove(i, count);\n this._head = (this._head + i + len) & this._capacityMask;\n }\n while (arg_len > arguments_index) {\n this.unshift(arguments[--arg_len]);\n }\n for (k = i; k > 0; k--) {\n this.unshift(temp[k - 1]);\n }\n } else {\n temp = new Array(size - (i + count));\n var leng = temp.length;\n for (k = 0; k < leng; k++) {\n temp[k] = this._list[(this._head + i + count + k) & this._capacityMask];\n }\n if (count === 0) {\n removed = [];\n if (i != size) {\n this._tail = (this._head + i + len) & this._capacityMask;\n }\n } else {\n removed = this.remove(i, count);\n this._tail = (this._tail - leng + len) & this._capacityMask;\n }\n while (arguments_index < arg_len) {\n this.push(arguments[arguments_index++]);\n }\n for (k = 0; k < leng; k++) {\n this.push(temp[k]);\n }\n }\n return removed;\n } else {\n return this.remove(i, count);\n }\n};\n\n/**\n * Soft clear - does not reset capacity.\n */\nDenque.prototype.clear = function clear() {\n this._list = new Array(this._list.length);\n this._head = 0;\n this._tail = 0;\n};\n\n/**\n * Returns true or false whether the list is empty.\n * @returns {boolean}\n */\nDenque.prototype.isEmpty = function isEmpty() {\n return this._head === this._tail;\n};\n\n/**\n * Returns an array of all queue items.\n * @returns {Array}\n */\nDenque.prototype.toArray = function toArray() {\n return this._copyArray(false);\n};\n\n/**\n * -------------\n * INTERNALS\n * -------------\n */\n\n/**\n * Fills the queue with items from an array\n * For use in the constructor\n * @param array\n * @private\n */\nDenque.prototype._fromArray = function _fromArray(array) {\n var length = array.length;\n var capacity = this._nextPowerOf2(length);\n\n this._list = new Array(capacity);\n this._capacityMask = capacity - 1;\n this._tail = length;\n\n for (var i = 0; i < length; i++) this._list[i] = array[i];\n};\n\n/**\n *\n * @param fullCopy\n * @param size Initialize the array with a specific size. Will default to the current list size\n * @returns {Array}\n * @private\n */\nDenque.prototype._copyArray = function _copyArray(fullCopy, size) {\n var src = this._list;\n var capacity = src.length;\n var length = this.length;\n size = size | length;\n\n // No prealloc requested and the buffer is contiguous\n if (size == length && this._head < this._tail) {\n // Simply do a fast slice copy\n return this._list.slice(this._head, this._tail);\n }\n\n var dest = new Array(size);\n\n var k = 0;\n var i;\n if (fullCopy || this._head > this._tail) {\n for (i = this._head; i < capacity; i++) dest[k++] = src[i];\n for (i = 0; i < this._tail; i++) dest[k++] = src[i];\n } else {\n for (i = this._head; i < this._tail; i++) dest[k++] = src[i];\n }\n\n return dest;\n}\n\n/**\n * Grows the internal list array.\n * @private\n */\nDenque.prototype._growArray = function _growArray() {\n if (this._head != 0) {\n // double array size and copy existing data, head to end, then beginning to tail.\n var newList = this._copyArray(true, this._list.length << 1);\n\n this._tail = this._list.length;\n this._head = 0;\n\n this._list = newList;\n } else {\n this._tail = this._list.length;\n this._list.length <<= 1;\n }\n\n this._capacityMask = (this._capacityMask << 1) | 1;\n};\n\n/**\n * Shrinks the internal list array.\n * @private\n */\nDenque.prototype._shrinkArray = function _shrinkArray() {\n this._list.length >>>= 1;\n this._capacityMask >>>= 1;\n};\n\n/**\n * Find the next power of 2, at least 4\n * @private\n * @param {number} num \n * @returns {number}\n */\nDenque.prototype._nextPowerOf2 = function _nextPowerOf2(num) {\n var log2 = Math.log(num) / Math.log(2);\n var nextPow2 = 1 << (log2 + 1);\n\n return Math.max(nextPow2, 4);\n}\n\nmodule.exports = Denque;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst utils_1 = require(\"../utils\");\nconst Deque = require(\"denque\");\nconst debug = (0, utils_1.Debug)(\"delayqueue\");\n/**\n * Queue that runs items after specified duration\n */\nclass DelayQueue {\n constructor() {\n this.queues = {};\n this.timeouts = {};\n }\n /**\n * Add a new item to the queue\n *\n * @param bucket bucket name\n * @param item function that will run later\n * @param options\n */\n push(bucket, item, options) {\n const callback = options.callback || process.nextTick;\n if (!this.queues[bucket]) {\n this.queues[bucket] = new Deque();\n }\n const queue = this.queues[bucket];\n queue.push(item);\n if (!this.timeouts[bucket]) {\n this.timeouts[bucket] = setTimeout(() => {\n callback(() => {\n this.timeouts[bucket] = null;\n this.execute(bucket);\n });\n }, options.timeout);\n }\n }\n execute(bucket) {\n const queue = this.queues[bucket];\n if (!queue) {\n return;\n }\n const { length } = queue;\n if (!length) {\n return;\n }\n debug(\"send %d commands in %s queue\", length, bucket);\n this.queues[bucket] = null;\n while (queue.length > 0) {\n queue.shift()();\n }\n }\n}\nexports.default = DelayQueue;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst utils_1 = require(\"../utils\");\nconst ClusterSubscriber_1 = require(\"./ClusterSubscriber\");\nconst ConnectionPool_1 = require(\"./ConnectionPool\");\nconst util_1 = require(\"./util\");\nconst calculateSlot = require(\"cluster-key-slot\");\nconst debug = (0, utils_1.Debug)(\"cluster:subscriberGroup\");\n/**\n * Redis differs between \"normal\" and sharded PubSub. If using the \"normal\" PubSub feature, exactly one\n * ClusterSubscriber exists per cluster instance. This works because the Redis cluster bus forwards m\n * messages between shards. However, this has scalability limitations, which is the reason why the sharded\n * PubSub feature was added to Redis. With sharded PubSub, each shard is responsible for its own messages.\n * Given that, we need at least one ClusterSubscriber per master endpoint/node.\n *\n * This class leverages the previously exising ClusterSubscriber by adding support for multiple such subscribers\n * in alignment to the master nodes of the cluster. The ClusterSubscriber class was extended in a non-breaking way\n * to support this feature.\n */\nclass ClusterSubscriberGroup {\n /**\n * Register callbacks\n *\n * @param cluster\n */\n constructor(cluster) {\n this.cluster = cluster;\n this.shardedSubscribers = new Map();\n this.clusterSlots = [];\n //Simple [min, max] slot ranges aren't enough because you can migrate single slots\n this.subscriberToSlotsIndex = new Map();\n this.channels = new Map();\n cluster.on(\"+node\", (redis) => {\n this._addSubscriber(redis);\n });\n cluster.on(\"-node\", (redis) => {\n this._removeSubscriber(redis);\n });\n cluster.on(\"refresh\", () => {\n this._refreshSlots(cluster);\n });\n }\n /**\n * Get the responsible subscriber.\n *\n * Returns null if no subscriber was found\n *\n * @param slot\n */\n getResponsibleSubscriber(slot) {\n const nodeKey = this.clusterSlots[slot][0];\n return this.shardedSubscribers.get(nodeKey);\n }\n /**\n * Adds a channel for which this subscriber group is responsible\n *\n * @param channels\n */\n addChannels(channels) {\n const slot = calculateSlot(channels[0]);\n //Check if the all channels belong to the same slot and otherwise reject the operation\n channels.forEach((c) => {\n if (calculateSlot(c) != slot)\n return -1;\n });\n const currChannels = this.channels.get(slot);\n if (!currChannels) {\n this.channels.set(slot, channels);\n }\n else {\n this.channels.set(slot, currChannels.concat(channels));\n }\n return [...this.channels.values()].flatMap(v => v).length;\n }\n /**\n * Removes channels for which the subscriber group is responsible by optionally unsubscribing\n * @param channels\n */\n removeChannels(channels) {\n const slot = calculateSlot(channels[0]);\n //Check if the all channels belong to the same slot and otherwise reject the operation\n channels.forEach((c) => {\n if (calculateSlot(c) != slot)\n return -1;\n });\n const slotChannels = this.channels.get(slot);\n if (slotChannels) {\n const updatedChannels = slotChannels.filter(c => !channels.includes(c));\n this.channels.set(slot, updatedChannels);\n }\n return [...this.channels.values()].flatMap(v => v).length;\n }\n /**\n * Disconnect all subscribers\n */\n stop() {\n for (const s of this.shardedSubscribers.values()) {\n s.stop();\n }\n }\n /**\n * Start all not yet started subscribers\n */\n start() {\n for (const s of this.shardedSubscribers.values()) {\n if (!s.isStarted()) {\n s.start();\n }\n }\n }\n /**\n * Add a subscriber to the group of subscribers\n *\n * @param redis\n */\n _addSubscriber(redis) {\n const pool = new ConnectionPool_1.default(redis.options);\n if (pool.addMasterNode(redis)) {\n const sub = new ClusterSubscriber_1.default(pool, this.cluster, true);\n const nodeKey = (0, util_1.getNodeKey)(redis.options);\n this.shardedSubscribers.set(nodeKey, sub);\n sub.start();\n // We need to attempt to resubscribe them in case the new node serves their slot\n this._resubscribe();\n this.cluster.emit(\"+subscriber\");\n return sub;\n }\n return null;\n }\n /**\n * Removes a subscriber from the group\n * @param redis\n */\n _removeSubscriber(redis) {\n const nodeKey = (0, util_1.getNodeKey)(redis.options);\n const sub = this.shardedSubscribers.get(nodeKey);\n if (sub) {\n sub.stop();\n this.shardedSubscribers.delete(nodeKey);\n // Even though the subscriber to this node is going down, we might have another subscriber\n // handling the same slots, so we need to attempt to subscribe the orphaned channels\n this._resubscribe();\n this.cluster.emit(\"-subscriber\");\n }\n return this.shardedSubscribers;\n }\n /**\n * Refreshes the subscriber-related slot ranges\n *\n * Returns false if no refresh was needed\n *\n * @param cluster\n */\n _refreshSlots(cluster) {\n //If there was an actual change, then reassign the slot ranges\n if (this._slotsAreEqual(cluster.slots)) {\n debug(\"Nothing to refresh because the new cluster map is equal to the previous one.\");\n }\n else {\n debug(\"Refreshing the slots of the subscriber group.\");\n //Rebuild the slots index\n this.subscriberToSlotsIndex = new Map();\n for (let slot = 0; slot < cluster.slots.length; slot++) {\n const node = cluster.slots[slot][0];\n if (!this.subscriberToSlotsIndex.has(node)) {\n this.subscriberToSlotsIndex.set(node, []);\n }\n this.subscriberToSlotsIndex.get(node).push(Number(slot));\n }\n //Update the subscribers from the index\n this._resubscribe();\n //Update the cached slots map\n this.clusterSlots = JSON.parse(JSON.stringify(cluster.slots));\n this.cluster.emit(\"subscribersReady\");\n return true;\n }\n return false;\n }\n /**\n * Resubscribes to the previous channels\n *\n * @private\n */\n _resubscribe() {\n if (this.shardedSubscribers) {\n this.shardedSubscribers.forEach((s, nodeKey) => {\n const subscriberSlots = this.subscriberToSlotsIndex.get(nodeKey);\n if (subscriberSlots) {\n //More for debugging purposes\n s.associateSlotRange(subscriberSlots);\n //Resubscribe on the underlying connection\n subscriberSlots.forEach((ss) => {\n //Might return null if being disconnected\n const redis = s.getInstance();\n const channels = this.channels.get(ss);\n if (channels && channels.length > 0) {\n //Try to subscribe now\n if (redis) {\n redis.ssubscribe(channels);\n //If the instance isn't ready yet, then register the re-subscription for later\n redis.on(\"ready\", () => {\n redis.ssubscribe(channels);\n });\n }\n }\n });\n }\n });\n }\n }\n /**\n * Deep equality of the cluster slots objects\n *\n * @param other\n * @private\n */\n _slotsAreEqual(other) {\n if (this.clusterSlots === undefined)\n return false;\n else\n return JSON.stringify(this.clusterSlots) === JSON.stringify(other);\n }\n}\nexports.default = ClusterSubscriberGroup;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst commands_1 = require(\"@ioredis/commands\");\nconst events_1 = require(\"events\");\nconst redis_errors_1 = require(\"redis-errors\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst Command_1 = require(\"../Command\");\nconst ClusterAllFailedError_1 = require(\"../errors/ClusterAllFailedError\");\nconst Redis_1 = require(\"../Redis\");\nconst ScanStream_1 = require(\"../ScanStream\");\nconst transaction_1 = require(\"../transaction\");\nconst utils_1 = require(\"../utils\");\nconst applyMixin_1 = require(\"../utils/applyMixin\");\nconst Commander_1 = require(\"../utils/Commander\");\nconst ClusterOptions_1 = require(\"./ClusterOptions\");\nconst ClusterSubscriber_1 = require(\"./ClusterSubscriber\");\nconst ConnectionPool_1 = require(\"./ConnectionPool\");\nconst DelayQueue_1 = require(\"./DelayQueue\");\nconst util_1 = require(\"./util\");\nconst Deque = require(\"denque\");\nconst ClusterSubscriberGroup_1 = require(\"./ClusterSubscriberGroup\");\nconst debug = (0, utils_1.Debug)(\"cluster\");\nconst REJECT_OVERWRITTEN_COMMANDS = new WeakSet();\n/**\n * Client for the official Redis Cluster\n */\nclass Cluster extends Commander_1.default {\n /**\n * Creates an instance of Cluster.\n */\n //TODO: Add an option that enables or disables sharded PubSub\n constructor(startupNodes, options = {}) {\n super();\n this.slots = [];\n /**\n * @ignore\n */\n this._groupsIds = {};\n /**\n * @ignore\n */\n this._groupsBySlot = Array(16384);\n /**\n * @ignore\n */\n this.isCluster = true;\n this.retryAttempts = 0;\n this.delayQueue = new DelayQueue_1.default();\n this.offlineQueue = new Deque();\n this.isRefreshing = false;\n this._refreshSlotsCacheCallbacks = [];\n this._autoPipelines = new Map();\n this._runningAutoPipelines = new Set();\n this._readyDelayedCallbacks = [];\n /**\n * Every time Cluster#connect() is called, this value will be\n * auto-incrementing. The purpose of this value is used for\n * discarding previous connect attampts when creating a new\n * connection.\n */\n this.connectionEpoch = 0;\n events_1.EventEmitter.call(this);\n this.startupNodes = startupNodes;\n this.options = (0, utils_1.defaults)({}, options, ClusterOptions_1.DEFAULT_CLUSTER_OPTIONS, this.options);\n if (this.options.shardedSubscribers == true)\n this.shardedSubscribers = new ClusterSubscriberGroup_1.default(this);\n if (this.options.redisOptions &&\n this.options.redisOptions.keyPrefix &&\n !this.options.keyPrefix) {\n this.options.keyPrefix = this.options.redisOptions.keyPrefix;\n }\n // validate options\n if (typeof this.options.scaleReads !== \"function\" &&\n [\"all\", \"master\", \"slave\"].indexOf(this.options.scaleReads) === -1) {\n throw new Error('Invalid option scaleReads \"' +\n this.options.scaleReads +\n '\". Expected \"all\", \"master\", \"slave\" or a custom function');\n }\n this.connectionPool = new ConnectionPool_1.default(this.options.redisOptions);\n this.connectionPool.on(\"-node\", (redis, key) => {\n this.emit(\"-node\", redis);\n });\n this.connectionPool.on(\"+node\", (redis) => {\n this.emit(\"+node\", redis);\n });\n this.connectionPool.on(\"drain\", () => {\n this.setStatus(\"close\");\n });\n this.connectionPool.on(\"nodeError\", (error, key) => {\n this.emit(\"node error\", error, key);\n });\n this.subscriber = new ClusterSubscriber_1.default(this.connectionPool, this);\n if (this.options.scripts) {\n Object.entries(this.options.scripts).forEach(([name, definition]) => {\n this.defineCommand(name, definition);\n });\n }\n if (this.options.lazyConnect) {\n this.setStatus(\"wait\");\n }\n else {\n this.connect().catch((err) => {\n debug(\"connecting failed: %s\", err);\n });\n }\n }\n /**\n * Connect to a cluster\n */\n connect() {\n return new Promise((resolve, reject) => {\n if (this.status === \"connecting\" ||\n this.status === \"connect\" ||\n this.status === \"ready\") {\n reject(new Error(\"Redis is already connecting/connected\"));\n return;\n }\n const epoch = ++this.connectionEpoch;\n this.setStatus(\"connecting\");\n this.resolveStartupNodeHostnames()\n .then((nodes) => {\n if (this.connectionEpoch !== epoch) {\n debug(\"discard connecting after resolving startup nodes because epoch not match: %d != %d\", epoch, this.connectionEpoch);\n reject(new redis_errors_1.RedisError(\"Connection is discarded because a new connection is made\"));\n return;\n }\n if (this.status !== \"connecting\") {\n debug(\"discard connecting after resolving startup nodes because the status changed to %s\", this.status);\n reject(new redis_errors_1.RedisError(\"Connection is aborted\"));\n return;\n }\n this.connectionPool.reset(nodes);\n const readyHandler = () => {\n this.setStatus(\"ready\");\n this.retryAttempts = 0;\n this.executeOfflineCommands();\n this.resetNodesRefreshInterval();\n resolve();\n };\n let closeListener = undefined;\n const refreshListener = () => {\n this.invokeReadyDelayedCallbacks(undefined);\n this.removeListener(\"close\", closeListener);\n this.manuallyClosing = false;\n this.setStatus(\"connect\");\n if (this.options.enableReadyCheck) {\n this.readyCheck((err, fail) => {\n if (err || fail) {\n debug(\"Ready check failed (%s). Reconnecting...\", err || fail);\n if (this.status === \"connect\") {\n this.disconnect(true);\n }\n }\n else {\n readyHandler();\n }\n });\n }\n else {\n readyHandler();\n }\n };\n closeListener = () => {\n const error = new Error(\"None of startup nodes is available\");\n this.removeListener(\"refresh\", refreshListener);\n this.invokeReadyDelayedCallbacks(error);\n reject(error);\n };\n this.once(\"refresh\", refreshListener);\n this.once(\"close\", closeListener);\n this.once(\"close\", this.handleCloseEvent.bind(this));\n this.refreshSlotsCache((err) => {\n if (err && err.message === ClusterAllFailedError_1.default.defaultMessage) {\n Redis_1.default.prototype.silentEmit.call(this, \"error\", err);\n this.connectionPool.reset([]);\n }\n });\n this.subscriber.start();\n if (this.options.shardedSubscribers) {\n this.shardedSubscribers.start();\n }\n })\n .catch((err) => {\n this.setStatus(\"close\");\n this.handleCloseEvent(err);\n this.invokeReadyDelayedCallbacks(err);\n reject(err);\n });\n });\n }\n /**\n * Disconnect from every node in the cluster.\n */\n disconnect(reconnect = false) {\n const status = this.status;\n this.setStatus(\"disconnecting\");\n if (!reconnect) {\n this.manuallyClosing = true;\n }\n if (this.reconnectTimeout && !reconnect) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n debug(\"Canceled reconnecting attempts\");\n }\n this.clearNodesRefreshInterval();\n this.subscriber.stop();\n if (this.options.shardedSubscribers) {\n this.shardedSubscribers.stop();\n }\n if (status === \"wait\") {\n this.setStatus(\"close\");\n this.handleCloseEvent();\n }\n else {\n this.connectionPool.reset([]);\n }\n }\n /**\n * Quit the cluster gracefully.\n */\n quit(callback) {\n const status = this.status;\n this.setStatus(\"disconnecting\");\n this.manuallyClosing = true;\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n this.clearNodesRefreshInterval();\n this.subscriber.stop();\n if (this.options.shardedSubscribers) {\n this.shardedSubscribers.stop();\n }\n if (status === \"wait\") {\n const ret = (0, standard_as_callback_1.default)(Promise.resolve(\"OK\"), callback);\n // use setImmediate to make sure \"close\" event\n // being emitted after quit() is returned\n setImmediate(function () {\n this.setStatus(\"close\");\n this.handleCloseEvent();\n }.bind(this));\n return ret;\n }\n return (0, standard_as_callback_1.default)(Promise.all(this.nodes().map((node) => node.quit().catch((err) => {\n // Ignore the error caused by disconnecting since\n // we're disconnecting...\n if (err.message === utils_1.CONNECTION_CLOSED_ERROR_MSG) {\n return \"OK\";\n }\n throw err;\n }))).then(() => \"OK\"), callback);\n }\n /**\n * Create a new instance with the same startup nodes and options as the current one.\n *\n * @example\n * ```js\n * var cluster = new Redis.Cluster([{ host: \"127.0.0.1\", port: \"30001\" }]);\n * var anotherCluster = cluster.duplicate();\n * ```\n */\n duplicate(overrideStartupNodes = [], overrideOptions = {}) {\n const startupNodes = overrideStartupNodes.length > 0\n ? overrideStartupNodes\n : this.startupNodes.slice(0);\n const options = Object.assign({}, this.options, overrideOptions);\n return new Cluster(startupNodes, options);\n }\n /**\n * Get nodes with the specified role\n */\n nodes(role = \"all\") {\n if (role !== \"all\" && role !== \"master\" && role !== \"slave\") {\n throw new Error('Invalid role \"' + role + '\". Expected \"all\", \"master\" or \"slave\"');\n }\n return this.connectionPool.getNodes(role);\n }\n /**\n * This is needed in order not to install a listener for each auto pipeline\n *\n * @ignore\n */\n delayUntilReady(callback) {\n this._readyDelayedCallbacks.push(callback);\n }\n /**\n * Get the number of commands queued in automatic pipelines.\n *\n * This is not available (and returns 0) until the cluster is connected and slots information have been received.\n */\n get autoPipelineQueueSize() {\n let queued = 0;\n for (const pipeline of this._autoPipelines.values()) {\n queued += pipeline.length;\n }\n return queued;\n }\n /**\n * Refresh the slot cache\n *\n * @ignore\n */\n refreshSlotsCache(callback) {\n if (callback) {\n this._refreshSlotsCacheCallbacks.push(callback);\n }\n if (this.isRefreshing) {\n return;\n }\n this.isRefreshing = true;\n const _this = this;\n const wrapper = (error) => {\n this.isRefreshing = false;\n for (const callback of this._refreshSlotsCacheCallbacks) {\n callback(error);\n }\n this._refreshSlotsCacheCallbacks = [];\n };\n const nodes = (0, utils_1.shuffle)(this.connectionPool.getNodes());\n let lastNodeError = null;\n function tryNode(index) {\n if (index === nodes.length) {\n const error = new ClusterAllFailedError_1.default(ClusterAllFailedError_1.default.defaultMessage, lastNodeError);\n return wrapper(error);\n }\n const node = nodes[index];\n const key = `${node.options.host}:${node.options.port}`;\n debug(\"getting slot cache from %s\", key);\n _this.getInfoFromNode(node, function (err) {\n switch (_this.status) {\n case \"close\":\n case \"end\":\n return wrapper(new Error(\"Cluster is disconnected.\"));\n case \"disconnecting\":\n return wrapper(new Error(\"Cluster is disconnecting.\"));\n }\n if (err) {\n _this.emit(\"node error\", err, key);\n lastNodeError = err;\n tryNode(index + 1);\n }\n else {\n _this.emit(\"refresh\");\n wrapper();\n }\n });\n }\n tryNode(0);\n }\n /**\n * @ignore\n */\n sendCommand(command, stream, node) {\n if (this.status === \"wait\") {\n this.connect().catch(utils_1.noop);\n }\n if (this.status === \"end\") {\n command.reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n return command.promise;\n }\n let to = this.options.scaleReads;\n if (to !== \"master\") {\n const isCommandReadOnly = command.isReadOnly ||\n ((0, commands_1.exists)(command.name) && (0, commands_1.hasFlag)(command.name, \"readonly\"));\n if (!isCommandReadOnly) {\n to = \"master\";\n }\n }\n let targetSlot = node ? node.slot : command.getSlot();\n const ttl = {};\n const _this = this;\n if (!node && !REJECT_OVERWRITTEN_COMMANDS.has(command)) {\n REJECT_OVERWRITTEN_COMMANDS.add(command);\n const reject = command.reject;\n command.reject = function (err) {\n const partialTry = tryConnection.bind(null, true);\n _this.handleError(err, ttl, {\n moved: function (slot, key) {\n debug(\"command %s is moved to %s\", command.name, key);\n targetSlot = Number(slot);\n if (_this.slots[slot]) {\n _this.slots[slot][0] = key;\n }\n else {\n _this.slots[slot] = [key];\n }\n _this._groupsBySlot[slot] =\n _this._groupsIds[_this.slots[slot].join(\";\")];\n _this.connectionPool.findOrCreate(_this.natMapper(key));\n tryConnection();\n debug(\"refreshing slot caches... (triggered by MOVED error)\");\n _this.refreshSlotsCache();\n },\n ask: function (slot, key) {\n debug(\"command %s is required to ask %s:%s\", command.name, key);\n const mapped = _this.natMapper(key);\n _this.connectionPool.findOrCreate(mapped);\n tryConnection(false, `${mapped.host}:${mapped.port}`);\n },\n tryagain: partialTry,\n clusterDown: partialTry,\n connectionClosed: partialTry,\n maxRedirections: function (redirectionError) {\n reject.call(command, redirectionError);\n },\n defaults: function () {\n reject.call(command, err);\n },\n });\n };\n }\n tryConnection();\n function tryConnection(random, asking) {\n if (_this.status === \"end\") {\n command.reject(new redis_errors_1.AbortError(\"Cluster is ended.\"));\n return;\n }\n let redis;\n if (_this.status === \"ready\" || command.name === \"cluster\") {\n if (node && node.redis) {\n redis = node.redis;\n }\n else if (Command_1.default.checkFlag(\"ENTER_SUBSCRIBER_MODE\", command.name) ||\n Command_1.default.checkFlag(\"EXIT_SUBSCRIBER_MODE\", command.name)) {\n if (_this.options.shardedSubscribers == true &&\n (command.name == \"ssubscribe\" || command.name == \"sunsubscribe\")) {\n const sub = _this.shardedSubscribers.getResponsibleSubscriber(targetSlot);\n let status = -1;\n if (command.name == \"ssubscribe\")\n status = _this.shardedSubscribers.addChannels(command.getKeys());\n if (command.name == \"sunsubscribe\")\n status = _this.shardedSubscribers.removeChannels(command.getKeys());\n if (status !== -1) {\n redis = sub.getInstance();\n }\n else {\n command.reject(new redis_errors_1.AbortError(\"Can't add or remove the given channels. Are they in the same slot?\"));\n }\n }\n else {\n redis = _this.subscriber.getInstance();\n }\n if (!redis) {\n command.reject(new redis_errors_1.AbortError(\"No subscriber for the cluster\"));\n return;\n }\n }\n else {\n if (!random) {\n if (typeof targetSlot === \"number\" && _this.slots[targetSlot]) {\n const nodeKeys = _this.slots[targetSlot];\n if (typeof to === \"function\") {\n const nodes = nodeKeys.map(function (key) {\n return _this.connectionPool.getInstanceByKey(key);\n });\n redis = to(nodes, command);\n if (Array.isArray(redis)) {\n redis = (0, utils_1.sample)(redis);\n }\n if (!redis) {\n redis = nodes[0];\n }\n }\n else {\n let key;\n if (to === \"all\") {\n key = (0, utils_1.sample)(nodeKeys);\n }\n else if (to === \"slave\" && nodeKeys.length > 1) {\n key = (0, utils_1.sample)(nodeKeys, 1);\n }\n else {\n key = nodeKeys[0];\n }\n redis = _this.connectionPool.getInstanceByKey(key);\n }\n }\n if (asking) {\n redis = _this.connectionPool.getInstanceByKey(asking);\n redis.asking();\n }\n }\n if (!redis) {\n redis =\n (typeof to === \"function\"\n ? null\n : _this.connectionPool.getSampleInstance(to)) ||\n _this.connectionPool.getSampleInstance(\"all\");\n }\n }\n if (node && !node.redis) {\n node.redis = redis;\n }\n }\n if (redis) {\n redis.sendCommand(command, stream);\n }\n else if (_this.options.enableOfflineQueue) {\n _this.offlineQueue.push({\n command: command,\n stream: stream,\n node: node,\n });\n }\n else {\n command.reject(new Error(\"Cluster isn't ready and enableOfflineQueue options is false\"));\n }\n }\n return command.promise;\n }\n sscanStream(key, options) {\n return this.createScanStream(\"sscan\", { key, options });\n }\n sscanBufferStream(key, options) {\n return this.createScanStream(\"sscanBuffer\", { key, options });\n }\n hscanStream(key, options) {\n return this.createScanStream(\"hscan\", { key, options });\n }\n hscanBufferStream(key, options) {\n return this.createScanStream(\"hscanBuffer\", { key, options });\n }\n zscanStream(key, options) {\n return this.createScanStream(\"zscan\", { key, options });\n }\n zscanBufferStream(key, options) {\n return this.createScanStream(\"zscanBuffer\", { key, options });\n }\n /**\n * @ignore\n */\n handleError(error, ttl, handlers) {\n if (typeof ttl.value === \"undefined\") {\n ttl.value = this.options.maxRedirections;\n }\n else {\n ttl.value -= 1;\n }\n if (ttl.value <= 0) {\n handlers.maxRedirections(new Error(\"Too many Cluster redirections. Last error: \" + error));\n return;\n }\n const errv = error.message.split(\" \");\n if (errv[0] === \"MOVED\") {\n const timeout = this.options.retryDelayOnMoved;\n if (timeout && typeof timeout === \"number\") {\n this.delayQueue.push(\"moved\", handlers.moved.bind(null, errv[1], errv[2]), { timeout });\n }\n else {\n handlers.moved(errv[1], errv[2]);\n }\n }\n else if (errv[0] === \"ASK\") {\n handlers.ask(errv[1], errv[2]);\n }\n else if (errv[0] === \"TRYAGAIN\") {\n this.delayQueue.push(\"tryagain\", handlers.tryagain, {\n timeout: this.options.retryDelayOnTryAgain,\n });\n }\n else if (errv[0] === \"CLUSTERDOWN\" &&\n this.options.retryDelayOnClusterDown > 0) {\n this.delayQueue.push(\"clusterdown\", handlers.connectionClosed, {\n timeout: this.options.retryDelayOnClusterDown,\n callback: this.refreshSlotsCache.bind(this),\n });\n }\n else if (error.message === utils_1.CONNECTION_CLOSED_ERROR_MSG &&\n this.options.retryDelayOnFailover > 0 &&\n this.status === \"ready\") {\n this.delayQueue.push(\"failover\", handlers.connectionClosed, {\n timeout: this.options.retryDelayOnFailover,\n callback: this.refreshSlotsCache.bind(this),\n });\n }\n else {\n handlers.defaults();\n }\n }\n resetOfflineQueue() {\n this.offlineQueue = new Deque();\n }\n clearNodesRefreshInterval() {\n if (this.slotsTimer) {\n clearTimeout(this.slotsTimer);\n this.slotsTimer = null;\n }\n }\n resetNodesRefreshInterval() {\n if (this.slotsTimer || !this.options.slotsRefreshInterval) {\n return;\n }\n const nextRound = () => {\n this.slotsTimer = setTimeout(() => {\n debug('refreshing slot caches... (triggered by \"slotsRefreshInterval\" option)');\n this.refreshSlotsCache(() => {\n nextRound();\n });\n }, this.options.slotsRefreshInterval);\n };\n nextRound();\n }\n /**\n * Change cluster instance's status\n */\n setStatus(status) {\n debug(\"status: %s -> %s\", this.status || \"[empty]\", status);\n this.status = status;\n process.nextTick(() => {\n this.emit(status);\n });\n }\n /**\n * Called when closed to check whether a reconnection should be made\n */\n handleCloseEvent(reason) {\n if (reason) {\n debug(\"closed because %s\", reason);\n }\n let retryDelay;\n if (!this.manuallyClosing &&\n typeof this.options.clusterRetryStrategy === \"function\") {\n retryDelay = this.options.clusterRetryStrategy.call(this, ++this.retryAttempts, reason);\n }\n if (typeof retryDelay === \"number\") {\n this.setStatus(\"reconnecting\");\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectTimeout = null;\n debug(\"Cluster is disconnected. Retrying after %dms\", retryDelay);\n this.connect().catch(function (err) {\n debug(\"Got error %s when reconnecting. Ignoring...\", err);\n });\n }, retryDelay);\n }\n else {\n this.setStatus(\"end\");\n this.flushQueue(new Error(\"None of startup nodes is available\"));\n }\n }\n /**\n * Flush offline queue with error.\n */\n flushQueue(error) {\n let item;\n while ((item = this.offlineQueue.shift())) {\n item.command.reject(error);\n }\n }\n executeOfflineCommands() {\n if (this.offlineQueue.length) {\n debug(\"send %d commands in offline queue\", this.offlineQueue.length);\n const offlineQueue = this.offlineQueue;\n this.resetOfflineQueue();\n let item;\n while ((item = offlineQueue.shift())) {\n this.sendCommand(item.command, item.stream, item.node);\n }\n }\n }\n natMapper(nodeKey) {\n const key = typeof nodeKey === \"string\"\n ? nodeKey\n : `${nodeKey.host}:${nodeKey.port}`;\n let mapped = null;\n if (this.options.natMap && typeof this.options.natMap === \"function\") {\n mapped = this.options.natMap(key);\n }\n else if (this.options.natMap && typeof this.options.natMap === \"object\") {\n mapped = this.options.natMap[key];\n }\n if (mapped) {\n debug(\"NAT mapping %s -> %O\", key, mapped);\n return Object.assign({}, mapped);\n }\n return typeof nodeKey === \"string\"\n ? (0, util_1.nodeKeyToRedisOptions)(nodeKey)\n : nodeKey;\n }\n getInfoFromNode(redis, callback) {\n if (!redis) {\n return callback(new Error(\"Node is disconnected\"));\n }\n // Use a duplication of the connection to avoid\n // timeouts when the connection is in the blocking\n // mode (e.g. waiting for BLPOP).\n const duplicatedConnection = redis.duplicate({\n enableOfflineQueue: true,\n enableReadyCheck: false,\n retryStrategy: null,\n connectionName: (0, util_1.getConnectionName)(\"refresher\", this.options.redisOptions && this.options.redisOptions.connectionName),\n });\n // Ignore error events since we will handle\n // exceptions for the CLUSTER SLOTS command.\n duplicatedConnection.on(\"error\", utils_1.noop);\n duplicatedConnection.cluster(\"SLOTS\", (0, utils_1.timeout)((err, result) => {\n duplicatedConnection.disconnect();\n if (err) {\n debug(\"error encountered running CLUSTER.SLOTS: %s\", err);\n return callback(err);\n }\n if (this.status === \"disconnecting\" ||\n this.status === \"close\" ||\n this.status === \"end\") {\n debug(\"ignore CLUSTER.SLOTS results (count: %d) since cluster status is %s\", result.length, this.status);\n callback();\n return;\n }\n const nodes = [];\n debug(\"cluster slots result count: %d\", result.length);\n for (let i = 0; i < result.length; ++i) {\n const items = result[i];\n const slotRangeStart = items[0];\n const slotRangeEnd = items[1];\n const keys = [];\n for (let j = 2; j < items.length; j++) {\n if (!items[j][0]) {\n continue;\n }\n const node = this.natMapper({\n host: items[j][0],\n port: items[j][1],\n });\n node.readOnly = j !== 2;\n nodes.push(node);\n keys.push(node.host + \":\" + node.port);\n }\n debug(\"cluster slots result [%d]: slots %d~%d served by %s\", i, slotRangeStart, slotRangeEnd, keys);\n for (let slot = slotRangeStart; slot <= slotRangeEnd; slot++) {\n this.slots[slot] = keys;\n }\n }\n // Assign to each node keys a numeric value to make autopipeline comparison faster.\n this._groupsIds = Object.create(null);\n let j = 0;\n for (let i = 0; i < 16384; i++) {\n const target = (this.slots[i] || []).join(\";\");\n if (!target.length) {\n this._groupsBySlot[i] = undefined;\n continue;\n }\n if (!this._groupsIds[target]) {\n this._groupsIds[target] = ++j;\n }\n this._groupsBySlot[i] = this._groupsIds[target];\n }\n this.connectionPool.reset(nodes);\n callback();\n }, this.options.slotsRefreshTimeout));\n }\n invokeReadyDelayedCallbacks(err) {\n for (const c of this._readyDelayedCallbacks) {\n process.nextTick(c, err);\n }\n this._readyDelayedCallbacks = [];\n }\n /**\n * Check whether Cluster is able to process commands\n */\n readyCheck(callback) {\n this.cluster(\"INFO\", (err, res) => {\n if (err) {\n return callback(err);\n }\n if (typeof res !== \"string\") {\n return callback();\n }\n let state;\n const lines = res.split(\"\\r\\n\");\n for (let i = 0; i < lines.length; ++i) {\n const parts = lines[i].split(\":\");\n if (parts[0] === \"cluster_state\") {\n state = parts[1];\n break;\n }\n }\n if (state === \"fail\") {\n debug(\"cluster state not ok (%s)\", state);\n callback(null, state);\n }\n else {\n callback();\n }\n });\n }\n resolveSrv(hostname) {\n return new Promise((resolve, reject) => {\n this.options.resolveSrv(hostname, (err, records) => {\n if (err) {\n return reject(err);\n }\n const self = this, groupedRecords = (0, util_1.groupSrvRecords)(records), sortedKeys = Object.keys(groupedRecords).sort((a, b) => parseInt(a) - parseInt(b));\n function tryFirstOne(err) {\n if (!sortedKeys.length) {\n return reject(err);\n }\n const key = sortedKeys[0], group = groupedRecords[key], record = (0, util_1.weightSrvRecords)(group);\n if (!group.records.length) {\n sortedKeys.shift();\n }\n self.dnsLookup(record.name).then((host) => resolve({\n host,\n port: record.port,\n }), tryFirstOne);\n }\n tryFirstOne();\n });\n });\n }\n dnsLookup(hostname) {\n return new Promise((resolve, reject) => {\n this.options.dnsLookup(hostname, (err, address) => {\n if (err) {\n debug(\"failed to resolve hostname %s to IP: %s\", hostname, err.message);\n reject(err);\n }\n else {\n debug(\"resolved hostname %s to IP %s\", hostname, address);\n resolve(address);\n }\n });\n });\n }\n /**\n * Normalize startup nodes, and resolving hostnames to IPs.\n *\n * This process happens every time when #connect() is called since\n * #startupNodes and DNS records may chanage.\n */\n async resolveStartupNodeHostnames() {\n if (!Array.isArray(this.startupNodes) || this.startupNodes.length === 0) {\n throw new Error(\"`startupNodes` should contain at least one node.\");\n }\n const startupNodes = (0, util_1.normalizeNodeOptions)(this.startupNodes);\n const hostnames = (0, util_1.getUniqueHostnamesFromOptions)(startupNodes);\n if (hostnames.length === 0) {\n return startupNodes;\n }\n const configs = await Promise.all(hostnames.map((this.options.useSRVRecords ? this.resolveSrv : this.dnsLookup).bind(this)));\n const hostnameToConfig = (0, utils_1.zipMap)(hostnames, configs);\n return startupNodes.map((node) => {\n const config = hostnameToConfig.get(node.host);\n if (!config) {\n return node;\n }\n if (this.options.useSRVRecords) {\n return Object.assign({}, node, config);\n }\n return Object.assign({}, node, { host: config });\n });\n }\n createScanStream(command, { key, options = {} }) {\n return new ScanStream_1.default({\n objectMode: true,\n key: key,\n redis: this,\n command: command,\n ...options,\n });\n }\n}\n(0, applyMixin_1.default)(Cluster, events_1.EventEmitter);\n(0, transaction_1.addTransactionSupport)(Cluster.prototype);\nexports.default = Cluster;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst utils_1 = require(\"../utils\");\nconst debug = (0, utils_1.Debug)(\"AbstractConnector\");\nclass AbstractConnector {\n constructor(disconnectTimeout) {\n this.connecting = false;\n this.disconnectTimeout = disconnectTimeout;\n }\n check(info) {\n return true;\n }\n disconnect() {\n this.connecting = false;\n if (this.stream) {\n const stream = this.stream; // Make sure callbacks refer to the same instance\n const timeout = setTimeout(() => {\n debug(\"stream %s:%s still open, destroying it\", stream.remoteAddress, stream.remotePort);\n stream.destroy();\n }, this.disconnectTimeout);\n stream.on(\"close\", () => clearTimeout(timeout));\n stream.end();\n }\n }\n}\nexports.default = AbstractConnector;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst net_1 = require(\"net\");\nconst tls_1 = require(\"tls\");\nconst utils_1 = require(\"../utils\");\nconst AbstractConnector_1 = require(\"./AbstractConnector\");\nclass StandaloneConnector extends AbstractConnector_1.default {\n constructor(options) {\n super(options.disconnectTimeout);\n this.options = options;\n }\n connect(_) {\n const { options } = this;\n this.connecting = true;\n let connectionOptions;\n if (\"path\" in options && options.path) {\n connectionOptions = {\n path: options.path,\n };\n }\n else {\n connectionOptions = {};\n if (\"port\" in options && options.port != null) {\n connectionOptions.port = options.port;\n }\n if (\"host\" in options && options.host != null) {\n connectionOptions.host = options.host;\n }\n if (\"family\" in options && options.family != null) {\n connectionOptions.family = options.family;\n }\n }\n if (options.tls) {\n Object.assign(connectionOptions, options.tls);\n }\n // TODO:\n // We use native Promise here since other Promise\n // implementation may use different schedulers that\n // cause issue when the stream is resolved in the\n // next tick.\n // Should use the provided promise in the next major\n // version and do not connect before resolved.\n return new Promise((resolve, reject) => {\n process.nextTick(() => {\n if (!this.connecting) {\n reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n return;\n }\n try {\n if (options.tls) {\n this.stream = (0, tls_1.connect)(connectionOptions);\n }\n else {\n this.stream = (0, net_1.createConnection)(connectionOptions);\n }\n }\n catch (err) {\n reject(err);\n return;\n }\n this.stream.once(\"error\", (err) => {\n this.firstError = err;\n });\n resolve(this.stream);\n });\n });\n }\n}\nexports.default = StandaloneConnector;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction isSentinelEql(a, b) {\n return ((a.host || \"127.0.0.1\") === (b.host || \"127.0.0.1\") &&\n (a.port || 26379) === (b.port || 26379));\n}\nclass SentinelIterator {\n constructor(sentinels) {\n this.cursor = 0;\n this.sentinels = sentinels.slice(0);\n }\n next() {\n const done = this.cursor >= this.sentinels.length;\n return { done, value: done ? undefined : this.sentinels[this.cursor++] };\n }\n reset(moveCurrentEndpointToFirst) {\n if (moveCurrentEndpointToFirst &&\n this.sentinels.length > 1 &&\n this.cursor !== 1) {\n this.sentinels.unshift(...this.sentinels.splice(this.cursor - 1));\n }\n this.cursor = 0;\n }\n add(sentinel) {\n for (let i = 0; i < this.sentinels.length; i++) {\n if (isSentinelEql(sentinel, this.sentinels[i])) {\n return false;\n }\n }\n this.sentinels.push(sentinel);\n return true;\n }\n toString() {\n return `${JSON.stringify(this.sentinels)} @${this.cursor}`;\n }\n}\nexports.default = SentinelIterator;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.FailoverDetector = void 0;\nconst utils_1 = require(\"../../utils\");\nconst debug = (0, utils_1.Debug)(\"FailoverDetector\");\nconst CHANNEL_NAME = \"+switch-master\";\nclass FailoverDetector {\n // sentinels can't be used for regular commands after this\n constructor(connector, sentinels) {\n this.isDisconnected = false;\n this.connector = connector;\n this.sentinels = sentinels;\n }\n cleanup() {\n this.isDisconnected = true;\n for (const sentinel of this.sentinels) {\n sentinel.client.disconnect();\n }\n }\n async subscribe() {\n debug(\"Starting FailoverDetector\");\n const promises = [];\n for (const sentinel of this.sentinels) {\n const promise = sentinel.client.subscribe(CHANNEL_NAME).catch((err) => {\n debug(\"Failed to subscribe to failover messages on sentinel %s:%s (%s)\", sentinel.address.host || \"127.0.0.1\", sentinel.address.port || 26739, err.message);\n });\n promises.push(promise);\n sentinel.client.on(\"message\", (channel) => {\n if (!this.isDisconnected && channel === CHANNEL_NAME) {\n this.disconnect();\n }\n });\n }\n await Promise.all(promises);\n }\n disconnect() {\n // Avoid disconnecting more than once per failover.\n // A new FailoverDetector will be created after reconnecting.\n this.isDisconnected = true;\n debug(\"Failover detected, disconnecting\");\n // Will call this.cleanup()\n this.connector.disconnect();\n }\n}\nexports.FailoverDetector = FailoverDetector;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.SentinelIterator = void 0;\nconst net_1 = require(\"net\");\nconst utils_1 = require(\"../../utils\");\nconst tls_1 = require(\"tls\");\nconst SentinelIterator_1 = require(\"./SentinelIterator\");\nexports.SentinelIterator = SentinelIterator_1.default;\nconst AbstractConnector_1 = require(\"../AbstractConnector\");\nconst Redis_1 = require(\"../../Redis\");\nconst FailoverDetector_1 = require(\"./FailoverDetector\");\nconst debug = (0, utils_1.Debug)(\"SentinelConnector\");\nclass SentinelConnector extends AbstractConnector_1.default {\n constructor(options) {\n super(options.disconnectTimeout);\n this.options = options;\n this.emitter = null;\n this.failoverDetector = null;\n if (!this.options.sentinels.length) {\n throw new Error(\"Requires at least one sentinel to connect to.\");\n }\n if (!this.options.name) {\n throw new Error(\"Requires the name of master.\");\n }\n this.sentinelIterator = new SentinelIterator_1.default(this.options.sentinels);\n }\n check(info) {\n const roleMatches = !info.role || this.options.role === info.role;\n if (!roleMatches) {\n debug(\"role invalid, expected %s, but got %s\", this.options.role, info.role);\n // Start from the next item.\n // Note that `reset` will move the cursor to the previous element,\n // so we advance two steps here.\n this.sentinelIterator.next();\n this.sentinelIterator.next();\n this.sentinelIterator.reset(true);\n }\n return roleMatches;\n }\n disconnect() {\n super.disconnect();\n if (this.failoverDetector) {\n this.failoverDetector.cleanup();\n }\n }\n connect(eventEmitter) {\n this.connecting = true;\n this.retryAttempts = 0;\n let lastError;\n const connectToNext = async () => {\n const endpoint = this.sentinelIterator.next();\n if (endpoint.done) {\n this.sentinelIterator.reset(false);\n const retryDelay = typeof this.options.sentinelRetryStrategy === \"function\"\n ? this.options.sentinelRetryStrategy(++this.retryAttempts)\n : null;\n let errorMsg = typeof retryDelay !== \"number\"\n ? \"All sentinels are unreachable and retry is disabled.\"\n : `All sentinels are unreachable. Retrying from scratch after ${retryDelay}ms.`;\n if (lastError) {\n errorMsg += ` Last error: ${lastError.message}`;\n }\n debug(errorMsg);\n const error = new Error(errorMsg);\n if (typeof retryDelay === \"number\") {\n eventEmitter(\"error\", error);\n await new Promise((resolve) => setTimeout(resolve, retryDelay));\n return connectToNext();\n }\n else {\n throw error;\n }\n }\n let resolved = null;\n let err = null;\n try {\n resolved = await this.resolve(endpoint.value);\n }\n catch (error) {\n err = error;\n }\n if (!this.connecting) {\n throw new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG);\n }\n const endpointAddress = endpoint.value.host + \":\" + endpoint.value.port;\n if (resolved) {\n debug(\"resolved: %s:%s from sentinel %s\", resolved.host, resolved.port, endpointAddress);\n if (this.options.enableTLSForSentinelMode && this.options.tls) {\n Object.assign(resolved, this.options.tls);\n this.stream = (0, tls_1.connect)(resolved);\n this.stream.once(\"secureConnect\", this.initFailoverDetector.bind(this));\n }\n else {\n this.stream = (0, net_1.createConnection)(resolved);\n this.stream.once(\"connect\", this.initFailoverDetector.bind(this));\n }\n this.stream.once(\"error\", (err) => {\n this.firstError = err;\n });\n return this.stream;\n }\n else {\n const errorMsg = err\n ? \"failed to connect to sentinel \" +\n endpointAddress +\n \" because \" +\n err.message\n : \"connected to sentinel \" +\n endpointAddress +\n \" successfully, but got an invalid reply: \" +\n resolved;\n debug(errorMsg);\n eventEmitter(\"sentinelError\", new Error(errorMsg));\n if (err) {\n lastError = err;\n }\n return connectToNext();\n }\n };\n return connectToNext();\n }\n async updateSentinels(client) {\n if (!this.options.updateSentinels) {\n return;\n }\n const result = await client.sentinel(\"sentinels\", this.options.name);\n if (!Array.isArray(result)) {\n return;\n }\n result\n .map(utils_1.packObject)\n .forEach((sentinel) => {\n const flags = sentinel.flags ? sentinel.flags.split(\",\") : [];\n if (flags.indexOf(\"disconnected\") === -1 &&\n sentinel.ip &&\n sentinel.port) {\n const endpoint = this.sentinelNatResolve(addressResponseToAddress(sentinel));\n if (this.sentinelIterator.add(endpoint)) {\n debug(\"adding sentinel %s:%s\", endpoint.host, endpoint.port);\n }\n }\n });\n debug(\"Updated internal sentinels: %s\", this.sentinelIterator);\n }\n async resolveMaster(client) {\n const result = await client.sentinel(\"get-master-addr-by-name\", this.options.name);\n await this.updateSentinels(client);\n return this.sentinelNatResolve(Array.isArray(result)\n ? { host: result[0], port: Number(result[1]) }\n : null);\n }\n async resolveSlave(client) {\n const result = await client.sentinel(\"slaves\", this.options.name);\n if (!Array.isArray(result)) {\n return null;\n }\n const availableSlaves = result\n .map(utils_1.packObject)\n .filter((slave) => slave.flags && !slave.flags.match(/(disconnected|s_down|o_down)/));\n return this.sentinelNatResolve(selectPreferredSentinel(availableSlaves, this.options.preferredSlaves));\n }\n sentinelNatResolve(item) {\n if (!item || !this.options.natMap)\n return item;\n const key = `${item.host}:${item.port}`;\n let result = item;\n if (typeof this.options.natMap === \"function\") {\n result = this.options.natMap(key) || item;\n }\n else if (typeof this.options.natMap === \"object\") {\n result = this.options.natMap[key] || item;\n }\n return result;\n }\n connectToSentinel(endpoint, options) {\n const redis = new Redis_1.default({\n port: endpoint.port || 26379,\n host: endpoint.host,\n username: this.options.sentinelUsername || null,\n password: this.options.sentinelPassword || null,\n family: endpoint.family ||\n // @ts-expect-error\n (\"path\" in this.options && this.options.path\n ? undefined\n : // @ts-expect-error\n this.options.family),\n tls: this.options.sentinelTLS,\n retryStrategy: null,\n enableReadyCheck: false,\n connectTimeout: this.options.connectTimeout,\n commandTimeout: this.options.sentinelCommandTimeout,\n ...options,\n });\n // @ts-expect-error\n return redis;\n }\n async resolve(endpoint) {\n const client = this.connectToSentinel(endpoint);\n // ignore the errors since resolve* methods will handle them\n client.on(\"error\", noop);\n try {\n if (this.options.role === \"slave\") {\n return await this.resolveSlave(client);\n }\n else {\n return await this.resolveMaster(client);\n }\n }\n finally {\n client.disconnect();\n }\n }\n async initFailoverDetector() {\n var _a;\n if (!this.options.failoverDetector) {\n return;\n }\n // Move the current sentinel to the first position\n this.sentinelIterator.reset(true);\n const sentinels = [];\n // In case of a large amount of sentinels, limit the number of concurrent connections\n while (sentinels.length < this.options.sentinelMaxConnections) {\n const { done, value } = this.sentinelIterator.next();\n if (done) {\n break;\n }\n const client = this.connectToSentinel(value, {\n lazyConnect: true,\n retryStrategy: this.options.sentinelReconnectStrategy,\n });\n client.on(\"reconnecting\", () => {\n var _a;\n // Tests listen to this event\n (_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit(\"sentinelReconnecting\");\n });\n sentinels.push({ address: value, client });\n }\n this.sentinelIterator.reset(false);\n if (this.failoverDetector) {\n // Clean up previous detector\n this.failoverDetector.cleanup();\n }\n this.failoverDetector = new FailoverDetector_1.FailoverDetector(this, sentinels);\n await this.failoverDetector.subscribe();\n // Tests listen to this event\n (_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit(\"failoverSubscribed\");\n }\n}\nexports.default = SentinelConnector;\nfunction selectPreferredSentinel(availableSlaves, preferredSlaves) {\n if (availableSlaves.length === 0) {\n return null;\n }\n let selectedSlave;\n if (typeof preferredSlaves === \"function\") {\n selectedSlave = preferredSlaves(availableSlaves);\n }\n else if (preferredSlaves !== null && typeof preferredSlaves === \"object\") {\n const preferredSlavesArray = Array.isArray(preferredSlaves)\n ? preferredSlaves\n : [preferredSlaves];\n // sort by priority\n preferredSlavesArray.sort((a, b) => {\n // default the priority to 1\n if (!a.prio) {\n a.prio = 1;\n }\n if (!b.prio) {\n b.prio = 1;\n }\n // lowest priority first\n if (a.prio < b.prio) {\n return -1;\n }\n if (a.prio > b.prio) {\n return 1;\n }\n return 0;\n });\n // loop over preferred slaves and return the first match\n for (let p = 0; p < preferredSlavesArray.length; p++) {\n for (let a = 0; a < availableSlaves.length; a++) {\n const slave = availableSlaves[a];\n if (slave.ip === preferredSlavesArray[p].ip) {\n if (slave.port === preferredSlavesArray[p].port) {\n selectedSlave = slave;\n break;\n }\n }\n }\n if (selectedSlave) {\n break;\n }\n }\n }\n // if none of the preferred slaves are available, a random available slave is returned\n if (!selectedSlave) {\n selectedSlave = (0, utils_1.sample)(availableSlaves);\n }\n return addressResponseToAddress(selectedSlave);\n}\nfunction addressResponseToAddress(input) {\n return { host: input.ip, port: Number(input.port) };\n}\nfunction noop() { }\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.SentinelConnector = exports.StandaloneConnector = void 0;\nconst StandaloneConnector_1 = require(\"./StandaloneConnector\");\nexports.StandaloneConnector = StandaloneConnector_1.default;\nconst SentinelConnector_1 = require(\"./SentinelConnector\");\nexports.SentinelConnector = SentinelConnector_1.default;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst redis_errors_1 = require(\"redis-errors\");\nclass MaxRetriesPerRequestError extends redis_errors_1.AbortError {\n constructor(maxRetriesPerRequest) {\n const message = `Reached the max retries per request limit (which is ${maxRetriesPerRequest}). Refer to \"maxRetriesPerRequest\" option for details.`;\n super(message);\n Error.captureStackTrace(this, this.constructor);\n }\n get name() {\n return this.constructor.name;\n }\n}\nexports.default = MaxRetriesPerRequestError;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.MaxRetriesPerRequestError = void 0;\nconst MaxRetriesPerRequestError_1 = require(\"./MaxRetriesPerRequestError\");\nexports.MaxRetriesPerRequestError = MaxRetriesPerRequestError_1.default;\n","'use strict'\n\nconst Buffer = require('buffer').Buffer\nconst StringDecoder = require('string_decoder').StringDecoder\nconst decoder = new StringDecoder()\nconst errors = require('redis-errors')\nconst ReplyError = errors.ReplyError\nconst ParserError = errors.ParserError\nvar bufferPool = Buffer.allocUnsafe(32 * 1024)\nvar bufferOffset = 0\nvar interval = null\nvar counter = 0\nvar notDecreased = 0\n\n/**\n * Used for integer numbers only\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|number}\n */\nfunction parseSimpleNumbers (parser) {\n const length = parser.buffer.length - 1\n var offset = parser.offset\n var number = 0\n var sign = 1\n\n if (parser.buffer[offset] === 45) {\n sign = -1\n offset++\n }\n\n while (offset < length) {\n const c1 = parser.buffer[offset++]\n if (c1 === 13) { // \\r\\n\n parser.offset = offset + 1\n return sign * number\n }\n number = (number * 10) + (c1 - 48)\n }\n}\n\n/**\n * Used for integer numbers in case of the returnNumbers option\n *\n * Reading the string as parts of n SMI is more efficient than\n * using a string directly.\n *\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|string}\n */\nfunction parseStringNumbers (parser) {\n const length = parser.buffer.length - 1\n var offset = parser.offset\n var number = 0\n var res = ''\n\n if (parser.buffer[offset] === 45) {\n res += '-'\n offset++\n }\n\n while (offset < length) {\n var c1 = parser.buffer[offset++]\n if (c1 === 13) { // \\r\\n\n parser.offset = offset + 1\n if (number !== 0) {\n res += number\n }\n return res\n } else if (number > 429496728) {\n res += (number * 10) + (c1 - 48)\n number = 0\n } else if (c1 === 48 && number === 0) {\n res += 0\n } else {\n number = (number * 10) + (c1 - 48)\n }\n }\n}\n\n/**\n * Parse a '+' redis simple string response but forward the offsets\n * onto convertBufferRange to generate a string.\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|string|Buffer}\n */\nfunction parseSimpleString (parser) {\n const start = parser.offset\n const buffer = parser.buffer\n const length = buffer.length - 1\n var offset = start\n\n while (offset < length) {\n if (buffer[offset++] === 13) { // \\r\\n\n parser.offset = offset + 1\n if (parser.optionReturnBuffers === true) {\n return parser.buffer.slice(start, offset - 1)\n }\n return parser.buffer.toString('utf8', start, offset - 1)\n }\n }\n}\n\n/**\n * Returns the read length\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|number}\n */\nfunction parseLength (parser) {\n const length = parser.buffer.length - 1\n var offset = parser.offset\n var number = 0\n\n while (offset < length) {\n const c1 = parser.buffer[offset++]\n if (c1 === 13) {\n parser.offset = offset + 1\n return number\n }\n number = (number * 10) + (c1 - 48)\n }\n}\n\n/**\n * Parse a ':' redis integer response\n *\n * If stringNumbers is activated the parser always returns numbers as string\n * This is important for big numbers (number > Math.pow(2, 53)) as js numbers\n * are 64bit floating point numbers with reduced precision\n *\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|number|string}\n */\nfunction parseInteger (parser) {\n if (parser.optionStringNumbers === true) {\n return parseStringNumbers(parser)\n }\n return parseSimpleNumbers(parser)\n}\n\n/**\n * Parse a '$' redis bulk string response\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|null|string}\n */\nfunction parseBulkString (parser) {\n const length = parseLength(parser)\n if (length === undefined) {\n return\n }\n if (length < 0) {\n return null\n }\n const offset = parser.offset + length\n if (offset + 2 > parser.buffer.length) {\n parser.bigStrSize = offset + 2\n parser.totalChunkSize = parser.buffer.length\n parser.bufferCache.push(parser.buffer)\n return\n }\n const start = parser.offset\n parser.offset = offset + 2\n if (parser.optionReturnBuffers === true) {\n return parser.buffer.slice(start, offset)\n }\n return parser.buffer.toString('utf8', start, offset)\n}\n\n/**\n * Parse a '-' redis error response\n * @param {JavascriptRedisParser} parser\n * @returns {ReplyError}\n */\nfunction parseError (parser) {\n var string = parseSimpleString(parser)\n if (string !== undefined) {\n if (parser.optionReturnBuffers === true) {\n string = string.toString()\n }\n return new ReplyError(string)\n }\n}\n\n/**\n * Parsing error handler, resets parser buffer\n * @param {JavascriptRedisParser} parser\n * @param {number} type\n * @returns {undefined}\n */\nfunction handleError (parser, type) {\n const err = new ParserError(\n 'Protocol error, got ' + JSON.stringify(String.fromCharCode(type)) + ' as reply type byte',\n JSON.stringify(parser.buffer),\n parser.offset\n )\n parser.buffer = null\n parser.returnFatalError(err)\n}\n\n/**\n * Parse a '*' redis array response\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|null|any[]}\n */\nfunction parseArray (parser) {\n const length = parseLength(parser)\n if (length === undefined) {\n return\n }\n if (length < 0) {\n return null\n }\n const responses = new Array(length)\n return parseArrayElements(parser, responses, 0)\n}\n\n/**\n * Push a partly parsed array to the stack\n *\n * @param {JavascriptRedisParser} parser\n * @param {any[]} array\n * @param {number} pos\n * @returns {undefined}\n */\nfunction pushArrayCache (parser, array, pos) {\n parser.arrayCache.push(array)\n parser.arrayPos.push(pos)\n}\n\n/**\n * Parse chunked redis array response\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|any[]}\n */\nfunction parseArrayChunks (parser) {\n const tmp = parser.arrayCache.pop()\n var pos = parser.arrayPos.pop()\n if (parser.arrayCache.length) {\n const res = parseArrayChunks(parser)\n if (res === undefined) {\n pushArrayCache(parser, tmp, pos)\n return\n }\n tmp[pos++] = res\n }\n return parseArrayElements(parser, tmp, pos)\n}\n\n/**\n * Parse redis array response elements\n * @param {JavascriptRedisParser} parser\n * @param {Array} responses\n * @param {number} i\n * @returns {undefined|null|any[]}\n */\nfunction parseArrayElements (parser, responses, i) {\n const bufferLength = parser.buffer.length\n while (i < responses.length) {\n const offset = parser.offset\n if (parser.offset >= bufferLength) {\n pushArrayCache(parser, responses, i)\n return\n }\n const response = parseType(parser, parser.buffer[parser.offset++])\n if (response === undefined) {\n if (!(parser.arrayCache.length || parser.bufferCache.length)) {\n parser.offset = offset\n }\n pushArrayCache(parser, responses, i)\n return\n }\n responses[i] = response\n i++\n }\n\n return responses\n}\n\n/**\n * Called the appropriate parser for the specified type.\n *\n * 36: $\n * 43: +\n * 42: *\n * 58: :\n * 45: -\n *\n * @param {JavascriptRedisParser} parser\n * @param {number} type\n * @returns {*}\n */\nfunction parseType (parser, type) {\n switch (type) {\n case 36:\n return parseBulkString(parser)\n case 43:\n return parseSimpleString(parser)\n case 42:\n return parseArray(parser)\n case 58:\n return parseInteger(parser)\n case 45:\n return parseError(parser)\n default:\n return handleError(parser, type)\n }\n}\n\n/**\n * Decrease the bufferPool size over time\n *\n * Balance between increasing and decreasing the bufferPool.\n * Decrease the bufferPool by 10% by removing the first 10% of the current pool.\n * @returns {undefined}\n */\nfunction decreaseBufferPool () {\n if (bufferPool.length > 50 * 1024) {\n if (counter === 1 || notDecreased > counter * 2) {\n const minSliceLen = Math.floor(bufferPool.length / 10)\n const sliceLength = minSliceLen < bufferOffset\n ? bufferOffset\n : minSliceLen\n bufferOffset = 0\n bufferPool = bufferPool.slice(sliceLength, bufferPool.length)\n } else {\n notDecreased++\n counter--\n }\n } else {\n clearInterval(interval)\n counter = 0\n notDecreased = 0\n interval = null\n }\n}\n\n/**\n * Check if the requested size fits in the current bufferPool.\n * If it does not, reset and increase the bufferPool accordingly.\n *\n * @param {number} length\n * @returns {undefined}\n */\nfunction resizeBuffer (length) {\n if (bufferPool.length < length + bufferOffset) {\n const multiplier = length > 1024 * 1024 * 75 ? 2 : 3\n if (bufferOffset > 1024 * 1024 * 111) {\n bufferOffset = 1024 * 1024 * 50\n }\n bufferPool = Buffer.allocUnsafe(length * multiplier + bufferOffset)\n bufferOffset = 0\n counter++\n if (interval === null) {\n interval = setInterval(decreaseBufferPool, 50)\n }\n }\n}\n\n/**\n * Concat a bulk string containing multiple chunks\n *\n * Notes:\n * 1) The first chunk might contain the whole bulk string including the \\r\n * 2) We are only safe to fully add up elements that are neither the first nor any of the last two elements\n *\n * @param {JavascriptRedisParser} parser\n * @returns {String}\n */\nfunction concatBulkString (parser) {\n const list = parser.bufferCache\n const oldOffset = parser.offset\n var chunks = list.length\n var offset = parser.bigStrSize - parser.totalChunkSize\n parser.offset = offset\n if (offset <= 2) {\n if (chunks === 2) {\n return list[0].toString('utf8', oldOffset, list[0].length + offset - 2)\n }\n chunks--\n offset = list[list.length - 2].length + offset\n }\n var res = decoder.write(list[0].slice(oldOffset))\n for (var i = 1; i < chunks - 1; i++) {\n res += decoder.write(list[i])\n }\n res += decoder.end(list[i].slice(0, offset - 2))\n return res\n}\n\n/**\n * Concat the collected chunks from parser.bufferCache.\n *\n * Increases the bufferPool size beforehand if necessary.\n *\n * @param {JavascriptRedisParser} parser\n * @returns {Buffer}\n */\nfunction concatBulkBuffer (parser) {\n const list = parser.bufferCache\n const oldOffset = parser.offset\n const length = parser.bigStrSize - oldOffset - 2\n var chunks = list.length\n var offset = parser.bigStrSize - parser.totalChunkSize\n parser.offset = offset\n if (offset <= 2) {\n if (chunks === 2) {\n return list[0].slice(oldOffset, list[0].length + offset - 2)\n }\n chunks--\n offset = list[list.length - 2].length + offset\n }\n resizeBuffer(length)\n const start = bufferOffset\n list[0].copy(bufferPool, start, oldOffset, list[0].length)\n bufferOffset += list[0].length - oldOffset\n for (var i = 1; i < chunks - 1; i++) {\n list[i].copy(bufferPool, bufferOffset)\n bufferOffset += list[i].length\n }\n list[i].copy(bufferPool, bufferOffset, 0, offset - 2)\n bufferOffset += offset - 2\n return bufferPool.slice(start, bufferOffset)\n}\n\nclass JavascriptRedisParser {\n /**\n * Javascript Redis Parser constructor\n * @param {{returnError: Function, returnReply: Function, returnFatalError?: Function, returnBuffers: boolean, stringNumbers: boolean }} options\n * @constructor\n */\n constructor (options) {\n if (!options) {\n throw new TypeError('Options are mandatory.')\n }\n if (typeof options.returnError !== 'function' || typeof options.returnReply !== 'function') {\n throw new TypeError('The returnReply and returnError options have to be functions.')\n }\n this.setReturnBuffers(!!options.returnBuffers)\n this.setStringNumbers(!!options.stringNumbers)\n this.returnError = options.returnError\n this.returnFatalError = options.returnFatalError || options.returnError\n this.returnReply = options.returnReply\n this.reset()\n }\n\n /**\n * Reset the parser values to the initial state\n *\n * @returns {undefined}\n */\n reset () {\n this.offset = 0\n this.buffer = null\n this.bigStrSize = 0\n this.totalChunkSize = 0\n this.bufferCache = []\n this.arrayCache = []\n this.arrayPos = []\n }\n\n /**\n * Set the returnBuffers option\n *\n * @param {boolean} returnBuffers\n * @returns {undefined}\n */\n setReturnBuffers (returnBuffers) {\n if (typeof returnBuffers !== 'boolean') {\n throw new TypeError('The returnBuffers argument has to be a boolean')\n }\n this.optionReturnBuffers = returnBuffers\n }\n\n /**\n * Set the stringNumbers option\n *\n * @param {boolean} stringNumbers\n * @returns {undefined}\n */\n setStringNumbers (stringNumbers) {\n if (typeof stringNumbers !== 'boolean') {\n throw new TypeError('The stringNumbers argument has to be a boolean')\n }\n this.optionStringNumbers = stringNumbers\n }\n\n /**\n * Parse the redis buffer\n * @param {Buffer} buffer\n * @returns {undefined}\n */\n execute (buffer) {\n if (this.buffer === null) {\n this.buffer = buffer\n this.offset = 0\n } else if (this.bigStrSize === 0) {\n const oldLength = this.buffer.length\n const remainingLength = oldLength - this.offset\n const newBuffer = Buffer.allocUnsafe(remainingLength + buffer.length)\n this.buffer.copy(newBuffer, 0, this.offset, oldLength)\n buffer.copy(newBuffer, remainingLength, 0, buffer.length)\n this.buffer = newBuffer\n this.offset = 0\n if (this.arrayCache.length) {\n const arr = parseArrayChunks(this)\n if (arr === undefined) {\n return\n }\n this.returnReply(arr)\n }\n } else if (this.totalChunkSize + buffer.length >= this.bigStrSize) {\n this.bufferCache.push(buffer)\n var tmp = this.optionReturnBuffers ? concatBulkBuffer(this) : concatBulkString(this)\n this.bigStrSize = 0\n this.bufferCache = []\n this.buffer = buffer\n if (this.arrayCache.length) {\n this.arrayCache[0][this.arrayPos[0]++] = tmp\n tmp = parseArrayChunks(this)\n if (tmp === undefined) {\n return\n }\n }\n this.returnReply(tmp)\n } else {\n this.bufferCache.push(buffer)\n this.totalChunkSize += buffer.length\n return\n }\n\n while (this.offset < this.buffer.length) {\n const offset = this.offset\n const type = this.buffer[this.offset++]\n const response = parseType(this, type)\n if (response === undefined) {\n if (!(this.arrayCache.length || this.bufferCache.length)) {\n this.offset = offset\n }\n return\n }\n\n if (type === 45) {\n this.returnError(response)\n } else {\n this.returnReply(response)\n }\n }\n\n this.buffer = null\n }\n}\n\nmodule.exports = JavascriptRedisParser\n","'use strict'\n\nmodule.exports = require('./lib/parser')\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n/**\n * Tiny class to simplify dealing with subscription set\n */\nclass SubscriptionSet {\n constructor() {\n this.set = {\n subscribe: {},\n psubscribe: {},\n ssubscribe: {},\n };\n }\n add(set, channel) {\n this.set[mapSet(set)][channel] = true;\n }\n del(set, channel) {\n delete this.set[mapSet(set)][channel];\n }\n channels(set) {\n return Object.keys(this.set[mapSet(set)]);\n }\n isEmpty() {\n return (this.channels(\"subscribe\").length === 0 &&\n this.channels(\"psubscribe\").length === 0 &&\n this.channels(\"ssubscribe\").length === 0);\n }\n}\nexports.default = SubscriptionSet;\nfunction mapSet(set) {\n if (set === \"unsubscribe\") {\n return \"subscribe\";\n }\n if (set === \"punsubscribe\") {\n return \"psubscribe\";\n }\n if (set === \"sunsubscribe\") {\n return \"ssubscribe\";\n }\n return set;\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst Command_1 = require(\"./Command\");\nconst utils_1 = require(\"./utils\");\nconst RedisParser = require(\"redis-parser\");\nconst SubscriptionSet_1 = require(\"./SubscriptionSet\");\nconst debug = (0, utils_1.Debug)(\"dataHandler\");\nclass DataHandler {\n constructor(redis, parserOptions) {\n this.redis = redis;\n const parser = new RedisParser({\n stringNumbers: parserOptions.stringNumbers,\n returnBuffers: true,\n returnError: (err) => {\n this.returnError(err);\n },\n returnFatalError: (err) => {\n this.returnFatalError(err);\n },\n returnReply: (reply) => {\n this.returnReply(reply);\n },\n });\n // prependListener ensures the parser receives and processes data before socket timeout checks are performed\n redis.stream.prependListener(\"data\", (data) => {\n parser.execute(data);\n });\n // prependListener() doesn't enable flowing mode automatically - we need to resume the stream manually\n redis.stream.resume();\n }\n returnFatalError(err) {\n err.message += \". Please report this.\";\n this.redis.recoverFromFatalError(err, err, { offlineQueue: false });\n }\n returnError(err) {\n const item = this.shiftCommand(err);\n if (!item) {\n return;\n }\n err.command = {\n name: item.command.name,\n args: item.command.args,\n };\n this.redis.handleReconnection(err, item);\n }\n returnReply(reply) {\n if (this.handleMonitorReply(reply)) {\n return;\n }\n if (this.handleSubscriberReply(reply)) {\n return;\n }\n const item = this.shiftCommand(reply);\n if (!item) {\n return;\n }\n if (Command_1.default.checkFlag(\"ENTER_SUBSCRIBER_MODE\", item.command.name)) {\n this.redis.condition.subscriber = new SubscriptionSet_1.default();\n this.redis.condition.subscriber.add(item.command.name, reply[1].toString());\n if (!fillSubCommand(item.command, reply[2])) {\n this.redis.commandQueue.unshift(item);\n }\n }\n else if (Command_1.default.checkFlag(\"EXIT_SUBSCRIBER_MODE\", item.command.name)) {\n if (!fillUnsubCommand(item.command, reply[2])) {\n this.redis.commandQueue.unshift(item);\n }\n }\n else {\n item.command.resolve(reply);\n }\n }\n handleSubscriberReply(reply) {\n if (!this.redis.condition.subscriber) {\n return false;\n }\n const replyType = Array.isArray(reply) ? reply[0].toString() : null;\n debug('receive reply \"%s\" in subscriber mode', replyType);\n switch (replyType) {\n case \"message\":\n if (this.redis.listeners(\"message\").length > 0) {\n // Check if there're listeners to avoid unnecessary `toString()`.\n this.redis.emit(\"message\", reply[1].toString(), reply[2] ? reply[2].toString() : \"\");\n }\n this.redis.emit(\"messageBuffer\", reply[1], reply[2]);\n break;\n case \"pmessage\": {\n const pattern = reply[1].toString();\n if (this.redis.listeners(\"pmessage\").length > 0) {\n this.redis.emit(\"pmessage\", pattern, reply[2].toString(), reply[3].toString());\n }\n this.redis.emit(\"pmessageBuffer\", pattern, reply[2], reply[3]);\n break;\n }\n case \"smessage\": {\n if (this.redis.listeners(\"smessage\").length > 0) {\n this.redis.emit(\"smessage\", reply[1].toString(), reply[2] ? reply[2].toString() : \"\");\n }\n this.redis.emit(\"smessageBuffer\", reply[1], reply[2]);\n break;\n }\n case \"ssubscribe\":\n case \"subscribe\":\n case \"psubscribe\": {\n const channel = reply[1].toString();\n this.redis.condition.subscriber.add(replyType, channel);\n const item = this.shiftCommand(reply);\n if (!item) {\n return;\n }\n if (!fillSubCommand(item.command, reply[2])) {\n this.redis.commandQueue.unshift(item);\n }\n break;\n }\n case \"sunsubscribe\":\n case \"unsubscribe\":\n case \"punsubscribe\": {\n const channel = reply[1] ? reply[1].toString() : null;\n if (channel) {\n this.redis.condition.subscriber.del(replyType, channel);\n }\n const count = reply[2];\n if (Number(count) === 0) {\n this.redis.condition.subscriber = false;\n }\n const item = this.shiftCommand(reply);\n if (!item) {\n return;\n }\n if (!fillUnsubCommand(item.command, count)) {\n this.redis.commandQueue.unshift(item);\n }\n break;\n }\n default: {\n const item = this.shiftCommand(reply);\n if (!item) {\n return;\n }\n item.command.resolve(reply);\n }\n }\n return true;\n }\n handleMonitorReply(reply) {\n if (this.redis.status !== \"monitoring\") {\n return false;\n }\n const replyStr = reply.toString();\n if (replyStr === \"OK\") {\n // Valid commands in the monitoring mode are AUTH and MONITOR,\n // both of which always reply with 'OK'.\n // So if we got an 'OK', we can make certain that\n // the reply is made to AUTH & MONITOR.\n return false;\n }\n // Since commands sent in the monitoring mode will trigger an exception,\n // any replies we received in the monitoring mode should consider to be\n // realtime monitor data instead of result of commands.\n const len = replyStr.indexOf(\" \");\n const timestamp = replyStr.slice(0, len);\n const argIndex = replyStr.indexOf('\"');\n const args = replyStr\n .slice(argIndex + 1, -1)\n .split('\" \"')\n .map((elem) => elem.replace(/\\\\\"/g, '\"'));\n const dbAndSource = replyStr.slice(len + 2, argIndex - 2).split(\" \");\n this.redis.emit(\"monitor\", timestamp, args, dbAndSource[1], dbAndSource[0]);\n return true;\n }\n shiftCommand(reply) {\n const item = this.redis.commandQueue.shift();\n if (!item) {\n const message = \"Command queue state error. If you can reproduce this, please report it.\";\n const error = new Error(message +\n (reply instanceof Error\n ? ` Last error: ${reply.message}`\n : ` Last reply: ${reply.toString()}`));\n this.redis.emit(\"error\", error);\n return null;\n }\n return item;\n }\n}\nexports.default = DataHandler;\nconst remainingRepliesMap = new WeakMap();\nfunction fillSubCommand(command, count) {\n let remainingReplies = remainingRepliesMap.has(command)\n ? remainingRepliesMap.get(command)\n : command.args.length;\n remainingReplies -= 1;\n if (remainingReplies <= 0) {\n command.resolve(count);\n remainingRepliesMap.delete(command);\n return true;\n }\n remainingRepliesMap.set(command, remainingReplies);\n return false;\n}\nfunction fillUnsubCommand(command, count) {\n let remainingReplies = remainingRepliesMap.has(command)\n ? remainingRepliesMap.get(command)\n : command.args.length;\n if (remainingReplies === 0) {\n if (Number(count) === 0) {\n remainingRepliesMap.delete(command);\n command.resolve(count);\n return true;\n }\n return false;\n }\n remainingReplies -= 1;\n if (remainingReplies <= 0) {\n command.resolve(count);\n return true;\n }\n remainingRepliesMap.set(command, remainingReplies);\n return false;\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.readyHandler = exports.errorHandler = exports.closeHandler = exports.connectHandler = void 0;\nconst redis_errors_1 = require(\"redis-errors\");\nconst Command_1 = require(\"../Command\");\nconst errors_1 = require(\"../errors\");\nconst utils_1 = require(\"../utils\");\nconst DataHandler_1 = require(\"../DataHandler\");\nconst debug = (0, utils_1.Debug)(\"connection\");\nfunction connectHandler(self) {\n return function () {\n self.setStatus(\"connect\");\n self.resetCommandQueue();\n // AUTH command should be processed before any other commands\n let flushed = false;\n const { connectionEpoch } = self;\n if (self.condition.auth) {\n self.auth(self.condition.auth, function (err) {\n if (connectionEpoch !== self.connectionEpoch) {\n return;\n }\n if (err) {\n if (err.message.indexOf(\"no password is set\") !== -1) {\n console.warn(\"[WARN] Redis server does not require a password, but a password was supplied.\");\n }\n else if (err.message.indexOf(\"without any password configured for the default user\") !== -1) {\n console.warn(\"[WARN] This Redis server's `default` user does not require a password, but a password was supplied\");\n }\n else if (err.message.indexOf(\"wrong number of arguments for 'auth' command\") !== -1) {\n console.warn(`[ERROR] The server returned \"wrong number of arguments for 'auth' command\". You are probably passing both username and password to Redis version 5 or below. You should only pass the 'password' option for Redis version 5 and under.`);\n }\n else {\n flushed = true;\n self.recoverFromFatalError(err, err);\n }\n }\n });\n }\n if (self.condition.select) {\n self.select(self.condition.select).catch((err) => {\n // If the node is in cluster mode, select is disallowed.\n // In this case, reconnect won't help.\n self.silentEmit(\"error\", err);\n });\n }\n if (!self.options.enableReadyCheck) {\n exports.readyHandler(self)();\n }\n /*\n No need to keep the reference of DataHandler here\n because we don't need to do the cleanup.\n `Stream#end()` will remove all listeners for us.\n */\n new DataHandler_1.default(self, {\n stringNumbers: self.options.stringNumbers,\n });\n if (self.options.enableReadyCheck) {\n self._readyCheck(function (err, info) {\n if (connectionEpoch !== self.connectionEpoch) {\n return;\n }\n if (err) {\n if (!flushed) {\n self.recoverFromFatalError(new Error(\"Ready check failed: \" + err.message), err);\n }\n }\n else {\n if (self.connector.check(info)) {\n exports.readyHandler(self)();\n }\n else {\n self.disconnect(true);\n }\n }\n });\n }\n };\n}\nexports.connectHandler = connectHandler;\nfunction abortError(command) {\n const err = new redis_errors_1.AbortError(\"Command aborted due to connection close\");\n err.command = {\n name: command.name,\n args: command.args,\n };\n return err;\n}\n// If a contiguous set of pipeline commands starts from index zero then they\n// can be safely reattempted. If however we have a chain of pipelined commands\n// starting at index 1 or more it means we received a partial response before\n// the connection close and those pipelined commands must be aborted. For\n// example, if the queue looks like this: [2, 3, 4, 0, 1, 2] then after\n// aborting and purging we'll have a queue that looks like this: [0, 1, 2]\nfunction abortIncompletePipelines(commandQueue) {\n var _a;\n let expectedIndex = 0;\n for (let i = 0; i < commandQueue.length;) {\n const command = (_a = commandQueue.peekAt(i)) === null || _a === void 0 ? void 0 : _a.command;\n const pipelineIndex = command.pipelineIndex;\n if (pipelineIndex === undefined || pipelineIndex === 0) {\n expectedIndex = 0;\n }\n if (pipelineIndex !== undefined && pipelineIndex !== expectedIndex++) {\n commandQueue.remove(i, 1);\n command.reject(abortError(command));\n continue;\n }\n i++;\n }\n}\n// If only a partial transaction result was received before connection close,\n// we have to abort any transaction fragments that may have ended up in the\n// offline queue\nfunction abortTransactionFragments(commandQueue) {\n var _a;\n for (let i = 0; i < commandQueue.length;) {\n const command = (_a = commandQueue.peekAt(i)) === null || _a === void 0 ? void 0 : _a.command;\n if (command.name === \"multi\") {\n break;\n }\n if (command.name === \"exec\") {\n commandQueue.remove(i, 1);\n command.reject(abortError(command));\n break;\n }\n if (command.inTransaction) {\n commandQueue.remove(i, 1);\n command.reject(abortError(command));\n }\n else {\n i++;\n }\n }\n}\nfunction closeHandler(self) {\n return function () {\n const prevStatus = self.status;\n self.setStatus(\"close\");\n if (self.commandQueue.length) {\n abortIncompletePipelines(self.commandQueue);\n }\n if (self.offlineQueue.length) {\n abortTransactionFragments(self.offlineQueue);\n }\n if (prevStatus === \"ready\") {\n if (!self.prevCondition) {\n self.prevCondition = self.condition;\n }\n if (self.commandQueue.length) {\n self.prevCommandQueue = self.commandQueue;\n }\n }\n if (self.manuallyClosing) {\n self.manuallyClosing = false;\n debug(\"skip reconnecting since the connection is manually closed.\");\n return close();\n }\n if (typeof self.options.retryStrategy !== \"function\") {\n debug(\"skip reconnecting because `retryStrategy` is not a function\");\n return close();\n }\n const retryDelay = self.options.retryStrategy(++self.retryAttempts);\n if (typeof retryDelay !== \"number\") {\n debug(\"skip reconnecting because `retryStrategy` doesn't return a number\");\n return close();\n }\n debug(\"reconnect in %sms\", retryDelay);\n self.setStatus(\"reconnecting\", retryDelay);\n self.reconnectTimeout = setTimeout(function () {\n self.reconnectTimeout = null;\n self.connect().catch(utils_1.noop);\n }, retryDelay);\n const { maxRetriesPerRequest } = self.options;\n if (typeof maxRetriesPerRequest === \"number\") {\n if (maxRetriesPerRequest < 0) {\n debug(\"maxRetriesPerRequest is negative, ignoring...\");\n }\n else {\n const remainder = self.retryAttempts % (maxRetriesPerRequest + 1);\n if (remainder === 0) {\n debug(\"reach maxRetriesPerRequest limitation, flushing command queue...\");\n self.flushQueue(new errors_1.MaxRetriesPerRequestError(maxRetriesPerRequest));\n }\n }\n }\n };\n function close() {\n self.setStatus(\"end\");\n self.flushQueue(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n }\n}\nexports.closeHandler = closeHandler;\nfunction errorHandler(self) {\n return function (error) {\n debug(\"error: %s\", error);\n self.silentEmit(\"error\", error);\n };\n}\nexports.errorHandler = errorHandler;\nfunction readyHandler(self) {\n return function () {\n self.setStatus(\"ready\");\n self.retryAttempts = 0;\n if (self.options.monitor) {\n self.call(\"monitor\").then(() => self.setStatus(\"monitoring\"), (error) => self.emit(\"error\", error));\n const { sendCommand } = self;\n self.sendCommand = function (command) {\n if (Command_1.default.checkFlag(\"VALID_IN_MONITOR_MODE\", command.name)) {\n return sendCommand.call(self, command);\n }\n command.reject(new Error(\"Connection is in monitoring mode, can't process commands.\"));\n return command.promise;\n };\n self.once(\"close\", function () {\n delete self.sendCommand;\n });\n return;\n }\n const finalSelect = self.prevCondition\n ? self.prevCondition.select\n : self.condition.select;\n if (self.options.connectionName) {\n debug(\"set the connection name [%s]\", self.options.connectionName);\n self.client(\"setname\", self.options.connectionName).catch(utils_1.noop);\n }\n if (self.options.readOnly) {\n debug(\"set the connection to readonly mode\");\n self.readonly().catch(utils_1.noop);\n }\n if (self.prevCondition) {\n const condition = self.prevCondition;\n self.prevCondition = null;\n if (condition.subscriber && self.options.autoResubscribe) {\n // We re-select the previous db first since\n // `SELECT` command is not valid in sub mode.\n if (self.condition.select !== finalSelect) {\n debug(\"connect to db [%d]\", finalSelect);\n self.select(finalSelect);\n }\n const subscribeChannels = condition.subscriber.channels(\"subscribe\");\n if (subscribeChannels.length) {\n debug(\"subscribe %d channels\", subscribeChannels.length);\n self.subscribe(subscribeChannels);\n }\n const psubscribeChannels = condition.subscriber.channels(\"psubscribe\");\n if (psubscribeChannels.length) {\n debug(\"psubscribe %d channels\", psubscribeChannels.length);\n self.psubscribe(psubscribeChannels);\n }\n const ssubscribeChannels = condition.subscriber.channels(\"ssubscribe\");\n if (ssubscribeChannels.length) {\n debug(\"ssubscribe %d channels\", ssubscribeChannels.length);\n self.ssubscribe(ssubscribeChannels);\n }\n }\n }\n if (self.prevCommandQueue) {\n if (self.options.autoResendUnfulfilledCommands) {\n debug(\"resend %d unfulfilled commands\", self.prevCommandQueue.length);\n while (self.prevCommandQueue.length > 0) {\n const item = self.prevCommandQueue.shift();\n if (item.select !== self.condition.select &&\n item.command.name !== \"select\") {\n self.select(item.select);\n }\n self.sendCommand(item.command, item.stream);\n }\n }\n else {\n self.prevCommandQueue = null;\n }\n }\n if (self.offlineQueue.length) {\n debug(\"send %d commands in offline queue\", self.offlineQueue.length);\n const offlineQueue = self.offlineQueue;\n self.resetOfflineQueue();\n while (offlineQueue.length > 0) {\n const item = offlineQueue.shift();\n if (item.select !== self.condition.select &&\n item.command.name !== \"select\") {\n self.select(item.select);\n }\n self.sendCommand(item.command, item.stream);\n }\n }\n if (self.condition.select !== finalSelect) {\n debug(\"connect to db [%d]\", finalSelect);\n self.select(finalSelect);\n }\n };\n}\nexports.readyHandler = readyHandler;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.DEFAULT_REDIS_OPTIONS = void 0;\nexports.DEFAULT_REDIS_OPTIONS = {\n // Connection\n port: 6379,\n host: \"localhost\",\n family: 4,\n connectTimeout: 10000,\n disconnectTimeout: 2000,\n retryStrategy: function (times) {\n return Math.min(times * 50, 2000);\n },\n keepAlive: 0,\n noDelay: true,\n connectionName: null,\n // Sentinel\n sentinels: null,\n name: null,\n role: \"master\",\n sentinelRetryStrategy: function (times) {\n return Math.min(times * 10, 1000);\n },\n sentinelReconnectStrategy: function () {\n // This strategy only applies when sentinels are used for detecting\n // a failover, not during initial master resolution.\n // The deployment can still function when some of the sentinels are down\n // for a long period of time, so we may not want to attempt reconnection\n // very often. Therefore the default interval is fairly long (1 minute).\n return 60000;\n },\n natMap: null,\n enableTLSForSentinelMode: false,\n updateSentinels: true,\n failoverDetector: false,\n // Status\n username: null,\n password: null,\n db: 0,\n // Others\n enableOfflineQueue: true,\n enableReadyCheck: true,\n autoResubscribe: true,\n autoResendUnfulfilledCommands: true,\n lazyConnect: false,\n keyPrefix: \"\",\n reconnectOnError: null,\n readOnly: false,\n stringNumbers: false,\n maxRetriesPerRequest: 20,\n maxLoadingRetryTime: 10000,\n enableAutoPipelining: false,\n autoPipeliningIgnoredCommands: [],\n sentinelMaxConnections: 10,\n};\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst commands_1 = require(\"@ioredis/commands\");\nconst events_1 = require(\"events\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst cluster_1 = require(\"./cluster\");\nconst Command_1 = require(\"./Command\");\nconst connectors_1 = require(\"./connectors\");\nconst SentinelConnector_1 = require(\"./connectors/SentinelConnector\");\nconst eventHandler = require(\"./redis/event_handler\");\nconst RedisOptions_1 = require(\"./redis/RedisOptions\");\nconst ScanStream_1 = require(\"./ScanStream\");\nconst transaction_1 = require(\"./transaction\");\nconst utils_1 = require(\"./utils\");\nconst applyMixin_1 = require(\"./utils/applyMixin\");\nconst Commander_1 = require(\"./utils/Commander\");\nconst lodash_1 = require(\"./utils/lodash\");\nconst Deque = require(\"denque\");\nconst debug = (0, utils_1.Debug)(\"redis\");\n/**\n * This is the major component of ioredis.\n * Use it to connect to a standalone Redis server or Sentinels.\n *\n * ```typescript\n * const redis = new Redis(); // Default port is 6379\n * async function main() {\n * redis.set(\"foo\", \"bar\");\n * redis.get(\"foo\", (err, result) => {\n * // `result` should be \"bar\"\n * console.log(err, result);\n * });\n * // Or use Promise\n * const result = await redis.get(\"foo\");\n * }\n * ```\n */\nclass Redis extends Commander_1.default {\n constructor(arg1, arg2, arg3) {\n super();\n this.status = \"wait\";\n /**\n * @ignore\n */\n this.isCluster = false;\n this.reconnectTimeout = null;\n this.connectionEpoch = 0;\n this.retryAttempts = 0;\n this.manuallyClosing = false;\n // Prepare autopipelines structures\n this._autoPipelines = new Map();\n this._runningAutoPipelines = new Set();\n this.parseOptions(arg1, arg2, arg3);\n events_1.EventEmitter.call(this);\n this.resetCommandQueue();\n this.resetOfflineQueue();\n if (this.options.Connector) {\n this.connector = new this.options.Connector(this.options);\n }\n else if (this.options.sentinels) {\n const sentinelConnector = new SentinelConnector_1.default(this.options);\n sentinelConnector.emitter = this;\n this.connector = sentinelConnector;\n }\n else {\n this.connector = new connectors_1.StandaloneConnector(this.options);\n }\n if (this.options.scripts) {\n Object.entries(this.options.scripts).forEach(([name, definition]) => {\n this.defineCommand(name, definition);\n });\n }\n // end(or wait) -> connecting -> connect -> ready -> end\n if (this.options.lazyConnect) {\n this.setStatus(\"wait\");\n }\n else {\n this.connect().catch(lodash_1.noop);\n }\n }\n /**\n * Create a Redis instance.\n * This is the same as `new Redis()` but is included for compatibility with node-redis.\n */\n static createClient(...args) {\n return new Redis(...args);\n }\n get autoPipelineQueueSize() {\n let queued = 0;\n for (const pipeline of this._autoPipelines.values()) {\n queued += pipeline.length;\n }\n return queued;\n }\n /**\n * Create a connection to Redis.\n * This method will be invoked automatically when creating a new Redis instance\n * unless `lazyConnect: true` is passed.\n *\n * When calling this method manually, a Promise is returned, which will\n * be resolved when the connection status is ready.\n */\n connect(callback) {\n const promise = new Promise((resolve, reject) => {\n if (this.status === \"connecting\" ||\n this.status === \"connect\" ||\n this.status === \"ready\") {\n reject(new Error(\"Redis is already connecting/connected\"));\n return;\n }\n this.connectionEpoch += 1;\n this.setStatus(\"connecting\");\n const { options } = this;\n this.condition = {\n select: options.db,\n auth: options.username\n ? [options.username, options.password]\n : options.password,\n subscriber: false,\n };\n const _this = this;\n (0, standard_as_callback_1.default)(this.connector.connect(function (type, err) {\n _this.silentEmit(type, err);\n }), function (err, stream) {\n if (err) {\n _this.flushQueue(err);\n _this.silentEmit(\"error\", err);\n reject(err);\n _this.setStatus(\"end\");\n return;\n }\n let CONNECT_EVENT = options.tls ? \"secureConnect\" : \"connect\";\n if (\"sentinels\" in options &&\n options.sentinels &&\n !options.enableTLSForSentinelMode) {\n CONNECT_EVENT = \"connect\";\n }\n _this.stream = stream;\n if (options.noDelay) {\n stream.setNoDelay(true);\n }\n // Node ignores setKeepAlive before connect, therefore we wait for the event:\n // https://github.com/nodejs/node/issues/31663\n if (typeof options.keepAlive === \"number\") {\n if (stream.connecting) {\n stream.once(CONNECT_EVENT, () => {\n stream.setKeepAlive(true, options.keepAlive);\n });\n }\n else {\n stream.setKeepAlive(true, options.keepAlive);\n }\n }\n if (stream.connecting) {\n stream.once(CONNECT_EVENT, eventHandler.connectHandler(_this));\n if (options.connectTimeout) {\n /*\n * Typically, Socket#setTimeout(0) will clear the timer\n * set before. However, in some platforms (Electron 3.x~4.x),\n * the timer will not be cleared. So we introduce a variable here.\n *\n * See https://github.com/electron/electron/issues/14915\n */\n let connectTimeoutCleared = false;\n stream.setTimeout(options.connectTimeout, function () {\n if (connectTimeoutCleared) {\n return;\n }\n stream.setTimeout(0);\n stream.destroy();\n const err = new Error(\"connect ETIMEDOUT\");\n // @ts-expect-error\n err.errorno = \"ETIMEDOUT\";\n // @ts-expect-error\n err.code = \"ETIMEDOUT\";\n // @ts-expect-error\n err.syscall = \"connect\";\n eventHandler.errorHandler(_this)(err);\n });\n stream.once(CONNECT_EVENT, function () {\n connectTimeoutCleared = true;\n stream.setTimeout(0);\n });\n }\n }\n else if (stream.destroyed) {\n const firstError = _this.connector.firstError;\n if (firstError) {\n process.nextTick(() => {\n eventHandler.errorHandler(_this)(firstError);\n });\n }\n process.nextTick(eventHandler.closeHandler(_this));\n }\n else {\n process.nextTick(eventHandler.connectHandler(_this));\n }\n if (!stream.destroyed) {\n stream.once(\"error\", eventHandler.errorHandler(_this));\n stream.once(\"close\", eventHandler.closeHandler(_this));\n }\n const connectionReadyHandler = function () {\n _this.removeListener(\"close\", connectionCloseHandler);\n resolve();\n };\n var connectionCloseHandler = function () {\n _this.removeListener(\"ready\", connectionReadyHandler);\n reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n };\n _this.once(\"ready\", connectionReadyHandler);\n _this.once(\"close\", connectionCloseHandler);\n });\n });\n return (0, standard_as_callback_1.default)(promise, callback);\n }\n /**\n * Disconnect from Redis.\n *\n * This method closes the connection immediately,\n * and may lose some pending replies that haven't written to client.\n * If you want to wait for the pending replies, use Redis#quit instead.\n */\n disconnect(reconnect = false) {\n if (!reconnect) {\n this.manuallyClosing = true;\n }\n if (this.reconnectTimeout && !reconnect) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n if (this.status === \"wait\") {\n eventHandler.closeHandler(this)();\n }\n else {\n this.connector.disconnect();\n }\n }\n /**\n * Disconnect from Redis.\n *\n * @deprecated\n */\n end() {\n this.disconnect();\n }\n /**\n * Create a new instance with the same options as the current one.\n *\n * @example\n * ```js\n * var redis = new Redis(6380);\n * var anotherRedis = redis.duplicate();\n * ```\n */\n duplicate(override) {\n return new Redis({ ...this.options, ...override });\n }\n /**\n * Mode of the connection.\n *\n * One of `\"normal\"`, `\"subscriber\"`, or `\"monitor\"`. When the connection is\n * not in `\"normal\"` mode, certain commands are not allowed.\n */\n get mode() {\n var _a;\n return this.options.monitor\n ? \"monitor\"\n : ((_a = this.condition) === null || _a === void 0 ? void 0 : _a.subscriber)\n ? \"subscriber\"\n : \"normal\";\n }\n /**\n * Listen for all requests received by the server in real time.\n *\n * This command will create a new connection to Redis and send a\n * MONITOR command via the new connection in order to avoid disturbing\n * the current connection.\n *\n * @param callback The callback function. If omit, a promise will be returned.\n * @example\n * ```js\n * var redis = new Redis();\n * redis.monitor(function (err, monitor) {\n * // Entering monitoring mode.\n * monitor.on('monitor', function (time, args, source, database) {\n * console.log(time + \": \" + util.inspect(args));\n * });\n * });\n *\n * // supports promise as well as other commands\n * redis.monitor().then(function (monitor) {\n * monitor.on('monitor', function (time, args, source, database) {\n * console.log(time + \": \" + util.inspect(args));\n * });\n * });\n * ```\n */\n monitor(callback) {\n const monitorInstance = this.duplicate({\n monitor: true,\n lazyConnect: false,\n });\n return (0, standard_as_callback_1.default)(new Promise(function (resolve, reject) {\n monitorInstance.once(\"error\", reject);\n monitorInstance.once(\"monitoring\", function () {\n resolve(monitorInstance);\n });\n }), callback);\n }\n /**\n * Send a command to Redis\n *\n * This method is used internally and in most cases you should not\n * use it directly. If you need to send a command that is not supported\n * by the library, you can use the `call` method:\n *\n * ```js\n * const redis = new Redis();\n *\n * redis.call('set', 'foo', 'bar');\n * // or\n * redis.call(['set', 'foo', 'bar']);\n * ```\n *\n * @ignore\n */\n sendCommand(command, stream) {\n var _a, _b;\n if (this.status === \"wait\") {\n this.connect().catch(lodash_1.noop);\n }\n if (this.status === \"end\") {\n command.reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n return command.promise;\n }\n if (((_a = this.condition) === null || _a === void 0 ? void 0 : _a.subscriber) &&\n !Command_1.default.checkFlag(\"VALID_IN_SUBSCRIBER_MODE\", command.name)) {\n command.reject(new Error(\"Connection in subscriber mode, only subscriber commands may be used\"));\n return command.promise;\n }\n if (typeof this.options.commandTimeout === \"number\") {\n command.setTimeout(this.options.commandTimeout);\n }\n let writable = this.status === \"ready\" ||\n (!stream &&\n this.status === \"connect\" &&\n (0, commands_1.exists)(command.name) &&\n (0, commands_1.hasFlag)(command.name, \"loading\"));\n if (!this.stream) {\n writable = false;\n }\n else if (!this.stream.writable) {\n writable = false;\n // @ts-expect-error\n }\n else if (this.stream._writableState && this.stream._writableState.ended) {\n // TODO: We should be able to remove this as the PR has already been merged.\n // https://github.com/iojs/io.js/pull/1217\n writable = false;\n }\n if (!writable) {\n if (!this.options.enableOfflineQueue) {\n command.reject(new Error(\"Stream isn't writeable and enableOfflineQueue options is false\"));\n return command.promise;\n }\n if (command.name === \"quit\" && this.offlineQueue.length === 0) {\n this.disconnect();\n command.resolve(Buffer.from(\"OK\"));\n return command.promise;\n }\n // @ts-expect-error\n if (debug.enabled) {\n debug(\"queue command[%s]: %d -> %s(%o)\", this._getDescription(), this.condition.select, command.name, command.args);\n }\n this.offlineQueue.push({\n command: command,\n stream: stream,\n select: this.condition.select,\n });\n }\n else {\n // @ts-expect-error\n if (debug.enabled) {\n debug(\"write command[%s]: %d -> %s(%o)\", this._getDescription(), (_b = this.condition) === null || _b === void 0 ? void 0 : _b.select, command.name, command.args);\n }\n if (stream) {\n if (\"isPipeline\" in stream && stream.isPipeline) {\n stream.write(command.toWritable(stream.destination.redis.stream));\n }\n else {\n stream.write(command.toWritable(stream));\n }\n }\n else {\n this.stream.write(command.toWritable(this.stream));\n }\n this.commandQueue.push({\n command: command,\n stream: stream,\n select: this.condition.select,\n });\n if (Command_1.default.checkFlag(\"WILL_DISCONNECT\", command.name)) {\n this.manuallyClosing = true;\n }\n if (this.options.socketTimeout !== undefined && this.socketTimeoutTimer === undefined) {\n this.setSocketTimeout();\n }\n }\n if (command.name === \"select\" && (0, utils_1.isInt)(command.args[0])) {\n const db = parseInt(command.args[0], 10);\n if (this.condition.select !== db) {\n this.condition.select = db;\n this.emit(\"select\", db);\n debug(\"switch to db [%d]\", this.condition.select);\n }\n }\n return command.promise;\n }\n setSocketTimeout() {\n this.socketTimeoutTimer = setTimeout(() => {\n this.stream.destroy(new Error(`Socket timeout. Expecting data, but didn't receive any in ${this.options.socketTimeout}ms.`));\n this.socketTimeoutTimer = undefined;\n }, this.options.socketTimeout);\n // this handler must run after the \"data\" handler in \"DataHandler\"\n // so that `this.commandQueue.length` will be updated\n this.stream.once(\"data\", () => {\n clearTimeout(this.socketTimeoutTimer);\n this.socketTimeoutTimer = undefined;\n if (this.commandQueue.length === 0)\n return;\n this.setSocketTimeout();\n });\n }\n scanStream(options) {\n return this.createScanStream(\"scan\", { options });\n }\n scanBufferStream(options) {\n return this.createScanStream(\"scanBuffer\", { options });\n }\n sscanStream(key, options) {\n return this.createScanStream(\"sscan\", { key, options });\n }\n sscanBufferStream(key, options) {\n return this.createScanStream(\"sscanBuffer\", { key, options });\n }\n hscanStream(key, options) {\n return this.createScanStream(\"hscan\", { key, options });\n }\n hscanBufferStream(key, options) {\n return this.createScanStream(\"hscanBuffer\", { key, options });\n }\n zscanStream(key, options) {\n return this.createScanStream(\"zscan\", { key, options });\n }\n zscanBufferStream(key, options) {\n return this.createScanStream(\"zscanBuffer\", { key, options });\n }\n /**\n * Emit only when there's at least one listener.\n *\n * @ignore\n */\n silentEmit(eventName, arg) {\n let error;\n if (eventName === \"error\") {\n error = arg;\n if (this.status === \"end\") {\n return;\n }\n if (this.manuallyClosing) {\n // ignore connection related errors when manually disconnecting\n if (error instanceof Error &&\n (error.message === utils_1.CONNECTION_CLOSED_ERROR_MSG ||\n // @ts-expect-error\n error.syscall === \"connect\" ||\n // @ts-expect-error\n error.syscall === \"read\")) {\n return;\n }\n }\n }\n if (this.listeners(eventName).length > 0) {\n return this.emit.apply(this, arguments);\n }\n if (error && error instanceof Error) {\n console.error(\"[ioredis] Unhandled error event:\", error.stack);\n }\n return false;\n }\n /**\n * @ignore\n */\n recoverFromFatalError(_commandError, err, options) {\n this.flushQueue(err, options);\n this.silentEmit(\"error\", err);\n this.disconnect(true);\n }\n /**\n * @ignore\n */\n handleReconnection(err, item) {\n var _a;\n let needReconnect = false;\n if (this.options.reconnectOnError) {\n needReconnect = this.options.reconnectOnError(err);\n }\n switch (needReconnect) {\n case 1:\n case true:\n if (this.status !== \"reconnecting\") {\n this.disconnect(true);\n }\n item.command.reject(err);\n break;\n case 2:\n if (this.status !== \"reconnecting\") {\n this.disconnect(true);\n }\n if (((_a = this.condition) === null || _a === void 0 ? void 0 : _a.select) !== item.select &&\n item.command.name !== \"select\") {\n this.select(item.select);\n }\n // TODO\n // @ts-expect-error\n this.sendCommand(item.command);\n break;\n default:\n item.command.reject(err);\n }\n }\n /**\n * Get description of the connection. Used for debugging.\n */\n _getDescription() {\n let description;\n if (\"path\" in this.options && this.options.path) {\n description = this.options.path;\n }\n else if (this.stream &&\n this.stream.remoteAddress &&\n this.stream.remotePort) {\n description = this.stream.remoteAddress + \":\" + this.stream.remotePort;\n }\n else if (\"host\" in this.options && this.options.host) {\n description = this.options.host + \":\" + this.options.port;\n }\n else {\n // Unexpected\n description = \"\";\n }\n if (this.options.connectionName) {\n description += ` (${this.options.connectionName})`;\n }\n return description;\n }\n resetCommandQueue() {\n this.commandQueue = new Deque();\n }\n resetOfflineQueue() {\n this.offlineQueue = new Deque();\n }\n parseOptions(...args) {\n const options = {};\n let isTls = false;\n for (let i = 0; i < args.length; ++i) {\n const arg = args[i];\n if (arg === null || typeof arg === \"undefined\") {\n continue;\n }\n if (typeof arg === \"object\") {\n (0, lodash_1.defaults)(options, arg);\n }\n else if (typeof arg === \"string\") {\n (0, lodash_1.defaults)(options, (0, utils_1.parseURL)(arg));\n if (arg.startsWith(\"rediss://\")) {\n isTls = true;\n }\n }\n else if (typeof arg === \"number\") {\n options.port = arg;\n }\n else {\n throw new Error(\"Invalid argument \" + arg);\n }\n }\n if (isTls) {\n (0, lodash_1.defaults)(options, { tls: true });\n }\n (0, lodash_1.defaults)(options, Redis.defaultOptions);\n if (typeof options.port === \"string\") {\n options.port = parseInt(options.port, 10);\n }\n if (typeof options.db === \"string\") {\n options.db = parseInt(options.db, 10);\n }\n // @ts-expect-error\n this.options = (0, utils_1.resolveTLSProfile)(options);\n }\n /**\n * Change instance's status\n */\n setStatus(status, arg) {\n // @ts-expect-error\n if (debug.enabled) {\n debug(\"status[%s]: %s -> %s\", this._getDescription(), this.status || \"[empty]\", status);\n }\n this.status = status;\n process.nextTick(this.emit.bind(this, status, arg));\n }\n createScanStream(command, { key, options = {} }) {\n return new ScanStream_1.default({\n objectMode: true,\n key: key,\n redis: this,\n command: command,\n ...options,\n });\n }\n /**\n * Flush offline queue and command queue with error.\n *\n * @param error The error object to send to the commands\n * @param options options\n */\n flushQueue(error, options) {\n options = (0, lodash_1.defaults)({}, options, {\n offlineQueue: true,\n commandQueue: true,\n });\n let item;\n if (options.offlineQueue) {\n while ((item = this.offlineQueue.shift())) {\n item.command.reject(error);\n }\n }\n if (options.commandQueue) {\n if (this.commandQueue.length > 0) {\n if (this.stream) {\n this.stream.removeAllListeners(\"data\");\n }\n while ((item = this.commandQueue.shift())) {\n item.command.reject(error);\n }\n }\n }\n }\n /**\n * Check whether Redis has finished loading the persistent data and is able to\n * process commands.\n */\n _readyCheck(callback) {\n const _this = this;\n this.info(function (err, res) {\n if (err) {\n if (err.message && err.message.includes(\"NOPERM\")) {\n console.warn(`Skipping the ready check because INFO command fails: \"${err.message}\". You can disable ready check with \"enableReadyCheck\". More: https://github.com/luin/ioredis/wiki/Disable-ready-check.`);\n return callback(null, {});\n }\n return callback(err);\n }\n if (typeof res !== \"string\") {\n return callback(null, res);\n }\n const info = {};\n const lines = res.split(\"\\r\\n\");\n for (let i = 0; i < lines.length; ++i) {\n const [fieldName, ...fieldValueParts] = lines[i].split(\":\");\n const fieldValue = fieldValueParts.join(\":\");\n if (fieldValue) {\n info[fieldName] = fieldValue;\n }\n }\n if (!info.loading || info.loading === \"0\") {\n callback(null, info);\n }\n else {\n const loadingEtaMs = (info.loading_eta_seconds || 1) * 1000;\n const retryTime = _this.options.maxLoadingRetryTime &&\n _this.options.maxLoadingRetryTime < loadingEtaMs\n ? _this.options.maxLoadingRetryTime\n : loadingEtaMs;\n debug(\"Redis server still loading, trying again in \" + retryTime + \"ms\");\n setTimeout(function () {\n _this._readyCheck(callback);\n }, retryTime);\n }\n }).catch(lodash_1.noop);\n }\n}\nRedis.Cluster = cluster_1.default;\nRedis.Command = Command_1.default;\n/**\n * Default options\n */\nRedis.defaultOptions = RedisOptions_1.DEFAULT_REDIS_OPTIONS;\n(0, applyMixin_1.default)(Redis, events_1.EventEmitter);\n(0, transaction_1.addTransactionSupport)(Redis.prototype);\nexports.default = Redis;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.print = exports.ReplyError = exports.SentinelIterator = exports.SentinelConnector = exports.AbstractConnector = exports.Pipeline = exports.ScanStream = exports.Command = exports.Cluster = exports.Redis = exports.default = void 0;\nexports = module.exports = require(\"./Redis\").default;\nvar Redis_1 = require(\"./Redis\");\nObject.defineProperty(exports, \"default\", { enumerable: true, get: function () { return Redis_1.default; } });\nvar Redis_2 = require(\"./Redis\");\nObject.defineProperty(exports, \"Redis\", { enumerable: true, get: function () { return Redis_2.default; } });\nvar cluster_1 = require(\"./cluster\");\nObject.defineProperty(exports, \"Cluster\", { enumerable: true, get: function () { return cluster_1.default; } });\n/**\n * @ignore\n */\nvar Command_1 = require(\"./Command\");\nObject.defineProperty(exports, \"Command\", { enumerable: true, get: function () { return Command_1.default; } });\n/**\n * @ignore\n */\nvar ScanStream_1 = require(\"./ScanStream\");\nObject.defineProperty(exports, \"ScanStream\", { enumerable: true, get: function () { return ScanStream_1.default; } });\n/**\n * @ignore\n */\nvar Pipeline_1 = require(\"./Pipeline\");\nObject.defineProperty(exports, \"Pipeline\", { enumerable: true, get: function () { return Pipeline_1.default; } });\n/**\n * @ignore\n */\nvar AbstractConnector_1 = require(\"./connectors/AbstractConnector\");\nObject.defineProperty(exports, \"AbstractConnector\", { enumerable: true, get: function () { return AbstractConnector_1.default; } });\n/**\n * @ignore\n */\nvar SentinelConnector_1 = require(\"./connectors/SentinelConnector\");\nObject.defineProperty(exports, \"SentinelConnector\", { enumerable: true, get: function () { return SentinelConnector_1.default; } });\nObject.defineProperty(exports, \"SentinelIterator\", { enumerable: true, get: function () { return SentinelConnector_1.SentinelIterator; } });\n// No TS typings\nexports.ReplyError = require(\"redis-errors\").ReplyError;\n/**\n * @ignore\n */\nObject.defineProperty(exports, \"Promise\", {\n get() {\n console.warn(\"ioredis v5 does not support plugging third-party Promise library anymore. Native Promise will be used.\");\n return Promise;\n },\n set(_lib) {\n console.warn(\"ioredis v5 does not support plugging third-party Promise library anymore. Native Promise will be used.\");\n },\n});\n/**\n * @ignore\n */\nfunction print(err, reply) {\n if (err) {\n console.log(\"Error: \" + err);\n }\n else {\n console.log(\"Reply: \" + reply);\n }\n}\nexports.print = print;\n","import {\n Redis,\n type Cluster,\n type ClusterNode,\n type ClusterOptions,\n type RedisOptions,\n} from \"ioredis\";\nimport { Logger } from \"@trigger.dev/core/logger\";\n\nexport {\n Redis,\n Cluster,\n type Callback,\n type RedisOptions,\n type ClusterNode,\n type ClusterOptions,\n type Result,\n type RedisCommander,\n} from \"ioredis\";\n\n/**\n * Either endpoint shape. A component that only issues key-addressed commands works against both, so\n * it should accept this rather than pin itself to a standalone connection. Commands with no key —\n * SCAN above all — do NOT fan out across a cluster, so anything that issues one must iterate\n * `cluster.nodes(\"master\")` itself.\n */\nexport type RedisClient = Redis | Cluster;\n\n/**\n * Reply-error -> reconnect mapping. Without this hook, an ElastiCache\n * vertical scale-up surfaces tens of thousands of READONLY / LOADING\n * reply errors to caller code over a healthy TCP/TLS connection (the\n * client keeps talking to a node whose role swapped underneath it).\n *\n * UNBLOCKED is the BLPOP-shaped case: the Redis primary forcibly\n * unblocks any blocking command on a connection whose node is about\n * to be demoted, returning an UNBLOCKED reply. Surfaced 65 times on\n * engine/v1/worker-actions/dequeue at the cutover instant during the\n * TRI-8873 test-cloud scale-up dry-run.\n *\n * Returning 2 tells ioredis to disconnect, reconnect, and retry the\n * command that triggered the error. After reconnect, DNS / SG routing\n * should land on a writable primary.\n *\n * Empirical confirmation on the harness in TRI-8878: this option\n * reduced a scale-up event from ~437,000 caller-surfaced errors to 2.\n */\nexport function defaultReconnectOnError(err: Error): boolean | 1 | 2 {\n const msg = err.message ?? \"\";\n if (msg.startsWith(\"READONLY\") || msg.startsWith(\"LOADING\") || msg.startsWith(\"UNBLOCKED\")) {\n return 2;\n }\n return false;\n}\n\nconst defaultOptions: Partial<RedisOptions> = {\n retryStrategy: (times: number) => {\n const delay = Math.min(times * 50, 1000);\n return delay;\n },\n maxRetriesPerRequest: process.env.GITHUB_ACTIONS ? 50 : process.env.VITEST ? 5 : 20,\n reconnectOnError: defaultReconnectOnError,\n};\n\nconst logger = new Logger(\"Redis\", \"debug\");\n\nexport function createRedisClient(\n options: RedisOptions,\n handlers?: { onError?: (err: Error) => void }\n): Redis {\n const client = new Redis({\n ...defaultOptions,\n ...options,\n });\n\n // Skip error handling setup if running in Vitest\n if (process.env.VITEST) {\n client.on(\"error\", (error) => {\n // swallow errors\n });\n return client;\n }\n\n client.on(\"error\", (error) => {\n if (handlers?.onError) {\n handlers.onError(error);\n } else {\n logger.error(`Redis client error:`, { error, keyPrefix: options.keyPrefix });\n }\n });\n\n return client;\n}\n\nexport type RedisClusterClientOptions = {\n nodes: ClusterNode[];\n clusterOptions?: Omit<ClusterOptions, \"redisOptions\">;\n redisOptions?: RedisOptions;\n /**\n * Fail a command while the cluster is unreachable instead of queueing it. For a caller on a\n * request path, where a queued command means a hung request rather than a slow one.\n */\n failFast?: boolean;\n};\n\n/**\n * Cluster-mode client. `defaultOptions` go on the INNER per-node options, so a role swap gets the\n * same reconnect-and-retry treatment a single-node client already gets.\n */\nexport function createRedisClusterClient(\n options: RedisClusterClientOptions,\n handlers?: { onError?: (err: Error) => void }\n): Cluster {\n const client = new Redis.Cluster(options.nodes, {\n // The offline queue is a CLUSTER-level setting, separate from the per-node one below. While a\n // cluster cannot refresh its slot cache it queues commands here, so a caller that wants a\n // failure during an outage rather than a wait has to turn THIS one off. Default stays `true`,\n // matching ioredis, so only a caller that asks for it changes behaviour.\n ...(options.failFast && { enableOfflineQueue: false }),\n ...options.clusterOptions,\n redisOptions: {\n ...defaultOptions,\n ...(options.failFast && { enableOfflineQueue: false }),\n ...options.redisOptions,\n },\n });\n\n if (process.env.VITEST) {\n client.on(\"error\", () => {});\n return client;\n }\n\n client.on(\"error\", (error) => {\n if (handlers?.onError) {\n handlers.onError(error);\n } else {\n logger.error(`Redis cluster client error:`, {\n error,\n keyPrefix: options.redisOptions?.keyPrefix,\n });\n }\n });\n\n return client;\n}\n","export let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\n","import { webcrypto as crypto } from 'node:crypto'\n\nimport { urlAlphabet as scopedUrlAlphabet } from './url-alphabet/index.js'\n\nexport { urlAlphabet } from './url-alphabet/index.js'\n\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\n\nfunction fillPool(bytes) {\n if (bytes < 0) throw new RangeError('Wrong ID size')\n try {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.getRandomValues(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.getRandomValues(pool)\n poolOffset = 0\n }\n } catch (e) {\n pool = undefined\n throw e\n }\n poolOffset += bytes\n}\n\nexport function random(bytes) {\n fillPool((bytes |= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\n\nexport function customRandom(alphabet, defaultSize, getRandom) {\n let safeByteCutoff = 256 - (256 % alphabet.length)\n\n if (safeByteCutoff === 256) {\n let mask = alphabet.length - 1\n\n return (size = defaultSize) => {\n if (!size) return ''\n let id = ''\n while (true) {\n let bytes = getRandom(size)\n let i = size\n while (i--) {\n id += alphabet[bytes[i] & mask]\n if (id.length >= size) return id\n }\n }\n }\n }\n\n let step = Math.ceil((1.6 * 256 * defaultSize) / safeByteCutoff)\n\n return (size = defaultSize) => {\n if (!size) return ''\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n if (bytes[i] < safeByteCutoff) {\n id += alphabet[bytes[i] % alphabet.length]\n if (id.length >= size) return id\n }\n }\n }\n }\n}\n\nexport function customAlphabet(alphabet, size = 21) {\n return customRandom(alphabet, size, random)\n}\n\nexport function nanoid(size = 21) {\n fillPool((size |= 0))\n\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += scopedUrlAlphabet[pool[i] & 63]\n }\n return id\n}\n","import {\n createRedisClient,\n type Redis,\n type Callback,\n type RedisOptions,\n type Result,\n} from \"@internal/redis\";\nimport { Logger } from \"@trigger.dev/core/logger\";\nimport type { AnyZodSchema, inferZodSchemaOutput } from \"@trigger.dev/core/v3\";\nimport { nanoid } from \"nanoid\";\n\nexport interface MessageCatalogSchema {\n [key: string]: AnyZodSchema;\n}\n\nexport type MessageCatalogKey<TMessageCatalog extends MessageCatalogSchema> = keyof TMessageCatalog;\nexport type MessageCatalogValue<\n TMessageCatalog extends MessageCatalogSchema,\n TKey extends MessageCatalogKey<TMessageCatalog>,\n> = inferZodSchemaOutput<TMessageCatalog[TKey]>;\n\nexport type AnyMessageCatalog = MessageCatalogSchema;\nexport type QueueItem<TMessageCatalog extends MessageCatalogSchema> = {\n id: string;\n job: MessageCatalogKey<TMessageCatalog>;\n item: MessageCatalogValue<TMessageCatalog, MessageCatalogKey<TMessageCatalog>>;\n visibilityTimeoutMs: number;\n attempt: number;\n timestamp: Date;\n deduplicationKey?: string;\n};\n\nexport type AnyQueueItem = {\n id: string;\n job: string;\n item: any;\n visibilityTimeoutMs: number;\n attempt: number;\n timestamp: Date;\n deduplicationKey?: string;\n};\n\nexport class SimpleQueue<TMessageCatalog extends MessageCatalogSchema> {\n name: string;\n private redis: Redis;\n private schema: TMessageCatalog;\n private logger: Logger;\n\n constructor({\n name,\n schema,\n redisOptions,\n logger,\n }: {\n name: string;\n schema: TMessageCatalog;\n redisOptions: RedisOptions;\n logger?: Logger;\n }) {\n this.name = name;\n this.logger = logger ?? new Logger(\"SimpleQueue\", \"debug\");\n\n this.redis = createRedisClient(\n {\n ...redisOptions,\n keyPrefix: `${redisOptions.keyPrefix ?? \"\"}{queue:${name}:}`,\n retryStrategy(times) {\n const delay = Math.min(times * 50, 1000);\n return delay;\n },\n maxRetriesPerRequest: 20,\n },\n {\n onError: (error) => {\n this.logger.error(`RedisWorker queue redis client error:`, {\n error,\n keyPrefix: redisOptions.keyPrefix,\n });\n },\n }\n );\n this.#registerCommands();\n this.schema = schema;\n }\n\n async cancel(cancellationKey: string): Promise<void> {\n await this.redis.set(`cancellationKey:${cancellationKey}`, \"1\", \"EX\", 60 * 60 * 24); // 1 day\n }\n\n async enqueue({\n id,\n job,\n item,\n attempt,\n availableAt,\n visibilityTimeoutMs,\n cancellationKey,\n }: {\n id?: string;\n job: MessageCatalogKey<TMessageCatalog>;\n item: MessageCatalogValue<TMessageCatalog, MessageCatalogKey<TMessageCatalog>>;\n attempt?: number;\n availableAt?: Date;\n visibilityTimeoutMs: number;\n cancellationKey?: string;\n }): Promise<void> {\n try {\n const score = availableAt ? availableAt.getTime() : Date.now();\n const deduplicationKey = nanoid();\n const serializedItem = JSON.stringify({\n job,\n item,\n visibilityTimeoutMs,\n attempt,\n deduplicationKey,\n });\n\n const result = cancellationKey\n ? await this.redis.enqueueItemWithCancellationKey(\n `queue`,\n `items`,\n `cancellationKey:${cancellationKey}`,\n id ?? nanoid(),\n score,\n serializedItem\n )\n : await this.redis.enqueueItem(`queue`, `items`, id ?? nanoid(), score, serializedItem);\n\n if (result !== 1) {\n throw new Error(\"Enqueue operation failed\");\n }\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.enqueue(): error enqueuing`, {\n queue: this.name,\n error: e,\n id,\n item,\n });\n throw e;\n }\n }\n\n async enqueueOnce({\n id,\n job,\n item,\n attempt,\n availableAt,\n visibilityTimeoutMs,\n }: {\n id: string;\n job: MessageCatalogKey<TMessageCatalog>;\n item: MessageCatalogValue<TMessageCatalog, MessageCatalogKey<TMessageCatalog>>;\n attempt?: number;\n availableAt?: Date;\n visibilityTimeoutMs: number;\n }): Promise<boolean> {\n if (!id) {\n throw new Error(\"enqueueOnce requires an id\");\n }\n try {\n const score = availableAt ? availableAt.getTime() : Date.now();\n const deduplicationKey = nanoid();\n const serializedItem = JSON.stringify({\n job,\n item,\n visibilityTimeoutMs,\n attempt,\n deduplicationKey,\n });\n const result = await this.redis.enqueueItemOnce(`queue`, `items`, id, score, serializedItem);\n // 1 if inserted, 0 if already exists\n return result === 1;\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.enqueueOnce(): error enqueuing`, {\n queue: this.name,\n error: e,\n id,\n item,\n });\n throw e;\n }\n }\n\n async dequeue(count: number = 1): Promise<Array<QueueItem<TMessageCatalog>>> {\n const now = Date.now();\n\n try {\n const results = await this.redis.dequeueItems(`queue`, `items`, now, count);\n\n if (!results || results.length === 0) {\n return [];\n }\n\n const dequeuedItems: Array<QueueItem<TMessageCatalog>> = [];\n\n for (const [id, serializedItem, score] of results) {\n const parsedItem = JSON.parse(serializedItem) as any;\n if (typeof parsedItem.job !== \"string\") {\n this.logger.error(`Invalid item in queue`, { queue: this.name, id, item: parsedItem });\n continue;\n }\n\n const timestamp = new Date(Number(score));\n\n const schema = this.schema[parsedItem.job];\n\n if (!schema) {\n this.logger.error(`Invalid item in queue, schema not found`, {\n queue: this.name,\n id,\n item: parsedItem,\n job: parsedItem.job,\n timestamp,\n availableJobs: Object.keys(this.schema),\n });\n continue;\n }\n\n // zod v4 narrows the generic schema union here; cast to public ZodType (has safeParse in v3 & v4)\n const validatedItem = schema.safeParse(parsedItem.item);\n\n if (!validatedItem.success) {\n this.logger.error(\"Invalid item in queue\", {\n queue: this.name,\n id,\n item: parsedItem,\n errors: validatedItem.error,\n attempt: parsedItem.attempt,\n timestamp,\n });\n continue;\n }\n\n const visibilityTimeoutMs = parsedItem.visibilityTimeoutMs as number;\n\n dequeuedItems.push({\n id,\n job: parsedItem.job,\n item: validatedItem.data as QueueItem<TMessageCatalog>[\"item\"],\n visibilityTimeoutMs,\n attempt: parsedItem.attempt ?? 0,\n timestamp,\n deduplicationKey: parsedItem.deduplicationKey,\n });\n }\n\n return dequeuedItems;\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.dequeue(): error dequeuing`, {\n queue: this.name,\n error: e,\n count,\n });\n throw e;\n }\n }\n\n async ack(id: string, deduplicationKey?: string): Promise<void> {\n try {\n const result = await this.redis.ackItem(`queue`, `items`, id, deduplicationKey ?? \"\");\n if (result !== 1) {\n this.logger.debug(\n `SimpleQueue ${this.name}.ack(): ack operation returned ${result}. This means it was not removed from the queue.`,\n {\n queue: this.name,\n id,\n deduplicationKey,\n result,\n }\n );\n }\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.ack(): error acknowledging item`, {\n queue: this.name,\n error: e,\n id,\n deduplicationKey,\n });\n throw e;\n }\n }\n\n async reschedule(id: string, availableAt: Date): Promise<void> {\n await this.redis.zadd(`queue`, \"XX\", availableAt.getTime(), id);\n }\n\n async size({ includeFuture = false }: { includeFuture?: boolean } = {}): Promise<number> {\n try {\n if (includeFuture) {\n // If includeFuture is true, return the total count of all items\n return await this.redis.zcard(`queue`);\n } else {\n // If includeFuture is false, return the count of items available now\n const now = Date.now();\n return await this.redis.zcount(`queue`, \"-inf\", now);\n }\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.size(): error getting queue size`, {\n queue: this.name,\n error: e,\n includeFuture,\n });\n throw e;\n }\n }\n\n /**\n * Age (in ms) of the oldest *overdue* message — the oldest item whose scheduled\n * time has already passed (score <= now). Returns 0 when the queue is empty or\n * only holds future/delayed or in-flight (future-scored) items.\n *\n * Resolves the candidate against the `items` hash so orphaned `queue` entries\n * (a member whose payload is missing — the same stale state `dequeueItems`\n * cleans up) don't report a phantom stall for work that can't be dequeued. The\n * Lua scans due items oldest-first and returns the first score whose payload\n * still exists.\n *\n * This is the generic stall signal: it stays at 0 while a queue drains healthily\n * and rises only when due work sits undrained (poison block, dead consumer,\n * backpressure).\n */\n async oldestMessageAge(): Promise<number> {\n try {\n const now = Date.now();\n // -1 sentinel = nothing due, or every due entry is orphaned.\n const score = Number(await this.redis.getOldestDueScore(`queue`, `items`, now));\n\n if (!Number.isFinite(score) || score < 0) {\n return 0;\n }\n\n return Math.max(0, now - score);\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.oldestMessageAge(): error getting oldest age`, {\n queue: this.name,\n error: e,\n });\n // Swallow: a transient Redis error must not break observable metric collection.\n return 0;\n }\n }\n\n async getJob(id: string): Promise<QueueItem<TMessageCatalog> | null> {\n const result = await this.redis.getJob(`queue`, `items`, id);\n\n if (!result) {\n return null;\n }\n\n const [_, score, serializedItem] = result;\n const item = JSON.parse(serializedItem) as QueueItem<TMessageCatalog>;\n\n return {\n id,\n job: item.job,\n item: item.item,\n visibilityTimeoutMs: item.visibilityTimeoutMs,\n attempt: item.attempt ?? 0,\n timestamp: new Date(Number(score)),\n deduplicationKey: item.deduplicationKey ?? undefined,\n };\n }\n\n async moveToDeadLetterQueue(id: string, errorMessage: string): Promise<void> {\n try {\n this.logger.debug(`SimpleQueue ${this.name}.moveToDeadLetterQueue(): moving item to DLQ`, {\n queue: this.name,\n id,\n errorMessage,\n });\n\n const result = await this.redis.moveToDeadLetterQueue(\n `queue`,\n `items`,\n `dlq`,\n `dlq:items`,\n id,\n errorMessage\n );\n\n if (result !== 1) {\n throw new Error(\"Move to Dead Letter Queue operation failed\");\n }\n } catch (e) {\n this.logger.error(\n `SimpleQueue ${this.name}.moveToDeadLetterQueue(): error moving item to DLQ`,\n {\n queue: this.name,\n error: e,\n id,\n errorMessage,\n }\n );\n throw e;\n }\n }\n\n async sizeOfDeadLetterQueue(): Promise<number> {\n try {\n return await this.redis.zcard(`dlq`);\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.dlqSize(): error getting DLQ size`, {\n queue: this.name,\n error: e,\n });\n throw e;\n }\n }\n\n async redriveFromDeadLetterQueue(id: string): Promise<void> {\n try {\n const result = await this.redis.redriveFromDeadLetterQueue(\n `queue`,\n `items`,\n `dlq`,\n `dlq:items`,\n id\n );\n\n if (result !== 1) {\n throw new Error(\"Redrive from Dead Letter Queue operation failed\");\n }\n } catch (e) {\n this.logger.error(\n `SimpleQueue ${this.name}.redriveFromDeadLetterQueue(): error redriving item from DLQ`,\n {\n queue: this.name,\n error: e,\n id,\n }\n );\n throw e;\n }\n }\n\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n #registerCommands() {\n this.redis.defineCommand(\"enqueueItem\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local id = ARGV[1]\n local score = ARGV[2]\n local serializedItem = ARGV[3]\n\n redis.call('ZADD', queue, score, id)\n redis.call('HSET', items, id, serializedItem)\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"enqueueItemWithCancellationKey\", {\n numberOfKeys: 3,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local cancellationKey = KEYS[3]\n\n local id = ARGV[1]\n local score = ARGV[2]\n local serializedItem = ARGV[3]\n\n -- if the cancellation key exists, return 1\n if redis.call('EXISTS', cancellationKey) == 1 then\n return 1\n end\n\n redis.call('ZADD', queue, score, id)\n redis.call('HSET', items, id, serializedItem)\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"dequeueItems\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local now = tonumber(ARGV[1])\n local count = tonumber(ARGV[2])\n\n local result = redis.call('ZRANGEBYSCORE', queue, '-inf', now, 'WITHSCORES', 'LIMIT', 0, count)\n\n if #result == 0 then\n return {}\n end\n\n local dequeued = {}\n\n for i = 1, #result, 2 do\n local id = result[i]\n local score = tonumber(result[i + 1])\n\n if score > now then\n break\n end\n\n local serializedItem = redis.call('HGET', items, id)\n\n if serializedItem then\n local item = cjson.decode(serializedItem)\n local visibilityTimeoutMs = tonumber(item.visibilityTimeoutMs)\n local invisibleUntil = now + visibilityTimeoutMs\n\n redis.call('ZADD', queue, invisibleUntil, id)\n table.insert(dequeued, {id, serializedItem, score})\n else\n -- Remove the orphaned queue entry if no corresponding item exists\n redis.call('ZREM', queue, id)\n end\n end\n\n return dequeued\n `,\n });\n\n this.redis.defineCommand(\"getOldestDueScore\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local now = tonumber(ARGV[1])\n\n -- Oldest-first scan of due items, bounded so a long prefix of orphans can't\n -- make this O(n). Orphans are rare (dequeueItems removes them), so in the\n -- common case this returns on the first iteration. Read-only: unlike\n -- dequeueItems we don't ZREM orphans here — a metric probe must not mutate.\n local result = redis.call('ZRANGEBYSCORE', queue, '-inf', now, 'WITHSCORES', 'LIMIT', 0, 100)\n\n for i = 1, #result, 2 do\n local id = result[i]\n if redis.call('HEXISTS', items, id) == 1 then\n return result[i + 1]\n end\n end\n\n return -1\n `,\n });\n\n this.redis.defineCommand(\"getJob\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local jobId = ARGV[1]\n\n local serializedItem = redis.call('HGET', items, jobId)\n\n if serializedItem == false then\n return nil\n end\n\n -- get the score from the queue sorted set\n local score = redis.call('ZSCORE', queue, jobId)\n\n return { jobId, score, serializedItem }\n `,\n });\n\n this.redis.defineCommand(\"ackItem\", {\n numberOfKeys: 2,\n lua: `\n local queueKey = KEYS[1]\n local itemsKey = KEYS[2]\n local id = ARGV[1]\n local deduplicationKey = ARGV[2]\n\n -- Get the item from the hash\n local item = redis.call('HGET', itemsKey, id)\n if not item then\n return -1\n end\n\n -- Only check deduplicationKey if a non-empty one was passed in\n if deduplicationKey and deduplicationKey ~= \"\" then\n local success, parsed = pcall(cjson.decode, item)\n if success then\n if parsed.deduplicationKey and parsed.deduplicationKey ~= deduplicationKey then\n return 0\n end\n end\n end\n\n -- Remove from sorted set and hash\n redis.call('ZREM', queueKey, id)\n redis.call('HDEL', itemsKey, id)\n return 1\n `,\n });\n\n this.redis.defineCommand(\"moveToDeadLetterQueue\", {\n numberOfKeys: 4,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local dlq = KEYS[3]\n local dlqItems = KEYS[4]\n local id = ARGV[1]\n local errorMessage = ARGV[2]\n\n local item = redis.call('HGET', items, id)\n if not item then\n return 0\n end\n\n local parsedItem = cjson.decode(item)\n parsedItem.errorMessage = errorMessage\n\n local time = redis.call('TIME')\n local now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)\n\n redis.call('ZREM', queue, id)\n redis.call('HDEL', items, id)\n\n redis.call('ZADD', dlq, now, id)\n redis.call('HSET', dlqItems, id, cjson.encode(parsedItem))\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"redriveFromDeadLetterQueue\", {\n numberOfKeys: 4,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local dlq = KEYS[3]\n local dlqItems = KEYS[4]\n local id = ARGV[1]\n\n local item = redis.call('HGET', dlqItems, id)\n if not item then\n return 0\n end\n\n local parsedItem = cjson.decode(item)\n parsedItem.errorMessage = nil\n\n local time = redis.call('TIME')\n local now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)\n\n redis.call('ZREM', dlq, id)\n redis.call('HDEL', dlqItems, id)\n\n redis.call('ZADD', queue, now, id)\n redis.call('HSET', items, id, cjson.encode(parsedItem))\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"enqueueItemOnce\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local id = ARGV[1]\n local score = ARGV[2]\n local serializedItem = ARGV[3]\n\n -- Only add if not exists\n local added = redis.call('HSETNX', items, id, serializedItem)\n if added == 1 then\n redis.call('ZADD', queue, 'NX', score, id)\n return 1\n else\n return 0\n end\n `,\n });\n }\n}\n\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n enqueueItem(\n //keys\n queue: string,\n items: string,\n //args\n id: string,\n score: number,\n serializedItem: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n enqueueItemWithCancellationKey(\n //keys\n queue: string,\n items: string,\n cancellationKey: string,\n //args\n id: string,\n score: number,\n serializedItem: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n dequeueItems(\n //keys\n queue: string,\n items: string,\n //args\n now: number,\n count: number,\n callback?: Callback<Array<[string, string, string]>>\n ): Result<Array<[string, string, string]>, Context>;\n\n ackItem(\n queue: string,\n items: string,\n id: string,\n deduplicationKey: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n redriveFromDeadLetterQueue(\n queue: string,\n items: string,\n dlq: string,\n dlqItems: string,\n id: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n moveToDeadLetterQueue(\n queue: string,\n items: string,\n dlq: string,\n dlqItems: string,\n id: string,\n errorMessage: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n enqueueItemOnce(\n queue: string,\n items: string,\n id: string,\n score: number,\n serializedItem: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n getJob(\n queue: string,\n items: string,\n id: string,\n callback?: Callback<[string, string, string] | null>\n ): Result<[string, string, string] | null, Context>;\n\n getOldestDueScore(\n //keys\n queue: string,\n items: string,\n //args\n now: number,\n callback?: Callback<string | number>\n ): Result<string | number, Context>;\n }\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n// this is autogenerated file, see scripts/version-update.js\nexport const VERSION = '1.9.1';\n//# sourceMappingURL=version.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { VERSION } from '../version';\nconst re = /^(\\d+)\\.(\\d+)\\.(\\d+)(-(.+))?$/;\n/**\n * Create a function to test an API version to see if it is compatible with the provided ownVersion.\n *\n * The returned function has the following semantics:\n * - Exact match is always compatible\n * - Major versions must match exactly\n * - 1.x package cannot use global 2.x package\n * - 2.x package cannot use global 1.x package\n * - The minor version of the API module requesting access to the global API must be less than or equal to the minor version of this API\n * - 1.3 package may use 1.4 global because the later global contains all functions 1.3 expects\n * - 1.4 package may NOT use 1.3 global because it may try to call functions which don't exist on 1.3\n * - If the major version is 0, the minor version is treated as the major and the patch is treated as the minor\n * - Patch and build tag differences are not considered at this time\n *\n * @param ownVersion version which should be checked against\n */\nexport function _makeCompatibilityCheck(ownVersion) {\n const acceptedVersions = new Set([ownVersion]);\n const rejectedVersions = new Set();\n const myVersionMatch = ownVersion.match(re);\n if (!myVersionMatch) {\n // we cannot guarantee compatibility so we always return noop\n return () => false;\n }\n const ownVersionParsed = {\n major: +myVersionMatch[1],\n minor: +myVersionMatch[2],\n patch: +myVersionMatch[3],\n prerelease: myVersionMatch[4],\n };\n // if ownVersion has a prerelease tag, versions must match exactly\n if (ownVersionParsed.prerelease != null) {\n return function isExactmatch(globalVersion) {\n return globalVersion === ownVersion;\n };\n }\n function _reject(v) {\n rejectedVersions.add(v);\n return false;\n }\n function _accept(v) {\n acceptedVersions.add(v);\n return true;\n }\n return function isCompatible(globalVersion) {\n if (acceptedVersions.has(globalVersion)) {\n return true;\n }\n if (rejectedVersions.has(globalVersion)) {\n return false;\n }\n const globalVersionMatch = globalVersion.match(re);\n if (!globalVersionMatch) {\n // cannot parse other version\n // we cannot guarantee compatibility so we always noop\n return _reject(globalVersion);\n }\n const globalVersionParsed = {\n major: +globalVersionMatch[1],\n minor: +globalVersionMatch[2],\n patch: +globalVersionMatch[3],\n prerelease: globalVersionMatch[4],\n };\n // if globalVersion has a prerelease tag, versions must match exactly\n if (globalVersionParsed.prerelease != null) {\n return _reject(globalVersion);\n }\n // major versions must match\n if (ownVersionParsed.major !== globalVersionParsed.major) {\n return _reject(globalVersion);\n }\n if (ownVersionParsed.major === 0) {\n if (ownVersionParsed.minor === globalVersionParsed.minor &&\n ownVersionParsed.patch <= globalVersionParsed.patch) {\n return _accept(globalVersion);\n }\n return _reject(globalVersion);\n }\n if (ownVersionParsed.minor <= globalVersionParsed.minor) {\n return _accept(globalVersion);\n }\n return _reject(globalVersion);\n };\n}\n/**\n * Test an API version to see if it is compatible with this API.\n *\n * - Exact match is always compatible\n * - Major versions must match exactly\n * - 1.x package cannot use global 2.x package\n * - 2.x package cannot use global 1.x package\n * - The minor version of the API module requesting access to the global API must be less than or equal to the minor version of this API\n * - 1.3 package may use 1.4 global because the later global contains all functions 1.3 expects\n * - 1.4 package may NOT use 1.3 global because it may try to call functions which don't exist on 1.3\n * - If the major version is 0, the minor version is treated as the major and the patch is treated as the minor\n * - Patch and build tag differences are not considered at this time\n *\n * @param version version of the API requesting an instance of the global API\n */\nexport const isCompatible = _makeCompatibilityCheck(VERSION);\n//# sourceMappingURL=semver.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { VERSION } from '../version';\nimport { isCompatible } from './semver';\nconst major = VERSION.split('.')[0];\nconst GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for(`opentelemetry.js.api.${major}`);\nconst _global = (typeof globalThis === 'object'\n ? globalThis\n : typeof self === 'object'\n ? self\n : typeof window === 'object'\n ? window\n : typeof global === 'object'\n ? global\n : {});\nexport function registerGlobal(type, instance, diag, allowOverride = false) {\n var _a;\n const api = (_global[GLOBAL_OPENTELEMETRY_API_KEY] = (_a = _global[GLOBAL_OPENTELEMETRY_API_KEY]) !== null && _a !== void 0 ? _a : {\n version: VERSION,\n });\n if (!allowOverride && api[type]) {\n // already registered an API of this type\n const err = new Error(`@opentelemetry/api: Attempted duplicate registration of API: ${type}`);\n diag.error(err.stack || err.message);\n return false;\n }\n if (api.version !== VERSION) {\n // All registered APIs must be of the same version exactly\n const err = new Error(`@opentelemetry/api: Registration of version v${api.version} for ${type} does not match previously registered API v${VERSION}`);\n diag.error(err.stack || err.message);\n return false;\n }\n api[type] = instance;\n diag.debug(`@opentelemetry/api: Registered a global for ${type} v${VERSION}.`);\n return true;\n}\nexport function getGlobal(type) {\n var _a, _b;\n const globalVersion = (_a = _global[GLOBAL_OPENTELEMETRY_API_KEY]) === null || _a === void 0 ? void 0 : _a.version;\n if (!globalVersion || !isCompatible(globalVersion)) {\n return;\n }\n return (_b = _global[GLOBAL_OPENTELEMETRY_API_KEY]) === null || _b === void 0 ? void 0 : _b[type];\n}\nexport function unregisterGlobal(type, diag) {\n diag.debug(`@opentelemetry/api: Unregistering a global for ${type} v${VERSION}.`);\n const api = _global[GLOBAL_OPENTELEMETRY_API_KEY];\n if (api) {\n delete api[type];\n }\n}\n//# sourceMappingURL=global-utils.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { getGlobal } from '../internal/global-utils';\n/**\n * Component Logger which is meant to be used as part of any component which\n * will add automatically additional namespace in front of the log message.\n * It will then forward all message to global diag logger\n * @example\n * const cLogger = diag.createComponentLogger({ namespace: '@opentelemetry/instrumentation-http' });\n * cLogger.debug('test');\n * // @opentelemetry/instrumentation-http test\n */\nexport class DiagComponentLogger {\n constructor(props) {\n this._namespace = props.namespace || 'DiagComponentLogger';\n }\n debug(...args) {\n return logProxy('debug', this._namespace, args);\n }\n error(...args) {\n return logProxy('error', this._namespace, args);\n }\n info(...args) {\n return logProxy('info', this._namespace, args);\n }\n warn(...args) {\n return logProxy('warn', this._namespace, args);\n }\n verbose(...args) {\n return logProxy('verbose', this._namespace, args);\n }\n}\nfunction logProxy(funcName, namespace, args) {\n const logger = getGlobal('diag');\n // shortcut if logger not set\n if (!logger) {\n return;\n }\n return logger[funcName](namespace, ...args);\n}\n//# sourceMappingURL=ComponentLogger.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * Defines the available internal logging levels for the diagnostic logger, the numeric values\n * of the levels are defined to match the original values from the initial LogLevel to avoid\n * compatibility/migration issues for any implementation that assume the numeric ordering.\n */\nexport var DiagLogLevel;\n(function (DiagLogLevel) {\n /** Diagnostic Logging level setting to disable all logging (except and forced logs) */\n DiagLogLevel[DiagLogLevel[\"NONE\"] = 0] = \"NONE\";\n /** Identifies an error scenario */\n DiagLogLevel[DiagLogLevel[\"ERROR\"] = 30] = \"ERROR\";\n /** Identifies a warning scenario */\n DiagLogLevel[DiagLogLevel[\"WARN\"] = 50] = \"WARN\";\n /** General informational log message */\n DiagLogLevel[DiagLogLevel[\"INFO\"] = 60] = \"INFO\";\n /** General debug log message */\n DiagLogLevel[DiagLogLevel[\"DEBUG\"] = 70] = \"DEBUG\";\n /**\n * Detailed trace level logging should only be used for development, should only be set\n * in a development environment.\n */\n DiagLogLevel[DiagLogLevel[\"VERBOSE\"] = 80] = \"VERBOSE\";\n /** Used to set the logging level to include all logging */\n DiagLogLevel[DiagLogLevel[\"ALL\"] = 9999] = \"ALL\";\n})(DiagLogLevel || (DiagLogLevel = {}));\n//# sourceMappingURL=types.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { DiagLogLevel } from '../types';\nexport function createLogLevelDiagLogger(maxLevel, logger) {\n if (maxLevel < DiagLogLevel.NONE) {\n maxLevel = DiagLogLevel.NONE;\n }\n else if (maxLevel > DiagLogLevel.ALL) {\n maxLevel = DiagLogLevel.ALL;\n }\n // In case the logger is null or undefined\n logger = logger || {};\n function _filterFunc(funcName, theLevel) {\n const theFunc = logger[funcName];\n if (typeof theFunc === 'function' && maxLevel >= theLevel) {\n return theFunc.bind(logger);\n }\n return function () { };\n }\n return {\n error: _filterFunc('error', DiagLogLevel.ERROR),\n warn: _filterFunc('warn', DiagLogLevel.WARN),\n info: _filterFunc('info', DiagLogLevel.INFO),\n debug: _filterFunc('debug', DiagLogLevel.DEBUG),\n verbose: _filterFunc('verbose', DiagLogLevel.VERBOSE),\n };\n}\n//# sourceMappingURL=logLevelLogger.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { DiagComponentLogger } from '../diag/ComponentLogger';\nimport { createLogLevelDiagLogger } from '../diag/internal/logLevelLogger';\nimport { DiagLogLevel } from '../diag/types';\nimport { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils';\nconst API_NAME = 'diag';\n/**\n * Singleton object which represents the entry point to the OpenTelemetry internal\n * diagnostic API\n *\n * @since 1.0.0\n */\nexport class DiagAPI {\n /** Get the singleton instance of the DiagAPI API */\n static instance() {\n if (!this._instance) {\n this._instance = new DiagAPI();\n }\n return this._instance;\n }\n /**\n * Private internal constructor\n * @private\n */\n constructor() {\n function _logProxy(funcName) {\n return function (...args) {\n const logger = getGlobal('diag');\n // shortcut if logger not set\n if (!logger)\n return;\n return logger[funcName](...args);\n };\n }\n // Using self local variable for minification purposes as 'this' cannot be minified\n const self = this;\n // DiagAPI specific functions\n const setLogger = (logger, optionsOrLogLevel = { logLevel: DiagLogLevel.INFO }) => {\n var _a, _b, _c;\n if (logger === self) {\n // There isn't much we can do here.\n // Logging to the console might break the user application.\n // Try to log to self. If a logger was previously registered it will receive the log.\n const err = new Error('Cannot use diag as the logger for itself. Please use a DiagLogger implementation like ConsoleDiagLogger or a custom implementation');\n self.error((_a = err.stack) !== null && _a !== void 0 ? _a : err.message);\n return false;\n }\n if (typeof optionsOrLogLevel === 'number') {\n optionsOrLogLevel = {\n logLevel: optionsOrLogLevel,\n };\n }\n const oldLogger = getGlobal('diag');\n const newLogger = createLogLevelDiagLogger((_b = optionsOrLogLevel.logLevel) !== null && _b !== void 0 ? _b : DiagLogLevel.INFO, logger);\n // There already is an logger registered. We'll let it know before overwriting it.\n if (oldLogger && !optionsOrLogLevel.suppressOverrideMessage) {\n const stack = (_c = new Error().stack) !== null && _c !== void 0 ? _c : '<failed to generate stacktrace>';\n oldLogger.warn(`Current logger will be overwritten from ${stack}`);\n newLogger.warn(`Current logger will overwrite one already registered from ${stack}`);\n }\n return registerGlobal('diag', newLogger, self, true);\n };\n self.setLogger = setLogger;\n self.disable = () => {\n unregisterGlobal(API_NAME, self);\n };\n self.createComponentLogger = (options) => {\n return new DiagComponentLogger(options);\n };\n self.verbose = _logProxy('verbose');\n self.debug = _logProxy('debug');\n self.info = _logProxy('info');\n self.warn = _logProxy('warn');\n self.error = _logProxy('error');\n }\n}\n//# sourceMappingURL=diag.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * Get a key to uniquely identify a context value\n *\n * @since 1.0.0\n */\nexport function createContextKey(description) {\n // The specification states that for the same input, multiple calls should\n // return different keys. Due to the nature of the JS dependency management\n // system, this creates problems where multiple versions of some package\n // could hold different keys for the same property.\n //\n // Therefore, we use Symbol.for which returns the same key for the same input.\n return Symbol.for(description);\n}\nclass BaseContext {\n /**\n * Construct a new context which inherits values from an optional parent context.\n *\n * @param parentContext a context from which to inherit values\n */\n constructor(parentContext) {\n // for minification\n const self = this;\n self._currentContext = parentContext ? new Map(parentContext) : new Map();\n self.getValue = (key) => self._currentContext.get(key);\n self.setValue = (key, value) => {\n const context = new BaseContext(self._currentContext);\n context._currentContext.set(key, value);\n return context;\n };\n self.deleteValue = (key) => {\n const context = new BaseContext(self._currentContext);\n context._currentContext.delete(key);\n return context;\n };\n }\n}\n/**\n * The root context is used as the default parent context when there is no active context\n *\n * @since 1.0.0\n */\nexport const ROOT_CONTEXT = new BaseContext();\n//# sourceMappingURL=context.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * NoopMeter is a noop implementation of the {@link Meter} interface. It reuses\n * constant NoopMetrics for all of its methods.\n */\nexport class NoopMeter {\n constructor() { }\n /**\n * @see {@link Meter.createGauge}\n */\n createGauge(_name, _options) {\n return NOOP_GAUGE_METRIC;\n }\n /**\n * @see {@link Meter.createHistogram}\n */\n createHistogram(_name, _options) {\n return NOOP_HISTOGRAM_METRIC;\n }\n /**\n * @see {@link Meter.createCounter}\n */\n createCounter(_name, _options) {\n return NOOP_COUNTER_METRIC;\n }\n /**\n * @see {@link Meter.createUpDownCounter}\n */\n createUpDownCounter(_name, _options) {\n return NOOP_UP_DOWN_COUNTER_METRIC;\n }\n /**\n * @see {@link Meter.createObservableGauge}\n */\n createObservableGauge(_name, _options) {\n return NOOP_OBSERVABLE_GAUGE_METRIC;\n }\n /**\n * @see {@link Meter.createObservableCounter}\n */\n createObservableCounter(_name, _options) {\n return NOOP_OBSERVABLE_COUNTER_METRIC;\n }\n /**\n * @see {@link Meter.createObservableUpDownCounter}\n */\n createObservableUpDownCounter(_name, _options) {\n return NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC;\n }\n /**\n * @see {@link Meter.addBatchObservableCallback}\n */\n addBatchObservableCallback(_callback, _observables) { }\n /**\n * @see {@link Meter.removeBatchObservableCallback}\n */\n removeBatchObservableCallback(_callback) { }\n}\nexport class NoopMetric {\n}\nexport class NoopCounterMetric extends NoopMetric {\n add(_value, _attributes) { }\n}\nexport class NoopUpDownCounterMetric extends NoopMetric {\n add(_value, _attributes) { }\n}\nexport class NoopGaugeMetric extends NoopMetric {\n record(_value, _attributes) { }\n}\nexport class NoopHistogramMetric extends NoopMetric {\n record(_value, _attributes) { }\n}\nexport class NoopObservableMetric {\n addCallback(_callback) { }\n removeCallback(_callback) { }\n}\nexport class NoopObservableCounterMetric extends NoopObservableMetric {\n}\nexport class NoopObservableGaugeMetric extends NoopObservableMetric {\n}\nexport class NoopObservableUpDownCounterMetric extends NoopObservableMetric {\n}\nexport const NOOP_METER = new NoopMeter();\n// Synchronous instruments\nexport const NOOP_COUNTER_METRIC = new NoopCounterMetric();\nexport const NOOP_GAUGE_METRIC = new NoopGaugeMetric();\nexport const NOOP_HISTOGRAM_METRIC = new NoopHistogramMetric();\nexport const NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric();\n// Asynchronous instruments\nexport const NOOP_OBSERVABLE_COUNTER_METRIC = new NoopObservableCounterMetric();\nexport const NOOP_OBSERVABLE_GAUGE_METRIC = new NoopObservableGaugeMetric();\nexport const NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC = new NoopObservableUpDownCounterMetric();\n/**\n * Create a no-op Meter\n *\n * @since 1.3.0\n */\nexport function createNoopMeter() {\n return NOOP_METER;\n}\n//# sourceMappingURL=NoopMeter.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * The Type of value. It describes how the data is reported.\n *\n * @since 1.3.0\n */\nexport var ValueType;\n(function (ValueType) {\n ValueType[ValueType[\"INT\"] = 0] = \"INT\";\n ValueType[ValueType[\"DOUBLE\"] = 1] = \"DOUBLE\";\n})(ValueType || (ValueType = {}));\n//# sourceMappingURL=Metric.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { ROOT_CONTEXT } from './context';\nexport class NoopContextManager {\n active() {\n return ROOT_CONTEXT;\n }\n with(_context, fn, thisArg, ...args) {\n return fn.call(thisArg, ...args);\n }\n bind(_context, target) {\n return target;\n }\n enable() {\n return this;\n }\n disable() {\n return this;\n }\n}\n//# sourceMappingURL=NoopContextManager.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NoopContextManager } from '../context/NoopContextManager';\nimport { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils';\nimport { DiagAPI } from './diag';\nconst API_NAME = 'context';\nconst NOOP_CONTEXT_MANAGER = new NoopContextManager();\n/**\n * Singleton object which represents the entry point to the OpenTelemetry Context API\n *\n * @since 1.0.0\n */\nexport class ContextAPI {\n /** Empty private constructor prevents end users from constructing a new instance of the API */\n constructor() { }\n /** Get the singleton instance of the Context API */\n static getInstance() {\n if (!this._instance) {\n this._instance = new ContextAPI();\n }\n return this._instance;\n }\n /**\n * Set the current context manager.\n *\n * @returns true if the context manager was successfully registered, else false\n */\n setGlobalContextManager(contextManager) {\n return registerGlobal(API_NAME, contextManager, DiagAPI.instance());\n }\n /**\n * Get the currently active context\n */\n active() {\n return this._getContextManager().active();\n }\n /**\n * Execute a function with an active context\n *\n * @param context context to be active during function execution\n * @param fn function to execute in a context\n * @param thisArg optional receiver to be used for calling fn\n * @param args optional arguments forwarded to fn\n */\n with(context, fn, thisArg, ...args) {\n return this._getContextManager().with(context, fn, thisArg, ...args);\n }\n /**\n * Bind a context to a target function or event emitter\n *\n * @param context context to bind to the event emitter or function. Defaults to the currently active context\n * @param target function or event emitter to bind\n */\n bind(context, target) {\n return this._getContextManager().bind(context, target);\n }\n _getContextManager() {\n return getGlobal(API_NAME) || NOOP_CONTEXT_MANAGER;\n }\n /** Disable and remove the global context manager */\n disable() {\n this._getContextManager().disable();\n unregisterGlobal(API_NAME, DiagAPI.instance());\n }\n}\n//# sourceMappingURL=context.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * @since 1.0.0\n */\nexport var TraceFlags;\n(function (TraceFlags) {\n /** Represents no flag set. */\n TraceFlags[TraceFlags[\"NONE\"] = 0] = \"NONE\";\n /** Bit to represent whether trace is sampled in trace flags. */\n TraceFlags[TraceFlags[\"SAMPLED\"] = 1] = \"SAMPLED\";\n})(TraceFlags || (TraceFlags = {}));\n//# sourceMappingURL=trace_flags.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { TraceFlags } from './trace_flags';\n/**\n * @since 1.0.0\n */\nexport const INVALID_SPANID = '0000000000000000';\n/**\n * @since 1.0.0\n */\nexport const INVALID_TRACEID = '00000000000000000000000000000000';\n/**\n * @since 1.0.0\n */\nexport const INVALID_SPAN_CONTEXT = {\n traceId: INVALID_TRACEID,\n spanId: INVALID_SPANID,\n traceFlags: TraceFlags.NONE,\n};\n//# sourceMappingURL=invalid-span-constants.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { INVALID_SPAN_CONTEXT } from './invalid-span-constants';\n/**\n * The NonRecordingSpan is the default {@link Span} that is used when no Span\n * implementation is available. All operations are no-op including context\n * propagation.\n */\nexport class NonRecordingSpan {\n constructor(spanContext = INVALID_SPAN_CONTEXT) {\n this._spanContext = spanContext;\n }\n // Returns a SpanContext.\n spanContext() {\n return this._spanContext;\n }\n // By default does nothing\n setAttribute(_key, _value) {\n return this;\n }\n // By default does nothing\n setAttributes(_attributes) {\n return this;\n }\n // By default does nothing\n addEvent(_name, _attributes) {\n return this;\n }\n addLink(_link) {\n return this;\n }\n addLinks(_links) {\n return this;\n }\n // By default does nothing\n setStatus(_status) {\n return this;\n }\n // By default does nothing\n updateName(_name) {\n return this;\n }\n // By default does nothing\n end(_endTime) { }\n // isRecording always returns false for NonRecordingSpan.\n isRecording() {\n return false;\n }\n // By default does nothing\n recordException(_exception, _time) { }\n}\n//# sourceMappingURL=NonRecordingSpan.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { createContextKey } from '../context/context';\nimport { NonRecordingSpan } from './NonRecordingSpan';\nimport { ContextAPI } from '../api/context';\n/**\n * span key\n */\nconst SPAN_KEY = createContextKey('OpenTelemetry Context Key SPAN');\n/**\n * Return the span if one exists\n *\n * @param context context to get span from\n */\nexport function getSpan(context) {\n return context.getValue(SPAN_KEY) || undefined;\n}\n/**\n * Gets the span from the current context, if one exists.\n */\nexport function getActiveSpan() {\n return getSpan(ContextAPI.getInstance().active());\n}\n/**\n * Set the span on a context\n *\n * @param context context to use as parent\n * @param span span to set active\n */\nexport function setSpan(context, span) {\n return context.setValue(SPAN_KEY, span);\n}\n/**\n * Remove current span stored in the context\n *\n * @param context context to delete span from\n */\nexport function deleteSpan(context) {\n return context.deleteValue(SPAN_KEY);\n}\n/**\n * Wrap span context in a NoopSpan and set as span in a new\n * context\n *\n * @param context context to set active span on\n * @param spanContext span context to be wrapped\n */\nexport function setSpanContext(context, spanContext) {\n return setSpan(context, new NonRecordingSpan(spanContext));\n}\n/**\n * Get the span context of the span if it exists.\n *\n * @param context context to get values from\n */\nexport function getSpanContext(context) {\n var _a;\n return (_a = getSpan(context)) === null || _a === void 0 ? void 0 : _a.spanContext();\n}\n//# sourceMappingURL=context-utils.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { INVALID_SPANID, INVALID_TRACEID } from './invalid-span-constants';\nimport { NonRecordingSpan } from './NonRecordingSpan';\n// Valid characters (0-9, a-f, A-F) are marked as 1.\nconst isHex = new Uint8Array([\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,\n]);\nfunction isValidHex(id, length) {\n // As of 1.9.0 the id was allowed to be a non-string value,\n // even though it was not possible in the types.\n if (typeof id !== 'string' || id.length !== length)\n return false;\n let r = 0;\n for (let i = 0; i < id.length; i += 4) {\n r +=\n (isHex[id.charCodeAt(i)] | 0) +\n (isHex[id.charCodeAt(i + 1)] | 0) +\n (isHex[id.charCodeAt(i + 2)] | 0) +\n (isHex[id.charCodeAt(i + 3)] | 0);\n }\n return r === length;\n}\n/**\n * @since 1.0.0\n */\nexport function isValidTraceId(traceId) {\n return isValidHex(traceId, 32) && traceId !== INVALID_TRACEID;\n}\n/**\n * @since 1.0.0\n */\nexport function isValidSpanId(spanId) {\n return isValidHex(spanId, 16) && spanId !== INVALID_SPANID;\n}\n/**\n * Returns true if this {@link SpanContext} is valid.\n * @return true if this {@link SpanContext} is valid.\n *\n * @since 1.0.0\n */\nexport function isSpanContextValid(spanContext) {\n return (isValidTraceId(spanContext.traceId) && isValidSpanId(spanContext.spanId));\n}\n/**\n * Wrap the given {@link SpanContext} in a new non-recording {@link Span}\n *\n * @param spanContext span context to be wrapped\n * @returns a new non-recording {@link Span} with the provided context\n */\nexport function wrapSpanContext(spanContext) {\n return new NonRecordingSpan(spanContext);\n}\n//# sourceMappingURL=spancontext-utils.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { ContextAPI } from '../api/context';\nimport { getSpanContext, setSpan } from '../trace/context-utils';\nimport { NonRecordingSpan } from './NonRecordingSpan';\nimport { isSpanContextValid } from './spancontext-utils';\nconst contextApi = ContextAPI.getInstance();\n/**\n * No-op implementations of {@link Tracer}.\n */\nexport class NoopTracer {\n // startSpan starts a noop span.\n startSpan(name, options, context = contextApi.active()) {\n const root = Boolean(options === null || options === void 0 ? void 0 : options.root);\n if (root) {\n return new NonRecordingSpan();\n }\n const parentFromContext = context && getSpanContext(context);\n if (isSpanContext(parentFromContext) &&\n isSpanContextValid(parentFromContext)) {\n return new NonRecordingSpan(parentFromContext);\n }\n else {\n return new NonRecordingSpan();\n }\n }\n startActiveSpan(name, arg2, arg3, arg4) {\n let opts;\n let ctx;\n let fn;\n if (arguments.length < 2) {\n return;\n }\n else if (arguments.length === 2) {\n fn = arg2;\n }\n else if (arguments.length === 3) {\n opts = arg2;\n fn = arg3;\n }\n else {\n opts = arg2;\n ctx = arg3;\n fn = arg4;\n }\n const parentContext = ctx !== null && ctx !== void 0 ? ctx : contextApi.active();\n const span = this.startSpan(name, opts, parentContext);\n const contextWithSpanSet = setSpan(parentContext, span);\n return contextApi.with(contextWithSpanSet, fn, undefined, span);\n }\n}\nfunction isSpanContext(spanContext) {\n return (spanContext !== null &&\n typeof spanContext === 'object' &&\n 'spanId' in spanContext &&\n typeof spanContext['spanId'] === 'string' &&\n 'traceId' in spanContext &&\n typeof spanContext['traceId'] === 'string' &&\n 'traceFlags' in spanContext &&\n typeof spanContext['traceFlags'] === 'number');\n}\n//# sourceMappingURL=NoopTracer.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NoopTracer } from './NoopTracer';\nconst NOOP_TRACER = new NoopTracer();\n/**\n * Proxy tracer provided by the proxy tracer provider\n *\n * @since 1.0.0\n */\nexport class ProxyTracer {\n constructor(provider, name, version, options) {\n this._provider = provider;\n this.name = name;\n this.version = version;\n this.options = options;\n }\n startSpan(name, options, context) {\n return this._getTracer().startSpan(name, options, context);\n }\n startActiveSpan(_name, _options, _context, _fn) {\n const tracer = this._getTracer();\n return Reflect.apply(tracer.startActiveSpan, tracer, arguments);\n }\n /**\n * Try to get a tracer from the proxy tracer provider.\n * If the proxy tracer provider has no delegate, return a noop tracer.\n */\n _getTracer() {\n if (this._delegate) {\n return this._delegate;\n }\n const tracer = this._provider.getDelegateTracer(this.name, this.version, this.options);\n if (!tracer) {\n return NOOP_TRACER;\n }\n this._delegate = tracer;\n return this._delegate;\n }\n}\n//# sourceMappingURL=ProxyTracer.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NoopTracer } from './NoopTracer';\n/**\n * An implementation of the {@link TracerProvider} which returns an impotent\n * Tracer for all calls to `getTracer`.\n *\n * All operations are no-op.\n */\nexport class NoopTracerProvider {\n getTracer(_name, _version, _options) {\n return new NoopTracer();\n }\n}\n//# sourceMappingURL=NoopTracerProvider.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { ProxyTracer } from './ProxyTracer';\nimport { NoopTracerProvider } from './NoopTracerProvider';\nconst NOOP_TRACER_PROVIDER = new NoopTracerProvider();\n/**\n * Tracer provider which provides {@link ProxyTracer}s.\n *\n * Before a delegate is set, tracers provided are NoOp.\n * When a delegate is set, traces are provided from the delegate.\n * When a delegate is set after tracers have already been provided,\n * all tracers already provided will use the provided delegate implementation.\n *\n * @deprecated This will be removed in the next major version.\n * @since 1.0.0\n */\nexport class ProxyTracerProvider {\n /**\n * Get a {@link ProxyTracer}\n */\n getTracer(name, version, options) {\n var _a;\n return ((_a = this.getDelegateTracer(name, version, options)) !== null && _a !== void 0 ? _a : new ProxyTracer(this, name, version, options));\n }\n getDelegate() {\n var _a;\n return (_a = this._delegate) !== null && _a !== void 0 ? _a : NOOP_TRACER_PROVIDER;\n }\n /**\n * Set the delegate tracer provider\n */\n setDelegate(delegate) {\n this._delegate = delegate;\n }\n getDelegateTracer(name, version, options) {\n var _a;\n return (_a = this._delegate) === null || _a === void 0 ? void 0 : _a.getTracer(name, version, options);\n }\n}\n//# sourceMappingURL=ProxyTracerProvider.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * @since 1.0.0\n */\nexport var SpanKind;\n(function (SpanKind) {\n /** Default value. Indicates that the span is used internally. */\n SpanKind[SpanKind[\"INTERNAL\"] = 0] = \"INTERNAL\";\n /**\n * Indicates that the span covers server-side handling of an RPC or other\n * remote request.\n */\n SpanKind[SpanKind[\"SERVER\"] = 1] = \"SERVER\";\n /**\n * Indicates that the span covers the client-side wrapper around an RPC or\n * other remote request.\n */\n SpanKind[SpanKind[\"CLIENT\"] = 2] = \"CLIENT\";\n /**\n * Indicates that the span describes producer sending a message to a\n * broker. Unlike client and server, there is no direct critical path latency\n * relationship between producer and consumer spans.\n */\n SpanKind[SpanKind[\"PRODUCER\"] = 3] = \"PRODUCER\";\n /**\n * Indicates that the span describes consumer receiving a message from a\n * broker. Unlike client and server, there is no direct critical path latency\n * relationship between producer and consumer spans.\n */\n SpanKind[SpanKind[\"CONSUMER\"] = 4] = \"CONSUMER\";\n})(SpanKind || (SpanKind = {}));\n//# sourceMappingURL=span_kind.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * An enumeration of status codes.\n *\n * @since 1.0.0\n */\nexport var SpanStatusCode;\n(function (SpanStatusCode) {\n /**\n * The default status.\n */\n SpanStatusCode[SpanStatusCode[\"UNSET\"] = 0] = \"UNSET\";\n /**\n * The operation has been validated by an Application developer or\n * Operator to have completed successfully.\n */\n SpanStatusCode[SpanStatusCode[\"OK\"] = 1] = \"OK\";\n /**\n * The operation contains an error.\n */\n SpanStatusCode[SpanStatusCode[\"ERROR\"] = 2] = \"ERROR\";\n})(SpanStatusCode || (SpanStatusCode = {}));\n//# sourceMappingURL=status.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n// Split module-level variable definition into separate files to allow\n// tree-shaking on each api instance.\nimport { ContextAPI } from './api/context';\n/**\n * Entrypoint for context API\n * @since 1.0.0\n */\nexport const context = ContextAPI.getInstance();\n//# sourceMappingURL=context-api.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NOOP_METER } from './NoopMeter';\n/**\n * An implementation of the {@link MeterProvider} which returns an impotent Meter\n * for all calls to `getMeter`\n */\nexport class NoopMeterProvider {\n getMeter(_name, _version, _options) {\n return NOOP_METER;\n }\n}\nexport const NOOP_METER_PROVIDER = new NoopMeterProvider();\n//# sourceMappingURL=NoopMeterProvider.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NOOP_METER_PROVIDER } from '../metrics/NoopMeterProvider';\nimport { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils';\nimport { DiagAPI } from './diag';\nconst API_NAME = 'metrics';\n/**\n * Singleton object which represents the entry point to the OpenTelemetry Metrics API\n */\nexport class MetricsAPI {\n /** Empty private constructor prevents end users from constructing a new instance of the API */\n constructor() { }\n /** Get the singleton instance of the Metrics API */\n static getInstance() {\n if (!this._instance) {\n this._instance = new MetricsAPI();\n }\n return this._instance;\n }\n /**\n * Set the current global meter provider.\n * Returns true if the meter provider was successfully registered, else false.\n */\n setGlobalMeterProvider(provider) {\n return registerGlobal(API_NAME, provider, DiagAPI.instance());\n }\n /**\n * Returns the global meter provider.\n */\n getMeterProvider() {\n return getGlobal(API_NAME) || NOOP_METER_PROVIDER;\n }\n /**\n * Returns a meter from the global meter provider.\n */\n getMeter(name, version, options) {\n return this.getMeterProvider().getMeter(name, version, options);\n }\n /** Remove the global meter provider */\n disable() {\n unregisterGlobal(API_NAME, DiagAPI.instance());\n }\n}\n//# sourceMappingURL=metrics.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n// Split module-level variable definition into separate files to allow\n// tree-shaking on each api instance.\nimport { MetricsAPI } from './api/metrics';\n/**\n * Entrypoint for metrics API\n *\n * @since 1.3.0\n */\nexport const metrics = MetricsAPI.getInstance();\n//# sourceMappingURL=metrics-api.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils';\nimport { ProxyTracerProvider } from '../trace/ProxyTracerProvider';\nimport { isSpanContextValid, wrapSpanContext, } from '../trace/spancontext-utils';\nimport { deleteSpan, getActiveSpan, getSpan, getSpanContext, setSpan, setSpanContext, } from '../trace/context-utils';\nimport { DiagAPI } from './diag';\nconst API_NAME = 'trace';\n/**\n * Singleton object which represents the entry point to the OpenTelemetry Tracing API\n *\n * @since 1.0.0\n */\nexport class TraceAPI {\n /** Empty private constructor prevents end users from constructing a new instance of the API */\n constructor() {\n this._proxyTracerProvider = new ProxyTracerProvider();\n this.wrapSpanContext = wrapSpanContext;\n this.isSpanContextValid = isSpanContextValid;\n this.deleteSpan = deleteSpan;\n this.getSpan = getSpan;\n this.getActiveSpan = getActiveSpan;\n this.getSpanContext = getSpanContext;\n this.setSpan = setSpan;\n this.setSpanContext = setSpanContext;\n }\n /** Get the singleton instance of the Trace API */\n static getInstance() {\n if (!this._instance) {\n this._instance = new TraceAPI();\n }\n return this._instance;\n }\n /**\n * Set the current global tracer.\n *\n * @returns true if the tracer provider was successfully registered, else false\n */\n setGlobalTracerProvider(provider) {\n const success = registerGlobal(API_NAME, this._proxyTracerProvider, DiagAPI.instance());\n if (success) {\n this._proxyTracerProvider.setDelegate(provider);\n }\n return success;\n }\n /**\n * Returns the global tracer provider.\n */\n getTracerProvider() {\n return getGlobal(API_NAME) || this._proxyTracerProvider;\n }\n /**\n * Returns a tracer from the global tracer provider.\n */\n getTracer(name, version) {\n return this.getTracerProvider().getTracer(name, version);\n }\n /** Remove the global tracer provider */\n disable() {\n unregisterGlobal(API_NAME, DiagAPI.instance());\n this._proxyTracerProvider = new ProxyTracerProvider();\n }\n}\n//# sourceMappingURL=trace.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n// Split module-level variable definition into separate files to allow\n// tree-shaking on each api instance.\nimport { TraceAPI } from './api/trace';\n/**\n * Entrypoint for trace API\n *\n * @since 1.0.0\n */\nexport const trace = TraceAPI.getInstance();\n//# sourceMappingURL=trace-api.js.map","import {\n type Meter,\n context,\n metrics,\n propagation,\n ROOT_CONTEXT,\n SpanKind,\n SpanStatusCode,\n trace,\n ValueType,\n type Attributes,\n type Context,\n type Counter,\n type Gauge,\n type Histogram,\n type Meter as MeterType,\n type MetricOptions,\n type ObservableCounter,\n type ObservableGauge,\n type ObservableResult,\n type ObservableUpDownCounter,\n type Span,\n type SpanOptions,\n type Tracer,\n type UpDownCounter,\n} from \"@opentelemetry/api\";\nimport { type Logger, SeverityNumber } from \"@opentelemetry/api-logs\";\nimport { flattenAttributes } from \"@trigger.dev/core/v3/utils/flattenAttributes\";\n\nexport * from \"@opentelemetry/semantic-conventions\";\n\nexport type {\n Attributes,\n Counter,\n Gauge,\n Histogram,\n MeterType as Meter,\n MetricOptions,\n ObservableCounter,\n ObservableGauge,\n ObservableResult,\n ObservableUpDownCounter,\n Span,\n SpanOptions,\n Tracer,\n UpDownCounter,\n};\nexport {\n context,\n metrics,\n propagation,\n ROOT_CONTEXT,\n SpanKind,\n SpanStatusCode,\n trace,\n ValueType,\n type Context,\n};\n\nexport function getTracer(name: string): Tracer {\n return trace.getTracer(name);\n}\n\nexport function getMeter(name: string): Meter {\n return metrics.getMeter(name);\n}\n\nexport async function startSpan<T>(\n tracer: Tracer | undefined,\n name: string,\n fn: (span: Span) => Promise<T>,\n options?: SpanOptions\n): Promise<T> {\n tracer ??= getTracer(\"default\");\n\n return tracer.startActiveSpan(name, options ?? {}, async (span) => {\n try {\n return await fn(span);\n } catch (error) {\n if (error instanceof Error) {\n span.recordException(error);\n } else if (typeof error === \"string\") {\n span.recordException(new Error(error));\n } else {\n span.recordException(new Error(String(error)));\n }\n\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n } finally {\n span.end();\n }\n });\n}\n\nexport function recordSpanError(span: Span, error: Error) {\n span.recordException(error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error.message,\n });\n}\n\nexport async function emitDebugLog(\n logger: Logger,\n message: string,\n params: Record<string, unknown> = {}\n) {\n logger.emit({\n severityNumber: SeverityNumber.DEBUG,\n body: message,\n attributes: { ...flattenAttributes(params, \"params\") },\n });\n}\n\nexport async function emitInfoLog(\n logger: Logger,\n message: string,\n params: Record<string, unknown> = {}\n) {\n logger.emit({\n severityNumber: SeverityNumber.INFO,\n body: message,\n attributes: { ...flattenAttributes(params, \"params\") },\n });\n}\n\nexport async function emitErrorLog(\n logger: Logger,\n message: string,\n params: Record<string, unknown> = {}\n) {\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n body: message,\n attributes: { ...flattenAttributes(params, \"params\") },\n });\n}\n\nexport async function emitWarnLog(\n logger: Logger,\n message: string,\n params: Record<string, unknown> = {}\n) {\n logger.emit({\n severityNumber: SeverityNumber.WARN,\n body: message,\n attributes: { ...flattenAttributes(params, \"params\") },\n });\n}\n","/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n}\n","import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tvalidateConcurrency(concurrency);\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tqueue.dequeue()();\n\t\t\t// Since `pendingCount` has been decreased by one, increase `activeCount` by one.\n\t\t\tactiveCount++;\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\tresolve(result);\n\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, arguments_) => {\n\t\t// Queue `internalResolve` instead of the `run` function\n\t\t// to preserve asynchronous context.\n\t\tnew Promise(internalResolve => {\n\t\t\tqueue.enqueue(internalResolve);\n\t\t}).then(\n\t\t\trun.bind(undefined, function_, resolve, arguments_),\n\t\t);\n\n\t\t(async () => {\n\t\t\t// This function needs to wait until the next microtask before comparing\n\t\t\t// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously\n\t\t\t// after the `internalResolve` function is dequeued and called. The comparison in the if-statement\n\t\t\t// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.\n\t\t\tawait Promise.resolve();\n\n\t\t\tif (activeCount < concurrency) {\n\t\t\t\tresumeNext();\n\t\t\t}\n\t\t})();\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise(resolve => {\n\t\tenqueue(function_, resolve, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tqueue.clear();\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, option) {\n\tconst {concurrency} = option;\n\tconst limit = pLimit(concurrency);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n","import { type Redis, createRedisClient, type RedisOptions } from \"@internal/redis\";\nimport {\n type Attributes,\n type Histogram,\n type Meter,\n type ObservableResult,\n type Tracer,\n metrics,\n SpanKind,\n startSpan,\n trace,\n ValueType,\n} from \"@internal/tracing\";\nimport { Logger } from \"@trigger.dev/core/logger\";\nimport {\n calculateNextRetryDelay,\n type AnyZodSchema,\n type inferZodSchemaOutput,\n} from \"@trigger.dev/core/v3\";\nimport { type RetryOptions } from \"@trigger.dev/core/v3/schemas\";\nimport { shutdownManager } from \"@trigger.dev/core/v3/serverOnly\";\nimport { nanoid } from \"nanoid\";\nimport pLimit from \"p-limit\";\nimport { z } from \"zod/v4\";\nimport { type AnyQueueItem, SimpleQueue } from \"./queue.js\";\nimport cronParser from \"cron-parser\";\n\nexport const CronSchema = z.object({\n cron: z.string(),\n lastTimestamp: z.number().optional(),\n timestamp: z.number(),\n});\n\nexport type CronSchema = z.infer<typeof CronSchema>;\n\nexport type BatchConfig = {\n maxSize: number;\n maxWaitMs: number;\n};\n\nexport type WorkerCatalog = {\n [key: string]: {\n schema: AnyZodSchema;\n visibilityTimeoutMs: number;\n retry?: RetryOptions;\n cron?: string;\n jitterInMs?: number;\n /** Defaults to true. If false, errors will not be logged. */\n logErrors?: boolean;\n /** When set, items are accumulated and delivered in batches to the handler. */\n batch?: BatchConfig;\n };\n};\n\ntype WorkerCatalogItem = WorkerCatalog[keyof WorkerCatalog];\n\ntype QueueCatalogFromWorkerCatalog<Catalog extends WorkerCatalog> = {\n [K in keyof Catalog]: Catalog[K][\"schema\"];\n};\n\nexport type JobHandlerParams<Catalog extends WorkerCatalog, K extends keyof Catalog> = {\n id: string;\n payload: inferZodSchemaOutput<Catalog[K][\"schema\"]>;\n visibilityTimeoutMs: number;\n attempt: number;\n deduplicationKey?: string;\n};\n\nexport type JobHandler<Catalog extends WorkerCatalog, K extends keyof Catalog> = (\n params: JobHandlerParams<Catalog, K>\n) => Promise<void>;\n\ntype JobHandlerFor<Catalog extends WorkerCatalog, K extends keyof Catalog> = Catalog[K] extends {\n batch: BatchConfig;\n}\n ? (items: Array<JobHandlerParams<Catalog, K>>) => Promise<void>\n : (params: JobHandlerParams<Catalog, K>) => Promise<void>;\n\nexport type WorkerConcurrencyOptions = {\n workers?: number;\n tasksPerWorker?: number;\n limit?: number;\n};\n\ntype WorkerOptions<TCatalog extends WorkerCatalog> = {\n name: string;\n redisOptions: RedisOptions;\n catalog: TCatalog;\n jobs: {\n [K in keyof TCatalog]: JobHandlerFor<TCatalog, K>;\n };\n concurrency?: WorkerConcurrencyOptions;\n pollIntervalMs?: number;\n immediatePollIntervalMs?: number;\n shutdownTimeoutMs?: number;\n logger?: Logger;\n tracer?: Tracer;\n meter?: Meter;\n};\n\n// This results in attempt 12 being a delay of 1 hour\nconst defaultRetrySettings = {\n maxAttempts: 12,\n factor: 2,\n //one second\n minTimeoutInMs: 1_000,\n //one hour\n maxTimeoutInMs: 3_600_000,\n randomize: true,\n};\n\nclass Worker<TCatalog extends WorkerCatalog> {\n private subscriber: Redis | undefined;\n private tracer: Tracer;\n private meter: Meter;\n\n private metrics: {\n enqueueDuration?: Histogram;\n dequeueDuration?: Histogram;\n jobDuration?: Histogram;\n ackDuration?: Histogram;\n redriveDuration?: Histogram;\n rescheduleDuration?: Histogram;\n } = {};\n\n queue: SimpleQueue<QueueCatalogFromWorkerCatalog<TCatalog>>;\n private jobs: WorkerOptions<TCatalog>[\"jobs\"];\n private logger: Logger;\n private workerLoops: Promise<void>[] = [];\n private isShuttingDown = false;\n private concurrency: Required<NonNullable<WorkerOptions<TCatalog>[\"concurrency\"]>>;\n private shutdownTimeoutMs: number;\n\n // The p-limit limiter to control overall concurrency.\n private limiters: Record<string, ReturnType<typeof pLimit>> = {};\n\n // Batch accumulators: one per batch-enabled job type\n private batchAccumulators: Map<\n string,\n {\n items: AnyQueueItem[];\n firstItemAt: number;\n }\n > = new Map();\n\n constructor(private options: WorkerOptions<TCatalog>) {\n this.logger = options.logger ?? new Logger(\"Worker\", \"debug\", [\"item\"]);\n this.tracer = options.tracer ?? trace.getTracer(options.name);\n this.meter = options.meter ?? metrics.getMeter(options.name);\n\n this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 60_000;\n\n const schema: QueueCatalogFromWorkerCatalog<TCatalog> = Object.fromEntries(\n Object.entries(this.options.catalog).map(([key, value]) => [key, value.schema])\n ) as QueueCatalogFromWorkerCatalog<TCatalog>;\n\n this.queue = new SimpleQueue({\n name: options.name,\n redisOptions: options.redisOptions,\n logger: this.logger,\n schema,\n });\n\n this.jobs = options.jobs;\n\n const { workers = 1, tasksPerWorker = 1, limit = 10 } = options.concurrency ?? {};\n this.concurrency = { workers, tasksPerWorker, limit };\n\n const masterQueueObservableGauge = this.meter.createObservableGauge(\"redis_worker.queue.size\", {\n description: \"The number of items in the queue\",\n unit: \"items\",\n valueType: ValueType.INT,\n });\n\n masterQueueObservableGauge.addCallback(this.#updateQueueSizeMetric.bind(this));\n\n const deadLetterQueueObservableGauge = this.meter.createObservableGauge(\n \"redis_worker.queue.dead_letter_size\",\n {\n description: \"The number of items in the dead letter queue\",\n unit: \"items\",\n valueType: ValueType.INT,\n }\n );\n\n deadLetterQueueObservableGauge.addCallback(this.#updateDeadLetterQueueSizeMetric.bind(this));\n\n const concurrencyLimitActiveObservableGauge = this.meter.createObservableGauge(\n \"redis_worker.concurrency.active\",\n {\n description: \"The number of active workers\",\n unit: \"workers\",\n valueType: ValueType.INT,\n }\n );\n\n concurrencyLimitActiveObservableGauge.addCallback(\n this.#updateConcurrencyLimitActiveMetric.bind(this)\n );\n\n const concurrencyLimitPendingObservableGauge = this.meter.createObservableGauge(\n \"redis_worker.concurrency.pending\",\n {\n description: \"The number of pending workers\",\n unit: \"workers\",\n valueType: ValueType.INT,\n }\n );\n\n concurrencyLimitPendingObservableGauge.addCallback(\n this.#updateConcurrencyLimitPendingMetric.bind(this)\n );\n\n const oldestMessageAgeObservableGauge = this.meter.createObservableGauge(\n \"redis_worker.queue.oldest_message_age\",\n {\n description: \"Age of the oldest overdue message in the queue\",\n unit: \"ms\",\n valueType: ValueType.INT,\n }\n );\n\n oldestMessageAgeObservableGauge.addCallback(this.#updateOldestMessageAgeMetric.bind(this));\n }\n\n async #updateQueueSizeMetric(observableResult: ObservableResult<Attributes>) {\n const queueSize = await this.queue.size();\n\n observableResult.observe(queueSize, {\n worker_name: this.options.name,\n });\n }\n\n async #updateDeadLetterQueueSizeMetric(observableResult: ObservableResult<Attributes>) {\n const deadLetterQueueSize = await this.queue.sizeOfDeadLetterQueue();\n observableResult.observe(deadLetterQueueSize, {\n worker_name: this.options.name,\n });\n }\n\n async #updateOldestMessageAgeMetric(observableResult: ObservableResult<Attributes>) {\n const oldestMessageAge = await this.queue.oldestMessageAge();\n\n observableResult.observe(oldestMessageAge, {\n worker_name: this.options.name,\n });\n }\n\n async #updateConcurrencyLimitActiveMetric(observableResult: ObservableResult<Attributes>) {\n for (const [workerId, limiter] of Object.entries(this.limiters)) {\n observableResult.observe(limiter.activeCount, {\n worker_name: this.options.name,\n worker_id: workerId,\n });\n }\n }\n\n async #updateConcurrencyLimitPendingMetric(observableResult: ObservableResult<Attributes>) {\n for (const [workerId, limiter] of Object.entries(this.limiters)) {\n observableResult.observe(limiter.pendingCount, {\n worker_name: this.options.name,\n worker_id: workerId,\n });\n }\n }\n\n public start() {\n const { workers, tasksPerWorker } = this.concurrency;\n\n this.logger.info(\"Starting worker\", {\n workers,\n tasksPerWorker,\n concurrency: this.concurrency,\n });\n\n // Launch a number of \"worker loops\" on the main thread.\n for (let i = 0; i < workers; i++) {\n this.workerLoops.push(this.runWorkerLoop(`worker-${nanoid(12)}`, tasksPerWorker, i, workers));\n }\n\n this.setupShutdownHandlers();\n\n this.subscriber = createRedisClient(this.options.redisOptions, {\n onError: (error) => {\n this.logger.error(`RedisWorker subscriber redis client error:`, {\n error,\n keyPrefix: this.options.redisOptions.keyPrefix,\n });\n },\n });\n\n this.setupSubscriber();\n this.setupCron();\n\n return this;\n }\n\n /**\n * Enqueues a job for processing.\n * @param options - The enqueue options.\n * @param options.id - Optional unique identifier for the job. If not provided, one will be generated. It prevents duplication.\n * @param options.job - The job type from the worker catalog.\n * @param options.payload - The job payload that matches the schema defined in the catalog.\n * @param options.visibilityTimeoutMs - Optional visibility timeout in milliseconds. Defaults to value from catalog.\n * @param options.availableAt - Optional date when the job should become available for processing. Defaults to now.\n * @returns A promise that resolves when the job is enqueued.\n */\n enqueue<K extends keyof TCatalog>({\n id,\n job,\n payload,\n visibilityTimeoutMs,\n availableAt,\n cancellationKey,\n }: {\n id?: string;\n job: K;\n payload: inferZodSchemaOutput<TCatalog[K][\"schema\"]>;\n visibilityTimeoutMs?: number;\n availableAt?: Date;\n cancellationKey?: string;\n }) {\n return startSpan(\n this.tracer,\n \"enqueue\",\n async (span) => {\n const timeout = visibilityTimeoutMs ?? this.options.catalog[job]?.visibilityTimeoutMs;\n\n if (!timeout) {\n throw new Error(`No visibility timeout found for job ${String(job)} with id ${id}`);\n }\n\n span.setAttribute(\"job_visibility_timeout_ms\", timeout);\n\n return this.withHistogram(\n this.metrics.enqueueDuration,\n this.queue.enqueue({\n id,\n job,\n item: payload,\n visibilityTimeoutMs: timeout,\n availableAt,\n cancellationKey,\n }),\n {\n job_type: String(job),\n has_available_at: availableAt ? \"true\" : \"false\",\n }\n );\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n job_type: String(job),\n job_id: id,\n },\n }\n );\n }\n\n /**\n * Enqueues a job for processing once. If the job is already in the queue, it will be ignored.\n * @param options - The enqueue options.\n * @param options.id - Required unique identifier for the job.\n * @param options.job - The job type from the worker catalog.\n * @param options.payload - The job payload that matches the schema defined in the catalog.\n * @param options.visibilityTimeoutMs - Optional visibility timeout in milliseconds. Defaults to value from catalog.\n * @param options.availableAt - Optional date when the job should become available for processing. Defaults to now.\n * @returns A promise that resolves when the job is enqueued.\n */\n enqueueOnce<K extends keyof TCatalog>({\n id,\n job,\n payload,\n visibilityTimeoutMs,\n availableAt,\n }: {\n id: string;\n job: K;\n payload: inferZodSchemaOutput<TCatalog[K][\"schema\"]>;\n visibilityTimeoutMs?: number;\n availableAt?: Date;\n }) {\n return startSpan(\n this.tracer,\n \"enqueueOnce\",\n async (span) => {\n const timeout = visibilityTimeoutMs ?? this.options.catalog[job]?.visibilityTimeoutMs;\n\n if (!timeout) {\n throw new Error(`No visibility timeout found for job ${String(job)} with id ${id}`);\n }\n\n span.setAttribute(\"job_visibility_timeout_ms\", timeout);\n\n return this.withHistogram(\n this.metrics.enqueueDuration,\n this.queue.enqueueOnce({\n id,\n job,\n item: payload,\n visibilityTimeoutMs: timeout,\n availableAt,\n }),\n {\n job_type: String(job),\n has_available_at: availableAt ? \"true\" : \"false\",\n }\n );\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n job_type: String(job),\n job_id: id,\n },\n }\n );\n }\n\n /**\n * Reschedules an existing job to a new available date.\n * If the job isn't in the queue, it will be ignored.\n */\n reschedule(id: string, availableAt: Date) {\n return startSpan(\n this.tracer,\n \"reschedule\",\n async (span) => {\n return this.withHistogram(\n this.metrics.rescheduleDuration,\n this.queue.reschedule(id, availableAt)\n );\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n job_id: id,\n },\n }\n );\n }\n\n /**\n * Cancels a job before it's enqueued.\n * @param cancellationKey - The cancellation key to cancel.\n * @returns A promise that resolves when the job is cancelled.\n *\n * Any jobs enqueued with the same cancellation key will be not be enqueued.\n */\n cancel(cancellationKey: string) {\n return startSpan(this.tracer, \"cancel\", () => this.queue.cancel(cancellationKey));\n }\n\n ack(id: string) {\n return startSpan(\n this.tracer,\n \"ack\",\n () => {\n return this.withHistogram(this.metrics.ackDuration, this.queue.ack(id));\n },\n {\n attributes: {\n job_id: id,\n },\n }\n );\n }\n\n async getJob(id: string) {\n return this.queue.getJob(id);\n }\n\n /**\n * Returns true if the given job type has batch config in the catalog.\n */\n private isBatchJob(jobType: string): boolean {\n const catalogItem = this.options.catalog[jobType as any];\n return !!catalogItem?.batch;\n }\n\n /**\n * Returns the batch config for a job type, or undefined if not batch-enabled.\n */\n private getBatchConfig(jobType: string): BatchConfig | undefined {\n const catalogItem = this.options.catalog[jobType as any];\n return catalogItem?.batch;\n }\n\n /**\n * The max dequeue count: the largest batch maxSize across catalog entries,\n * falling back to tasksPerWorker for non-batch catalogs.\n */\n private get maxDequeueCount(): number {\n const batchSizes = Object.values(this.options.catalog)\n .filter((entry): entry is typeof entry & { batch: BatchConfig } => !!entry.batch)\n .map((entry) => entry.batch.maxSize);\n\n if (batchSizes.length > 0) {\n return Math.max(...batchSizes);\n }\n return this.concurrency.tasksPerWorker;\n }\n\n /**\n * The main loop that each worker runs. It repeatedly polls for items,\n * processes them, and then waits before the next iteration.\n */\n private async runWorkerLoop(\n workerId: string,\n taskCount: number,\n workerIndex: number,\n totalWorkers: number\n ): Promise<void> {\n const limiter = pLimit(this.concurrency.limit);\n this.limiters[workerId] = limiter;\n\n const pollIntervalMs = this.options.pollIntervalMs ?? 1000;\n const immediatePollIntervalMs = this.options.immediatePollIntervalMs ?? 100;\n\n // Calculate the delay between starting each worker loop so that they don't all start at the same time.\n const delayBetweenWorkers = this.options.pollIntervalMs ?? 1000;\n const delay = delayBetweenWorkers * (totalWorkers - workerIndex);\n await Worker.delay(delay);\n\n this.logger.info(\"Starting worker loop\", {\n workerIndex,\n totalWorkers,\n delay,\n workerId,\n taskCount,\n pollIntervalMs,\n immediatePollIntervalMs,\n concurrencyOptions: this.concurrency,\n });\n\n while (!this.isShuttingDown) {\n // 1. Flush any timed-out batch accumulators\n await this.flushTimedOutBatches(workerId, limiter);\n\n // 2. Check overall load. If at capacity, wait a bit before trying to dequeue more.\n if (limiter.activeCount + limiter.pendingCount >= this.concurrency.limit) {\n this.logger.debug(\"Worker at capacity, waiting\", {\n workerId,\n concurrencyOptions: this.concurrency,\n activeCount: limiter.activeCount,\n pendingCount: limiter.pendingCount,\n });\n\n await Worker.delay(pollIntervalMs);\n\n continue;\n }\n\n // 3. Calculate dequeue count - use max batch size if we have batch jobs\n const $taskCount = Math.min(\n this.maxDequeueCount,\n this.concurrency.limit - limiter.activeCount - limiter.pendingCount\n );\n\n let itemsFound = false;\n\n try {\n const items = await this.withHistogram(\n this.metrics.dequeueDuration,\n this.queue.dequeue($taskCount),\n {\n worker_id: workerId,\n task_count: $taskCount,\n }\n );\n\n itemsFound = items.length > 0;\n\n if (items.length === 0 && this.batchAccumulators.size === 0) {\n this.logger.debug(\"No items to dequeue\", {\n workerId,\n concurrencyOptions: this.concurrency,\n activeCount: limiter.activeCount,\n pendingCount: limiter.pendingCount,\n });\n\n await Worker.delay(pollIntervalMs);\n continue;\n }\n\n if (items.length > 0) {\n this.logger.debug(\"Dequeued items\", {\n workerId,\n itemCount: items.length,\n concurrencyOptions: this.concurrency,\n activeCount: limiter.activeCount,\n pendingCount: limiter.pendingCount,\n });\n }\n\n // 4. Route items: batch-enabled go to accumulators, others processed immediately\n for (const item of items) {\n const queueItem = item as AnyQueueItem;\n\n if (this.isBatchJob(queueItem.job)) {\n this.addToAccumulator(queueItem);\n\n const batchConfig = this.getBatchConfig(queueItem.job)!;\n const accumulator = this.batchAccumulators.get(queueItem.job);\n if (accumulator && accumulator.items.length >= batchConfig.maxSize) {\n await this.flushBatch(queueItem.job, workerId, limiter);\n }\n } else {\n limiter(() => this.processItem(queueItem, items.length, workerId, limiter)).catch(\n (err) => {\n this.logger.error(\"Unhandled error in processItem:\", {\n error: err,\n workerId,\n id: queueItem.id,\n job: queueItem.job,\n });\n }\n );\n }\n }\n } catch (error) {\n this.logger.error(\"Error dequeuing items:\", { name: this.options.name, error });\n await Worker.delay(pollIntervalMs);\n continue;\n }\n\n // 5. If we found items or have pending batch items, poll quickly\n if (itemsFound || this.batchAccumulators.size > 0) {\n await Worker.delay(immediatePollIntervalMs);\n } else {\n await Worker.delay(pollIntervalMs);\n }\n }\n\n // On shutdown, flush all remaining batch accumulators\n await this.flushAllBatches(workerId, limiter);\n\n this.logger.info(\"Worker loop finished\", { workerId });\n }\n\n /**\n * Adds an item to the batch accumulator for its job type.\n */\n private addToAccumulator(item: AnyQueueItem): void {\n let accumulator = this.batchAccumulators.get(item.job);\n if (!accumulator) {\n accumulator = { items: [], firstItemAt: Date.now() };\n this.batchAccumulators.set(item.job, accumulator);\n }\n accumulator.items.push(item);\n }\n\n /**\n * Flushes any batch accumulators that have exceeded their maxWaitMs.\n */\n private async flushTimedOutBatches(\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n const now = Date.now();\n for (const [jobType, accumulator] of this.batchAccumulators) {\n const batchConfig = this.getBatchConfig(jobType);\n if (!batchConfig) continue;\n\n if (now - accumulator.firstItemAt >= batchConfig.maxWaitMs) {\n await this.flushBatch(jobType, workerId, limiter);\n }\n }\n }\n\n /**\n * Flushes all batch accumulators (used during shutdown).\n */\n private async flushAllBatches(\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n for (const jobType of this.batchAccumulators.keys()) {\n await this.flushBatch(jobType, workerId, limiter);\n }\n }\n\n /**\n * Flushes the batch accumulator for a specific job type.\n * Removes items from the accumulator and submits them to the limiter as a single batch.\n */\n private async flushBatch(\n jobType: string,\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n const accumulator = this.batchAccumulators.get(jobType);\n if (!accumulator || accumulator.items.length === 0) return;\n\n const items = accumulator.items;\n this.batchAccumulators.delete(jobType);\n\n this.logger.debug(\"Flushing batch\", {\n jobType,\n batchSize: items.length,\n workerId,\n accumulatedMs: Date.now() - accumulator.firstItemAt,\n });\n\n limiter(() => this.processBatch(items, jobType, workerId, limiter)).catch((err) => {\n this.logger.error(\"Unhandled error in processBatch:\", {\n error: err,\n workerId,\n jobType,\n batchSize: items.length,\n });\n });\n }\n\n /**\n * Processes a batch of items for a batch-enabled job type.\n */\n private async processBatch(\n items: AnyQueueItem[],\n jobType: string,\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n const catalogItem = this.options.catalog[jobType as any];\n const handler = this.jobs[jobType as any] as\n | ((items: Array<JobHandlerParams<TCatalog, any>>) => Promise<void>)\n | undefined;\n\n if (!handler) {\n this.logger.error(`Worker no handler found for batch job type: ${jobType}`);\n return;\n }\n\n if (!catalogItem) {\n this.logger.error(`Worker no catalog item found for batch job type: ${jobType}`);\n return;\n }\n\n const batchParams = items.map((item) => ({\n id: item.id,\n payload: item.item,\n visibilityTimeoutMs: item.visibilityTimeoutMs,\n attempt: item.attempt,\n deduplicationKey: item.deduplicationKey,\n }));\n\n await startSpan(\n this.tracer,\n \"processBatch\",\n async () => {\n await this.withHistogram(this.metrics.jobDuration, handler(batchParams), {\n worker_id: workerId,\n batch_size: items.length,\n job_type: jobType,\n });\n\n // On success, acknowledge all items individually.\n await Promise.all(items.map((item) => this.queue.ack(item.id, item.deduplicationKey)));\n },\n {\n kind: SpanKind.CONSUMER,\n attributes: {\n job_type: jobType,\n batch_size: items.length,\n worker_id: workerId,\n worker_name: this.options.name,\n },\n }\n ).catch(async (error) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const shouldLogError = catalogItem.logErrors ?? true;\n const errorLogLevel =\n error && typeof error === \"object\" && \"logLevel\" in error ? error.logLevel : undefined;\n\n const logAttributes = {\n name: this.options.name,\n jobType,\n batchSize: items.length,\n error,\n errorMessage,\n };\n\n if (!shouldLogError) {\n this.logger.info(`Worker failed to process batch`, logAttributes);\n } else if (errorLogLevel === \"warn\") {\n this.logger.warn(`Worker error processing batch`, logAttributes);\n } else if (errorLogLevel === \"info\") {\n this.logger.info(`Worker error processing batch`, logAttributes);\n } else {\n this.logger.error(`Worker error processing batch`, logAttributes);\n }\n\n // Re-enqueue each item individually with retry logic\n for (const item of items) {\n try {\n const newAttempt = item.attempt + 1;\n const retrySettings = {\n ...defaultRetrySettings,\n ...catalogItem?.retry,\n };\n const retryDelay = calculateNextRetryDelay(retrySettings, newAttempt);\n\n if (!retryDelay) {\n const dlqLogAttributes = {\n name: this.options.name,\n id: item.id,\n jobType,\n attempt: newAttempt,\n };\n\n if (!shouldLogError) {\n this.logger.info(\n `Worker batch item reached max attempts. Moving to DLQ.`,\n dlqLogAttributes\n );\n } else if (errorLogLevel === \"warn\") {\n this.logger.warn(\n `Worker batch item reached max attempts. Moving to DLQ.`,\n dlqLogAttributes\n );\n } else if (errorLogLevel === \"info\") {\n this.logger.info(\n `Worker batch item reached max attempts. Moving to DLQ.`,\n dlqLogAttributes\n );\n } else {\n this.logger.error(\n `Worker batch item reached max attempts. Moving to DLQ.`,\n dlqLogAttributes\n );\n }\n\n await this.queue.moveToDeadLetterQueue(item.id, errorMessage);\n continue;\n }\n\n const retryDate = new Date(Date.now() + retryDelay);\n this.logger.info(`Worker requeuing failed batch item with delay`, {\n name: this.options.name,\n id: item.id,\n jobType,\n retryDate,\n retryDelay,\n attempt: newAttempt,\n });\n\n await this.queue.enqueue({\n id: item.id,\n job: item.job,\n item: item.item,\n availableAt: retryDate,\n attempt: newAttempt,\n visibilityTimeoutMs: item.visibilityTimeoutMs,\n });\n } catch (requeueError) {\n this.logger.error(\n `Worker failed to requeue batch item. It will be retried after the visibility timeout.`,\n {\n name: this.options.name,\n id: item.id,\n jobType,\n visibilityTimeoutMs: item.visibilityTimeoutMs,\n error: requeueError,\n }\n );\n }\n }\n });\n }\n\n /**\n * Processes a single item.\n */\n private async processItem(\n { id, job, item, visibilityTimeoutMs, attempt, timestamp, deduplicationKey }: AnyQueueItem,\n batchSize: number,\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n const catalogItem = this.options.catalog[job as any];\n // processItem is only called for non-batch jobs, so the handler takes a single param\n const handler = this.jobs[job as any] as\n | ((params: JobHandlerParams<TCatalog, any>) => Promise<void>)\n | undefined;\n if (!handler) {\n this.logger.error(`Worker no handler found for job type: ${job}`);\n return;\n }\n\n if (!catalogItem) {\n this.logger.error(`Worker no catalog item found for job type: ${job}`);\n return;\n }\n\n await startSpan(\n this.tracer,\n \"processItem\",\n async () => {\n await this.withHistogram(\n this.metrics.jobDuration,\n handler({ id, payload: item, visibilityTimeoutMs, attempt, deduplicationKey }),\n {\n worker_id: workerId,\n batch_size: batchSize,\n job_type: job,\n attempt,\n }\n );\n\n // On success, acknowledge the item.\n await this.queue.ack(id, deduplicationKey);\n\n if (catalogItem.cron) {\n await this.rescheduleCronJob(job, catalogItem, item);\n }\n },\n {\n kind: SpanKind.CONSUMER,\n attributes: {\n job_id: id,\n job_type: job,\n attempt,\n job_timestamp: timestamp.getTime(),\n job_age_in_ms: Date.now() - timestamp.getTime(),\n worker_id: workerId,\n worker_limit_concurrency: limiter.concurrency,\n worker_limit_active: limiter.activeCount,\n worker_limit_pending: limiter.pendingCount,\n worker_name: this.options.name,\n batch_size: batchSize,\n },\n }\n ).catch(async (error) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n const shouldLogError = catalogItem.logErrors ?? true;\n const errorLogLevel =\n error && typeof error === \"object\" && \"logLevel\" in error ? error.logLevel : undefined;\n\n // Never include the raw item/payload here: it is job data that may be\n // customer-controlled. It is retrievable via `getJob(id)` if needed for triage.\n const logAttributes = {\n name: this.options.name,\n id,\n job,\n visibilityTimeoutMs,\n error,\n errorMessage,\n };\n\n if (!shouldLogError) {\n this.logger.info(`Worker failed to process item`, logAttributes);\n } else if (errorLogLevel === \"warn\") {\n this.logger.warn(`Worker error processing item`, logAttributes);\n } else if (errorLogLevel === \"info\") {\n this.logger.info(`Worker error processing item`, logAttributes);\n } else {\n this.logger.error(`Worker error processing item`, logAttributes);\n }\n\n // Attempt requeue logic.\n try {\n const newAttempt = attempt + 1;\n const retrySettings = {\n ...defaultRetrySettings,\n ...catalogItem?.retry,\n };\n const retryDelay = calculateNextRetryDelay(retrySettings, newAttempt);\n\n if (!retryDelay) {\n if (!shouldLogError || errorLogLevel === \"info\") {\n this.logger.info(`Worker item reached max attempts. Moving to DLQ.`, {\n ...logAttributes,\n attempt: newAttempt,\n });\n } else if (errorLogLevel === \"warn\") {\n this.logger.warn(`Worker item reached max attempts. Moving to DLQ.`, {\n ...logAttributes,\n attempt: newAttempt,\n });\n } else {\n this.logger.error(`Worker item reached max attempts. Moving to DLQ.`, {\n ...logAttributes,\n attempt: newAttempt,\n });\n }\n\n await this.queue.moveToDeadLetterQueue(id, errorMessage);\n\n if (catalogItem.cron) {\n await this.rescheduleCronJob(job, catalogItem, item);\n }\n\n return;\n }\n\n const retryDate = new Date(Date.now() + retryDelay);\n this.logger.info(`Worker requeuing failed item with delay`, {\n name: this.options.name,\n id,\n job,\n retryDate,\n retryDelay,\n visibilityTimeoutMs,\n attempt: newAttempt,\n });\n await this.queue.enqueue({\n id,\n job,\n item,\n availableAt: retryDate,\n attempt: newAttempt,\n visibilityTimeoutMs,\n });\n } catch (requeueError) {\n this.logger.error(\n `Worker failed to requeue item. It will be retried after the visibility timeout.`,\n {\n name: this.options.name,\n id,\n job,\n visibilityTimeoutMs,\n error: requeueError,\n }\n );\n }\n });\n }\n\n private async withHistogram<T>(\n histogram: Histogram | undefined,\n promise: Promise<T>,\n labels?: Record<string, string | number>\n ): Promise<T> {\n if (!histogram) {\n return promise;\n }\n\n const start = Date.now();\n try {\n return await promise;\n } finally {\n const duration = (Date.now() - start) / 1000; // Convert to seconds\n histogram.record(duration, { worker_name: this.options.name, ...labels });\n }\n }\n\n // A simple helper to delay for a given number of milliseconds.\n private static delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private setupCron() {\n const cronJobs = Object.entries(this.options.catalog).filter(([_, value]) => value.cron);\n\n if (cronJobs.length === 0) {\n return;\n }\n\n this.logger.info(\"Setting up cron jobs\", {\n cronJobs: cronJobs.map(([job, value]) => ({\n job,\n cron: value.cron,\n jitterInMs: value.jitterInMs,\n })),\n });\n\n // For each cron job, we need to try and enqueue a job with the next timestamp of the cron job.\n const enqueuePromises = cronJobs.map(([job, value]) =>\n this.enqueueCronJob(value.cron!, job, value.jitterInMs)\n );\n\n Promise.allSettled(enqueuePromises).then((results) => {\n results.forEach((result) => {\n if (result.status === \"fulfilled\") {\n this.logger.debug(\"Enqueued cron job\", { result: result.value });\n } else {\n this.logger.error(\"Failed to enqueue cron job\", { reason: result.reason });\n }\n });\n });\n }\n\n private async enqueueCronJob(cron: string, job: string, jitter?: number, lastTimestamp?: Date) {\n const scheduledAt = this.calculateNextScheduledAt(cron, lastTimestamp);\n const identifier = [job, this.timestampIdentifier(scheduledAt)].join(\":\");\n // Calculate the availableAt date by calculating a random number between -jitter/2 and jitter/2 and adding it to the scheduledAt\n const appliedJitter = typeof jitter === \"number\" ? Math.random() * jitter - jitter / 2 : 0;\n const availableAt = new Date(scheduledAt.getTime() + appliedJitter);\n\n const enqueued = await this.enqueueOnce({\n id: identifier,\n job,\n // job is a runtime string here, so K widens and the payload can't match a\n // single catalog entry statically; the shape is correct for the cron job.\n payload: {\n timestamp: scheduledAt.getTime(),\n lastTimestamp: lastTimestamp?.getTime(),\n cron,\n } as inferZodSchemaOutput<TCatalog[string][\"schema\"]>,\n availableAt,\n });\n\n this.logger.debug(\"Enqueued cron job\", {\n identifier,\n cron,\n job,\n scheduledAt,\n enqueued,\n availableAt,\n appliedJitter,\n jitter,\n });\n\n return {\n identifier,\n cron,\n job,\n scheduledAt,\n enqueued,\n };\n }\n\n private async rescheduleCronJob(job: string, catalogItem: WorkerCatalogItem, item: CronSchema) {\n if (!catalogItem.cron) {\n return;\n }\n\n return this.enqueueCronJob(\n catalogItem.cron,\n job,\n catalogItem.jitterInMs,\n new Date(item.timestamp)\n );\n }\n\n private calculateNextScheduledAt(cron: string, lastTimestamp?: Date): Date {\n const scheduledAt = cronParser\n .parseExpression(cron, {\n currentDate: lastTimestamp,\n })\n .next()\n .toDate();\n\n // If scheduledAt is in the past, we should just calculate the next one based on the current time\n if (scheduledAt < new Date()) {\n return this.calculateNextScheduledAt(cron);\n }\n\n return scheduledAt;\n }\n\n private timestampIdentifier(timestamp: Date) {\n const year = timestamp.getUTCFullYear();\n const month = timestamp.getUTCMonth();\n const day = timestamp.getUTCDate();\n const hour = timestamp.getUTCHours();\n const minute = timestamp.getUTCMinutes();\n const second = timestamp.getUTCSeconds();\n\n return `${year}-${month}-${day}-${hour}-${minute}-${second}`;\n }\n\n private setupSubscriber() {\n const channel = `${this.options.name}:redrive`;\n this.subscriber?.subscribe(channel, (err) => {\n if (err) {\n this.logger.error(`Failed to subscribe to ${channel}`, { error: err });\n } else {\n this.logger.debug(`Subscribed to ${channel}`);\n }\n });\n\n this.subscriber?.on(\"message\", this.handleRedriveMessage.bind(this));\n }\n\n private async handleRedriveMessage(channel: string, message: string) {\n try {\n const { id } = JSON.parse(message) as any;\n if (typeof id !== \"string\") {\n throw new Error(\"Invalid message format: id must be a string\");\n }\n await this.withHistogram(\n this.metrics.redriveDuration,\n this.queue.redriveFromDeadLetterQueue(id)\n );\n this.logger.log(`Redrived item ${id} from Dead Letter Queue`);\n } catch (error) {\n this.logger.error(\"Error processing redrive message\", { error, message });\n }\n }\n\n private setupShutdownHandlers() {\n shutdownManager.register(`redis-worker:${this.options.name}`, this.shutdown.bind(this));\n }\n\n private async shutdown(signal?: NodeJS.Signals) {\n if (this.isShuttingDown) {\n this.logger.log(\"Worker already shutting down\", { signal });\n return;\n }\n\n this.isShuttingDown = true;\n this.logger.log(\"Shutting down worker loops...\", { signal });\n\n // Wait for all worker loops to finish, retaining ownership of the deadline timer so the\n // losing timeout cannot keep the process alive after a prompt shutdown.\n let shutdownDeadline: ReturnType<typeof setTimeout> | undefined;\n const deadlinePromise = new Promise<void>((resolve) => {\n shutdownDeadline = setTimeout(() => {\n this.logger.error(\"Worker shutdown timed out\", {\n signal,\n shutdownTimeoutMs: this.shutdownTimeoutMs,\n });\n resolve();\n }, this.shutdownTimeoutMs);\n });\n\n try {\n await Promise.race([Promise.all(this.workerLoops), deadlinePromise]);\n } finally {\n if (shutdownDeadline) {\n clearTimeout(shutdownDeadline);\n }\n }\n\n await this.subscriber?.unsubscribe();\n await this.subscriber?.quit();\n await this.queue.close();\n this.logger.log(\"All workers and subscribers shut down.\", { signal });\n }\n\n public async stop() {\n shutdownManager.unregister(`redis-worker:${this.options.name}`);\n await this.shutdown();\n }\n}\n\nexport { Worker };\n","/**\n * Check if an error is an AbortError.\n *\n * This handles both:\n * - Custom abort errors created with `new Error(\"AbortError\")` (sets .message)\n * - Native Node.js AbortError from timers/promises (sets .name)\n */\nexport function isAbortError(error: unknown): boolean {\n return error instanceof Error && (error.name === \"AbortError\" || error.message === \"AbortError\");\n}\n","import { createRedisClient, type Redis, type RedisOptions } from \"@internal/redis\";\nimport type {\n ConcurrencyCheckResult,\n ConcurrencyGroupConfig,\n ConcurrencyState,\n FairQueueKeyProducer,\n QueueDescriptor,\n} from \"./types.js\";\n\n/**\n * Page size for iterating a concurrency set's members (SSCAN COUNT) and cap on how many\n * members one sweep script invocation checks, bounding both the snapshot reads and the\n * time the atomic Lua script can hold up Redis when a set has accumulated many leaked\n * members.\n */\nconst SWEEP_MEMBER_CHUNK_SIZE = 500;\n\nexport interface ConcurrencyManagerOptions {\n redis: RedisOptions;\n keys: FairQueueKeyProducer;\n groups: ConcurrencyGroupConfig[];\n logger?: {\n debug: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n };\n}\n\n/**\n * ConcurrencyManager handles multi-level concurrency tracking and limiting.\n *\n * Features:\n * - Multiple concurrent concurrency groups (tenant, org, project, etc.)\n * - Atomic reserve/release operations using Lua scripts\n * - Efficient batch checking of all groups\n */\nexport class ConcurrencyManager {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private groups: ConcurrencyGroupConfig[];\n private groupsByName: Map<string, ConcurrencyGroupConfig>;\n private logger: NonNullable<ConcurrencyManagerOptions[\"logger\"]>;\n\n constructor(private options: ConcurrencyManagerOptions) {\n this.redis = createRedisClient(options.redis);\n this.keys = options.keys;\n this.groups = options.groups;\n this.groupsByName = new Map(options.groups.map((g) => [g.name, g]));\n this.logger = options.logger ?? {\n debug: () => {},\n error: () => {},\n };\n\n this.#registerCommands();\n }\n\n // ============================================================================\n // Public Methods\n // ============================================================================\n\n /**\n * Check if a message can be processed given all concurrency constraints.\n * Checks all configured groups and returns the first one at capacity.\n */\n async canProcess(queue: QueueDescriptor): Promise<ConcurrencyCheckResult> {\n for (const group of this.groups) {\n const groupId = group.extractGroupId(queue);\n const isAtCapacity = await this.isAtCapacity(group.name, groupId);\n\n if (isAtCapacity) {\n const state = await this.getState(group.name, groupId);\n return {\n allowed: false,\n blockedBy: state,\n };\n }\n }\n\n return { allowed: true };\n }\n\n /**\n * Reserve concurrency slots for a message across all groups.\n * Atomic - either all groups are reserved or none.\n *\n * @returns true if reservation successful, false if any group is at capacity\n */\n async reserve(queue: QueueDescriptor, messageId: string): Promise<boolean> {\n // Build list of group keys and limits\n const groupData = await Promise.all(\n this.groups.map(async (group) => {\n const groupId = group.extractGroupId(queue);\n const limit = await group.getLimit(groupId);\n return {\n key: this.keys.concurrencyKey(group.name, groupId),\n limit: limit || group.defaultLimit,\n };\n })\n );\n\n // Use Lua script for atomic multi-group reservation\n // Pass keys as KEYS array so ioredis applies keyPrefix correctly\n const keys = groupData.map((g) => g.key);\n const limits = groupData.map((g) => g.limit.toString());\n\n // Args order: messageId, ...limits (keys are passed separately)\n const result = await this.redis.reserveConcurrency(keys.length, keys, messageId, ...limits);\n\n return result === 1;\n }\n\n /**\n * Release concurrency slots for a message across all groups.\n */\n async release(queue: QueueDescriptor, messageId: string): Promise<void> {\n const pipeline = this.redis.pipeline();\n\n for (const group of this.groups) {\n const groupId = group.extractGroupId(queue);\n const key = this.keys.concurrencyKey(group.name, groupId);\n pipeline.srem(key, messageId);\n }\n\n this.#assertPipelineSucceeded(await pipeline.exec(), 1);\n }\n\n /**\n * Throw if any command in a released pipeline failed. ioredis resolves `exec()` even when\n * individual commands error, so an unchecked pipeline reports success while leaving the\n * slot held, which strands it permanently once the caller drops the in-flight record.\n */\n #assertPipelineSucceeded(\n results: Array<[Error | null, unknown]> | null,\n messageCount: number\n ): void {\n if (results === null) {\n throw new Error(\n `Concurrency release pipeline for ${messageCount} message(s) was discarded without executing`\n );\n }\n\n const errors = results\n .map(([error]) => error)\n .filter((error): error is Error => Boolean(error));\n\n if (errors.length > 0) {\n throw new Error(\n `Failed to release ${errors.length} of ${\n results?.length ?? 0\n } concurrency slot commands across ${messageCount} message(s): ${errors\n .map((error) => error.message)\n .join(\"; \")}`\n );\n }\n }\n\n /**\n * Release concurrency slots for multiple messages in a single pipeline.\n * More efficient than calling release() multiple times.\n */\n async releaseBatch(\n messages: Array<{ queue: QueueDescriptor; messageId: string }>\n ): Promise<void> {\n if (messages.length === 0) {\n return;\n }\n\n const pipeline = this.redis.pipeline();\n\n for (const { queue, messageId } of messages) {\n for (const group of this.groups) {\n const groupId = group.extractGroupId(queue);\n const key = this.keys.concurrencyKey(group.name, groupId);\n pipeline.srem(key, messageId);\n }\n }\n\n this.#assertPipelineSucceeded(await pipeline.exec(), messages.length);\n }\n\n /**\n * Remove concurrency set members that no longer correspond to an in-flight message,\n * healing slots leaked by failed releases. Scans every set of every group and, per\n * member, atomically removes it unless the message id appears in one of the given\n * in-flight data hashes. Sound because a message is registered in-flight before its\n * slot is reserved, so at the moment of the atomic check a member with no in-flight\n * record can only be a leak; if the message is about to be re-claimed, reserve simply\n * re-adds the member.\n *\n * @param inflightDataKeys - The in-flight data hash keys for every shard. The sweep\n * refuses to run when this is empty, since with nowhere to look for running messages\n * every member would look orphaned and all concurrency accounting would be erased.\n * @returns The message ids that were removed, and how many sets were checked\n */\n async sweepOrphanedSlots(\n inflightDataKeys: string[]\n ): Promise<{ scannedSets: number; removed: string[] }> {\n if (inflightDataKeys.length === 0) {\n this.logger.error(\n \"Refusing to sweep concurrency slots without any in-flight data keys: every member would look orphaned and all concurrency accounting would be erased\"\n );\n return { scannedSets: 0, removed: [] };\n }\n\n const keyPrefix = this.options.redis.keyPrefix ?? \"\";\n let scannedSets = 0;\n const removed: string[] = [];\n\n for (const group of this.groups) {\n const pattern = `${keyPrefix}${this.keys.concurrencyKey(group.name, \"*\")}`;\n let cursor = \"0\";\n\n do {\n const [nextCursor, foundKeys] = await this.redis.scan(\n cursor,\n \"MATCH\",\n pattern,\n \"COUNT\",\n 1000\n );\n cursor = nextCursor;\n\n for (const fullKey of foundKeys) {\n const key =\n keyPrefix && fullKey.startsWith(keyPrefix) ? fullKey.slice(keyPrefix.length) : fullKey;\n\n try {\n let sawMembers = false;\n let memberCursor = \"0\";\n\n do {\n const [nextMemberCursor, page] = await this.redis.sscan(\n key,\n memberCursor,\n \"COUNT\",\n SWEEP_MEMBER_CHUNK_SIZE\n );\n memberCursor = nextMemberCursor;\n\n if (page.length === 0) {\n continue;\n }\n sawMembers = true;\n\n for (let i = 0; i < page.length; i += SWEEP_MEMBER_CHUNK_SIZE) {\n const chunk = page.slice(i, i + SWEEP_MEMBER_CHUNK_SIZE);\n const removedIds = await this.redis.removeOrphanedConcurrencySlots(\n 1 + inflightDataKeys.length,\n [key, ...inflightDataKeys],\n ...chunk\n );\n removed.push(...removedIds);\n }\n } while (memberCursor !== \"0\");\n\n if (sawMembers) {\n scannedSets++;\n }\n } catch (error) {\n this.logger.error(\"Failed to sweep concurrency set, skipping it\", {\n key,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n } while (cursor !== \"0\");\n }\n\n return { scannedSets, removed };\n }\n\n /**\n * Get current concurrency for a specific group.\n */\n async getCurrentConcurrency(groupName: string, groupId: string): Promise<number> {\n const key = this.keys.concurrencyKey(groupName, groupId);\n return await this.redis.scard(key);\n }\n\n /**\n * Get available capacity for a queue across all concurrency groups.\n * Returns the minimum available capacity across all groups.\n */\n async getAvailableCapacity(queue: QueueDescriptor): Promise<number> {\n if (this.groups.length === 0) {\n return 0;\n }\n\n // Build group data for parallel fetching\n const groupData = this.groups.map((group) => ({\n group,\n groupId: group.extractGroupId(queue),\n }));\n\n // Fetch all current counts and limits in parallel\n const [currents, limits] = await Promise.all([\n Promise.all(\n groupData.map(({ group, groupId }) =>\n this.redis.scard(this.keys.concurrencyKey(group.name, groupId))\n )\n ),\n Promise.all(\n groupData.map(({ group, groupId }) =>\n group.getLimit(groupId).then((limit) => limit || group.defaultLimit)\n )\n ),\n ]);\n\n // Calculate minimum available capacity across all groups\n let minCapacity = Infinity;\n for (let i = 0; i < groupData.length; i++) {\n const available = Math.max(0, limits[i]! - currents[i]!);\n minCapacity = Math.min(minCapacity, available);\n }\n\n return minCapacity === Infinity ? 0 : minCapacity;\n }\n\n /**\n * Get concurrency limit for a specific group.\n */\n async getConcurrencyLimit(groupName: string, groupId: string): Promise<number> {\n const group = this.groupsByName.get(groupName);\n if (!group) {\n throw new Error(`Unknown concurrency group: ${groupName}`);\n }\n return (await group.getLimit(groupId)) || group.defaultLimit;\n }\n\n /**\n * Check if a group is at capacity.\n */\n async isAtCapacity(groupName: string, groupId: string): Promise<boolean> {\n const [current, limit] = await Promise.all([\n this.getCurrentConcurrency(groupName, groupId),\n this.getConcurrencyLimit(groupName, groupId),\n ]);\n return current >= limit;\n }\n\n /**\n * Get full state for a group.\n */\n async getState(groupName: string, groupId: string): Promise<ConcurrencyState> {\n const [current, limit] = await Promise.all([\n this.getCurrentConcurrency(groupName, groupId),\n this.getConcurrencyLimit(groupName, groupId),\n ]);\n return {\n groupName,\n groupId,\n current,\n limit,\n };\n }\n\n /**\n * Get all active message IDs for a group.\n */\n async getActiveMessages(groupName: string, groupId: string): Promise<string[]> {\n const key = this.keys.concurrencyKey(groupName, groupId);\n return await this.redis.smembers(key);\n }\n\n /**\n * Force-clear concurrency for a group (use with caution).\n * Useful for cleanup after crashes.\n */\n async clearGroup(groupName: string, groupId: string): Promise<void> {\n const key = this.keys.concurrencyKey(groupName, groupId);\n await this.redis.del(key);\n }\n\n /**\n * Remove a specific message from concurrency tracking.\n * Useful for cleanup.\n */\n async removeMessage(messageId: string, queue: QueueDescriptor): Promise<void> {\n await this.release(queue, messageId);\n }\n\n /**\n * Get configured group names.\n */\n getGroupNames(): string[] {\n return this.groups.map((g) => g.name);\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n #registerCommands(): void {\n // Atomic multi-group reservation\n // KEYS: concurrency set keys for each group (keyPrefix is applied by ioredis)\n // ARGV[1]: messageId\n // ARGV[2..n]: limits for each group (in same order as KEYS)\n this.redis.defineCommand(\"reserveConcurrency\", {\n lua: `\nlocal numGroups = #KEYS\nlocal messageId = ARGV[1]\n\n-- Check all groups first. A message that is already a member of a group's set passes\n-- that group's check: re-admitting it does not increase concurrency (SADD is a no-op),\n-- and counting its own leftover slot against it would let a message whose earlier\n-- release failed block its own retry forever.\nfor i = 1, numGroups do\n local key = KEYS[i]\n local limit = tonumber(ARGV[1 + i]) -- Limits start at ARGV[2]\n\n if redis.call('SISMEMBER', key, messageId) == 0 then\n local current = redis.call('SCARD', key)\n\n if current >= limit then\n return 0 -- At capacity\n end\n end\nend\n\n-- All groups have capacity, add message to all\nfor i = 1, numGroups do\n local key = KEYS[i]\n redis.call('SADD', key, messageId)\nend\n\nreturn 1\n `,\n });\n\n // Atomic orphan sweep for one concurrency set\n // KEYS[1]: concurrency set key\n // KEYS[2..n]: in-flight data hash keys for every shard\n // ARGV: candidate messageIds (a snapshot of the set's members)\n this.redis.defineCommand(\"removeOrphanedConcurrencySlots\", {\n lua: `\nlocal concurrencyKey = KEYS[1]\nlocal removedIds = {}\n\nfor i = 1, #ARGV do\n local messageId = ARGV[i]\n local inflight = false\n\n for j = 2, #KEYS do\n if redis.call('HEXISTS', KEYS[j], messageId) == 1 then\n inflight = true\n break\n end\n end\n\n if not inflight then\n if redis.call('SREM', concurrencyKey, messageId) == 1 then\n table.insert(removedIds, messageId)\n end\n end\nend\n\nreturn removedIds\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n reserveConcurrency(\n numKeys: number,\n keys: string[],\n messageId: string,\n ...limits: string[]\n ): Promise<number>;\n\n removeOrphanedConcurrencySlots(\n numKeys: number,\n keys: string[],\n ...messageIds: string[]\n ): Promise<string[]>;\n }\n}\n","import { createRedisClient, type Redis, type RedisOptions } from \"@internal/redis\";\nimport { jumpHash } from \"@trigger.dev/core/v3/serverOnly\";\nimport type { FairQueueKeyProducer, QueueWithScore } from \"./types.js\";\n\nexport interface MasterQueueOptions {\n redis: RedisOptions;\n keys: FairQueueKeyProducer;\n shardCount: number;\n}\n\n/**\n * Master queue manages the top-level queue of queues.\n *\n * Features:\n * - Sharding for horizontal scaling\n * - Consistent hashing for queue-to-shard assignment\n * - Queues scored by oldest message timestamp\n */\nexport class MasterQueue {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private shardCount: number;\n\n constructor(private options: MasterQueueOptions) {\n this.redis = createRedisClient(options.redis);\n this.keys = options.keys;\n this.shardCount = Math.max(1, options.shardCount);\n\n this.#registerCommands();\n }\n\n // ============================================================================\n // Public Methods\n // ============================================================================\n\n /**\n * Get the shard ID for a queue.\n * Uses consistent hashing based on queue ID.\n */\n getShardForQueue(queueId: string): number {\n return this.#hashToShard(queueId);\n }\n\n /**\n * Add a queue to its master queue shard.\n * Updates the score to the oldest message timestamp.\n *\n * @param queueId - The queue identifier\n * @param oldestMessageTimestamp - Timestamp of the oldest message in the queue\n */\n async addQueue(queueId: string, oldestMessageTimestamp: number): Promise<void> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n // Just use plain ZADD - it will add if not exists, or update if exists\n // The score represents the oldest message timestamp\n // We rely on the enqueue Lua scripts to set the correct score\n await this.redis.zadd(masterKey, oldestMessageTimestamp, queueId);\n }\n\n /**\n * Update a queue's score in the master queue.\n * This is typically called after dequeuing to update to the new oldest message.\n *\n * @param queueId - The queue identifier\n * @param newOldestTimestamp - New timestamp of the oldest message\n */\n async updateQueueScore(queueId: string, newOldestTimestamp: number): Promise<void> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n await this.redis.zadd(masterKey, newOldestTimestamp, queueId);\n }\n\n /**\n * Remove a queue from its master queue shard.\n * Called when a queue becomes empty.\n *\n * @param queueId - The queue identifier\n */\n async removeQueue(queueId: string): Promise<void> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n await this.redis.zrem(masterKey, queueId);\n }\n\n /**\n * Get queues from a shard, ordered by oldest message (lowest score first).\n *\n * @param shardId - The shard to query\n * @param limit - Maximum number of queues to return (default: 1000)\n * @param maxScore - Maximum score (timestamp) to include (default: now)\n */\n async getQueuesFromShard(\n shardId: number,\n limit: number = 1000,\n maxScore?: number\n ): Promise<QueueWithScore[]> {\n const masterKey = this.keys.masterQueueKey(shardId);\n const score = maxScore ?? Date.now();\n\n // Get queues with scores up to maxScore\n const results = await this.redis.zrangebyscore(\n masterKey,\n \"-inf\",\n score,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n limit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId: this.keys.extractTenantId(queueId),\n });\n }\n }\n\n return queues;\n }\n\n /**\n * Get the number of queues in a shard.\n */\n async getShardQueueCount(shardId: number): Promise<number> {\n const masterKey = this.keys.masterQueueKey(shardId);\n return await this.redis.zcard(masterKey);\n }\n\n /**\n * Get total queue count across all shards.\n */\n async getTotalQueueCount(): Promise<number> {\n const counts = await Promise.all(\n Array.from({ length: this.shardCount }, (_, i) => this.getShardQueueCount(i))\n );\n return counts.reduce((sum, count) => sum + count, 0);\n }\n\n /**\n * Atomically add a queue to master queue only if queue has messages.\n * Uses Lua script for atomicity.\n *\n * @param queueId - The queue identifier\n * @param queueKey - The actual queue sorted set key\n * @returns Whether the queue was added to the master queue\n */\n async addQueueIfNotEmpty(queueId: string, queueKey: string): Promise<boolean> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n const result = await this.redis.addQueueIfNotEmpty(masterKey, queueKey, queueId);\n return result === 1;\n }\n\n /**\n * Atomically remove a queue from master queue only if queue is empty.\n * Uses Lua script for atomicity.\n *\n * @param queueId - The queue identifier\n * @param queueKey - The actual queue sorted set key\n * @returns Whether the queue was removed from the master queue\n */\n async removeQueueIfEmpty(queueId: string, queueKey: string): Promise<boolean> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n const result = await this.redis.removeQueueIfEmpty(masterKey, queueKey, queueId);\n return result === 1;\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n /**\n * Map queue ID to shard using Jump Consistent Hash.\n * Provides better distribution than djb2 and minimal reshuffling when shard count changes.\n */\n #hashToShard(queueId: string): number {\n return jumpHash(queueId, this.shardCount);\n }\n\n #registerCommands(): void {\n // Atomically add queue to master if it has messages\n this.redis.defineCommand(\"addQueueIfNotEmpty\", {\n numberOfKeys: 2,\n lua: `\nlocal masterKey = KEYS[1]\nlocal queueKey = KEYS[2]\nlocal queueId = ARGV[1]\n\n-- Check if queue has any messages\nlocal count = redis.call('ZCARD', queueKey)\nif count == 0 then\n return 0\nend\n\n-- Get the oldest message timestamp (lowest score)\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest == 0 then\n return 0\nend\n\nlocal score = oldest[2]\n\n-- Add to master queue with the oldest message score\nredis.call('ZADD', masterKey, score, queueId)\nreturn 1\n `,\n });\n\n // Atomically remove queue from master if it's empty\n this.redis.defineCommand(\"removeQueueIfEmpty\", {\n numberOfKeys: 2,\n lua: `\nlocal masterKey = KEYS[1]\nlocal queueKey = KEYS[2]\nlocal queueId = ARGV[1]\n\n-- Check if queue is empty\nlocal count = redis.call('ZCARD', queueKey)\nif count > 0 then\n return 0\nend\n\n-- Remove from master queue\nredis.call('ZREM', masterKey, queueId)\nreturn 1\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n addQueueIfNotEmpty(masterKey: string, queueKey: string, queueId: string): Promise<number>;\n\n removeQueueIfEmpty(masterKey: string, queueKey: string, queueId: string): Promise<number>;\n }\n}\n","import type {\n Attributes,\n Counter,\n Histogram,\n Meter,\n ObservableGauge,\n Span,\n SpanKind,\n SpanOptions,\n Tracer,\n Context,\n} from \"@internal/tracing\";\nimport { context, trace, SpanStatusCode, ROOT_CONTEXT } from \"@internal/tracing\";\n\n/**\n * Semantic attributes for fair queue messaging operations.\n */\nexport const FairQueueAttributes = {\n QUEUE_ID: \"fairqueue.queue_id\",\n TENANT_ID: \"fairqueue.tenant_id\",\n MESSAGE_ID: \"fairqueue.message_id\",\n SHARD_ID: \"fairqueue.shard_id\",\n WORKER_QUEUE: \"fairqueue.worker_queue\",\n CONSUMER_ID: \"fairqueue.consumer_id\",\n ATTEMPT: \"fairqueue.attempt\",\n CONCURRENCY_GROUP: \"fairqueue.concurrency_group\",\n MESSAGE_COUNT: \"fairqueue.message_count\",\n RESULT: \"fairqueue.result\",\n} as const;\n\n/**\n * Standard messaging semantic attributes.\n */\nexport const MessagingAttributes = {\n SYSTEM: \"messaging.system\",\n OPERATION: \"messaging.operation\",\n MESSAGE_ID: \"messaging.message_id\",\n DESTINATION_NAME: \"messaging.destination.name\",\n} as const;\n\n/**\n * FairQueue metrics collection.\n */\nexport interface FairQueueMetrics {\n // Counters\n messagesEnqueued: Counter;\n messagesCompleted: Counter;\n messagesFailed: Counter;\n messagesRetried: Counter;\n messagesToDLQ: Counter;\n\n // Histograms\n processingTime: Histogram;\n queueTime: Histogram;\n\n // Observable gauges (registered with callbacks)\n queueLength: ObservableGauge;\n masterQueueLength: ObservableGauge;\n dispatchLength: ObservableGauge;\n inflightCount: ObservableGauge;\n dlqLength: ObservableGauge;\n}\n\n/**\n * Options for creating FairQueue telemetry.\n */\nexport interface TelemetryOptions {\n tracer?: Tracer;\n meter?: Meter;\n /** Custom name for metrics prefix */\n name?: string;\n}\n\n/**\n * Telemetry helper for FairQueue.\n *\n * Provides:\n * - Span creation with proper attributes\n * - Metric recording\n * - Context propagation helpers\n */\nexport class FairQueueTelemetry {\n private tracer?: Tracer;\n private meter?: Meter;\n private metrics?: FairQueueMetrics;\n private name: string;\n\n constructor(options: TelemetryOptions) {\n this.tracer = options.tracer;\n this.meter = options.meter;\n this.name = options.name ?? \"fairqueue\";\n\n if (this.meter) {\n this.#initializeMetrics();\n }\n }\n\n // ============================================================================\n // Tracing\n // ============================================================================\n\n /**\n * Create a traced span for an operation.\n * Returns the result of the function, or throws any error after recording it.\n */\n async trace<T>(\n name: string,\n fn: (span: Span) => Promise<T>,\n options?: {\n kind?: SpanKind;\n attributes?: Attributes;\n }\n ): Promise<T> {\n if (!this.tracer) {\n // No tracer, just execute the function with a no-op span\n return fn(noopSpan);\n }\n\n const spanOptions: SpanOptions = {\n kind: options?.kind,\n attributes: {\n [MessagingAttributes.SYSTEM]: this.name,\n ...options?.attributes,\n },\n };\n\n return this.tracer.startActiveSpan(`${this.name}.${name}`, spanOptions, async (span) => {\n try {\n const result = await fn(span);\n return result;\n } catch (error) {\n if (error instanceof Error) {\n span.recordException(error);\n } else {\n span.recordException(new Error(String(error)));\n }\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n /**\n * Synchronous version of trace.\n */\n traceSync<T>(\n name: string,\n fn: (span: Span) => T,\n options?: {\n kind?: SpanKind;\n attributes?: Attributes;\n }\n ): T {\n if (!this.tracer) {\n return fn(noopSpan);\n }\n\n const spanOptions: SpanOptions = {\n kind: options?.kind,\n attributes: {\n [MessagingAttributes.SYSTEM]: this.name,\n ...options?.attributes,\n },\n };\n\n return this.tracer.startActiveSpan(`${this.name}.${name}`, spanOptions, (span) => {\n try {\n return fn(span);\n } catch (error) {\n if (error instanceof Error) {\n span.recordException(error);\n } else {\n span.recordException(new Error(String(error)));\n }\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n // ============================================================================\n // Metrics\n // ============================================================================\n\n /**\n * Record a message enqueued.\n */\n recordEnqueue(attributes?: Attributes): void {\n this.metrics?.messagesEnqueued.add(1, attributes);\n }\n\n /**\n * Record a batch of messages enqueued.\n */\n recordEnqueueBatch(count: number, attributes?: Attributes): void {\n this.metrics?.messagesEnqueued.add(count, attributes);\n }\n\n /**\n * Record a message completed successfully.\n */\n recordComplete(attributes?: Attributes): void {\n this.metrics?.messagesCompleted.add(1, attributes);\n }\n\n /**\n * Record a message processing failure.\n */\n recordFailure(attributes?: Attributes): void {\n this.metrics?.messagesFailed.add(1, attributes);\n }\n\n /**\n * Record a message retry.\n */\n recordRetry(attributes?: Attributes): void {\n this.metrics?.messagesRetried.add(1, attributes);\n }\n\n /**\n * Record a message sent to DLQ.\n */\n recordDLQ(attributes?: Attributes): void {\n this.metrics?.messagesToDLQ.add(1, attributes);\n }\n\n /**\n * Record message processing time.\n *\n * @param durationMs - Processing duration in milliseconds\n */\n recordProcessingTime(durationMs: number, attributes?: Attributes): void {\n this.metrics?.processingTime.record(durationMs, attributes);\n }\n\n /**\n * Record time a message spent waiting in queue.\n *\n * @param durationMs - Queue wait time in milliseconds\n */\n recordQueueTime(durationMs: number, attributes?: Attributes): void {\n this.metrics?.queueTime.record(durationMs, attributes);\n }\n\n /**\n * Register observable gauge callbacks.\n * Call this after FairQueue is initialized to register the gauge callbacks.\n */\n registerGaugeCallbacks(callbacks: {\n getQueueLength?: (queueId: string) => Promise<number>;\n getMasterQueueLength?: (shardId: number) => Promise<number>;\n getDispatchLength?: (shardId: number) => Promise<number>;\n getInflightCount?: (shardId: number) => Promise<number>;\n getDLQLength?: (tenantId: string) => Promise<number>;\n shardCount?: number;\n observedQueues?: string[];\n observedTenants?: string[];\n }): void {\n if (!this.metrics) return;\n\n // Queue length gauge\n if (callbacks.getQueueLength && callbacks.observedQueues) {\n const getQueueLength = callbacks.getQueueLength;\n const queues = callbacks.observedQueues;\n\n this.metrics.queueLength.addCallback(async (observableResult) => {\n for (const queueId of queues) {\n const length = await getQueueLength(queueId);\n observableResult.observe(length, {\n [FairQueueAttributes.QUEUE_ID]: queueId,\n });\n }\n });\n }\n\n // Legacy master queue length gauge (draining, should trend to 0)\n if (callbacks.getMasterQueueLength && callbacks.shardCount) {\n const getMasterQueueLength = callbacks.getMasterQueueLength;\n const shardCount = callbacks.shardCount;\n\n this.metrics.masterQueueLength.addCallback(async (observableResult) => {\n for (let shardId = 0; shardId < shardCount; shardId++) {\n const length = await getMasterQueueLength(shardId);\n observableResult.observe(length, {\n [FairQueueAttributes.SHARD_ID]: shardId.toString(),\n });\n }\n });\n }\n\n // Dispatch index length gauge (new two-level dispatch, tenant count per shard)\n if (callbacks.getDispatchLength && callbacks.shardCount) {\n const getDispatchLength = callbacks.getDispatchLength;\n const shardCount = callbacks.shardCount;\n\n this.metrics.dispatchLength.addCallback(async (observableResult) => {\n for (let shardId = 0; shardId < shardCount; shardId++) {\n const length = await getDispatchLength(shardId);\n observableResult.observe(length, {\n [FairQueueAttributes.SHARD_ID]: shardId.toString(),\n });\n }\n });\n }\n\n // Inflight count gauge\n if (callbacks.getInflightCount && callbacks.shardCount) {\n const getInflightCount = callbacks.getInflightCount;\n const shardCount = callbacks.shardCount;\n\n this.metrics.inflightCount.addCallback(async (observableResult) => {\n for (let shardId = 0; shardId < shardCount; shardId++) {\n const count = await getInflightCount(shardId);\n observableResult.observe(count, {\n [FairQueueAttributes.SHARD_ID]: shardId.toString(),\n });\n }\n });\n }\n\n // DLQ length gauge\n if (callbacks.getDLQLength && callbacks.observedTenants) {\n const getDLQLength = callbacks.getDLQLength;\n const tenants = callbacks.observedTenants;\n\n this.metrics.dlqLength.addCallback(async (observableResult) => {\n for (const tenantId of tenants) {\n const length = await getDLQLength(tenantId);\n observableResult.observe(length, {\n [FairQueueAttributes.TENANT_ID]: tenantId,\n });\n }\n });\n }\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n /**\n * Create standard attributes for a message operation (for spans/traces).\n * Use this for span attributes where high cardinality is acceptable.\n */\n messageAttributes(params: {\n queueId?: string;\n tenantId?: string;\n messageId?: string;\n attempt?: number;\n workerQueue?: string;\n consumerId?: string;\n }): Attributes {\n const attrs: Attributes = {};\n\n if (params.queueId) attrs[FairQueueAttributes.QUEUE_ID] = params.queueId;\n if (params.tenantId) attrs[FairQueueAttributes.TENANT_ID] = params.tenantId;\n if (params.messageId) attrs[FairQueueAttributes.MESSAGE_ID] = params.messageId;\n if (params.attempt !== undefined) attrs[FairQueueAttributes.ATTEMPT] = params.attempt;\n if (params.workerQueue) attrs[FairQueueAttributes.WORKER_QUEUE] = params.workerQueue;\n if (params.consumerId) attrs[FairQueueAttributes.CONSUMER_ID] = params.consumerId;\n\n return attrs;\n }\n\n /**\n * Check if telemetry is enabled.\n */\n get isEnabled(): boolean {\n return !!this.tracer || !!this.meter;\n }\n\n /**\n * Check if tracing is enabled.\n */\n get hasTracer(): boolean {\n return !!this.tracer;\n }\n\n /**\n * Check if metrics are enabled.\n */\n get hasMetrics(): boolean {\n return !!this.meter;\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n #initializeMetrics(): void {\n if (!this.meter) return;\n\n this.metrics = {\n // Counters\n messagesEnqueued: this.meter.createCounter(`${this.name}.messages.enqueued`, {\n description: \"Number of messages enqueued\",\n unit: \"messages\",\n }),\n messagesCompleted: this.meter.createCounter(`${this.name}.messages.completed`, {\n description: \"Number of messages completed successfully\",\n unit: \"messages\",\n }),\n messagesFailed: this.meter.createCounter(`${this.name}.messages.failed`, {\n description: \"Number of messages that failed processing\",\n unit: \"messages\",\n }),\n messagesRetried: this.meter.createCounter(`${this.name}.messages.retried`, {\n description: \"Number of message retries\",\n unit: \"messages\",\n }),\n messagesToDLQ: this.meter.createCounter(`${this.name}.messages.dlq`, {\n description: \"Number of messages sent to dead letter queue\",\n unit: \"messages\",\n }),\n\n // Histograms\n processingTime: this.meter.createHistogram(`${this.name}.message.processing_time`, {\n description: \"Message processing time\",\n unit: \"ms\",\n }),\n queueTime: this.meter.createHistogram(`${this.name}.message.queue_time`, {\n description: \"Time message spent waiting in queue\",\n unit: \"ms\",\n }),\n\n // Observable gauges\n queueLength: this.meter.createObservableGauge(`${this.name}.queue.length`, {\n description: \"Number of messages in a queue\",\n unit: \"messages\",\n }),\n masterQueueLength: this.meter.createObservableGauge(`${this.name}.master_queue.length`, {\n description: \"Number of queues in legacy master queue shard (draining)\",\n unit: \"queues\",\n }),\n dispatchLength: this.meter.createObservableGauge(`${this.name}.dispatch.length`, {\n description: \"Number of tenants in dispatch index shard\",\n unit: \"tenants\",\n }),\n inflightCount: this.meter.createObservableGauge(`${this.name}.inflight.count`, {\n description: \"Number of messages currently being processed\",\n unit: \"messages\",\n }),\n dlqLength: this.meter.createObservableGauge(`${this.name}.dlq.length`, {\n description: \"Number of messages in dead letter queue\",\n unit: \"messages\",\n }),\n };\n }\n}\n\n// ============================================================================\n// Batched Span Manager\n// ============================================================================\n\n/**\n * State for tracking a consumer loop's batched span.\n */\nexport interface ConsumerLoopState {\n /** Countdown of iterations before starting a new span */\n perTraceCountdown: number;\n /** When the current trace started */\n traceStartedAt: Date;\n /** The current batched span */\n currentSpan?: Span;\n /** The context for the current batched span */\n currentSpanContext?: Context;\n /** Number of iterations in the current span */\n iterationsCount: number;\n /** Total iterations across all spans */\n totalIterationsCount: number;\n /** Running duration in milliseconds for the current span */\n runningDurationInMs: number;\n /** Stats counters for the current span */\n stats: Record<string, number>;\n /** Flag to force span end on next iteration */\n endSpanInNextIteration: boolean;\n}\n\n/**\n * Configuration for the BatchedSpanManager.\n */\nexport interface BatchedSpanManagerOptions {\n /** The tracer to use for creating spans */\n tracer?: Tracer;\n /** Name prefix for spans */\n name: string;\n /** Maximum iterations before rotating the span */\n maxIterations: number;\n /** Maximum seconds before rotating the span */\n timeoutSeconds: number;\n /** Optional callback to get dynamic attributes when starting a new batched span */\n getDynamicAttributes?: () => Attributes;\n}\n\n/**\n * Manages batched spans for consumer loops.\n *\n * This allows multiple iterations to be grouped into a single parent span,\n * reducing the volume of spans while maintaining observability.\n */\nexport class BatchedSpanManager {\n private tracer?: Tracer;\n private name: string;\n private maxIterations: number;\n private timeoutSeconds: number;\n private loopStates = new Map<string, ConsumerLoopState>();\n private getDynamicAttributes?: () => Attributes;\n\n constructor(options: BatchedSpanManagerOptions) {\n this.tracer = options.tracer;\n this.name = options.name;\n this.maxIterations = options.maxIterations;\n this.timeoutSeconds = options.timeoutSeconds;\n this.getDynamicAttributes = options.getDynamicAttributes;\n }\n\n /**\n * Initialize state for a consumer loop.\n */\n initializeLoop(loopId: string): void {\n this.loopStates.set(loopId, {\n perTraceCountdown: this.maxIterations,\n traceStartedAt: new Date(),\n iterationsCount: 0,\n totalIterationsCount: 0,\n runningDurationInMs: 0,\n stats: {},\n endSpanInNextIteration: false,\n });\n }\n\n /**\n * Get the state for a consumer loop.\n */\n getState(loopId: string): ConsumerLoopState | undefined {\n return this.loopStates.get(loopId);\n }\n\n /**\n * Increment a stat counter for a loop.\n */\n incrementStat(loopId: string, statName: string, value: number = 1): void {\n const state = this.loopStates.get(loopId);\n if (state) {\n state.stats[statName] = (state.stats[statName] ?? 0) + value;\n }\n }\n\n /**\n * Mark that the span should end on the next iteration.\n */\n markForRotation(loopId: string): void {\n const state = this.loopStates.get(loopId);\n if (state) {\n state.endSpanInNextIteration = true;\n }\n }\n\n /**\n * Check if the span should be rotated (ended and a new one started).\n */\n shouldRotate(loopId: string): boolean {\n const state = this.loopStates.get(loopId);\n if (!state) return true;\n\n return (\n state.perTraceCountdown <= 0 ||\n Date.now() - state.traceStartedAt.getTime() > this.timeoutSeconds * 1000 ||\n state.currentSpanContext === undefined ||\n state.endSpanInNextIteration\n );\n }\n\n /**\n * End the current span for a loop and record stats.\n */\n endCurrentSpan(loopId: string): void {\n const state = this.loopStates.get(loopId);\n if (!state?.currentSpan) return;\n\n // Record stats as span attributes\n for (const [statName, count] of Object.entries(state.stats)) {\n state.currentSpan.setAttribute(`stats.${statName}`, count);\n }\n\n state.currentSpan.end();\n state.currentSpan = undefined;\n state.currentSpanContext = undefined;\n }\n\n /**\n * Start a new batched span for a loop.\n */\n startNewSpan(loopId: string, attributes?: Attributes): void {\n if (!this.tracer) return;\n\n const state = this.loopStates.get(loopId);\n if (!state) return;\n\n // End any existing span first\n this.endCurrentSpan(loopId);\n\n // Calculate metrics from previous span period\n const traceDurationInMs = state.traceStartedAt\n ? Date.now() - state.traceStartedAt.getTime()\n : undefined;\n const iterationsPerSecond =\n traceDurationInMs && traceDurationInMs > 0\n ? state.iterationsCount / (traceDurationInMs / 1000)\n : undefined;\n\n // Get dynamic attributes if callback is provided\n const dynamicAttributes = this.getDynamicAttributes?.() ?? {};\n\n // Start new span\n state.currentSpan = this.tracer.startSpan(\n `${this.name}.consumerLoop`,\n {\n kind: 1, // SpanKind.CONSUMER\n attributes: {\n loop_id: loopId,\n max_iterations: this.maxIterations,\n timeout_seconds: this.timeoutSeconds,\n previous_iterations: state.iterationsCount,\n previous_duration_ms: traceDurationInMs,\n previous_iterations_per_second: iterationsPerSecond,\n total_iterations: state.totalIterationsCount,\n ...dynamicAttributes,\n ...attributes,\n },\n },\n ROOT_CONTEXT\n );\n\n // Set up context for child spans\n state.currentSpanContext = trace.setSpan(ROOT_CONTEXT, state.currentSpan);\n\n // Reset counters\n state.perTraceCountdown = this.maxIterations;\n state.traceStartedAt = new Date();\n state.iterationsCount = 0;\n state.runningDurationInMs = 0;\n state.stats = {};\n state.endSpanInNextIteration = false;\n }\n\n /**\n * Execute a function within the batched span context.\n * Automatically handles span rotation and iteration tracking.\n */\n async withBatchedSpan<T>(\n loopId: string,\n fn: (span: Span) => Promise<T>,\n options?: {\n iterationSpanName?: string;\n attributes?: Attributes;\n }\n ): Promise<T> {\n let state = this.loopStates.get(loopId);\n\n // Initialize state if not present\n if (!state) {\n this.initializeLoop(loopId);\n state = this.loopStates.get(loopId)!;\n }\n\n // Check if we need to rotate the span\n if (this.shouldRotate(loopId)) {\n this.startNewSpan(loopId);\n }\n\n const startTime = performance.now();\n\n try {\n // If no tracer, just execute the function\n if (!this.tracer || !state.currentSpanContext) {\n return await fn(noopSpan);\n }\n\n // Execute within the batched span context\n return await context.with(state.currentSpanContext, async () => {\n // Create an iteration span within the batched span\n const iterationSpanName = options?.iterationSpanName ?? \"iteration\";\n\n return await this.tracer!.startActiveSpan(\n `${this.name}.${iterationSpanName}`,\n {\n attributes: {\n loop_id: loopId,\n iteration: state.iterationsCount,\n ...options?.attributes,\n },\n },\n async (iterationSpan) => {\n try {\n return await fn(iterationSpan);\n } catch (error) {\n if (error instanceof Error) {\n iterationSpan.recordException(error);\n state.currentSpan?.recordException(error);\n }\n iterationSpan.setStatus({ code: SpanStatusCode.ERROR });\n state.endSpanInNextIteration = true;\n throw error;\n } finally {\n iterationSpan.end();\n }\n }\n );\n });\n } finally {\n // Update iteration tracking\n const duration = performance.now() - startTime;\n state.runningDurationInMs += duration;\n state.iterationsCount++;\n state.totalIterationsCount++;\n state.perTraceCountdown--;\n }\n }\n\n /**\n * Clean up state for a loop when it's stopped.\n */\n cleanup(loopId: string): void {\n this.endCurrentSpan(loopId);\n this.loopStates.delete(loopId);\n }\n\n /**\n * Clean up all loop states.\n */\n cleanupAll(): void {\n for (const loopId of this.loopStates.keys()) {\n this.cleanup(loopId);\n }\n }\n}\n\n/**\n * No-op span implementation for when telemetry is disabled.\n */\nconst noopSpan: Span = {\n spanContext: () => ({\n traceId: \"\",\n spanId: \"\",\n traceFlags: 0,\n }),\n setAttribute: () => noopSpan,\n setAttributes: () => noopSpan,\n addEvent: () => noopSpan,\n addLink: () => noopSpan,\n addLinks: () => noopSpan,\n setStatus: () => noopSpan,\n updateName: () => noopSpan,\n end: () => {},\n isRecording: () => false,\n recordException: () => {},\n};\n\n/**\n * No-op telemetry instance for when telemetry is disabled.\n */\nexport const noopTelemetry = new FairQueueTelemetry({});\n","import { createRedisClient, type Redis, type RedisOptions } from \"@internal/redis\";\nimport { jumpHash } from \"@trigger.dev/core/v3/serverOnly\";\nimport type { FairQueueKeyProducer, QueueWithScore } from \"./types.js\";\n\nexport interface TenantDispatchOptions {\n redis: RedisOptions;\n keys: FairQueueKeyProducer;\n shardCount: number;\n}\n\nexport interface TenantWithScore {\n tenantId: string;\n score: number;\n}\n\n/**\n * TenantDispatch manages the two-level tenant dispatch index.\n *\n * Level 1 - Dispatch Index (per shard):\n * Key: {prefix}:dispatch:{shardId}\n * ZSET of tenantIds scored by oldest message timestamp across their queues.\n * Only tenants with queues containing messages appear here.\n *\n * Level 2 - Per-Tenant Queue Index:\n * Key: {prefix}:tenantq:{tenantId}\n * ZSET of queueIds scored by oldest message timestamp in that queue.\n *\n * This replaces the flat master queue for new enqueues, isolating each tenant's\n * queue backlog so the scheduler iterates tenants (not queues) at Level 1.\n */\nexport class TenantDispatch {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private shardCount: number;\n\n constructor(private options: TenantDispatchOptions) {\n this.redis = createRedisClient(options.redis);\n this.keys = options.keys;\n this.shardCount = Math.max(1, options.shardCount);\n }\n\n /**\n * Get the dispatch shard ID for a tenant.\n * Uses jump consistent hash on the tenant ID so each tenant\n * always maps to exactly one dispatch shard.\n */\n getShardForTenant(tenantId: string): number {\n return jumpHash(tenantId, this.shardCount);\n }\n\n /**\n * Get eligible tenants from a dispatch shard (Level 1).\n * Returns tenants ordered by oldest message (lowest score first).\n */\n async getTenantsFromShard(\n shardId: number,\n limit: number = 1000,\n maxScore?: number\n ): Promise<TenantWithScore[]> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n const score = maxScore ?? Date.now();\n\n const results = await this.redis.zrangebyscore(\n dispatchKey,\n \"-inf\",\n score,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n limit\n );\n\n const tenants: TenantWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const tenantId = results[i];\n const scoreStr = results[i + 1];\n if (tenantId && scoreStr) {\n tenants.push({\n tenantId,\n score: parseFloat(scoreStr),\n });\n }\n }\n\n return tenants;\n }\n\n /**\n * Get queues for a specific tenant (Level 2).\n * Returns queues ordered by oldest message (lowest score first).\n */\n async getQueuesForTenant(\n tenantId: string,\n limit: number = 1000,\n maxScore?: number\n ): Promise<QueueWithScore[]> {\n const tenantQueueKey = this.keys.tenantQueueIndexKey(tenantId);\n const score = maxScore ?? Date.now();\n\n const results = await this.redis.zrangebyscore(\n tenantQueueKey,\n \"-inf\",\n score,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n limit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId,\n });\n }\n }\n\n return queues;\n }\n\n /**\n * Get the number of tenants in a dispatch shard.\n */\n async getShardTenantCount(shardId: number): Promise<number> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n return await this.redis.zcard(dispatchKey);\n }\n\n /**\n * Get total tenant count across all dispatch shards.\n * Note: tenants may appear in multiple shards, so this may overcount.\n */\n async getTotalTenantCount(): Promise<number> {\n const counts = await Promise.all(\n Array.from({ length: this.shardCount }, (_, i) => this.getShardTenantCount(i))\n );\n return counts.reduce((sum, count) => sum + count, 0);\n }\n\n /**\n * Get the number of queues for a tenant.\n */\n async getTenantQueueCount(tenantId: string): Promise<number> {\n const tenantQueueKey = this.keys.tenantQueueIndexKey(tenantId);\n return await this.redis.zcard(tenantQueueKey);\n }\n\n /**\n * Remove a tenant from a specific dispatch shard.\n */\n async removeTenantFromShard(shardId: number, tenantId: string): Promise<void> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n await this.redis.zrem(dispatchKey, tenantId);\n }\n\n /**\n * Add a tenant to a dispatch shard with the given score.\n */\n async addTenantToShard(shardId: number, tenantId: string, score: number): Promise<void> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n await this.redis.zadd(dispatchKey, score, tenantId);\n }\n\n /**\n * Remove a queue from a tenant's queue index.\n */\n async removeQueueFromTenant(tenantId: string, queueId: string): Promise<void> {\n const tenantQueueKey = this.keys.tenantQueueIndexKey(tenantId);\n await this.redis.zrem(tenantQueueKey, queueId);\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n}\n","import { createRedisClient, type Redis, type RedisOptions } from \"@internal/redis\";\nimport { jumpHash } from \"@trigger.dev/core/v3/serverOnly\";\nimport type {\n ClaimResult,\n FairQueueKeyProducer,\n InFlightMessage,\n ReclaimedMessageInfo,\n StoredMessage,\n} from \"./types.js\";\n\nexport interface VisibilityManagerOptions {\n redis: RedisOptions;\n keys: FairQueueKeyProducer;\n shardCount: number;\n defaultTimeoutMs: number;\n logger?: {\n debug: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n };\n}\n\n/**\n * VisibilityManager handles message visibility timeouts for safe message processing.\n *\n * Features:\n * - Claim messages with visibility timeout\n * - Heartbeat to extend timeout\n * - Automatic reclaim of timed-out messages\n * - Per-shard in-flight tracking\n *\n * Data structures:\n * - In-flight sorted set: score = deadline timestamp, member = \"{messageId}:{queueId}\"\n * - In-flight data hash: field = messageId, value = JSON message data\n */\nexport class VisibilityManager {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private shardCount: number;\n private defaultTimeoutMs: number;\n private logger: NonNullable<VisibilityManagerOptions[\"logger\"]>;\n\n constructor(private options: VisibilityManagerOptions) {\n this.redis = createRedisClient(options.redis);\n this.keys = options.keys;\n this.shardCount = options.shardCount;\n this.defaultTimeoutMs = options.defaultTimeoutMs;\n this.logger = options.logger ?? {\n debug: () => {},\n error: () => {},\n };\n\n this.#registerCommands();\n }\n\n // ============================================================================\n // Public Methods\n // ============================================================================\n\n /**\n * Claim a message for processing.\n * Moves the message from its queue to the in-flight set with a visibility timeout.\n *\n * @param queueId - The queue to claim from\n * @param queueKey - The Redis key for the queue sorted set\n * @param queueItemsKey - The Redis key for the queue items hash\n * @param consumerId - ID of the consumer claiming the message\n * @param timeoutMs - Visibility timeout in milliseconds\n * @returns Claim result with the message if successful\n */\n async claim<TPayload = unknown>(\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n consumerId: string,\n timeoutMs?: number\n ): Promise<ClaimResult<TPayload>> {\n const timeout = timeoutMs ?? this.defaultTimeoutMs;\n const deadline = Date.now() + timeout;\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Use Lua script to atomically:\n // 1. Pop oldest message from queue\n // 2. Add to in-flight set with deadline\n // 3. Store message data\n const result = await this.redis.claimMessage(\n queueKey,\n queueItemsKey,\n inflightKey,\n inflightDataKey,\n queueId,\n consumerId,\n deadline.toString()\n );\n\n if (!result) {\n return { claimed: false };\n }\n\n const [messageId, payloadJson] = result;\n\n try {\n const payload = JSON.parse(payloadJson) as TPayload;\n const message: InFlightMessage<TPayload> = {\n messageId,\n queueId,\n payload,\n deadline,\n consumerId,\n };\n\n this.logger.debug(\"Message claimed\", {\n messageId,\n queueId,\n consumerId,\n deadline,\n });\n\n return { claimed: true, message };\n } catch (error) {\n // JSON parse error - message data is corrupted\n this.logger.error(\"Failed to parse claimed message\", {\n messageId,\n queueId,\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Remove the corrupted message from in-flight\n await this.#removeFromInflight(shardId, messageId, queueId);\n\n return { claimed: false };\n }\n }\n\n /**\n * Claim multiple messages for processing (batch claim).\n * Moves up to maxCount messages from the queue to the in-flight set.\n *\n * @param queueId - The queue to claim from\n * @param queueKey - The Redis key for the queue sorted set\n * @param queueItemsKey - The Redis key for the queue items hash\n * @param consumerId - ID of the consumer claiming the messages\n * @param maxCount - Maximum number of messages to claim\n * @param timeoutMs - Visibility timeout in milliseconds\n * @returns Array of claimed messages\n */\n async claimBatch<TPayload = unknown>(\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n consumerId: string,\n maxCount: number,\n timeoutMs?: number\n ): Promise<Array<InFlightMessage<TPayload>>> {\n const timeout = timeoutMs ?? this.defaultTimeoutMs;\n const deadline = Date.now() + timeout;\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Use Lua script to atomically claim up to maxCount messages\n const result = await this.redis.claimMessageBatch(\n queueKey,\n queueItemsKey,\n inflightKey,\n inflightDataKey,\n queueId,\n deadline.toString(),\n maxCount.toString()\n );\n\n if (!result || result.length === 0) {\n return [];\n }\n\n const messages: Array<InFlightMessage<TPayload>> = [];\n\n // Results come in pairs: [messageId1, payload1, messageId2, payload2, ...]\n for (let i = 0; i < result.length; i += 2) {\n const messageId = result[i];\n const payloadJson = result[i + 1];\n\n // Skip if either value is missing\n if (!messageId || !payloadJson) {\n continue;\n }\n\n try {\n const payload = JSON.parse(payloadJson) as TPayload;\n messages.push({\n messageId,\n queueId,\n payload,\n deadline,\n consumerId,\n });\n } catch (error) {\n // JSON parse error - skip this message\n this.logger.error(\"Failed to parse claimed message in batch\", {\n messageId,\n queueId,\n error: error instanceof Error ? error.message : String(error),\n });\n // Remove the corrupted message from in-flight\n await this.#removeFromInflight(shardId, messageId, queueId);\n }\n }\n\n if (messages.length > 0) {\n this.logger.debug(\"Batch claimed messages\", {\n queueId,\n consumerId,\n count: messages.length,\n deadline,\n });\n }\n\n return messages;\n }\n\n /**\n * Extend the visibility timeout for a message (heartbeat).\n *\n * @param messageId - The message ID\n * @param queueId - The queue ID\n * @param extendMs - Additional milliseconds to add to the deadline\n * @returns true if the heartbeat was successful\n */\n async heartbeat(messageId: string, queueId: string, extendMs: number): Promise<boolean> {\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const member = this.#makeMember(messageId, queueId);\n const newDeadline = Date.now() + extendMs;\n\n // Use Lua script to atomically check existence and update score\n // ZADD XX returns 0 even on successful updates, so we use a custom command\n const result = await this.redis.heartbeatMessage(inflightKey, member, newDeadline.toString());\n\n const success = result === 1;\n\n if (success) {\n this.logger.debug(\"Heartbeat successful\", {\n messageId,\n queueId,\n newDeadline,\n });\n }\n\n return success;\n }\n\n /**\n * Mark a message as successfully processed.\n * Removes the message from in-flight tracking.\n *\n * @param messageId - The message ID\n * @param queueId - The queue ID\n */\n async complete(messageId: string, queueId: string): Promise<void> {\n const shardId = this.#getShardForQueue(queueId);\n await this.#removeFromInflight(shardId, messageId, queueId);\n\n this.logger.debug(\"Message completed\", {\n messageId,\n queueId,\n });\n }\n\n /**\n * Release a message back to its queue.\n * Used when processing fails or consumer wants to retry later.\n *\n * @param messageId - The message ID\n * @param queueId - The queue ID\n * @param queueKey - The Redis key for the queue\n * @param queueItemsKey - The Redis key for the queue items hash\n * @param tenantQueueIndexKey - The Redis key for the tenant queue index (Level 2)\n * @param dispatchKey - The Redis key for the dispatch index (Level 1)\n * @param tenantId - The tenant ID\n * @param score - Optional score for the message (defaults to now)\n */\n async release<_TPayload = unknown>(\n messageId: string,\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n tenantId: string,\n score?: number,\n updatedData?: string\n ): Promise<void> {\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const member = this.#makeMember(messageId, queueId);\n const messageScore = score ?? Date.now();\n\n // Use Lua script to atomically:\n // 1. Get message data from in-flight (or use updatedData if provided)\n // 2. Remove from in-flight\n // 3. Add back to queue\n // 4. Update dispatch indexes to ensure queue is picked up\n await this.redis.releaseMessage(\n inflightKey,\n inflightDataKey,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n member,\n messageId,\n messageScore.toString(),\n queueId,\n updatedData ?? \"\",\n tenantId\n );\n\n this.logger.debug(\"Message released\", {\n messageId,\n queueId,\n score: messageScore,\n });\n }\n\n /**\n * Release multiple messages back to their queue in a single operation.\n * Used when processing fails or consumer wants to retry later.\n * All messages must belong to the same queue.\n *\n * @param messages - Array of messages to release (must all have same queueId)\n * @param queueId - The queue ID\n * @param queueKey - The Redis key for the queue\n * @param queueItemsKey - The Redis key for the queue items hash\n * @param tenantQueueIndexKey - The Redis key for the tenant queue index (Level 2)\n * @param dispatchKey - The Redis key for the dispatch index (Level 1)\n * @param tenantId - The tenant ID\n * @param score - Optional score for the messages (defaults to now)\n */\n async releaseBatch(\n messages: Array<{ messageId: string }>,\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n tenantId: string,\n score?: number\n ): Promise<void> {\n if (messages.length === 0) {\n return;\n }\n\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const messageScore = score ?? Date.now();\n\n // Build arrays of members and messageIds for the Lua script\n const messageIds = messages.map((m) => m.messageId);\n const members = messages.map((m) => this.#makeMember(m.messageId, queueId));\n\n await this.redis.releaseMessageBatch(\n inflightKey,\n inflightDataKey,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n messageScore.toString(),\n queueId,\n tenantId,\n ...members,\n ...messageIds\n );\n\n this.logger.debug(\"Batch messages released\", {\n queueId,\n count: messages.length,\n score: messageScore,\n });\n }\n\n /**\n * Reclaim timed-out messages from a shard.\n * Returns messages to their original queues.\n *\n * @param shardId - The shard to check\n * @param getQueueKeys - Function to get queue keys for a queue ID\n * @param onBeforeRequeue - Hook invoked with the batch before any message is requeued,\n * used to free concurrency slots. A throw aborts the whole batch, leaving the\n * messages in-flight for the next reclaim tick.\n * @returns Array of reclaimed message info\n */\n async reclaimTimedOut(\n shardId: number,\n getQueueKeys: (queueId: string) => {\n queueKey: string;\n queueItemsKey: string;\n tenantQueueIndexKey: string;\n dispatchKey: string;\n tenantId: string;\n },\n onBeforeRequeue?: (messages: ReclaimedMessageInfo[]) => Promise<void>\n ): Promise<ReclaimedMessageInfo[]> {\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const now = Date.now();\n\n // Get all messages past their deadline\n const timedOut = await this.redis.zrangebyscore(\n inflightKey,\n \"-inf\",\n now,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n 100 // Process in batches\n );\n\n const candidates: Array<{\n member: string;\n deadlineScore: string;\n info: ReclaimedMessageInfo;\n storedMessage: StoredMessage | null;\n }> = [];\n\n for (let i = 0; i < timedOut.length; i += 2) {\n const member = timedOut[i];\n const deadlineScore = timedOut[i + 1];\n if (!member || !deadlineScore) {\n continue;\n }\n const { messageId, queueId } = this.#parseMember(member);\n\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n let storedMessage: StoredMessage | null = null;\n if (dataJson) {\n try {\n storedMessage = JSON.parse(dataJson);\n } catch {\n // Ignore parse error, proceed with reclaim\n }\n }\n\n if (!storedMessage) {\n this.logger.error(\"Missing or corrupted message data during reclaim, using fallback\", {\n messageId,\n queueId,\n });\n }\n\n candidates.push({\n member,\n deadlineScore,\n storedMessage,\n info: {\n messageId,\n queueId,\n tenantId: storedMessage?.tenantId ?? this.keys.extractTenantId(queueId),\n metadata: storedMessage?.metadata ?? {},\n },\n });\n }\n\n if (candidates.length === 0) {\n return [];\n }\n\n if (onBeforeRequeue) {\n await onBeforeRequeue(candidates.map((candidate) => candidate.info));\n }\n\n const reclaimedMessages: ReclaimedMessageInfo[] = [];\n\n for (const { member, deadlineScore, storedMessage, info } of candidates) {\n const { messageId, queueId } = info;\n\n const { queueKey, queueItemsKey, tenantQueueIndexKey, dispatchKey, tenantId } =\n getQueueKeys(queueId);\n\n try {\n // Re-add to queue with original timestamp to preserve priority\n // Fall back to now if we can't get the original timestamp\n const score = storedMessage?.timestamp ?? now;\n await this.redis.releaseMessage(\n inflightKey,\n inflightDataKey,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n member,\n messageId,\n score.toString(),\n queueId,\n \"\",\n tenantId\n );\n\n reclaimedMessages.push(info);\n\n this.logger.debug(\"Reclaimed timed-out message\", {\n messageId,\n queueId,\n deadline: deadlineScore,\n });\n } catch (error) {\n this.logger.error(\"Failed to reclaim message\", {\n messageId,\n queueId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return reclaimedMessages;\n }\n\n /**\n * Get all in-flight messages for a shard.\n */\n async getInflightMessages(shardId: number): Promise<\n Array<{\n messageId: string;\n queueId: string;\n deadline: number;\n }>\n > {\n const inflightKey = this.keys.inflightKey(shardId);\n const results = await this.redis.zrange(inflightKey, 0, -1, \"WITHSCORES\");\n\n const messages: Array<{ messageId: string; queueId: string; deadline: number }> = [];\n\n for (let i = 0; i < results.length; i += 2) {\n const member = results[i];\n const deadlineStr = results[i + 1];\n if (!member || !deadlineStr) {\n continue;\n }\n const deadline = parseFloat(deadlineStr);\n const { messageId, queueId } = this.#parseMember(member);\n\n messages.push({ messageId, queueId, deadline });\n }\n\n return messages;\n }\n\n /**\n * Get count of in-flight messages for a shard.\n */\n async getInflightCount(shardId: number): Promise<number> {\n const inflightKey = this.keys.inflightKey(shardId);\n return await this.redis.zcard(inflightKey);\n }\n\n /**\n * Get total in-flight count across all shards.\n */\n async getTotalInflightCount(): Promise<number> {\n const counts = await Promise.all(\n Array.from({ length: this.shardCount }, (_, i) => this.getInflightCount(i))\n );\n return counts.reduce((sum, count) => sum + count, 0);\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n /**\n * Map queue ID to shard using Jump Consistent Hash.\n * Must use same algorithm as MasterQueue for consistency.\n */\n #getShardForQueue(queueId: string): number {\n return jumpHash(queueId, this.shardCount);\n }\n\n #makeMember(messageId: string, queueId: string): string {\n return `${messageId}:${queueId}`;\n }\n\n #parseMember(member: string): { messageId: string; queueId: string } {\n const colonIndex = member.indexOf(\":\");\n if (colonIndex === -1) {\n return { messageId: member, queueId: \"\" };\n }\n return {\n messageId: member.substring(0, colonIndex),\n queueId: member.substring(colonIndex + 1),\n };\n }\n\n async #removeFromInflight(shardId: number, messageId: string, queueId: string): Promise<void> {\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const member = this.#makeMember(messageId, queueId);\n\n const pipeline = this.redis.pipeline();\n pipeline.zrem(inflightKey, member);\n pipeline.hdel(inflightDataKey, messageId);\n await pipeline.exec();\n }\n\n #registerCommands(): void {\n // Atomic claim: pop from queue, add to in-flight\n this.redis.defineCommand(\"claimMessage\", {\n numberOfKeys: 4,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal inflightKey = KEYS[3]\nlocal inflightDataKey = KEYS[4]\n\nlocal queueId = ARGV[1]\nlocal consumerId = ARGV[2]\nlocal deadline = tonumber(ARGV[3])\n\n-- Get oldest message from queue\nlocal items = redis.call('ZRANGE', queueKey, 0, 0)\nif #items == 0 then\n return nil\nend\n\nlocal messageId = items[1]\n\n-- Get message data\nlocal payload = redis.call('HGET', queueItemsKey, messageId)\nif not payload then\n -- Message data missing, remove from queue and return nil\n redis.call('ZREM', queueKey, messageId)\n return nil\nend\n\n-- Remove from queue\nredis.call('ZREM', queueKey, messageId)\nredis.call('HDEL', queueItemsKey, messageId)\n\n-- Add to in-flight set with deadline\nlocal member = messageId .. ':' .. queueId\nredis.call('ZADD', inflightKey, deadline, member)\n\n-- Store message data for potential release\nredis.call('HSET', inflightDataKey, messageId, payload)\n\nreturn {messageId, payload}\n `,\n });\n\n // Atomic batch claim: pop up to N messages from queue, add to in-flight\n this.redis.defineCommand(\"claimMessageBatch\", {\n numberOfKeys: 4,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal inflightKey = KEYS[3]\nlocal inflightDataKey = KEYS[4]\n\nlocal queueId = ARGV[1]\nlocal deadline = tonumber(ARGV[2])\nlocal maxCount = tonumber(ARGV[3])\n\n-- Get up to maxCount oldest messages from queue\nlocal items = redis.call('ZRANGE', queueKey, 0, maxCount - 1)\nif #items == 0 then\n return {}\nend\n\nlocal results = {}\n\nfor i, messageId in ipairs(items) do\n -- Get message data\n local payload = redis.call('HGET', queueItemsKey, messageId)\n \n if payload then\n -- Remove from queue\n redis.call('ZREM', queueKey, messageId)\n redis.call('HDEL', queueItemsKey, messageId)\n \n -- Add to in-flight set with deadline\n local member = messageId .. ':' .. queueId\n redis.call('ZADD', inflightKey, deadline, member)\n \n -- Store message data for potential release\n redis.call('HSET', inflightDataKey, messageId, payload)\n \n -- Add to results\n table.insert(results, messageId)\n table.insert(results, payload)\n else\n -- Message data missing, remove from queue\n redis.call('ZREM', queueKey, messageId)\n end\nend\n\nreturn results\n `,\n });\n\n // Atomic release: remove from in-flight, add back to queue, update dispatch indexes\n this.redis.defineCommand(\"releaseMessage\", {\n numberOfKeys: 6,\n lua: `\nlocal inflightKey = KEYS[1]\nlocal inflightDataKey = KEYS[2]\nlocal queueKey = KEYS[3]\nlocal queueItemsKey = KEYS[4]\nlocal tenantQueueIndexKey = KEYS[5]\nlocal dispatchKey = KEYS[6]\n\nlocal member = ARGV[1]\nlocal messageId = ARGV[2]\nlocal score = tonumber(ARGV[3])\nlocal queueId = ARGV[4]\nlocal updatedData = ARGV[5]\nlocal tenantId = ARGV[6]\n\n-- Get message data from in-flight\nlocal payload = redis.call('HGET', inflightDataKey, messageId)\nif not payload then\n -- Message not in in-flight or already released. Drop the dangling in-flight\n -- entry so it stops consuming a slot in every future reclaim scan.\n redis.call('ZREM', inflightKey, member)\n return 0\nend\n\n-- Use updatedData if provided (e.g. incremented attempt count for retries),\n-- otherwise use the original in-flight data\nif updatedData and updatedData ~= \"\" then\n payload = updatedData\nend\n\n-- Add back to queue before dropping the in-flight record. Lua does not roll back on\n-- error, so removing first would lose the message outright if the queue write failed.\nredis.call('ZADD', queueKey, score, messageId)\nredis.call('HSET', queueItemsKey, messageId, payload)\n\n-- Remove from in-flight\nredis.call('ZREM', inflightKey, member)\nredis.call('HDEL', inflightDataKey, messageId)\n\n-- Update tenant queue index (Level 2) with queue's oldest message\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\nend\n\n-- Update dispatch index (Level 1) with tenant's oldest across all queues\nlocal tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\nif #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\nend\n\nreturn 1\n `,\n });\n\n // Atomic batch release: release multiple messages back to queue\n this.redis.defineCommand(\"releaseMessageBatch\", {\n numberOfKeys: 6,\n lua: `\nlocal inflightKey = KEYS[1]\nlocal inflightDataKey = KEYS[2]\nlocal queueKey = KEYS[3]\nlocal queueItemsKey = KEYS[4]\nlocal tenantQueueIndexKey = KEYS[5]\nlocal dispatchKey = KEYS[6]\n\nlocal score = tonumber(ARGV[1])\nlocal queueId = ARGV[2]\nlocal tenantId = ARGV[3]\n\n-- Remaining args are: members..., messageIds...\n-- Calculate how many messages we have\nlocal numMessages = (table.getn(ARGV) - 3) / 2\nlocal membersStart = 4\nlocal messageIdsStart = membersStart + numMessages\n\nlocal releasedCount = 0\n\nfor i = 0, numMessages - 1 do\n local member = ARGV[membersStart + i]\n local messageId = ARGV[messageIdsStart + i]\n\n -- Get message data from in-flight\n local payload = redis.call('HGET', inflightDataKey, messageId)\n if payload then\n -- Add back to queue before dropping the in-flight record, so a failed queue write\n -- cannot lose the message: Lua does not roll back already-applied commands.\n redis.call('ZADD', queueKey, score, messageId)\n redis.call('HSET', queueItemsKey, messageId, payload)\n\n -- Remove from in-flight\n redis.call('ZREM', inflightKey, member)\n redis.call('HDEL', inflightDataKey, messageId)\n\n releasedCount = releasedCount + 1\n else\n -- Dangling in-flight entry with no payload: drop it so it stops consuming\n -- a slot in every future reclaim scan.\n redis.call('ZREM', inflightKey, member)\n end\nend\n\n-- Update dispatch indexes (only once at the end)\nif releasedCount > 0 then\n -- Update tenant queue index (Level 2)\n local oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\n if #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\n end\n -- Update dispatch index (Level 1)\n local tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\n if #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\n end\nend\n\nreturn releasedCount\n `,\n });\n\n // Atomic heartbeat: check if member exists and update score\n // ZADD XX returns 0 even on successful updates (it counts new additions only)\n // So we need to check existence first with ZSCORE\n this.redis.defineCommand(\"heartbeatMessage\", {\n numberOfKeys: 1,\n lua: `\nlocal inflightKey = KEYS[1]\nlocal member = ARGV[1]\nlocal newDeadline = tonumber(ARGV[2])\n\n-- Check if member exists in the in-flight set\nlocal score = redis.call('ZSCORE', inflightKey, member)\nif not score then\n return 0\nend\n\n-- Update the deadline\nredis.call('ZADD', inflightKey, 'XX', newDeadline, member)\nreturn 1\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n claimMessage(\n queueKey: string,\n queueItemsKey: string,\n inflightKey: string,\n inflightDataKey: string,\n queueId: string,\n consumerId: string,\n deadline: string\n ): Promise<[string, string] | null>;\n\n claimMessageBatch(\n queueKey: string,\n queueItemsKey: string,\n inflightKey: string,\n inflightDataKey: string,\n queueId: string,\n deadline: string,\n maxCount: string\n ): Promise<string[]>;\n\n releaseMessage(\n inflightKey: string,\n inflightDataKey: string,\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n member: string,\n messageId: string,\n score: string,\n queueId: string,\n updatedData: string,\n tenantId: string\n ): Promise<number>;\n\n releaseMessageBatch(\n inflightKey: string,\n inflightDataKey: string,\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n score: string,\n queueId: string,\n tenantId: string,\n ...membersAndMessageIds: string[]\n ): Promise<number>;\n\n heartbeatMessage(inflightKey: string, member: string, newDeadline: string): Promise<number>;\n }\n}\n","import { createRedisClient, type Redis, type RedisOptions } from \"@internal/redis\";\nimport type { FairQueueKeyProducer } from \"./types.js\";\n\nexport interface WorkerQueueManagerOptions {\n redis: RedisOptions;\n keys: FairQueueKeyProducer;\n logger?: {\n debug: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n };\n}\n\n/**\n * WorkerQueueManager handles the intermediate worker queue layer.\n *\n * This provides:\n * - Low-latency message delivery via blocking pop (BLPOP)\n * - Routing of messages to specific workers/consumers\n * - Efficient waiting without polling\n *\n * Flow:\n * 1. Master queue consumer claims message from message queue\n * 2. Message key is pushed to worker queue\n * 3. Worker queue consumer does blocking pop to receive message\n */\nexport class WorkerQueueManager {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private logger: NonNullable<WorkerQueueManagerOptions[\"logger\"]>;\n\n constructor(private options: WorkerQueueManagerOptions) {\n this.redis = createRedisClient(options.redis);\n this.keys = options.keys;\n this.logger = options.logger ?? {\n debug: () => {},\n error: () => {},\n };\n this.#registerCommands();\n }\n\n // ============================================================================\n // Public Methods\n // ============================================================================\n\n /**\n * Push a message key to a worker queue.\n * Called after claiming a message from the message queue.\n *\n * @param workerQueueId - The worker queue identifier\n * @param messageKey - The message key to push (typically \"messageId:queueId\")\n */\n async push(workerQueueId: string, messageKey: string): Promise<void> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n await this.redis.rpush(workerQueueKey, messageKey);\n\n this.logger.debug(\"Pushed to worker queue\", {\n workerQueueId,\n workerQueueKey,\n messageKey,\n });\n }\n\n /**\n * Push multiple message keys to a worker queue.\n *\n * @param workerQueueId - The worker queue identifier\n * @param messageKeys - The message keys to push\n */\n async pushBatch(workerQueueId: string, messageKeys: string[]): Promise<void> {\n if (messageKeys.length === 0) {\n return;\n }\n\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n await this.redis.rpush(workerQueueKey, ...messageKeys);\n\n this.logger.debug(\"Pushed batch to worker queue\", {\n workerQueueId,\n workerQueueKey,\n count: messageKeys.length,\n });\n }\n\n /**\n * Blocking pop from a worker queue.\n * Waits until a message is available or timeout expires.\n *\n * @param workerQueueId - The worker queue identifier\n * @param timeoutSeconds - Maximum time to wait (0 = wait forever)\n * @param signal - Optional abort signal to cancel waiting\n * @returns The message key, or null if timeout\n */\n async blockingPop(\n workerQueueId: string,\n timeoutSeconds: number,\n signal?: AbortSignal\n ): Promise<string | null> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n\n // Create a separate client for blocking operation\n // This is required because BLPOP blocks the connection\n const blockingClient = this.redis.duplicate();\n\n // Define cleanup outside try so it's accessible in finally\n // This prevents listener accumulation on the AbortSignal\n const cleanup = signal\n ? () => {\n blockingClient.disconnect();\n }\n : null;\n\n try {\n // Set up abort handler\n if (signal && cleanup) {\n signal.addEventListener(\"abort\", cleanup, { once: true });\n\n if (signal.aborted) {\n return null;\n }\n }\n\n const result = await blockingClient.blpop(workerQueueKey, timeoutSeconds);\n\n if (!result) {\n return null;\n }\n\n // BLPOP returns [key, value]\n const [, messageKey] = result;\n\n this.logger.debug(\"Blocking pop received message\", {\n workerQueueId,\n workerQueueKey,\n messageKey,\n });\n\n return messageKey;\n } catch (error) {\n // Handle abort/disconnect\n if (signal?.aborted) {\n return null;\n }\n\n this.logger.error(\"Blocking pop error\", {\n workerQueueId,\n error: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n } finally {\n // Always remove the listener to prevent accumulation on the AbortSignal\n // (once: true only removes if abort fires, not on normal completion)\n if (cleanup && signal) {\n signal.removeEventListener(\"abort\", cleanup);\n }\n if (blockingClient.status !== \"end\") {\n await blockingClient.quit().catch(() => {\n // Ignore quit errors (may already be disconnected)\n });\n }\n }\n }\n\n /**\n * Non-blocking pop from a worker queue.\n *\n * @param workerQueueId - The worker queue identifier\n * @returns The message key and queue length, or null if empty\n */\n async pop(workerQueueId: string): Promise<{ messageKey: string; queueLength: number } | null> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n\n const result = await this.redis.popWithLength(workerQueueKey);\n\n if (!result) {\n return null;\n }\n\n const [messageKey, queueLength] = result;\n\n this.logger.debug(\"Non-blocking pop received message\", {\n workerQueueId,\n workerQueueKey,\n messageKey,\n queueLength,\n });\n\n return { messageKey, queueLength: Number(queueLength) };\n }\n\n /**\n * Get the current length of a worker queue.\n */\n async getLength(workerQueueId: string): Promise<number> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n return await this.redis.llen(workerQueueKey);\n }\n\n /**\n * Peek at all messages in a worker queue without removing them.\n * Useful for debugging and tests.\n */\n async peek(workerQueueId: string): Promise<string[]> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n return await this.redis.lrange(workerQueueKey, 0, -1);\n }\n\n /**\n * Remove a specific message from the worker queue.\n * Used when a message needs to be removed without processing.\n *\n * @param workerQueueId - The worker queue identifier\n * @param messageKey - The message key to remove\n * @returns Number of removed items\n */\n async remove(workerQueueId: string, messageKey: string): Promise<number> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n return await this.redis.lrem(workerQueueKey, 0, messageKey);\n }\n\n /**\n * Clear all messages from a worker queue.\n */\n async clear(workerQueueId: string): Promise<void> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n await this.redis.del(workerQueueKey);\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private - Register Commands\n // ============================================================================\n\n /**\n * Initialize custom Redis commands.\n */\n #registerCommands(): void {\n // Non-blocking pop with queue length\n this.redis.defineCommand(\"popWithLength\", {\n numberOfKeys: 1,\n lua: `\nlocal workerQueueKey = KEYS[1]\n\n-- Pop the first message\nlocal messageKey = redis.call('LPOP', workerQueueKey)\nif not messageKey then\n return nil\nend\n\n-- Get remaining queue length\nlocal queueLength = redis.call('LLEN', workerQueueKey)\n\nreturn {messageKey, queueLength}\n `,\n });\n }\n\n /**\n * Register custom commands on an external Redis client.\n * Use this when initializing FairQueue with worker queues.\n */\n registerCommands(redis: Redis): void {\n redis.defineCommand(\"popWithLength\", {\n numberOfKeys: 1,\n lua: `\nlocal workerQueueKey = KEYS[1]\n\n-- Pop the first message\nlocal messageKey = redis.call('LPOP', workerQueueKey)\nif not messageKey then\n return nil\nend\n\n-- Get remaining queue length\nlocal queueLength = redis.call('LLEN', workerQueueKey)\n\nreturn {messageKey, queueLength}\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n popWithLength(workerQueueKey: string): Promise<[string, string] | null>;\n }\n}\n","import type { FairQueueKeyProducer } from \"./types.js\";\n\n/**\n * Default key producer for the fair queue system.\n * Uses a configurable prefix and standard key structure.\n *\n * Key structure:\n * - Master queue: {prefix}:master:{shardId} (legacy, drain-only)\n * - Dispatch index: {prefix}:dispatch:{shardId} (Level 1: tenantIds)\n * - Tenant queue index: {prefix}:tenantq:{tenantId} (Level 2: queueIds)\n * - Queue: {prefix}:queue:{queueId}\n * - Queue items: {prefix}:queue:{queueId}:items\n * - Concurrency: {prefix}:concurrency:{groupName}:{groupId}\n * - In-flight: {prefix}:inflight:{shardId}\n * - In-flight data: {prefix}:inflight:{shardId}:data\n * - Worker queue: {prefix}:worker:{consumerId}\n */\nexport class DefaultFairQueueKeyProducer implements FairQueueKeyProducer {\n private readonly prefix: string;\n private readonly separator: string;\n\n constructor(options: { prefix?: string; separator?: string } = {}) {\n this.prefix = options.prefix ?? \"fq\";\n this.separator = options.separator ?? \":\";\n }\n\n // ============================================================================\n // Master Queue Keys\n // ============================================================================\n\n masterQueueKey(shardId: number): string {\n return this.#buildKey(\"master\", shardId.toString());\n }\n\n // ============================================================================\n // Queue Keys\n // ============================================================================\n\n queueKey(queueId: string): string {\n return this.#buildKey(\"queue\", queueId);\n }\n\n queueItemsKey(queueId: string): string {\n return this.#buildKey(\"queue\", queueId, \"items\");\n }\n\n // ============================================================================\n // Concurrency Keys\n // ============================================================================\n\n concurrencyKey(groupName: string, groupId: string): string {\n return this.#buildKey(\"concurrency\", groupName, groupId);\n }\n\n // ============================================================================\n // In-Flight Keys\n // ============================================================================\n\n inflightKey(shardId: number): string {\n return this.#buildKey(\"inflight\", shardId.toString());\n }\n\n inflightDataKey(shardId: number): string {\n return this.#buildKey(\"inflight\", shardId.toString(), \"data\");\n }\n\n // ============================================================================\n // Worker Queue Keys\n // ============================================================================\n\n workerQueueKey(consumerId: string): string {\n return this.#buildKey(\"worker\", consumerId);\n }\n\n // ============================================================================\n // Tenant Dispatch Keys (Two-Level Index)\n // ============================================================================\n\n dispatchKey(shardId: number): string {\n return this.#buildKey(\"dispatch\", shardId.toString());\n }\n\n tenantQueueIndexKey(tenantId: string): string {\n return this.#buildKey(\"tenantq\", tenantId);\n }\n\n // ============================================================================\n // Dead Letter Queue Keys\n // ============================================================================\n\n deadLetterQueueKey(tenantId: string): string {\n return this.#buildKey(\"dlq\", tenantId);\n }\n\n deadLetterQueueDataKey(tenantId: string): string {\n return this.#buildKey(\"dlq\", tenantId, \"data\");\n }\n\n // ============================================================================\n // Extraction Methods\n // ============================================================================\n\n /**\n * Extract tenant ID from a queue ID.\n * Default implementation assumes queue IDs are formatted as: tenant:{tenantId}:...\n * Override this method for custom queue ID formats.\n */\n extractTenantId(queueId: string): string {\n const parts = queueId.split(this.separator);\n // Expect format: tenant:{tenantId}:...\n if (parts.length >= 2 && parts[0] === \"tenant\" && parts[1]) {\n return parts[1];\n }\n // Fallback: return the first segment\n return parts[0] ?? \"\";\n }\n\n /**\n * Extract a group ID from a queue ID.\n * Default implementation looks for pattern: {groupName}:{groupId}:...\n * Override this method for custom queue ID formats.\n */\n extractGroupId(groupName: string, queueId: string): string {\n const parts = queueId.split(this.separator);\n\n // Look for the group name in the queue ID parts\n for (let i = 0; i < parts.length - 1; i++) {\n if (parts[i] === groupName) {\n const nextPart = parts[i + 1];\n if (nextPart) {\n return nextPart;\n }\n }\n }\n\n // Fallback: return an empty string\n return \"\";\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n #buildKey(...parts: string[]): string {\n return [this.prefix, ...parts].join(this.separator);\n }\n}\n\n/**\n * Key producer with custom extraction logic via callbacks.\n * Useful when queue IDs don't follow a standard pattern.\n */\nexport class CallbackFairQueueKeyProducer extends DefaultFairQueueKeyProducer {\n private readonly tenantExtractor: (queueId: string) => string;\n private readonly groupExtractor: (groupName: string, queueId: string) => string;\n\n constructor(options: {\n prefix?: string;\n separator?: string;\n extractTenantId: (queueId: string) => string;\n extractGroupId: (groupName: string, queueId: string) => string;\n }) {\n super({ prefix: options.prefix, separator: options.separator });\n this.tenantExtractor = options.extractTenantId;\n this.groupExtractor = options.extractGroupId;\n }\n\n override extractTenantId(queueId: string): string {\n return this.tenantExtractor(queueId);\n }\n\n override extractGroupId(groupName: string, queueId: string): string {\n return this.groupExtractor(groupName, queueId);\n }\n}\n","import { calculateNextRetryDelay } from \"@trigger.dev/core/v3\";\nimport type { RetryOptions } from \"@trigger.dev/core/v3/schemas\";\n\n/**\n * RetryStrategy interface for pluggable retry logic.\n */\nexport interface RetryStrategy {\n /**\n * Calculate the next retry delay in milliseconds.\n * Return null to indicate the message should be sent to DLQ.\n *\n * @param attempt - Current attempt number (1-indexed)\n * @param error - Optional error from the failed attempt\n * @returns Delay in milliseconds, or null to send to DLQ\n */\n getNextDelay(attempt: number, error?: Error): number | null;\n\n /**\n * Maximum number of attempts before moving to DLQ.\n */\n maxAttempts: number;\n}\n\n/**\n * Exponential backoff retry strategy.\n *\n * Uses the same algorithm as @trigger.dev/core's calculateNextRetryDelay.\n */\nexport class ExponentialBackoffRetry implements RetryStrategy {\n readonly maxAttempts: number;\n private options: RetryOptions;\n\n constructor(options?: Partial<RetryOptions>) {\n this.options = {\n maxAttempts: options?.maxAttempts ?? 12,\n factor: options?.factor ?? 2,\n minTimeoutInMs: options?.minTimeoutInMs ?? 1_000,\n maxTimeoutInMs: options?.maxTimeoutInMs ?? 3_600_000, // 1 hour\n randomize: options?.randomize ?? true,\n };\n this.maxAttempts = this.options.maxAttempts ?? 12;\n }\n\n getNextDelay(attempt: number, _error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null; // Send to DLQ\n }\n\n const delay = calculateNextRetryDelay(this.options, attempt);\n return delay ?? null;\n }\n}\n\n/**\n * Fixed delay retry strategy.\n *\n * Always waits the same amount of time between retries.\n */\nexport class FixedDelayRetry implements RetryStrategy {\n readonly maxAttempts: number;\n private delayMs: number;\n\n constructor(options: { maxAttempts: number; delayMs: number }) {\n this.maxAttempts = options.maxAttempts;\n this.delayMs = options.delayMs;\n }\n\n getNextDelay(attempt: number, _error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null; // Send to DLQ\n }\n return this.delayMs;\n }\n}\n\n/**\n * Linear backoff retry strategy.\n *\n * Delay increases linearly with each attempt.\n */\nexport class LinearBackoffRetry implements RetryStrategy {\n readonly maxAttempts: number;\n private baseDelayMs: number;\n private maxDelayMs: number;\n\n constructor(options: { maxAttempts: number; baseDelayMs: number; maxDelayMs?: number }) {\n this.maxAttempts = options.maxAttempts;\n this.baseDelayMs = options.baseDelayMs;\n this.maxDelayMs = options.maxDelayMs ?? options.baseDelayMs * options.maxAttempts;\n }\n\n getNextDelay(attempt: number, _error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null; // Send to DLQ\n }\n const delay = this.baseDelayMs * attempt;\n return Math.min(delay, this.maxDelayMs);\n }\n}\n\n/**\n * No retry strategy.\n *\n * Messages go directly to DLQ on first failure.\n */\nexport class NoRetry implements RetryStrategy {\n readonly maxAttempts = 1;\n\n getNextDelay(_attempt: number, _error?: Error): number | null {\n return null; // Always send to DLQ\n }\n}\n\n/**\n * Immediate retry strategy.\n *\n * Retries immediately without any delay.\n */\nexport class ImmediateRetry implements RetryStrategy {\n readonly maxAttempts: number;\n\n constructor(maxAttempts: number) {\n this.maxAttempts = maxAttempts;\n }\n\n getNextDelay(attempt: number, _error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null; // Send to DLQ\n }\n return 0; // Immediate retry\n }\n}\n\n/**\n * Custom retry strategy that uses a user-provided function.\n */\nexport class CustomRetry implements RetryStrategy {\n readonly maxAttempts: number;\n private calculateDelay: (attempt: number, error?: Error) => number | null;\n\n constructor(options: {\n maxAttempts: number;\n calculateDelay: (attempt: number, error?: Error) => number | null;\n }) {\n this.maxAttempts = options.maxAttempts;\n this.calculateDelay = options.calculateDelay;\n }\n\n getNextDelay(attempt: number, error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null;\n }\n return this.calculateDelay(attempt, error);\n }\n}\n\n/**\n * Default retry options matching @trigger.dev/core defaults.\n */\nexport const defaultRetryOptions: RetryOptions = {\n maxAttempts: 12,\n factor: 2,\n minTimeoutInMs: 1_000,\n maxTimeoutInMs: 3_600_000,\n randomize: true,\n};\n\n/**\n * Create an exponential backoff retry strategy with default options.\n */\nexport function createDefaultRetryStrategy(): RetryStrategy {\n return new ExponentialBackoffRetry(defaultRetryOptions);\n}\n","import type { FairScheduler, SchedulerContext, TenantQueues } from \"./types.js\";\n\n/**\n * Re-export scheduler types for convenience.\n */\nexport type { FairScheduler, SchedulerContext, TenantQueues };\n\n/**\n * Base class for scheduler implementations.\n * Provides common utilities and default implementations.\n */\nexport abstract class BaseScheduler implements FairScheduler {\n /**\n * Select queues for processing from a master queue shard.\n * Must be implemented by subclasses.\n */\n abstract selectQueues(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<TenantQueues[]>;\n\n /**\n * Called after processing a message to update scheduler state.\n * Default implementation does nothing.\n */\n async recordProcessed(_tenantId: string, _queueId: string): Promise<void> {\n // Default: no state tracking\n }\n\n /**\n * Called after processing multiple messages to update scheduler state.\n * Batch variant for efficiency - reduces Redis calls when processing multiple messages.\n * Default implementation does nothing.\n */\n async recordProcessedBatch(_tenantId: string, _queueId: string, _count: number): Promise<void> {\n // Default: no state tracking\n }\n\n /**\n * Initialize the scheduler.\n * Default implementation does nothing.\n */\n async initialize(): Promise<void> {\n // Default: no initialization needed\n }\n\n /**\n * Cleanup scheduler resources.\n * Default implementation does nothing.\n */\n async close(): Promise<void> {\n // Default: no cleanup needed\n }\n\n /**\n * Helper to group queues by tenant.\n */\n protected groupQueuesByTenant(\n queues: Array<{ queueId: string; tenantId: string }>\n ): Map<string, string[]> {\n const grouped = new Map<string, string[]>();\n\n for (const { queueId, tenantId } of queues) {\n const existing = grouped.get(tenantId) ?? [];\n existing.push(queueId);\n grouped.set(tenantId, existing);\n }\n\n return grouped;\n }\n\n /**\n * Helper to convert grouped queues to TenantQueues array.\n */\n protected toTenantQueuesArray(grouped: Map<string, string[]>): TenantQueues[] {\n return Array.from(grouped.entries()).map(([tenantId, queues]) => ({\n tenantId,\n queues,\n }));\n }\n\n /**\n * Helper to filter out tenants at capacity.\n */\n protected async filterAtCapacity(\n tenants: TenantQueues[],\n context: SchedulerContext,\n groupName: string = \"tenant\"\n ): Promise<TenantQueues[]> {\n const filtered: TenantQueues[] = [];\n\n for (const tenant of tenants) {\n const isAtCapacity = await context.isAtCapacity(groupName, tenant.tenantId);\n if (!isAtCapacity) {\n filtered.push(tenant);\n }\n }\n\n return filtered;\n }\n}\n\n/**\n * Simple noop scheduler that returns empty results.\n * Useful for testing or disabling scheduling.\n */\nexport class NoopScheduler extends BaseScheduler {\n async selectQueues(\n _masterQueueShard: string,\n _consumerId: string,\n _context: SchedulerContext\n ): Promise<TenantQueues[]> {\n return [];\n }\n}\n","import { createRedisClient, type Redis } from \"@internal/redis\";\nimport { BaseScheduler } from \"../scheduler.js\";\nimport type {\n DRRSchedulerConfig,\n DispatchSchedulerContext,\n FairQueueKeyProducer,\n SchedulerContext,\n TenantQueues,\n QueueWithScore,\n} from \"../types.js\";\n\n/**\n * Deficit Round Robin (DRR) Scheduler.\n *\n * DRR ensures fair processing across tenants by:\n * - Allocating a \"quantum\" of credits to each tenant per round\n * - Accumulating unused credits as \"deficit\"\n * - Processing from tenants with available deficit\n * - Capping deficit to prevent starvation\n *\n * Key improvements over basic implementations:\n * - Atomic deficit operations using Lua scripts\n * - Efficient iteration through tenants\n * - Automatic deficit cleanup for inactive tenants\n */\nexport class DRRScheduler extends BaseScheduler {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private quantum: number;\n private maxDeficit: number;\n private masterQueueLimit: number;\n private logger: NonNullable<DRRSchedulerConfig[\"logger\"]>;\n\n constructor(private config: DRRSchedulerConfig) {\n super();\n this.redis = createRedisClient(config.redis);\n this.keys = config.keys;\n this.quantum = config.quantum;\n this.maxDeficit = config.maxDeficit;\n this.masterQueueLimit = config.masterQueueLimit ?? 1000;\n this.logger = config.logger ?? {\n debug: () => {},\n error: () => {},\n };\n\n this.#registerCommands();\n }\n\n // ============================================================================\n // FairScheduler Implementation\n // ============================================================================\n\n /**\n * Select queues for processing using DRR algorithm.\n *\n * Algorithm:\n * 1. Get all queues from the master shard\n * 2. Group by tenant\n * 3. Filter out tenants at concurrency capacity\n * 4. Add quantum to each tenant's deficit (atomically)\n * 5. Select queues from tenants with deficit >= 1\n * 6. Order tenants by deficit (highest first for fairness)\n */\n async selectQueues(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<TenantQueues[]> {\n // Get all queues from the master shard\n const queues = await this.#getQueuesFromShard(masterQueueShard);\n\n if (queues.length === 0) {\n return [];\n }\n\n // Group queues by tenant\n const queuesByTenant = this.groupQueuesByTenant(\n queues.map((q) => ({ queueId: q.queueId, tenantId: q.tenantId }))\n );\n\n // Get unique tenant IDs\n const tenantIds = Array.from(queuesByTenant.keys());\n\n // Add quantum to all active tenants atomically\n const deficits = await this.#addQuantumToTenants(tenantIds);\n\n // Build tenant data with deficits\n const tenantData: Array<{\n tenantId: string;\n deficit: number;\n queues: string[];\n isAtCapacity: boolean;\n }> = await Promise.all(\n tenantIds.map(async (tenantId, index) => {\n const isAtCapacity = await context.isAtCapacity(\"tenant\", tenantId);\n return {\n tenantId,\n deficit: deficits[index] ?? 0,\n queues: queuesByTenant.get(tenantId) ?? [],\n isAtCapacity,\n };\n })\n );\n\n // Filter out tenants at capacity or with no deficit\n const eligibleTenants = tenantData.filter((t) => !t.isAtCapacity && t.deficit >= 1);\n\n // Log tenants blocked by capacity\n const blockedTenants = tenantData.filter((t) => t.isAtCapacity);\n if (blockedTenants.length > 0) {\n this.logger.debug(\"DRR: tenants blocked by concurrency\", {\n blockedCount: blockedTenants.length,\n blockedTenants: blockedTenants.map((t) => t.tenantId),\n });\n }\n\n // Sort by deficit (highest first for fairness)\n eligibleTenants.sort((a, b) => b.deficit - a.deficit);\n\n this.logger.debug(\"DRR: queue selection complete\", {\n totalQueues: queues.length,\n totalTenants: tenantIds.length,\n eligibleTenants: eligibleTenants.length,\n topTenantDeficit: eligibleTenants[0]?.deficit,\n });\n\n // Convert to TenantQueues format\n return eligibleTenants.map((t) => ({\n tenantId: t.tenantId,\n queues: t.queues,\n }));\n }\n\n /**\n * Select queues using the two-level tenant dispatch index.\n *\n * Algorithm:\n * 1. ZRANGEBYSCORE on dispatch index (gets only tenants with queues - much smaller)\n * 2. Add quantum to each tenant's deficit (atomically)\n * 3. Check capacity as safety net (dispatch should only have tenants with capacity)\n * 4. Select tenants with deficit >= 1, sorted by deficit (highest first)\n * 5. For each tenant, fetch their queues from Level 2 index\n */\n async selectQueuesFromDispatch(\n dispatchShardKey: string,\n consumerId: string,\n context: DispatchSchedulerContext\n ): Promise<TenantQueues[]> {\n // Level 1: Get tenants from dispatch index\n const tenants = await this.#getTenantsFromDispatch(dispatchShardKey);\n\n if (tenants.length === 0) {\n return [];\n }\n\n const tenantIds = tenants.map((t) => t.tenantId);\n\n // Add quantum to all active tenants atomically (1 Lua call)\n const deficits = await this.#addQuantumToTenants(tenantIds);\n\n // Build candidates sorted by deficit (highest first)\n const candidates = tenantIds\n .map((tenantId, index) => ({ tenantId, deficit: deficits[index] ?? 0 }))\n .filter((t) => t.deficit >= 1);\n\n candidates.sort((a, b) => b.deficit - a.deficit);\n\n // Pick the first tenant with available capacity and fetch their queues.\n // This keeps the scheduler cheap: O(1) in the common case where the\n // highest-deficit tenant has capacity. The consumer loop iterates fast\n // (1ms yield between rounds) so we cycle through tenants quickly.\n for (const { tenantId, deficit } of candidates) {\n const isAtCapacity = await context.isAtCapacity(\"tenant\", tenantId);\n if (isAtCapacity) continue;\n\n // Limit queues fetched to what the tenant can actually process this round.\n // deficit = max messages this tenant should process, so no point fetching\n // more queues than that (each queue yields at least 1 message).\n const queueLimit = Math.ceil(deficit);\n const queues = await context.getQueuesForTenant(tenantId, queueLimit);\n if (queues.length > 0) {\n this.logger.debug(\"DRR dispatch: selected tenant\", {\n dispatchTenants: tenants.length,\n candidates: candidates.length,\n selectedTenant: tenantId,\n deficit,\n queueLimit,\n queuesReturned: queues.length,\n });\n\n return [{ tenantId, queues: queues.map((q) => q.queueId) }];\n }\n }\n\n return [];\n }\n\n /**\n * Record that a message was processed from a tenant.\n * Decrements the tenant's deficit.\n */\n override async recordProcessed(tenantId: string, _queueId: string): Promise<void> {\n await this.#decrementDeficit(tenantId);\n }\n\n /**\n * Record that multiple messages were processed from a tenant.\n * Decrements the tenant's deficit by count atomically.\n */\n override async recordProcessedBatch(\n tenantId: string,\n _queueId: string,\n count: number\n ): Promise<void> {\n await this.#decrementDeficitBatch(tenantId, count);\n }\n\n override async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Public Methods for Deficit Management\n // ============================================================================\n\n /**\n * Get the current deficit for a tenant.\n */\n async getDeficit(tenantId: string): Promise<number> {\n const key = this.#deficitKey();\n const value = await this.redis.hget(key, tenantId);\n return value ? parseFloat(value) : 0;\n }\n\n /**\n * Reset deficit for a tenant.\n * Used when a tenant has no more active queues.\n */\n async resetDeficit(tenantId: string): Promise<void> {\n const key = this.#deficitKey();\n await this.redis.hdel(key, tenantId);\n }\n\n /**\n * Get all tenant deficits.\n */\n async getAllDeficits(): Promise<Map<string, number>> {\n const key = this.#deficitKey();\n const data = await this.redis.hgetall(key);\n const result = new Map<string, number>();\n for (const [tenantId, value] of Object.entries(data)) {\n result.set(tenantId, parseFloat(value));\n }\n return result;\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n #deficitKey(): string {\n // Use a fixed key for DRR deficit tracking\n return `${this.keys.masterQueueKey(0).split(\":\")[0]}:drr:deficit`;\n }\n\n async #getTenantsFromDispatch(\n dispatchKey: string\n ): Promise<Array<{ tenantId: string; score: number }>> {\n const now = Date.now();\n const results = await this.redis.zrangebyscore(\n dispatchKey,\n \"-inf\",\n now,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n this.masterQueueLimit\n );\n\n const tenants: Array<{ tenantId: string; score: number }> = [];\n for (let i = 0; i < results.length; i += 2) {\n const tenantId = results[i];\n const scoreStr = results[i + 1];\n if (tenantId && scoreStr) {\n tenants.push({\n tenantId,\n score: parseFloat(scoreStr),\n });\n }\n }\n\n return tenants;\n }\n\n async #getQueuesFromShard(shardKey: string): Promise<QueueWithScore[]> {\n const now = Date.now();\n const results = await this.redis.zrangebyscore(\n shardKey,\n \"-inf\",\n now,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n this.masterQueueLimit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId: this.keys.extractTenantId(queueId),\n });\n }\n }\n\n return queues;\n }\n\n /**\n * Add quantum to multiple tenants atomically.\n * Returns the new deficit values.\n */\n async #addQuantumToTenants(tenantIds: string[]): Promise<number[]> {\n if (tenantIds.length === 0) {\n return [];\n }\n\n const key = this.#deficitKey();\n\n // Use Lua script for atomic quantum addition with capping\n const results = await this.redis.drrAddQuantum(\n key,\n this.quantum.toString(),\n this.maxDeficit.toString(),\n ...tenantIds\n );\n\n return results.map((r) => parseFloat(r));\n }\n\n /**\n * Decrement deficit for a tenant atomically.\n */\n async #decrementDeficit(tenantId: string): Promise<number> {\n const key = this.#deficitKey();\n\n // Use Lua script to decrement and ensure non-negative\n const result = await this.redis.drrDecrementDeficit(key, tenantId);\n return parseFloat(result);\n }\n\n /**\n * Decrement deficit for a tenant by a count atomically.\n */\n async #decrementDeficitBatch(tenantId: string, count: number): Promise<number> {\n const key = this.#deficitKey();\n\n // Use Lua script to decrement by count and ensure non-negative\n const result = await this.redis.drrDecrementDeficitBatch(key, tenantId, count.toString());\n return parseFloat(result);\n }\n\n #registerCommands(): void {\n // Atomic quantum addition with capping for multiple tenants\n this.redis.defineCommand(\"drrAddQuantum\", {\n numberOfKeys: 1,\n lua: `\nlocal deficitKey = KEYS[1]\nlocal quantum = tonumber(ARGV[1])\nlocal maxDeficit = tonumber(ARGV[2])\nlocal results = {}\n\nfor i = 3, #ARGV do\n local tenantId = ARGV[i]\n \n -- Add quantum to deficit\n local newDeficit = redis.call('HINCRBYFLOAT', deficitKey, tenantId, quantum)\n newDeficit = tonumber(newDeficit)\n \n -- Cap at maxDeficit\n if newDeficit > maxDeficit then\n redis.call('HSET', deficitKey, tenantId, maxDeficit)\n newDeficit = maxDeficit\n end\n \n table.insert(results, tostring(newDeficit))\nend\n\nreturn results\n `,\n });\n\n // Atomic deficit decrement with floor at 0\n this.redis.defineCommand(\"drrDecrementDeficit\", {\n numberOfKeys: 1,\n lua: `\nlocal deficitKey = KEYS[1]\nlocal tenantId = ARGV[1]\n\nlocal newDeficit = redis.call('HINCRBYFLOAT', deficitKey, tenantId, -1)\nnewDeficit = tonumber(newDeficit)\n\n-- Floor at 0\nif newDeficit < 0 then\n redis.call('HSET', deficitKey, tenantId, 0)\n newDeficit = 0\nend\n\nreturn tostring(newDeficit)\n `,\n });\n\n // Atomic deficit decrement by count with floor at 0\n this.redis.defineCommand(\"drrDecrementDeficitBatch\", {\n numberOfKeys: 1,\n lua: `\nlocal deficitKey = KEYS[1]\nlocal tenantId = ARGV[1]\nlocal count = tonumber(ARGV[2])\n\nlocal newDeficit = redis.call('HINCRBYFLOAT', deficitKey, tenantId, -count)\nnewDeficit = tonumber(newDeficit)\n\n-- Floor at 0\nif newDeficit < 0 then\n redis.call('HSET', deficitKey, tenantId, 0)\n newDeficit = 0\nend\n\nreturn tostring(newDeficit)\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n drrAddQuantum(\n deficitKey: string,\n quantum: string,\n maxDeficit: string,\n ...tenantIds: string[]\n ): Promise<string[]>;\n\n drrDecrementDeficit(deficitKey: string, tenantId: string): Promise<string>;\n\n drrDecrementDeficitBatch(deficitKey: string, tenantId: string, count: string): Promise<string>;\n }\n}\n","import { createRedisClient, type Redis } from \"@internal/redis\";\nimport seedrandom from \"seedrandom\";\nimport { BaseScheduler } from \"../scheduler.js\";\nimport type {\n FairQueueKeyProducer,\n SchedulerContext,\n TenantQueues,\n QueueWithScore,\n WeightedSchedulerBiases,\n WeightedSchedulerConfig,\n} from \"../types.js\";\n\ninterface TenantConcurrency {\n current: number;\n limit: number;\n}\n\ninterface TenantSnapshot {\n tenantId: string;\n concurrency: TenantConcurrency;\n queues: Array<{ queueId: string; age: number }>;\n}\n\ninterface QueueSnapshot {\n id: string;\n tenants: Map<string, TenantSnapshot>;\n queues: Array<{ queueId: string; tenantId: string; age: number }>;\n}\n\nconst defaultBiases: WeightedSchedulerBiases = {\n concurrencyLimitBias: 0,\n availableCapacityBias: 0,\n queueAgeRandomization: 0,\n};\n\n/**\n * Weighted Shuffle Scheduler.\n *\n * Uses weighted random selection to balance between:\n * - Concurrency limit (higher limits get more weight)\n * - Available capacity (tenants with more capacity get more weight)\n * - Queue age (older queues get priority, with configurable randomization)\n *\n * Features:\n * - Snapshot caching to reduce Redis calls\n * - Configurable biases for fine-tuning\n * - Maximum tenant count to limit iteration\n */\nexport class WeightedScheduler extends BaseScheduler {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private rng: seedrandom.PRNG;\n private biases: WeightedSchedulerBiases;\n private defaultTenantLimit: number;\n private masterQueueLimit: number;\n private reuseSnapshotCount: number;\n private maximumTenantCount: number;\n\n // Snapshot cache\n private snapshotCache: Map<string, { snapshot: QueueSnapshot; reuseCount: number }> = new Map();\n\n constructor(private config: WeightedSchedulerConfig) {\n super();\n this.redis = createRedisClient(config.redis);\n this.keys = config.keys;\n this.rng = seedrandom(config.seed);\n this.biases = config.biases ?? defaultBiases;\n this.defaultTenantLimit = config.defaultTenantConcurrencyLimit ?? 100;\n this.masterQueueLimit = config.masterQueueLimit ?? 100;\n this.reuseSnapshotCount = config.reuseSnapshotCount ?? 0;\n this.maximumTenantCount = config.maximumTenantCount ?? 0;\n }\n\n // ============================================================================\n // FairScheduler Implementation\n // ============================================================================\n\n async selectQueues(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<TenantQueues[]> {\n const snapshot = await this.#getOrCreateSnapshot(masterQueueShard, consumerId, context);\n\n if (snapshot.queues.length === 0) {\n return [];\n }\n\n // Shuffle tenants based on weights\n const shuffledTenants = this.#shuffleTenantsByWeight(snapshot);\n\n // Order queues within each tenant\n return shuffledTenants.map((tenantId) => ({\n tenantId,\n queues: this.#orderQueuesForTenant(snapshot, tenantId),\n }));\n }\n\n override async close(): Promise<void> {\n this.snapshotCache.clear();\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n async #getOrCreateSnapshot(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<QueueSnapshot> {\n const cacheKey = `${masterQueueShard}:${consumerId}`;\n\n // Check cache\n if (this.reuseSnapshotCount > 0) {\n const cached = this.snapshotCache.get(cacheKey);\n if (cached && cached.reuseCount < this.reuseSnapshotCount) {\n this.snapshotCache.set(cacheKey, {\n snapshot: cached.snapshot,\n reuseCount: cached.reuseCount + 1,\n });\n return cached.snapshot;\n }\n }\n\n // Create new snapshot\n const snapshot = await this.#createSnapshot(masterQueueShard, context);\n\n // Cache if enabled\n if (this.reuseSnapshotCount > 0) {\n this.snapshotCache.set(cacheKey, { snapshot, reuseCount: 0 });\n }\n\n return snapshot;\n }\n\n async #createSnapshot(\n masterQueueShard: string,\n context: SchedulerContext\n ): Promise<QueueSnapshot> {\n const now = Date.now();\n\n // Get queues from master shard\n let rawQueues = await this.#getQueuesFromShard(masterQueueShard, now);\n\n if (rawQueues.length === 0) {\n return { id: crypto.randomUUID(), tenants: new Map(), queues: [] };\n }\n\n // Apply maximum tenant count if configured\n if (this.maximumTenantCount > 0) {\n rawQueues = this.#selectTopTenantQueues(rawQueues);\n }\n\n // Build tenant data\n const tenantIds = new Set<string>();\n const queuesByTenant = new Map<string, Array<{ queueId: string; age: number }>>();\n\n for (const queue of rawQueues) {\n tenantIds.add(queue.tenantId);\n const tenantQueues = queuesByTenant.get(queue.tenantId) ?? [];\n tenantQueues.push({\n queueId: queue.queueId,\n age: now - queue.score,\n });\n queuesByTenant.set(queue.tenantId, tenantQueues);\n }\n\n // Get concurrency for each tenant\n const tenants = new Map<string, TenantSnapshot>();\n for (const tenantId of tenantIds) {\n const [current, limit] = await Promise.all([\n context.getCurrentConcurrency(\"tenant\", tenantId),\n context.getConcurrencyLimit(\"tenant\", tenantId),\n ]);\n\n // Skip tenants at capacity\n if (current >= limit) {\n continue;\n }\n\n tenants.set(tenantId, {\n tenantId,\n concurrency: { current, limit },\n queues: queuesByTenant.get(tenantId) ?? [],\n });\n }\n\n // Build final queue list (only from non-capacity tenants)\n const queues = rawQueues\n .filter((q) => tenants.has(q.tenantId))\n .map((q) => ({\n queueId: q.queueId,\n tenantId: q.tenantId,\n age: now - q.score,\n }));\n\n return {\n id: crypto.randomUUID(),\n tenants,\n queues,\n };\n }\n\n async #getQueuesFromShard(shardKey: string, maxScore: number): Promise<QueueWithScore[]> {\n const results = await this.redis.zrangebyscore(\n shardKey,\n \"-inf\",\n maxScore,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n this.masterQueueLimit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId: this.keys.extractTenantId(queueId),\n });\n }\n }\n\n return queues;\n }\n\n #selectTopTenantQueues(queues: QueueWithScore[]): QueueWithScore[] {\n // Group by tenant and calculate average age\n const queuesByTenant = new Map<string, QueueWithScore[]>();\n for (const queue of queues) {\n const tenantQueues = queuesByTenant.get(queue.tenantId) ?? [];\n tenantQueues.push(queue);\n queuesByTenant.set(queue.tenantId, tenantQueues);\n }\n\n // Calculate average age per tenant\n const tenantAges = Array.from(queuesByTenant.entries()).map(([tenantId, tQueues]) => {\n const avgAge = tQueues.reduce((sum, q) => sum + q.score, 0) / tQueues.length;\n return { tenantId, avgAge };\n });\n\n // Weighted shuffle to select top N tenants\n const maxAge = Math.max(...tenantAges.map((t) => t.avgAge));\n // Guard against division by zero: if maxAge is 0, assign equal weights\n const weightedTenants =\n maxAge === 0\n ? tenantAges.map((t) => ({\n tenantId: t.tenantId,\n weight: 1 / tenantAges.length,\n }))\n : tenantAges.map((t) => ({\n tenantId: t.tenantId,\n weight: t.avgAge / maxAge,\n }));\n\n const selectedTenants = new Set<string>();\n let remaining = [...weightedTenants];\n let totalWeight = remaining.reduce((sum, t) => sum + t.weight, 0);\n\n while (selectedTenants.size < this.maximumTenantCount && remaining.length > 0) {\n let random = this.rng() * totalWeight;\n let index = 0;\n\n while (random > 0 && index < remaining.length) {\n const item = remaining[index];\n if (item) {\n random -= item.weight;\n }\n index++;\n }\n index = Math.max(0, index - 1);\n\n const selected = remaining[index];\n if (selected) {\n selectedTenants.add(selected.tenantId);\n totalWeight -= selected.weight;\n remaining.splice(index, 1);\n }\n }\n\n // Return queues only from selected tenants\n return queues.filter((q) => selectedTenants.has(q.tenantId));\n }\n\n #shuffleTenantsByWeight(snapshot: QueueSnapshot): string[] {\n const tenantIds = Array.from(snapshot.tenants.keys());\n\n if (tenantIds.length === 0) {\n return [];\n }\n\n const { concurrencyLimitBias, availableCapacityBias } = this.biases;\n\n // If no biases, do simple shuffle\n if (concurrencyLimitBias === 0 && availableCapacityBias === 0) {\n return this.#shuffle(tenantIds);\n }\n\n // Calculate weights\n const maxLimit = Math.max(\n ...tenantIds.map((id) => snapshot.tenants.get(id)!.concurrency.limit)\n );\n\n const weightedTenants = tenantIds.map((tenantId) => {\n const tenant = snapshot.tenants.get(tenantId)!;\n let weight = 1;\n\n // Concurrency limit bias\n if (concurrencyLimitBias > 0) {\n // Guard against division by zero: if maxLimit is 0, treat normalizedLimit as 0\n const normalizedLimit = maxLimit > 0 ? tenant.concurrency.limit / maxLimit : 0;\n weight *= 1 + Math.pow(normalizedLimit * concurrencyLimitBias, 2);\n }\n\n // Available capacity bias\n if (availableCapacityBias > 0) {\n // Guard against division by zero: if limit is 0, treat as fully used (no bonus)\n const usedPercentage =\n tenant.concurrency.limit > 0 ? tenant.concurrency.current / tenant.concurrency.limit : 1;\n const availableBonus = 1 - usedPercentage;\n weight *= 1 + Math.pow(availableBonus * availableCapacityBias, 2);\n }\n\n return { tenantId, weight };\n });\n\n return this.#weightedShuffle(weightedTenants);\n }\n\n #orderQueuesForTenant(snapshot: QueueSnapshot, tenantId: string): string[] {\n const tenant = snapshot.tenants.get(tenantId);\n if (!tenant || tenant.queues.length === 0) {\n return [];\n }\n\n const queues = [...tenant.queues];\n const { queueAgeRandomization } = this.biases;\n\n // Strict age-based ordering\n if (queueAgeRandomization === 0) {\n return queues.sort((a, b) => b.age - a.age).map((q) => q.queueId);\n }\n\n // Weighted random based on age\n const maxAge = Math.max(...queues.map((q) => q.age));\n // Guard against division by zero: if maxAge is 0, all queues have equal weight\n const ageDenom = maxAge === 0 ? 1 : maxAge;\n const weightedQueues = queues.map((q) => ({\n queue: q,\n weight: 1 + (q.age / ageDenom) * queueAgeRandomization,\n }));\n\n const result: string[] = [];\n let remaining = [...weightedQueues];\n let totalWeight = remaining.reduce((sum, q) => sum + q.weight, 0);\n\n while (remaining.length > 0) {\n let random = this.rng() * totalWeight;\n let index = 0;\n\n while (random > 0 && index < remaining.length) {\n const item = remaining[index];\n if (item) {\n random -= item.weight;\n }\n index++;\n }\n index = Math.max(0, index - 1);\n\n const selected = remaining[index];\n if (selected) {\n result.push(selected.queue.queueId);\n totalWeight -= selected.weight;\n remaining.splice(index, 1);\n }\n }\n\n return result;\n }\n\n #shuffle<T>(array: T[]): T[] {\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(this.rng() * (i + 1));\n const temp = result[i];\n const swapValue = result[j];\n if (temp !== undefined && swapValue !== undefined) {\n result[i] = swapValue;\n result[j] = temp;\n }\n }\n return result;\n }\n\n #weightedShuffle(items: Array<{ tenantId: string; weight: number }>): string[] {\n const result: string[] = [];\n let remaining = [...items];\n let totalWeight = remaining.reduce((sum, item) => sum + item.weight, 0);\n\n while (remaining.length > 0) {\n let random = this.rng() * totalWeight;\n let index = 0;\n\n while (random > 0 && index < remaining.length) {\n const item = remaining[index];\n if (item) {\n random -= item.weight;\n }\n index++;\n }\n index = Math.max(0, index - 1);\n\n const selected = remaining[index];\n if (selected) {\n result.push(selected.tenantId);\n totalWeight -= selected.weight;\n remaining.splice(index, 1);\n }\n }\n\n return result;\n }\n}\n","import { createRedisClient, type Redis, type RedisOptions } from \"@internal/redis\";\nimport { BaseScheduler } from \"../scheduler.js\";\nimport type {\n FairQueueKeyProducer,\n SchedulerContext,\n TenantQueues,\n QueueWithScore,\n} from \"../types.js\";\n\ninterface RoundRobinSchedulerConfig {\n redis: RedisOptions;\n keys: FairQueueKeyProducer;\n /** Maximum queues to fetch from master queue per iteration */\n masterQueueLimit?: number;\n}\n\n/**\n * Round Robin Scheduler.\n *\n * Simple scheduler that processes tenants in strict rotation order.\n * Maintains a \"last served\" pointer in Redis to track position.\n *\n * Features:\n * - Predictable ordering (good for debugging)\n * - Fair rotation through all tenants\n * - No weighting or bias\n */\nexport class RoundRobinScheduler extends BaseScheduler {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private masterQueueLimit: number;\n\n constructor(private config: RoundRobinSchedulerConfig) {\n super();\n this.redis = createRedisClient(config.redis);\n this.keys = config.keys;\n this.masterQueueLimit = config.masterQueueLimit ?? 1000;\n }\n\n // ============================================================================\n // FairScheduler Implementation\n // ============================================================================\n\n async selectQueues(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<TenantQueues[]> {\n const now = Date.now();\n\n // Get all queues from master shard\n const queues = await this.#getQueuesFromShard(masterQueueShard, now);\n\n if (queues.length === 0) {\n return [];\n }\n\n // Group queues by tenant\n const queuesByTenant = new Map<string, string[]>();\n const tenantOrder: string[] = [];\n\n for (const queue of queues) {\n if (!queuesByTenant.has(queue.tenantId)) {\n queuesByTenant.set(queue.tenantId, []);\n tenantOrder.push(queue.tenantId);\n }\n queuesByTenant.get(queue.tenantId)!.push(queue.queueId);\n }\n\n // Get last served index\n const lastServedIndex = await this.#getLastServedIndex(masterQueueShard);\n\n // Rotate tenant order based on last served\n const rotatedTenants = this.#rotateArray(tenantOrder, lastServedIndex);\n\n // Filter out tenants at capacity\n const eligibleTenants: TenantQueues[] = [];\n\n for (const tenantId of rotatedTenants) {\n const isAtCapacity = await context.isAtCapacity(\"tenant\", tenantId);\n if (!isAtCapacity) {\n const tenantQueues = queuesByTenant.get(tenantId) ?? [];\n // Sort queues by age (oldest first based on original scores)\n eligibleTenants.push({\n tenantId,\n queues: tenantQueues,\n });\n }\n }\n\n // Update last served index to the first eligible tenant\n const firstEligible = eligibleTenants[0];\n if (firstEligible) {\n const firstTenantIndex = tenantOrder.indexOf(firstEligible.tenantId);\n await this.#setLastServedIndex(masterQueueShard, firstTenantIndex + 1);\n }\n\n return eligibleTenants;\n }\n\n override async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n async #getQueuesFromShard(shardKey: string, maxScore: number): Promise<QueueWithScore[]> {\n const results = await this.redis.zrangebyscore(\n shardKey,\n \"-inf\",\n maxScore,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n this.masterQueueLimit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId: this.keys.extractTenantId(queueId),\n });\n }\n }\n\n return queues;\n }\n\n #lastServedKey(shardKey: string): string {\n return `${shardKey}:rr:lastServed`;\n }\n\n async #getLastServedIndex(shardKey: string): Promise<number> {\n const key = this.#lastServedKey(shardKey);\n const value = await this.redis.get(key);\n return value ? parseInt(value, 10) : 0;\n }\n\n async #setLastServedIndex(shardKey: string, index: number): Promise<void> {\n const key = this.#lastServedKey(shardKey);\n await this.redis.set(key, index.toString());\n }\n\n #rotateArray<T>(array: T[], startIndex: number): T[] {\n if (array.length === 0) return [];\n const normalizedIndex = startIndex % array.length;\n return [...array.slice(normalizedIndex), ...array.slice(0, normalizedIndex)];\n }\n}\n","import { createRedisClient, type Redis } from \"@internal/redis\";\nimport { SpanKind, type Span } from \"@internal/tracing\";\nimport { Logger } from \"@trigger.dev/core/logger\";\nimport type { AnyZodSchema, inferZodSchemaOutput } from \"@trigger.dev/core/v3\";\nimport { nanoid } from \"nanoid\";\nimport { setInterval, setTimeout as delay } from \"node:timers/promises\";\nimport { type z } from \"zod/v4\";\nimport { isAbortError } from \"../utils.js\";\nimport { ConcurrencyManager } from \"./concurrency.js\";\nimport { MasterQueue } from \"./masterQueue.js\";\nimport { type RetryStrategy } from \"./retry.js\";\nimport {\n BatchedSpanManager,\n FairQueueAttributes,\n FairQueueTelemetry,\n MessagingAttributes,\n} from \"./telemetry.js\";\nimport { TenantDispatch } from \"./tenantDispatch.js\";\nimport type {\n DeadLetterMessage,\n DispatchSchedulerContext,\n EnqueueBatchOptions,\n EnqueueOptions,\n FairQueueKeyProducer,\n FairQueueOptions,\n FairScheduler,\n QueueCooloffState,\n QueueDescriptor,\n ReclaimedMessageInfo,\n SchedulerContext,\n StoredMessage,\n TenantQueues,\n} from \"./types.js\";\nimport { VisibilityManager } from \"./visibility.js\";\nimport { WorkerQueueManager } from \"./workerQueue.js\";\n\n// Re-export all types and components\nexport * from \"./concurrency.js\";\nexport * from \"./keyProducer.js\";\nexport * from \"./masterQueue.js\";\nexport * from \"./retry.js\";\nexport * from \"./scheduler.js\";\nexport * from \"./schedulers/index.js\";\nexport * from \"./telemetry.js\";\nexport * from \"./tenantDispatch.js\";\nexport * from \"./types.js\";\nexport * from \"./visibility.js\";\nexport * from \"./workerQueue.js\";\n\n/**\n * FairQueue is the main orchestrator for fair queue message routing.\n *\n * FairQueue handles:\n * - Master queue with sharding (using jump consistent hash)\n * - Fair scheduling via pluggable schedulers\n * - Multi-level concurrency limiting\n * - Visibility timeouts with heartbeats\n * - Routing messages to worker queues\n * - Retry strategies with dead letter queue\n * - OpenTelemetry tracing and metrics\n *\n * External consumers are responsible for:\n * - Running their own worker queue consumer loops\n * - Calling complete/release/fail APIs after processing\n *\n * @typeParam TPayloadSchema - Zod schema for message payload validation\n */\nexport class FairQueue<TPayloadSchema extends AnyZodSchema = z.ZodUnknown> {\n private redis: Redis;\n private keys: FairQueueKeyProducer;\n private scheduler: FairScheduler;\n private masterQueue: MasterQueue;\n private concurrencyManager?: ConcurrencyManager;\n private visibilityManager: VisibilityManager;\n private workerQueueManager: WorkerQueueManager;\n private telemetry: FairQueueTelemetry;\n private logger: Logger;\n\n // Configuration\n private payloadSchema?: TPayloadSchema;\n private validateOnEnqueue: boolean;\n private retryStrategy?: RetryStrategy;\n private deadLetterQueueEnabled: boolean;\n private shardCount: number;\n private consumerCount: number;\n private consumerIntervalMs: number;\n private visibilityTimeoutMs: number;\n private heartbeatIntervalMs: number;\n private reclaimIntervalMs: number;\n private reconcileIntervalMs: number;\n private workerQueueResolver: (\n message: StoredMessage<inferZodSchemaOutput<TPayloadSchema>>\n ) => string;\n private batchClaimSize: number;\n\n // Cooloff state\n private cooloffEnabled: boolean;\n private cooloffThreshold: number;\n private cooloffPeriodMs: number;\n private maxCooloffStatesSize: number;\n private queueCooloffStates = new Map<string, QueueCooloffState>();\n\n // Worker queue backpressure\n private workerQueueMaxDepth: number;\n private workerQueueDepthCheckId?: string;\n\n // Consumer tracing\n private consumerTraceMaxIterations: number;\n private consumerTraceTimeoutSeconds: number;\n private batchedSpanManager: BatchedSpanManager;\n\n // Runtime state\n private isRunning = false;\n private abortController: AbortController;\n private masterQueueConsumerLoops: Promise<void>[] = [];\n private reclaimLoop?: Promise<void>;\n private reconcileLoop?: Promise<void>;\n\n // Queue descriptor cache for message processing\n private queueDescriptorCache = new Map<string, QueueDescriptor>();\n\n // Two-level tenant dispatch\n private tenantDispatch: TenantDispatch;\n\n constructor(private options: FairQueueOptions<TPayloadSchema>) {\n this.redis = createRedisClient(options.redis);\n this.keys = options.keys;\n this.scheduler = options.scheduler;\n this.logger = options.logger ?? new Logger(\"FairQueue\", \"info\");\n this.abortController = new AbortController();\n\n // Payload validation\n this.payloadSchema = options.payloadSchema;\n this.validateOnEnqueue = options.validateOnEnqueue ?? false;\n\n // Retry and DLQ\n this.retryStrategy = options.retry?.strategy;\n this.deadLetterQueueEnabled = options.retry?.deadLetterQueue ?? true;\n\n // Configuration\n this.shardCount = options.shardCount ?? 1;\n this.consumerCount = options.consumerCount ?? 1;\n this.consumerIntervalMs = options.consumerIntervalMs ?? 100;\n this.visibilityTimeoutMs = options.visibilityTimeoutMs ?? 30_000;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? this.visibilityTimeoutMs / 3;\n this.reclaimIntervalMs = options.reclaimIntervalMs ?? 5_000;\n this.reconcileIntervalMs = options.reconcileIntervalMs ?? 60_000;\n\n // Worker queue resolver (required)\n this.workerQueueResolver = options.workerQueue.resolveWorkerQueue;\n\n // Batch claiming\n this.batchClaimSize = options.batchClaimSize ?? 10;\n\n // Cooloff\n this.cooloffEnabled = options.cooloff?.enabled ?? true;\n this.cooloffThreshold = options.cooloff?.threshold ?? 10;\n this.cooloffPeriodMs = options.cooloff?.periodMs ?? 10_000;\n this.maxCooloffStatesSize = options.cooloff?.maxStatesSize ?? 1000;\n\n // Worker queue backpressure\n this.workerQueueMaxDepth = options.workerQueueMaxDepth ?? 0;\n this.workerQueueDepthCheckId = options.workerQueueDepthCheckId;\n\n // Consumer tracing\n this.consumerTraceMaxIterations = options.consumerTraceMaxIterations ?? 500;\n this.consumerTraceTimeoutSeconds = options.consumerTraceTimeoutSeconds ?? 60;\n\n // Initialize telemetry\n this.telemetry = new FairQueueTelemetry({\n tracer: options.tracer,\n meter: options.meter,\n name: options.name ?? \"fairqueue\",\n });\n\n // Initialize batched span manager for consumer tracing\n this.batchedSpanManager = new BatchedSpanManager({\n tracer: options.tracer,\n name: options.name ?? \"fairqueue\",\n maxIterations: this.consumerTraceMaxIterations,\n timeoutSeconds: this.consumerTraceTimeoutSeconds,\n getDynamicAttributes: () => ({\n \"cache.descriptor_size\": this.queueDescriptorCache.size,\n \"cache.cooloff_states_size\": this.queueCooloffStates.size,\n }),\n });\n\n // Initialize components\n this.masterQueue = new MasterQueue({\n redis: options.redis,\n keys: options.keys,\n shardCount: this.shardCount,\n });\n\n this.tenantDispatch = new TenantDispatch({\n redis: options.redis,\n keys: options.keys,\n shardCount: this.shardCount,\n });\n\n if (options.concurrencyGroups && options.concurrencyGroups.length > 0) {\n this.concurrencyManager = new ConcurrencyManager({\n redis: options.redis,\n keys: options.keys,\n groups: options.concurrencyGroups,\n logger: {\n debug: (msg, ctx) => this.logger.debug(msg, ctx),\n error: (msg, ctx) => this.logger.error(msg, ctx),\n },\n });\n }\n\n this.visibilityManager = new VisibilityManager({\n redis: options.redis,\n keys: options.keys,\n shardCount: this.shardCount,\n defaultTimeoutMs: this.visibilityTimeoutMs,\n logger: {\n debug: (msg, ctx) => this.logger.debug(msg, ctx),\n error: (msg, ctx) => this.logger.error(msg, ctx),\n },\n });\n\n // Worker queue manager for pushing messages to worker queues\n this.workerQueueManager = new WorkerQueueManager({\n redis: options.redis,\n keys: options.keys,\n logger: {\n debug: (msg, ctx) => this.logger.debug(msg, ctx),\n error: (msg, ctx) => this.logger.error(msg, ctx),\n },\n });\n\n this.#registerCommands();\n\n // Auto-start consumers if not disabled\n if (options.startConsumers !== false) {\n this.start();\n }\n }\n\n // ============================================================================\n // Public API - Telemetry\n // ============================================================================\n\n /**\n * Register observable gauge callbacks for telemetry.\n * Call this after FairQueue is created to enable gauge metrics.\n *\n * @param options.observedTenants - List of tenant IDs to observe for DLQ metrics\n */\n registerTelemetryGauges(options?: { observedTenants?: string[] }): void {\n this.telemetry.registerGaugeCallbacks({\n getMasterQueueLength: async (shardId: number) => {\n return await this.masterQueue.getShardQueueCount(shardId);\n },\n getDispatchLength: async (shardId: number) => {\n return await this.tenantDispatch.getShardTenantCount(shardId);\n },\n getInflightCount: async (shardId: number) => {\n return await this.visibilityManager.getInflightCount(shardId);\n },\n getDLQLength: async (tenantId: string) => {\n return await this.getDeadLetterQueueLength(tenantId);\n },\n shardCount: this.shardCount,\n observedTenants: options?.observedTenants,\n });\n }\n\n // ============================================================================\n // Public API - Enqueueing\n // ============================================================================\n\n /**\n * Enqueue a single message to a queue.\n */\n async enqueue(options: EnqueueOptions<inferZodSchemaOutput<TPayloadSchema>>): Promise<string> {\n return this.telemetry.trace(\n \"enqueue\",\n async (span) => {\n const messageId = options.messageId ?? nanoid();\n const timestamp = options.timestamp ?? Date.now();\n const queueKey = this.keys.queueKey(options.queueId);\n const queueItemsKey = this.keys.queueItemsKey(options.queueId);\n const dispatchShardId = this.tenantDispatch.getShardForTenant(options.tenantId);\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(options.tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n\n // Validate payload if schema provided and validation enabled\n if (this.validateOnEnqueue && this.payloadSchema) {\n const result = this.payloadSchema.safeParse(options.payload);\n if (!result.success) {\n throw new Error(`Payload validation failed: ${result.error.message}`);\n }\n }\n\n // Store queue descriptor for later use\n const descriptor: QueueDescriptor = {\n id: options.queueId,\n tenantId: options.tenantId,\n metadata: options.metadata ?? {},\n };\n this.queueDescriptorCache.set(options.queueId, descriptor);\n\n // Build stored message\n const storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>> = {\n id: messageId,\n queueId: options.queueId,\n tenantId: options.tenantId,\n payload: options.payload,\n timestamp,\n attempt: 1,\n workerQueue: this.workerQueueResolver\n ? this.workerQueueResolver({\n id: messageId,\n queueId: options.queueId,\n tenantId: options.tenantId,\n payload: options.payload,\n timestamp,\n attempt: 1,\n metadata: options.metadata,\n })\n : undefined,\n metadata: options.metadata,\n };\n\n // Use atomic Lua script to enqueue and update tenant dispatch indexes\n await this.redis.enqueueMessageAtomicV2(\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n options.queueId,\n messageId,\n timestamp.toString(),\n JSON.stringify(storedMessage),\n options.tenantId\n );\n\n span.setAttributes({\n [FairQueueAttributes.QUEUE_ID]: options.queueId,\n [FairQueueAttributes.TENANT_ID]: options.tenantId,\n [FairQueueAttributes.MESSAGE_ID]: messageId,\n [FairQueueAttributes.SHARD_ID]: dispatchShardId.toString(),\n });\n\n this.telemetry.recordEnqueue();\n\n this.logger.debug(\"Message enqueued\", {\n queueId: options.queueId,\n messageId,\n timestamp,\n });\n\n return messageId;\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n [MessagingAttributes.OPERATION]: \"publish\",\n },\n }\n );\n }\n\n /**\n * Enqueue multiple messages to a queue.\n */\n async enqueueBatch(\n options: EnqueueBatchOptions<inferZodSchemaOutput<TPayloadSchema>>\n ): Promise<string[]> {\n return this.telemetry.trace(\n \"enqueueBatch\",\n async (span) => {\n const queueKey = this.keys.queueKey(options.queueId);\n const queueItemsKey = this.keys.queueItemsKey(options.queueId);\n const dispatchShardId = this.tenantDispatch.getShardForTenant(options.tenantId);\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(options.tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n const now = Date.now();\n\n // Store queue descriptor\n const descriptor: QueueDescriptor = {\n id: options.queueId,\n tenantId: options.tenantId,\n metadata: options.metadata ?? {},\n };\n this.queueDescriptorCache.set(options.queueId, descriptor);\n\n const messageIds: string[] = [];\n const args: string[] = [];\n\n for (const message of options.messages) {\n const messageId = message.messageId ?? nanoid();\n const timestamp = message.timestamp ?? now;\n\n // Validate if enabled\n if (this.validateOnEnqueue && this.payloadSchema) {\n const result = this.payloadSchema.safeParse(message.payload);\n if (!result.success) {\n throw new Error(\n `Payload validation failed for message ${messageId}: ${result.error.message}`\n );\n }\n }\n\n const storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>> = {\n id: messageId,\n queueId: options.queueId,\n tenantId: options.tenantId,\n payload: message.payload,\n timestamp,\n attempt: 1,\n workerQueue: this.workerQueueResolver\n ? this.workerQueueResolver({\n id: messageId,\n queueId: options.queueId,\n tenantId: options.tenantId,\n payload: message.payload,\n timestamp,\n attempt: 1,\n metadata: options.metadata,\n })\n : undefined,\n metadata: options.metadata,\n };\n\n messageIds.push(messageId);\n args.push(messageId, timestamp.toString(), JSON.stringify(storedMessage));\n }\n\n // Use atomic Lua script for batch enqueue with tenant dispatch indexes\n await this.redis.enqueueBatchAtomicV2(\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n options.queueId,\n options.tenantId,\n ...args\n );\n\n span.setAttributes({\n [FairQueueAttributes.QUEUE_ID]: options.queueId,\n [FairQueueAttributes.TENANT_ID]: options.tenantId,\n [FairQueueAttributes.MESSAGE_COUNT]: messageIds.length,\n [FairQueueAttributes.SHARD_ID]: dispatchShardId.toString(),\n });\n\n this.telemetry.recordEnqueueBatch(messageIds.length);\n\n this.logger.debug(\"Batch enqueued\", {\n queueId: options.queueId,\n messageCount: messageIds.length,\n });\n\n return messageIds;\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n [MessagingAttributes.OPERATION]: \"publish\",\n },\n }\n );\n }\n\n // ============================================================================\n // Public API - Dead Letter Queue\n // ============================================================================\n\n /**\n * Get messages from the dead letter queue for a tenant.\n */\n async getDeadLetterMessages(\n tenantId: string,\n limit: number = 100\n ): Promise<DeadLetterMessage<inferZodSchemaOutput<TPayloadSchema>>[]> {\n if (!this.deadLetterQueueEnabled) {\n return [];\n }\n\n const dlqKey = this.keys.deadLetterQueueKey(tenantId);\n const dlqDataKey = this.keys.deadLetterQueueDataKey(tenantId);\n\n // Get message IDs with scores (deadLetteredAt timestamps)\n const results = await this.redis.zrange(dlqKey, 0, limit - 1, \"WITHSCORES\");\n\n const messages: DeadLetterMessage<inferZodSchemaOutput<TPayloadSchema>>[] = [];\n\n for (let i = 0; i < results.length; i += 2) {\n const messageId = results[i];\n const deadLetteredAtStr = results[i + 1];\n if (!messageId || !deadLetteredAtStr) continue;\n\n const dataJson = await this.redis.hget(dlqDataKey, messageId);\n if (!dataJson) continue;\n\n try {\n const data = JSON.parse(dataJson) as DeadLetterMessage<\n inferZodSchemaOutput<TPayloadSchema>\n >;\n data.deadLetteredAt = parseFloat(deadLetteredAtStr);\n messages.push(data);\n } catch {\n this.logger.error(\"Failed to parse DLQ message\", { messageId, tenantId });\n }\n }\n\n return messages;\n }\n\n /**\n * Redrive a message from DLQ back to its original queue.\n */\n async redriveMessage(tenantId: string, messageId: string): Promise<boolean> {\n if (!this.deadLetterQueueEnabled) {\n return false;\n }\n\n return this.telemetry.trace(\n \"redriveMessage\",\n async (span) => {\n const dlqKey = this.keys.deadLetterQueueKey(tenantId);\n const dlqDataKey = this.keys.deadLetterQueueDataKey(tenantId);\n\n // Get the message data\n const dataJson = await this.redis.hget(dlqDataKey, messageId);\n if (!dataJson) {\n return false;\n }\n\n const dlqMessage = JSON.parse(dataJson) as DeadLetterMessage<\n inferZodSchemaOutput<TPayloadSchema>\n >;\n\n // Re-enqueue with reset attempt count\n await this.enqueue({\n queueId: dlqMessage.queueId,\n tenantId: dlqMessage.tenantId,\n payload: dlqMessage.payload,\n messageId: dlqMessage.id,\n timestamp: Date.now(),\n });\n\n // Remove from DLQ\n const pipeline = this.redis.pipeline();\n pipeline.zrem(dlqKey, messageId);\n pipeline.hdel(dlqDataKey, messageId);\n await pipeline.exec();\n\n span.setAttributes({\n [FairQueueAttributes.TENANT_ID]: tenantId,\n [FairQueueAttributes.MESSAGE_ID]: messageId,\n });\n\n this.logger.info(\"Redrived message from DLQ\", { tenantId, messageId });\n\n return true;\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n [MessagingAttributes.OPERATION]: \"redrive\",\n },\n }\n );\n }\n\n /**\n * Redrive all messages from DLQ back to their original queues.\n */\n async redriveAll(tenantId: string): Promise<number> {\n const messages = await this.getDeadLetterMessages(tenantId, 1000);\n let count = 0;\n\n for (const message of messages) {\n const success = await this.redriveMessage(tenantId, message.id);\n if (success) count++;\n }\n\n return count;\n }\n\n /**\n * Purge all messages from a tenant's DLQ.\n */\n async purgeDeadLetterQueue(tenantId: string): Promise<number> {\n if (!this.deadLetterQueueEnabled) {\n return 0;\n }\n\n const dlqKey = this.keys.deadLetterQueueKey(tenantId);\n const dlqDataKey = this.keys.deadLetterQueueDataKey(tenantId);\n\n const count = await this.redis.zcard(dlqKey);\n\n const pipeline = this.redis.pipeline();\n pipeline.del(dlqKey);\n pipeline.del(dlqDataKey);\n await pipeline.exec();\n\n this.logger.info(\"Purged DLQ\", { tenantId, count });\n\n return count;\n }\n\n /**\n * Get the number of messages in a tenant's DLQ.\n */\n async getDeadLetterQueueLength(tenantId: string): Promise<number> {\n if (!this.deadLetterQueueEnabled) {\n return 0;\n }\n\n const dlqKey = this.keys.deadLetterQueueKey(tenantId);\n return await this.redis.zcard(dlqKey);\n }\n\n /**\n * Get the size of the in-memory queue descriptor cache.\n * This cache stores metadata for queues that have been enqueued.\n * The cache is cleaned up when queues are fully processed.\n */\n getQueueDescriptorCacheSize(): number {\n return this.queueDescriptorCache.size;\n }\n\n /**\n * Get the size of the in-memory cooloff states cache.\n * This cache tracks queues that are in cooloff due to repeated failures.\n * The cache is cleaned up when queues are fully processed or cooloff expires.\n */\n getQueueCooloffStatesSize(): number {\n return this.queueCooloffStates.size;\n }\n\n /**\n * Get all in-memory cache sizes for monitoring.\n * Useful for adding as span attributes.\n */\n getCacheSizes(): { descriptorCacheSize: number; cooloffStatesSize: number } {\n return {\n descriptorCacheSize: this.queueDescriptorCache.size,\n cooloffStatesSize: this.queueCooloffStates.size,\n };\n }\n\n // ============================================================================\n // Public API - Lifecycle\n // ============================================================================\n\n /**\n * Start the master queue consumer loops and reclaim loop.\n * FairQueue claims messages and pushes them to worker queues.\n * External consumers are responsible for consuming from worker queues.\n */\n start(): void {\n if (this.isRunning) {\n return;\n }\n\n this.isRunning = true;\n this.abortController = new AbortController();\n\n // Start master queue consumers (one per shard)\n // These claim messages from queues and push to worker queues\n for (let shardId = 0; shardId < this.shardCount; shardId++) {\n const loop = this.#runMasterQueueConsumerLoop(shardId);\n this.masterQueueConsumerLoops.push(loop);\n }\n\n // Start reclaim loop for handling timed-out messages\n this.reclaimLoop = this.#runReclaimLoop();\n\n if (this.concurrencyManager && this.reconcileIntervalMs > 0) {\n this.reconcileLoop = this.#runReconcileLoop();\n }\n\n this.logger.info(\"FairQueue started\", {\n consumerCount: this.consumerCount,\n shardCount: this.shardCount,\n consumerIntervalMs: this.consumerIntervalMs,\n });\n }\n\n /**\n * Stop the consumer loops gracefully.\n */\n async stop(): Promise<void> {\n if (!this.isRunning) {\n return;\n }\n\n this.isRunning = false;\n this.abortController.abort();\n\n await Promise.allSettled([\n ...this.masterQueueConsumerLoops,\n this.reclaimLoop,\n this.reconcileLoop,\n ]);\n\n this.masterQueueConsumerLoops = [];\n this.reclaimLoop = undefined;\n this.reconcileLoop = undefined;\n\n this.logger.info(\"FairQueue stopped\");\n }\n\n /**\n * Close all resources.\n */\n async close(): Promise<void> {\n await this.stop();\n\n // Clean up any remaining batched spans\n this.batchedSpanManager.cleanupAll();\n\n await Promise.all([\n this.masterQueue.close(),\n this.tenantDispatch.close(),\n this.concurrencyManager?.close(),\n this.visibilityManager.close(),\n this.workerQueueManager.close(),\n this.scheduler.close?.(),\n this.redis.quit(),\n ]);\n }\n\n // ============================================================================\n // Public API - Inspection\n // ============================================================================\n\n /**\n * Get the number of messages in a queue.\n */\n async getQueueLength(queueId: string): Promise<number> {\n const queueKey = this.keys.queueKey(queueId);\n return await this.redis.zcard(queueKey);\n }\n\n /**\n * Get total tenant count across dispatch shards plus any legacy queues still draining.\n */\n async getTotalQueueCount(): Promise<number> {\n const [dispatchCount, legacyCount] = await Promise.all([\n this.tenantDispatch.getTotalTenantCount(),\n this.masterQueue.getTotalQueueCount(),\n ]);\n return dispatchCount + legacyCount;\n }\n\n /**\n * Get total in-flight message count.\n */\n async getTotalInflightCount(): Promise<number> {\n return await this.visibilityManager.getTotalInflightCount();\n }\n\n /**\n * Get the shard ID for a queue.\n */\n getShardForQueue(queueId: string): number {\n return this.masterQueue.getShardForQueue(queueId);\n }\n\n // ============================================================================\n // Private - Master Queue Consumer Loop (Two-Stage)\n // ============================================================================\n\n async #runMasterQueueConsumerLoop(shardId: number): Promise<void> {\n const loopId = `master-shard-${shardId}`;\n\n // Initialize batched span tracking for this loop\n this.batchedSpanManager.initializeLoop(loopId);\n\n try {\n while (this.isRunning) {\n // Check abort signal\n if (this.abortController.signal.aborted) {\n break;\n }\n\n let hadWork = false;\n try {\n hadWork = await this.batchedSpanManager.withBatchedSpan(\n loopId,\n async (span) => {\n span.setAttribute(\"shard_id\", shardId);\n return await this.#processShardIteration(loopId, shardId, span);\n },\n {\n iterationSpanName: \"processMasterQueueShard\",\n attributes: { shard_id: shardId },\n }\n );\n } catch (error) {\n this.logger.error(\"Master queue consumer error\", {\n loopId,\n shardId,\n error: error instanceof Error ? error.message : String(error),\n });\n this.batchedSpanManager.markForRotation(loopId);\n }\n\n // Wait between iterations to prevent CPU spin\n // Short delay when there's work (yield to event loop), longer delay when idle\n const waitMs = hadWork ? 1 : this.consumerIntervalMs;\n await new Promise<void>((resolve, reject) => {\n const abortHandler = () => {\n clearTimeout(timeout);\n reject(new Error(\"AbortError\"));\n };\n const timeout = setTimeout(() => {\n // Must remove listener when timeout fires, otherwise listeners accumulate\n // (the { once: true } option only removes on abort, not on timeout)\n this.abortController.signal.removeEventListener(\"abort\", abortHandler);\n resolve();\n }, waitMs);\n this.abortController.signal.addEventListener(\"abort\", abortHandler, { once: true });\n });\n }\n } catch (error) {\n if (isAbortError(error)) {\n this.logger.debug(\"Master queue consumer aborted\", { loopId });\n this.batchedSpanManager.cleanup(loopId);\n return;\n }\n throw error;\n } finally {\n this.batchedSpanManager.cleanup(loopId);\n }\n }\n\n /**\n * Process a shard iteration. Runs both the new tenant dispatch path\n * and the legacy master queue drain path.\n */\n async #processShardIteration(\n loopId: string,\n shardId: number,\n parentSpan?: Span\n ): Promise<boolean> {\n let hadWork = false;\n\n // Main path: new two-level tenant dispatch (gets full DRR scheduling)\n hadWork = await this.#processDispatchShard(loopId, shardId, parentSpan);\n\n // Drain path: legacy master queue (simple scheduling, no DRR)\n // Check ZCARD first (O(1)) to skip the drain path when empty\n const legacyCount = await this.masterQueue.getShardQueueCount(shardId);\n if (legacyCount > 0) {\n const drainHadWork = await this.#drainLegacyMasterQueueShard(loopId, shardId, parentSpan);\n hadWork = hadWork || drainHadWork;\n }\n\n return hadWork;\n }\n\n /**\n * Main path: process queues using the two-level tenant dispatch index.\n * Level 1: dispatch index → tenantIds. Level 2: per-tenant → queueIds.\n */\n async #processDispatchShard(\n loopId: string,\n shardId: number,\n parentSpan?: Span\n ): Promise<boolean> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n\n // Get dispatch index size for observability\n const dispatchSize = await this.tenantDispatch.getShardTenantCount(shardId);\n parentSpan?.setAttribute(\"dispatch_size\", dispatchSize);\n this.batchedSpanManager.incrementStat(loopId, \"dispatch_size_sum\", dispatchSize);\n\n // Create dispatch-aware scheduler context\n const schedulerContext: DispatchSchedulerContext = {\n ...this.#createSchedulerContext(),\n getQueuesForTenant: async (tenantId: string, limit?: number) => {\n return this.tenantDispatch.getQueuesForTenant(tenantId, limit);\n },\n };\n\n // Get queues to process from scheduler\n let tenantQueues: TenantQueues[];\n\n if (this.scheduler.selectQueuesFromDispatch) {\n // Use dispatch-aware scheduler method (DRR with two-level lookup)\n tenantQueues = await this.telemetry.trace(\n \"selectQueuesFromDispatch\",\n async (span) => {\n span.setAttribute(FairQueueAttributes.SHARD_ID, shardId.toString());\n span.setAttribute(FairQueueAttributes.CONSUMER_ID, loopId);\n span.setAttribute(\"dispatch_size\", dispatchSize);\n const result = await this.scheduler.selectQueuesFromDispatch!(\n dispatchKey,\n loopId,\n schedulerContext\n );\n span.setAttribute(\"tenant_count\", result.length);\n span.setAttribute(\n \"queue_count\",\n result.reduce((acc, t) => acc + t.queues.length, 0)\n );\n return result;\n },\n { kind: SpanKind.INTERNAL }\n );\n } else {\n // Fallback: read dispatch index, build flat queue list, use legacy selectQueues\n tenantQueues = await this.#fallbackDispatchToLegacyScheduler(\n loopId,\n shardId,\n schedulerContext,\n parentSpan\n );\n }\n\n if (tenantQueues.length === 0) {\n this.batchedSpanManager.incrementStat(loopId, \"empty_iterations\");\n return false;\n }\n\n return this.#processSelectedQueues(loopId, shardId, tenantQueues);\n }\n\n /**\n * Drain path: process remaining messages from the legacy master queue shard.\n * Uses simple ZRANGEBYSCORE without DRR - just flushing pre-deploy messages.\n */\n async #drainLegacyMasterQueueShard(\n loopId: string,\n shardId: number,\n parentSpan?: Span\n ): Promise<boolean> {\n const masterQueueKey = this.keys.masterQueueKey(shardId);\n const now = Date.now();\n\n // Simple fetch from old master queue - no DRR needed for drain\n const results = await this.redis.zrangebyscore(\n masterQueueKey,\n \"-inf\",\n now,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n 100\n );\n\n if (results.length === 0) {\n return false;\n }\n\n // Parse results into QueueWithScore, group by tenant\n const byTenant = new Map<string, string[]>();\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const _score = results[i + 1];\n if (queueId && _score) {\n const tenantId = this.keys.extractTenantId(queueId);\n const existing = byTenant.get(tenantId) ?? [];\n existing.push(queueId);\n byTenant.set(tenantId, existing);\n }\n }\n\n // Build TenantQueues, filter at-capacity tenants\n const tenantQueues: TenantQueues[] = [];\n for (const [tenantId, queueIds] of byTenant) {\n if (this.concurrencyManager) {\n const atCapacity = await this.concurrencyManager.isAtCapacity(\"tenant\", tenantId);\n if (atCapacity) continue;\n }\n tenantQueues.push({ tenantId, queues: queueIds });\n }\n\n if (tenantQueues.length === 0) {\n return false;\n }\n\n parentSpan?.setAttribute(\"drain_tenants\", tenantQueues.length);\n this.batchedSpanManager.incrementStat(loopId, \"drain_tenants\", tenantQueues.length);\n\n return this.#processSelectedQueues(loopId, shardId, tenantQueues);\n }\n\n /**\n * Fallback for schedulers that don't implement selectQueuesFromDispatch.\n * Reads dispatch index, fetches per-tenant queues, groups by tenant,\n * and filters at-capacity tenants. No DRR deficit tracking in this path.\n */\n async #fallbackDispatchToLegacyScheduler(\n loopId: string,\n shardId: number,\n context: DispatchSchedulerContext,\n parentSpan?: Span\n ): Promise<TenantQueues[]> {\n // Get tenants from dispatch\n const tenants = await this.tenantDispatch.getTenantsFromShard(shardId);\n if (tenants.length === 0) return [];\n\n // For each tenant, get their queues and build grouped result\n const tenantQueues: TenantQueues[] = [];\n for (const { tenantId } of tenants) {\n if (this.concurrencyManager) {\n const atCapacity = await this.concurrencyManager.isAtCapacity(\"tenant\", tenantId);\n if (atCapacity) continue;\n }\n const queues = await this.tenantDispatch.getQueuesForTenant(tenantId);\n if (queues.length > 0) {\n tenantQueues.push({ tenantId, queues: queues.map((q) => q.queueId) });\n }\n }\n\n return tenantQueues;\n }\n\n /**\n * Shared claim loop: process selected queues from either dispatch or drain path.\n * Claims messages and pushes to worker queues.\n */\n async #processSelectedQueues(\n loopId: string,\n shardId: number,\n tenantQueues: TenantQueues[]\n ): Promise<boolean> {\n // Track stats\n this.batchedSpanManager.incrementStat(loopId, \"tenants_selected\", tenantQueues.length);\n this.batchedSpanManager.incrementStat(\n loopId,\n \"queues_selected\",\n tenantQueues.reduce((acc, t) => acc + t.queues.length, 0)\n );\n\n let messagesProcessed = 0;\n\n for (const { tenantId, queues } of tenantQueues) {\n for (const queueId of queues) {\n // Check cooloff\n if (this.cooloffEnabled && this.#isInCooloff(queueId)) {\n this.batchedSpanManager.incrementStat(loopId, \"cooloff_skipped\");\n continue;\n }\n\n // Check tenant capacity before attempting to process\n if (this.concurrencyManager) {\n const isAtCapacity = await this.concurrencyManager.isAtCapacity(\"tenant\", tenantId);\n if (isAtCapacity) {\n this.batchedSpanManager.incrementStat(loopId, \"tenant_capacity_skipped\");\n break;\n }\n }\n\n const processedFromQueue = await this.telemetry.trace(\n \"claimAndPushToWorkerQueue\",\n async (span) => {\n span.setAttribute(FairQueueAttributes.QUEUE_ID, queueId);\n span.setAttribute(FairQueueAttributes.TENANT_ID, tenantId);\n span.setAttribute(FairQueueAttributes.SHARD_ID, shardId.toString());\n const count = await this.#claimAndPushToWorkerQueue(loopId, queueId, tenantId, shardId);\n span.setAttribute(\"messages_claimed\", count);\n return count;\n },\n { kind: SpanKind.INTERNAL }\n );\n\n if (processedFromQueue > 0) {\n messagesProcessed += processedFromQueue;\n this.batchedSpanManager.incrementStat(loopId, \"messages_claimed\", processedFromQueue);\n\n if (this.scheduler.recordProcessedBatch) {\n await this.telemetry.trace(\n \"recordProcessedBatch\",\n async (span) => {\n span.setAttribute(FairQueueAttributes.QUEUE_ID, queueId);\n span.setAttribute(FairQueueAttributes.TENANT_ID, tenantId);\n span.setAttribute(\"count\", processedFromQueue);\n await this.scheduler.recordProcessedBatch!(tenantId, queueId, processedFromQueue);\n },\n { kind: SpanKind.INTERNAL }\n );\n } else if (this.scheduler.recordProcessed) {\n for (let i = 0; i < processedFromQueue; i++) {\n await this.telemetry.trace(\n \"recordProcessed\",\n async (span) => {\n span.setAttribute(FairQueueAttributes.QUEUE_ID, queueId);\n span.setAttribute(FairQueueAttributes.TENANT_ID, tenantId);\n await this.scheduler.recordProcessed!(tenantId, queueId);\n },\n { kind: SpanKind.INTERNAL }\n );\n }\n }\n } else {\n this.batchedSpanManager.incrementStat(loopId, \"claim_skipped\");\n }\n }\n }\n\n return messagesProcessed > 0;\n }\n\n async #claimAndPushToWorkerQueue(\n loopId: string,\n queueId: string,\n tenantId: string,\n _consumerShardId: number\n ): Promise<number> {\n // Dispatch shard is tenant-based (tenantId hash), not queue-based.\n // In-flight/master queue shard is queue-based.\n const dispatchShardId = this.tenantDispatch.getShardForTenant(tenantId);\n const queueKey = this.keys.queueKey(queueId);\n const queueItemsKey = this.keys.queueItemsKey(queueId);\n const descriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId,\n metadata: {},\n };\n\n // Determine how many messages we can claim based on concurrency\n let maxClaimCount = this.batchClaimSize;\n if (this.concurrencyManager) {\n const availableCapacity = await this.concurrencyManager.getAvailableCapacity(descriptor);\n if (availableCapacity === 0) {\n // Queue at max concurrency - don't increment cooloff here.\n // The outer loop already handles this case (concurrency blocked)\n // and explicitly avoids cooloff for it. Cooloff here causes\n // spurious 5s stalls when capacity races between the tenant\n // pre-check and this per-queue check.\n return 0;\n }\n maxClaimCount = Math.min(maxClaimCount, availableCapacity);\n }\n\n // Check worker queue depth to prevent unbounded growth.\n // Messages in the worker queue are already in-flight with a visibility timeout.\n // If the queue is too deep, consumers can't keep up, and messages risk timing out.\n if (this.workerQueueMaxDepth > 0 && this.workerQueueDepthCheckId) {\n const depth = await this.workerQueueManager.getLength(this.workerQueueDepthCheckId);\n if (depth >= this.workerQueueMaxDepth) {\n return 0;\n }\n // Cap claim size to remaining capacity so we don't overshoot the depth limit\n const remainingCapacity = this.workerQueueMaxDepth - depth;\n maxClaimCount = Math.min(maxClaimCount, remainingCapacity);\n }\n\n // Claim batch of messages with visibility timeout\n const claimedMessages = await this.visibilityManager.claimBatch<\n StoredMessage<inferZodSchemaOutput<TPayloadSchema>>\n >(queueId, queueKey, queueItemsKey, loopId, maxClaimCount, this.visibilityTimeoutMs);\n\n if (claimedMessages.length === 0) {\n // Queue is empty, update both old and new indexes and clean up caches\n await this.#updateAllIndexesAfterDequeue(queueId, tenantId);\n this.queueDescriptorCache.delete(queueId);\n this.queueCooloffStates.delete(queueId);\n return 0;\n }\n\n let processedCount = 0;\n\n // Reserve concurrency and push each message to worker queue\n for (let i = 0; i < claimedMessages.length; i++) {\n const message = claimedMessages[i]!;\n\n // Reserve concurrency slot\n if (this.concurrencyManager) {\n const reserved = await this.concurrencyManager.reserve(descriptor, message.messageId);\n if (!reserved) {\n // Release ALL remaining messages (from index i onward) back to queue\n // This prevents messages from being stranded in the in-flight set\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n await this.visibilityManager.releaseBatch(\n claimedMessages.slice(i),\n queueId,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n tenantId\n );\n // Stop processing more messages from this queue since we're at capacity\n break;\n }\n }\n\n // Resolve which worker queue this message should go to\n const workerQueueId = this.workerQueueResolver(message.payload);\n\n // Push to worker queue with format \"messageId:queueId\"\n const messageKey = `${message.messageId}:${queueId}`;\n await this.workerQueueManager.push(workerQueueId, messageKey);\n processedCount++;\n }\n\n if (processedCount > 0) {\n this.#resetCooloff(queueId);\n }\n\n return processedCount;\n }\n\n // ============================================================================\n // Public API - Message Lifecycle (for external consumers)\n // ============================================================================\n\n /**\n * Get message data from in-flight storage.\n * External consumers use this to retrieve the stored message after popping from worker queue.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n * @returns The stored message or null if not found\n */\n async getMessageData(\n messageId: string,\n queueId: string\n ): Promise<StoredMessage<inferZodSchemaOutput<TPayloadSchema>> | null> {\n const shardId = this.masterQueue.getShardForQueue(queueId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n\n if (!dataJson) {\n return null;\n }\n\n try {\n return JSON.parse(dataJson) as StoredMessage<inferZodSchemaOutput<TPayloadSchema>>;\n } catch {\n this.logger.error(\"Failed to parse message data\", { messageId, queueId });\n return null;\n }\n }\n\n /**\n * Extend the visibility timeout for a message.\n * External consumers should call this periodically during long-running processing.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n * @returns true if heartbeat was successful\n */\n async heartbeatMessage(messageId: string, queueId: string): Promise<boolean> {\n return this.visibilityManager.heartbeat(messageId, queueId, this.heartbeatIntervalMs);\n }\n\n /**\n * Mark a message as successfully processed.\n * This removes the message from in-flight and releases concurrency.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n */\n async completeMessage(messageId: string, queueId: string): Promise<void> {\n const shardId = this.masterQueue.getShardForQueue(queueId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Get stored message for concurrency release\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n let storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>> | null = null;\n if (dataJson) {\n try {\n storedMessage = JSON.parse(dataJson);\n } catch {\n // Ignore parse error, proceed with completion\n }\n }\n\n const descriptor: QueueDescriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: storedMessage?.tenantId ?? this.keys.extractTenantId(queueId),\n metadata: storedMessage?.metadata ?? {},\n };\n\n await this.#releaseConcurrencySafely(descriptor, messageId, \"completeMessage\");\n\n // Complete in visibility manager\n await this.visibilityManager.complete(messageId, queueId);\n\n // Update both old and new indexes, clean up caches if queue is empty\n const { queueEmpty } = await this.#updateAllIndexesAfterDequeue(queueId, descriptor.tenantId);\n if (queueEmpty) {\n this.queueDescriptorCache.delete(queueId);\n this.queueCooloffStates.delete(queueId);\n }\n\n this.telemetry.recordComplete();\n\n this.logger.debug(\"Message completed\", {\n messageId,\n queueId,\n });\n }\n\n /**\n * Release a message back to the queue for processing by another consumer.\n * The message is placed at the back of the queue.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n */\n async releaseMessage(messageId: string, queueId: string): Promise<void> {\n const shardId = this.masterQueue.getShardForQueue(queueId);\n const queueKey = this.keys.queueKey(queueId);\n const queueItemsKey = this.keys.queueItemsKey(queueId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Get stored message for concurrency release\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n let storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>> | null = null;\n if (dataJson) {\n try {\n storedMessage = JSON.parse(dataJson);\n } catch {\n // Ignore parse error\n }\n }\n\n const descriptor: QueueDescriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: storedMessage?.tenantId ?? this.keys.extractTenantId(queueId),\n metadata: storedMessage?.metadata ?? {},\n };\n\n // Release concurrency\n await this.#releaseConcurrencySafely(descriptor, messageId, \"releaseMessage\");\n\n // Release back to queue (visibility manager updates dispatch indexes atomically)\n // Dispatch shard is tenant-based, not queue-based\n const dispatchShardId = this.tenantDispatch.getShardForTenant(descriptor.tenantId);\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(descriptor.tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n await this.visibilityManager.release(\n messageId,\n queueId,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n descriptor.tenantId,\n Date.now() // Put at back of queue\n );\n\n this.logger.debug(\"Message released\", {\n messageId,\n queueId,\n });\n }\n\n /**\n * Release a message's concurrency slots without letting a failure escape. Release is\n * best-effort cleanup: the primary state transition (complete, retry, DLQ, requeue)\n * must proceed even when the slot cannot be freed, because aborting the transition\n * re-delivers or strands the message, while a leaked slot is recoverable — reserve()\n * re-admits a message that already holds its own slot, and the reconcile loop removes\n * members that are no longer in flight.\n */\n async #releaseConcurrencySafely(\n descriptor: QueueDescriptor,\n messageId: string,\n context: string\n ): Promise<void> {\n if (!this.concurrencyManager) {\n return;\n }\n\n try {\n await this.concurrencyManager.release(descriptor, messageId);\n } catch (error) {\n this.logger.error(\"Failed to release concurrency slot, leaving it for the reconciler\", {\n context,\n messageId,\n queueId: descriptor.id,\n tenantId: descriptor.tenantId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n /**\n * Release a concurrency slot for a message we can no longer describe, deriving the\n * group from the queue id alone. Used on paths that bail out before the stored\n * message is available, where the slot would otherwise be held with nothing left\n * to reclaim it.\n */\n async #releaseOrphanedConcurrency(messageId: string, queueId: string): Promise<void> {\n if (!this.concurrencyManager) {\n return;\n }\n\n const descriptor: QueueDescriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: this.keys.extractTenantId(queueId),\n metadata: {},\n };\n\n await this.#releaseConcurrencySafely(descriptor, messageId, \"failMessage:missing-record\");\n }\n\n /**\n * Mark a message as failed. This will trigger retry logic if configured,\n * or move the message to the dead letter queue.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n * @param error - Optional error that caused the failure\n */\n async failMessage(messageId: string, queueId: string, error?: Error): Promise<void> {\n const shardId = this.masterQueue.getShardForQueue(queueId);\n const queueKey = this.keys.queueKey(queueId);\n const queueItemsKey = this.keys.queueItemsKey(queueId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Get stored message\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n if (!dataJson) {\n this.logger.error(\"Cannot fail message: not found in in-flight data\", { messageId, queueId });\n await this.#releaseOrphanedConcurrency(messageId, queueId);\n return;\n }\n\n let storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>>;\n try {\n storedMessage = JSON.parse(dataJson);\n } catch {\n this.logger.error(\"Cannot fail message: failed to parse stored message\", {\n messageId,\n queueId,\n });\n await this.#releaseOrphanedConcurrency(messageId, queueId);\n return;\n }\n\n const descriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: storedMessage.tenantId,\n metadata: storedMessage.metadata ?? {},\n };\n\n const dispatchShardId = this.tenantDispatch.getShardForTenant(descriptor.tenantId);\n await this.#handleMessageFailure(\n storedMessage,\n queueId,\n queueKey,\n queueItemsKey,\n dispatchShardId,\n descriptor,\n error\n );\n }\n\n // ============================================================================\n // Private - Message Processing Helpers\n // ============================================================================\n\n async #handleMessageFailure(\n storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>>,\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n dispatchShardId: number,\n descriptor: QueueDescriptor,\n error?: Error\n ): Promise<void> {\n this.telemetry.recordFailure();\n\n // Check retry strategy\n if (this.retryStrategy) {\n const nextDelay = this.retryStrategy.getNextDelay(storedMessage.attempt, error);\n\n if (nextDelay !== null) {\n // Retry with incremented attempt\n const updatedMessage = {\n ...storedMessage,\n attempt: storedMessage.attempt + 1,\n };\n\n await this.#releaseConcurrencySafely(descriptor, storedMessage.id, \"retry\");\n\n // Release with delay, passing the updated message data so the Lua script\n // atomically writes the incremented attempt count when re-queuing.\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(descriptor.tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n await this.visibilityManager.release(\n storedMessage.id,\n queueId,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n descriptor.tenantId,\n Date.now() + nextDelay,\n JSON.stringify(updatedMessage)\n );\n\n this.telemetry.recordRetry();\n\n this.logger.debug(\"Message scheduled for retry\", {\n messageId: storedMessage.id,\n queueId,\n attempt: storedMessage.attempt + 1,\n delayMs: nextDelay,\n });\n\n return;\n }\n }\n\n // Release concurrency\n await this.#releaseConcurrencySafely(descriptor, storedMessage.id, \"deadLetter\");\n\n // Move to DLQ\n await this.#moveToDeadLetterQueue(storedMessage, error?.message);\n }\n\n async #moveToDeadLetterQueue(\n storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>>,\n errorMessage?: string\n ): Promise<void> {\n if (!this.deadLetterQueueEnabled) {\n // Just complete and discard\n await this.visibilityManager.complete(storedMessage.id, storedMessage.queueId);\n return;\n }\n\n const dlqKey = this.keys.deadLetterQueueKey(storedMessage.tenantId);\n const dlqDataKey = this.keys.deadLetterQueueDataKey(storedMessage.tenantId);\n const _shardId = this.masterQueue.getShardForQueue(storedMessage.queueId);\n\n const dlqMessage: DeadLetterMessage<inferZodSchemaOutput<TPayloadSchema>> = {\n id: storedMessage.id,\n queueId: storedMessage.queueId,\n tenantId: storedMessage.tenantId,\n payload: storedMessage.payload,\n deadLetteredAt: Date.now(),\n attempts: storedMessage.attempt,\n lastError: errorMessage,\n originalTimestamp: storedMessage.timestamp,\n };\n\n // Complete in visibility manager\n await this.visibilityManager.complete(storedMessage.id, storedMessage.queueId);\n\n // Add to DLQ\n const pipeline = this.redis.pipeline();\n pipeline.zadd(dlqKey, dlqMessage.deadLetteredAt, storedMessage.id);\n pipeline.hset(dlqDataKey, storedMessage.id, JSON.stringify(dlqMessage));\n await pipeline.exec();\n\n this.telemetry.recordDLQ();\n\n this.logger.info(\"Message moved to DLQ\", {\n messageId: storedMessage.id,\n queueId: storedMessage.queueId,\n tenantId: storedMessage.tenantId,\n attempts: storedMessage.attempt,\n error: errorMessage,\n });\n }\n\n // ============================================================================\n // Private - Reclaim Loop\n // ============================================================================\n\n async #runReclaimLoop(): Promise<void> {\n try {\n for await (const _ of setInterval(this.reclaimIntervalMs, null, {\n signal: this.abortController.signal,\n })) {\n try {\n await this.#reclaimTimedOutMessages();\n } catch (error) {\n this.logger.error(\"Reclaim loop error\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n } catch (error) {\n if (isAbortError(error)) {\n this.logger.debug(\"Reclaim loop aborted\");\n return;\n }\n throw error;\n }\n }\n\n /**\n * Free every timed-out message's concurrency slot in one pipeline before the batch is\n * requeued. A failed release never blocks the requeue: holding the message in-flight\n * would stall it behind a persistent release failure, while the leaked slot self-heals\n * when the message is re-admitted (reserve is idempotent for a message that already\n * holds its own slot) or via the reconcile loop.\n */\n async #releaseReclaimedConcurrency(messages: ReclaimedMessageInfo[]): Promise<void> {\n if (!this.concurrencyManager || messages.length === 0) {\n return;\n }\n\n const descriptorFor = (message: ReclaimedMessageInfo): QueueDescriptor => ({\n id: message.queueId,\n tenantId: message.tenantId,\n metadata: message.metadata ?? {},\n });\n\n try {\n await this.concurrencyManager.releaseBatch(\n messages.map((message) => ({ queue: descriptorFor(message), messageId: message.messageId }))\n );\n return;\n } catch (error) {\n this.logger.error(\"Batch concurrency release failed, retrying message by message\", {\n count: messages.length,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n for (const message of messages) {\n await this.#releaseConcurrencySafely(descriptorFor(message), message.messageId, \"reclaim\");\n }\n }\n\n async #reclaimTimedOutMessages(): Promise<void> {\n let totalReclaimed = 0;\n\n for (let shardId = 0; shardId < this.shardCount; shardId++) {\n try {\n const reclaimedMessages = await this.visibilityManager.reclaimTimedOut(\n shardId,\n (queueId) => {\n const tenantId = this.keys.extractTenantId(queueId);\n const dispatchShardId = this.tenantDispatch.getShardForTenant(tenantId);\n return {\n queueKey: this.keys.queueKey(queueId),\n queueItemsKey: this.keys.queueItemsKey(queueId),\n tenantQueueIndexKey: this.keys.tenantQueueIndexKey(tenantId),\n dispatchKey: this.keys.dispatchKey(dispatchShardId),\n tenantId,\n };\n },\n this.#releaseReclaimedConcurrency.bind(this)\n );\n\n totalReclaimed += reclaimedMessages.length;\n } catch (error) {\n this.logger.error(\"Failed to reclaim shard, leaving messages in-flight for the next tick\", {\n shardId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (totalReclaimed > 0) {\n this.logger.info(\"Reclaimed timed-out messages\", { count: totalReclaimed });\n }\n }\n\n /**\n * The initial delay is jittered so instances sharing a Redis do not all sweep at once.\n */\n async #runReconcileLoop(): Promise<void> {\n try {\n await delay(Math.random() * this.reconcileIntervalMs, null, {\n signal: this.abortController.signal,\n });\n\n for await (const _ of setInterval(this.reconcileIntervalMs, null, {\n signal: this.abortController.signal,\n })) {\n try {\n await this.#reconcileConcurrency();\n } catch (error) {\n this.logger.error(\"Concurrency reconcile loop error\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n } catch (error) {\n if (isAbortError(error)) {\n this.logger.debug(\"Concurrency reconcile loop aborted\");\n return;\n }\n throw error;\n }\n }\n\n /**\n * Heal orphaned concurrency slots: remove any concurrency set member whose message is\n * not registered in-flight on any shard. This is the recovery path for slots leaked by\n * failed releases, which otherwise count against a tenant's limit forever and can\n * wedge every queue the tenant owns.\n */\n async #reconcileConcurrency(): Promise<void> {\n if (!this.concurrencyManager) {\n return;\n }\n\n const inflightDataKeys = Array.from({ length: this.shardCount }, (_, shardId) =>\n this.keys.inflightDataKey(shardId)\n );\n\n const { scannedSets, removed } =\n await this.concurrencyManager.sweepOrphanedSlots(inflightDataKeys);\n\n if (removed.length > 0) {\n this.logger.info(\"Reconciled orphaned concurrency slots\", {\n count: removed.length,\n scannedSets,\n messageIds: removed.slice(0, 50),\n });\n }\n }\n\n // ============================================================================\n // Private - Cooloff State\n // ============================================================================\n\n #isInCooloff(queueId: string): boolean {\n const state = this.queueCooloffStates.get(queueId);\n if (!state) return false;\n\n if (state.tag === \"cooloff\") {\n if (Date.now() >= state.expiresAt) {\n this.queueCooloffStates.delete(queueId);\n return false;\n }\n return true;\n }\n\n return false;\n }\n\n #resetCooloff(queueId: string): void {\n this.queueCooloffStates.delete(queueId);\n }\n\n // ============================================================================\n // Private - Helpers\n // ============================================================================\n\n /**\n * Update both old master queue and new dispatch indexes after a dequeue/complete.\n * Both calls are idempotent - ZREM on a non-existent member is a no-op.\n * This handles the transition period where queues may exist in either or both indexes.\n */\n async #updateAllIndexesAfterDequeue(\n queueId: string,\n tenantId: string\n ): Promise<{ queueEmpty: boolean }> {\n const queueShardId = this.masterQueue.getShardForQueue(queueId);\n const dispatchShardId = this.tenantDispatch.getShardForTenant(tenantId);\n const queueKey = this.keys.queueKey(queueId);\n const masterQueueKey = this.keys.masterQueueKey(queueShardId);\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n\n // Update legacy master queue (drain path, no-op if queue not there)\n const removedFromMaster = await this.redis.updateMasterQueueIfEmpty(\n masterQueueKey,\n queueKey,\n queueId\n );\n\n // Update new dispatch indexes\n const removedFromDispatch = await this.redis.updateDispatchIndexes(\n queueKey,\n tenantQueueIndexKey,\n dispatchKey,\n queueId,\n tenantId\n );\n\n return { queueEmpty: removedFromMaster === 1 || removedFromDispatch === 1 };\n }\n\n #createSchedulerContext(): SchedulerContext {\n return {\n getCurrentConcurrency: async (groupName, groupId) => {\n if (!this.concurrencyManager) return 0;\n return this.concurrencyManager.getCurrentConcurrency(groupName, groupId);\n },\n getConcurrencyLimit: async (groupName, groupId) => {\n if (!this.concurrencyManager) return Infinity;\n return this.concurrencyManager.getConcurrencyLimit(groupName, groupId);\n },\n isAtCapacity: async (groupName, groupId) => {\n if (!this.concurrencyManager) return false;\n return this.concurrencyManager.isAtCapacity(groupName, groupId);\n },\n getQueueDescriptor: (queueId) => {\n return (\n this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: this.keys.extractTenantId(queueId),\n metadata: {},\n }\n );\n },\n };\n }\n\n // ============================================================================\n // Private - Redis Commands\n // ============================================================================\n\n #registerCommands(): void {\n // ---- Legacy Lua scripts (kept for drain of old master queue) ----\n\n // Atomic single message enqueue with master queue update (legacy, used for drain only)\n this.redis.defineCommand(\"enqueueMessageAtomic\", {\n numberOfKeys: 3,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal masterQueueKey = KEYS[3]\n\nlocal queueId = ARGV[1]\nlocal messageId = ARGV[2]\nlocal timestamp = tonumber(ARGV[3])\nlocal payload = ARGV[4]\n\nredis.call('ZADD', queueKey, timestamp, messageId)\nredis.call('HSET', queueItemsKey, messageId, payload)\n\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', masterQueueKey, oldest[2], queueId)\nend\n\nreturn 1\n `,\n });\n\n // Atomic batch message enqueue with master queue update (legacy, used for drain only)\n this.redis.defineCommand(\"enqueueBatchAtomic\", {\n numberOfKeys: 3,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal masterQueueKey = KEYS[3]\n\nlocal queueId = ARGV[1]\n\nfor i = 2, #ARGV, 3 do\n local messageId = ARGV[i]\n local timestamp = tonumber(ARGV[i + 1])\n local payload = ARGV[i + 2]\n redis.call('ZADD', queueKey, timestamp, messageId)\n redis.call('HSET', queueItemsKey, messageId, payload)\nend\n\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', masterQueueKey, oldest[2], queueId)\nend\n\nreturn (#ARGV - 1) / 3\n `,\n });\n\n // Remove queue from legacy master queue if empty (drain-only, never re-adds)\n this.redis.defineCommand(\"updateMasterQueueIfEmpty\", {\n numberOfKeys: 2,\n lua: `\nlocal masterQueueKey = KEYS[1]\nlocal queueKey = KEYS[2]\nlocal queueId = ARGV[1]\n\nlocal count = redis.call('ZCARD', queueKey)\nif count == 0 then\n redis.call('ZREM', masterQueueKey, queueId)\n return 1\nend\n\n-- Queue still has messages but don't re-add to legacy master queue.\n-- New enqueues go through the V2 dispatch path, so we only drain here.\n-- Just remove it so it doesn't linger.\nredis.call('ZREM', masterQueueKey, queueId)\nreturn 0\n `,\n });\n\n // ---- New V2 Lua scripts (two-level tenant dispatch) ----\n\n // Atomic single message enqueue with tenant dispatch index update\n this.redis.defineCommand(\"enqueueMessageAtomicV2\", {\n numberOfKeys: 4,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal tenantQueueIndexKey = KEYS[3]\nlocal dispatchKey = KEYS[4]\n\nlocal queueId = ARGV[1]\nlocal messageId = ARGV[2]\nlocal timestamp = tonumber(ARGV[3])\nlocal payload = ARGV[4]\nlocal tenantId = ARGV[5]\n\n-- Add to per-queue storage (same as before)\nredis.call('ZADD', queueKey, timestamp, messageId)\nredis.call('HSET', queueItemsKey, messageId, payload)\n\n-- Update tenant queue index (Level 2) with queue's oldest message\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\nend\n\n-- Update dispatch index (Level 1) with tenant's oldest across all queues\nlocal tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\nif #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\nend\n\nreturn 1\n `,\n });\n\n // Atomic batch message enqueue with tenant dispatch index update\n this.redis.defineCommand(\"enqueueBatchAtomicV2\", {\n numberOfKeys: 4,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal tenantQueueIndexKey = KEYS[3]\nlocal dispatchKey = KEYS[4]\n\nlocal queueId = ARGV[1]\nlocal tenantId = ARGV[2]\n\n-- Args after queueId and tenantId are triples: [messageId, timestamp, payload, ...]\nfor i = 3, #ARGV, 3 do\n local messageId = ARGV[i]\n local timestamp = tonumber(ARGV[i + 1])\n local payload = ARGV[i + 2]\n redis.call('ZADD', queueKey, timestamp, messageId)\n redis.call('HSET', queueItemsKey, messageId, payload)\nend\n\n-- Update tenant queue index (Level 2)\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\nend\n\n-- Update dispatch index (Level 1)\nlocal tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\nif #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\nend\n\nreturn (#ARGV - 2) / 3\n `,\n });\n\n // Update tenant dispatch indexes after dequeue/complete\n // Handles both queue-empty (remove from indexes) and queue-has-messages (update scores)\n this.redis.defineCommand(\"updateDispatchIndexes\", {\n numberOfKeys: 3,\n lua: `\nlocal queueKey = KEYS[1]\nlocal tenantQueueIndexKey = KEYS[2]\nlocal dispatchKey = KEYS[3]\nlocal queueId = ARGV[1]\nlocal tenantId = ARGV[2]\n\nlocal count = redis.call('ZCARD', queueKey)\nif count == 0 then\n -- Queue is empty: remove from tenant queue index\n redis.call('ZREM', tenantQueueIndexKey, queueId)\n\n -- Check if tenant has any queues left\n local tenantQueueCount = redis.call('ZCARD', tenantQueueIndexKey)\n if tenantQueueCount == 0 then\n -- No more queues: remove tenant from dispatch\n redis.call('ZREM', dispatchKey, tenantId)\n else\n -- Update dispatch score to tenant's new oldest\n local tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\n if #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\n end\n end\n return 1\nelse\n -- Queue still has messages: update scores\n local oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\n if #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\n end\n local tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\n if #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\n end\n return 0\nend\n `,\n });\n\n // Register worker queue commands if enabled\n if (this.workerQueueManager) {\n this.workerQueueManager.registerCommands(this.redis);\n }\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n // Legacy commands (kept for drain of old master queue)\n enqueueMessageAtomic(\n queueKey: string,\n queueItemsKey: string,\n masterQueueKey: string,\n queueId: string,\n messageId: string,\n timestamp: string,\n payload: string\n ): Promise<number>;\n\n enqueueBatchAtomic(\n queueKey: string,\n queueItemsKey: string,\n masterQueueKey: string,\n queueId: string,\n ...args: string[]\n ): Promise<number>;\n\n updateMasterQueueIfEmpty(\n masterQueueKey: string,\n queueKey: string,\n queueId: string\n ): Promise<number>;\n\n // V2 commands (two-level tenant dispatch)\n enqueueMessageAtomicV2(\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n queueId: string,\n messageId: string,\n timestamp: string,\n payload: string,\n tenantId: string\n ): Promise<number>;\n\n enqueueBatchAtomicV2(\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n queueId: string,\n tenantId: string,\n ...args: string[]\n ): Promise<number>;\n\n updateDispatchIndexes(\n queueKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n queueId: string,\n tenantId: string\n ): Promise<number>;\n }\n}\n","import { z } from \"zod/v4\";\n\nexport const BufferEntryStatus = z.enum([\"QUEUED\", \"DRAINING\", \"FAILED\"]);\nexport type BufferEntryStatus = z.infer<typeof BufferEntryStatus>;\n\nexport const BufferEntryError = z.object({\n code: z.string(),\n message: z.string(),\n});\nexport type BufferEntryError = z.infer<typeof BufferEntryError>;\n\nconst stringToInt = z.string().transform((v, ctx) => {\n const n = Number(v);\n if (!Number.isInteger(n) || n < 0) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: \"expected non-negative integer string\" });\n return z.NEVER;\n }\n return n;\n});\n\nconst stringToDate = z.string().transform((v, ctx) => {\n const d = new Date(v);\n if (Number.isNaN(d.getTime())) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: \"expected ISO date string\" });\n return z.NEVER;\n }\n return d;\n});\n\nconst stringToBool = z\n .union([z.literal(\"true\"), z.literal(\"false\")])\n .transform((v) => v === \"true\");\n\nconst stringToError = z.string().transform((v, ctx) => {\n try {\n return BufferEntryError.parse(JSON.parse(v));\n } catch {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"expected JSON-encoded BufferEntryError\",\n });\n return z.NEVER;\n }\n});\n\nexport const BufferEntrySchema = z.object({\n runId: z.string().min(1),\n envId: z.string().min(1),\n orgId: z.string().min(1),\n payload: z.string(),\n status: BufferEntryStatus,\n attempts: stringToInt,\n createdAt: stringToDate,\n // Microsecond epoch of accept time, kept as a hash field for dwell\n // metrics. Not a queue sort key (the queue is a FIFO LIST). Defaulted\n // so an entry written by an accept Lua predating this field — or one\n // surviving across the deploy that introduced it — still parses instead\n // of being silently dropped on pop.\n createdAtMicros: stringToInt.default(0),\n // Drainer-ack flag: `true` once the drainer has materialised this run\n // into PG. The hash persists for a short grace TTL after ack so direct\n // reads (retrieve, trace, etc.) still resolve while PG replica lag\n // settles. Absent on pre-ack entries.\n materialised: stringToBool.default(false),\n // Denormalised pointer to the Redis idempotency lookup key (set when\n // the run was accepted with an idempotency key, empty otherwise). The\n // ack Lua reads this to DEL the lookup atomically with marking the\n // entry materialised.\n idempotencyLookupKey: z.string().optional().default(\"\"),\n // Optimistic-lock counter for the snapshot's `metadata` field.\n // Incremented atomically by the CAS metadata Lua. Matches the\n // semantic of `TaskRun.metadataVersion` on the PG side (which the\n // UpdateMetadataService uses for the same retry-on-conflict pattern).\n metadataVersion: stringToInt.default(0),\n lastError: stringToError.optional(),\n});\n\nexport type BufferEntry = z.infer<typeof BufferEntrySchema>;\n\nexport function serialiseSnapshot(snapshot: unknown): string {\n return JSON.stringify(snapshot);\n}\n\nexport function deserialiseSnapshot<T = unknown>(serialised: string): T {\n return JSON.parse(serialised) as T;\n}\n","import {\n createRedisClient,\n type Callback,\n type Redis,\n type RedisOptions,\n type Result,\n} from \"@internal/redis\";\nimport { Logger } from \"@trigger.dev/core/logger\";\nimport type { BufferEntry } from \"./schemas.js\";\nimport { BufferEntrySchema } from \"./schemas.js\";\n\nexport type MollifierBufferOptions = {\n redisOptions: RedisOptions;\n logger?: Logger;\n // Grace TTL applied to the entry hash on drainer ack. The entry survives\n // this long after materialisation so direct reads (retrieve, trace, etc.)\n // have a safety net while PG replica lag settles. Defaults to 30s.\n ackGraceTtlSeconds?: number;\n // ioredis per-request retry limit on the buffer's Redis client. Defaults to 20.\n maxRetriesPerRequest?: number;\n // Reconnect backoff envelope (see `mollifierReconnectDelayMs`). Defaults\n // to 50ms per attempt capped at 1000ms.\n reconnectStepMs?: number;\n reconnectMaxMs?: number;\n};\n\n// Default grace TTL applied to the entry hash on drainer ack.\nconst DEFAULT_ACK_GRACE_TTL_SECONDS = 30;\n// Default ioredis reconnect backoff envelope for the buffer client.\nconst DEFAULT_RECONNECT_STEP_MS = 50;\nconst DEFAULT_RECONNECT_MAX_MS = 1000;\n// Default ioredis per-request retry limit.\nconst DEFAULT_MAX_RETRIES_PER_REQUEST = 20;\n\n// Observability-only sorted set of entries currently in DRAINING state\n// (popped by the drainer, not yet acked/failed/requeued). Score is the\n// pop wall-clock in milliseconds — `ZRANGEBYSCORE 0 <now-Xms>` gives\n// the entries stuck mid-drain for longer than X. NOT load-bearing for\n// correctness: the per-entry hash already carries `status` and the\n// stale-sweep would catch stranded entries via the queue LISTs. This\n// set is a fast top-level index for ops (gauge cardinality, post-crash\n// forensics after an ECS OOM) — see `mollifierDrainerWorker` for the\n// gauge wiring.\nexport const DRAINING_SET_KEY = \"mollifier:draining\";\n\n// ioredis reconnect backoff for the mollifier buffer client. The base\n// grows linearly with the attempt count and is capped at 1s (the same\n// envelope as the previous fixed `Math.min(times * 50, 1000)` schedule).\n// We then apply equal jitter — a uniform pick in `[base/2, base]` — so a\n// fleet of webapp instances reconnecting after the same Redis blip don't\n// retry in lockstep and stampede Redis on recovery (thundering herd).\n// Because the jittered value never exceeds the original cap, this is never\n// slower than before — just decorrelated. Mirrors the jittered-backoff\n// approach the mutate-fallback wait loop adopted for the same reason.\nexport function mollifierReconnectDelayMs(\n times: number,\n random: () => number = Math.random,\n stepMs: number = DEFAULT_RECONNECT_STEP_MS,\n maxMs: number = DEFAULT_RECONNECT_MAX_MS\n): number {\n const base = Math.min(times * stepMs, maxMs);\n const half = Math.floor(base / 2);\n return half + Math.round(random() * (base - half));\n}\n\nexport type SnapshotPatch =\n // `maxTags`, when set, caps the deduped tag count atomically inside the\n // Lua: if appending would push the snapshot over the limit the patch is\n // rejected (\"limit_exceeded\") and nothing is written, mirroring the\n // PG-path MAX_TAGS_PER_RUN check so a buffered run can't accumulate more\n // tags than the trigger validator would have allowed at creation.\n | { type: \"append_tags\"; tags: string[]; maxTags?: number }\n | { type: \"set_metadata\"; metadata: string; metadataType: string }\n | { type: \"set_delay\"; delayUntil: string }\n | { type: \"mark_cancelled\"; cancelledAt: string; cancelReason?: string };\n\nexport type MutateSnapshotResult = \"applied_to_snapshot\" | \"not_found\" | \"busy\" | \"limit_exceeded\";\n\nexport type CasSetMetadataResult =\n | { kind: \"applied\"; newVersion: number }\n | { kind: \"version_conflict\"; currentVersion: number }\n | { kind: \"not_found\" }\n | { kind: \"busy\" };\n\nexport type AcceptResult =\n | { kind: \"accepted\" }\n | { kind: \"duplicate_run_id\" }\n | { kind: \"duplicate_idempotency\"; existingRunId: string };\n\nexport type IdempotencyLookupInput = {\n envId: string;\n taskIdentifier: string;\n idempotencyKey: string;\n};\n\n// Reversible encoding for Redis-key segments. The composite-key builders\n// concatenate `envId`, `taskIdentifier`, and `idempotencyKey` with `:`\n// separators; if any segment contains a literal `:` (envId is internal\n// and `:`-free, but taskIdentifier and idempotencyKey are\n// customer-supplied) different tuples would map to the same Redis key\n// and dedupe the wrong run. base64url has no `:` in its alphabet and is\n// bijective on the input string, so the encoded keys are\n// collision-free.\nfunction encodeKeyPart(value: string): string {\n return Buffer.from(value, \"utf8\").toString(\"base64url\");\n}\n\n// Exported so tests can compute the same Redis key the buffer writes\n// without hard-coding the encoding (which is a buffer-internal detail).\nexport function idempotencyLookupKeyFor(input: IdempotencyLookupInput): string {\n return `mollifier:idempotency:${encodeKeyPart(input.envId)}:${encodeKeyPart(input.taskIdentifier)}:${encodeKeyPart(input.idempotencyKey)}`;\n}\n\n// Pre-gate claim key namespace, distinct from `mollifier:idempotency` so the\n// existing buffer-side dedup stays isolated. The claim is the\n// authoritative cross-store \"this idempotency key is in flight or\n// resolved\" pointer used by the trigger hot path. Values:\n// \"pending:<token>\" → claimed by a trigger pipeline; `<token>` is the\n// caller-supplied ownership token. Release and\n// publish compare-and-act on this token so a\n// late release from a previous claimant whose TTL\n// expired cannot erase a new owner's claim.\n// <runId> → the winning trigger's resolved runId.\nconst PENDING_PREFIX = \"pending:\";\n\n// Exported (like `idempotencyLookupKeyFor`) so tests can target the same\n// claim key the buffer writes without hard-coding the encoding.\nexport function makeIdempotencyClaimKey(input: IdempotencyLookupInput): string {\n return `mollifier:claim:${encodeKeyPart(input.envId)}:${encodeKeyPart(input.taskIdentifier)}:${encodeKeyPart(input.idempotencyKey)}`;\n}\n\nexport type IdempotencyClaimResult =\n | { kind: \"claimed\" }\n | { kind: \"pending\" }\n | { kind: \"resolved\"; runId: string };\n\nexport class MollifierBuffer {\n private readonly redis: Redis;\n private readonly logger: Logger;\n private readonly ackGraceTtlSeconds: number;\n\n constructor(options: MollifierBufferOptions) {\n this.logger = options.logger ?? new Logger(\"MollifierBuffer\", \"debug\");\n this.ackGraceTtlSeconds = options.ackGraceTtlSeconds ?? DEFAULT_ACK_GRACE_TTL_SECONDS;\n const reconnectStepMs = options.reconnectStepMs ?? DEFAULT_RECONNECT_STEP_MS;\n const reconnectMaxMs = options.reconnectMaxMs ?? DEFAULT_RECONNECT_MAX_MS;\n\n this.redis = createRedisClient(\n {\n ...options.redisOptions,\n retryStrategy(times) {\n return mollifierReconnectDelayMs(times, Math.random, reconnectStepMs, reconnectMaxMs);\n },\n maxRetriesPerRequest: options.maxRetriesPerRequest ?? DEFAULT_MAX_RETRIES_PER_REQUEST,\n },\n {\n onError: (error) => {\n this.logger.error(\"MollifierBuffer redis client error:\", { error });\n },\n }\n );\n this.#registerCommands();\n }\n\n // Three outcomes:\n // - { kind: \"accepted\" } — entry was newly written.\n // - { kind: \"duplicate_run_id\" } — runId was already buffered (idempotent\n // no-op, same semantic as the previous boolean-false return).\n // - { kind: \"duplicate_idempotency\", existingRunId } — the (env, task,\n // idempotencyKey) tuple was already bound to another buffered run.\n // The Lua's atomic SETNX is the race-winner; the second caller gets\n // the winner's runId so it can return that as the trigger response.\n async accept(input: {\n runId: string;\n envId: string;\n orgId: string;\n payload: string;\n // Optional idempotency-key triple. When all three are present we\n // SETNX a Redis lookup at `mollifier:idempotency:{env}:{task}:{key}`\n // pointing at the runId so trigger-time dedup during the buffered\n // window resolves the same way PG's unique constraint resolves it\n // post-materialisation.\n idempotencyKey?: string;\n taskIdentifier?: string;\n }): Promise<AcceptResult> {\n const entryKey = `mollifier:entries:${input.runId}`;\n const queueKey = `mollifier:queue:${input.envId}`;\n const orgsKey = \"mollifier:orgs\";\n const nowMs = Date.now();\n const createdAt = new Date(nowMs).toISOString();\n // Microsecond epoch, stored as a hash field for dwell-time metrics\n // (stale sweep, drainer dwell span). FIFO ordering comes from the\n // LIST itself (LPUSH head / RPOP tail), not from this value — it is\n // no longer a queue sort key.\n const createdAtMicros = nowMs * 1000;\n const idempotencyLookupKey =\n input.idempotencyKey && input.taskIdentifier\n ? idempotencyLookupKeyFor({\n envId: input.envId,\n taskIdentifier: input.taskIdentifier,\n idempotencyKey: input.idempotencyKey,\n })\n : \"\";\n const result = await this.redis.acceptMollifierEntry(\n entryKey,\n queueKey,\n orgsKey,\n input.runId,\n input.envId,\n input.orgId,\n input.payload,\n createdAt,\n String(createdAtMicros),\n \"mollifier:org-envs:\",\n idempotencyLookupKey,\n \"mollifier:entries:\"\n );\n // Lua returns 1 (accepted), 0 (duplicate runId), or a string runId\n // (duplicate idempotency — value is the existing winner's runId).\n if (typeof result === \"string\" && result.length > 0) {\n return { kind: \"duplicate_idempotency\", existingRunId: result };\n }\n if (result === 1) return { kind: \"accepted\" };\n return { kind: \"duplicate_run_id\" };\n }\n\n async pop(envId: string): Promise<BufferEntry | null> {\n const queueKey = `mollifier:queue:${envId}`;\n const orgsKey = \"mollifier:orgs\";\n const entryPrefix = \"mollifier:entries:\";\n const encoded = (await this.redis.popAndMarkDraining(\n queueKey,\n orgsKey,\n DRAINING_SET_KEY,\n entryPrefix,\n envId,\n \"mollifier:org-envs:\"\n )) as string | null;\n if (!encoded) return null;\n\n let raw: unknown;\n try {\n raw = JSON.parse(encoded);\n } catch {\n this.logger.error(\"MollifierBuffer.pop: failed to parse script result\", { envId });\n return null;\n }\n\n const parsed = BufferEntrySchema.safeParse(raw);\n if (!parsed.success) {\n this.logger.error(\"MollifierBuffer.pop: invalid entry shape\", {\n envId,\n errors: parsed.error.flatten(),\n });\n return null;\n }\n return parsed.data;\n }\n\n async getEntry(runId: string): Promise<BufferEntry | null> {\n const raw = await this.redis.hgetall(`mollifier:entries:${runId}`);\n if (!raw || Object.keys(raw).length === 0) return null;\n\n const parsed = BufferEntrySchema.safeParse(raw);\n if (!parsed.success) {\n this.logger.error(\"MollifierBuffer.getEntry: invalid entry shape\", {\n runId,\n errors: parsed.error.flatten(),\n });\n return null;\n }\n return parsed.data;\n }\n\n // Drainer walks these two methods to schedule pops with org-level\n // fairness: one env per org per tick. The Lua scripts maintain both\n // sets atomically with the per-env queues, so an org/env appears here\n // exactly when at least one of its envs has a queued entry.\n async listOrgs(): Promise<string[]> {\n return this.redis.smembers(\"mollifier:orgs\");\n }\n\n async listEnvsForOrg(orgId: string): Promise<string[]> {\n return this.redis.smembers(`mollifier:org-envs:${orgId}`);\n }\n\n // Read-only enumeration of currently-queued entries for a single env.\n // Used by the stale-sweep to compute per-entry dwell time, so order is\n // immaterial — LRANGE returns them newest-first (LPUSH head) but the\n // caller scans the whole window. Non-destructive: the drainer still\n // RPOPs these entries in FIFO order.\n //\n // The entry HGETALLs are issued in a single pipelined batch (one\n // network round-trip instead of N) — at the stale-sweep's default\n // maxCount=1000 the serial implementation cost ~1000 RTTs per env,\n // which dominated sweep wall-time at any meaningful backlog.\n //\n // A missing entry (empty hash) is skipped: the drainer's RPOP+DEL of\n // the entry hash can race our LRANGE→HGETALL window, so a runId on\n // the queue with no backing hash is an expected concurrency outcome,\n // not an error.\n async listEntriesForEnv(envId: string, maxCount: number): Promise<BufferEntry[]> {\n if (maxCount <= 0) return [];\n const runIds = await this.redis.lrange(`mollifier:queue:${envId}`, 0, maxCount - 1);\n if (runIds.length === 0) return [];\n\n const pipeline = this.redis.pipeline();\n for (const runId of runIds) {\n pipeline.hgetall(`mollifier:entries:${runId}`);\n }\n const results = await pipeline.exec();\n if (!results) return [];\n\n const entries: BufferEntry[] = [];\n for (let i = 0; i < results.length; i++) {\n const [err, raw] = results[i] as [Error | null, Record<string, string> | null];\n if (err) {\n this.logger.error(\"MollifierBuffer.listEntriesForEnv: hgetall failed\", {\n runId: runIds[i],\n err: err.message,\n });\n continue;\n }\n if (!raw || Object.keys(raw).length === 0) continue;\n const parsed = BufferEntrySchema.safeParse(raw);\n if (!parsed.success) {\n this.logger.error(\"MollifierBuffer.listEntriesForEnv: invalid entry shape\", {\n runId: runIds[i],\n errors: parsed.error.flatten(),\n });\n continue;\n }\n entries.push(parsed.data);\n }\n return entries;\n }\n\n // Atomic snapshot mutation. Used by customer-mutation API endpoints\n // (tags, metadata-put, reschedule, cancel) when the run is still in\n // the buffer. Three outcomes:\n // - \"applied_to_snapshot\": entry was QUEUED + not materialised; the\n // drainer will read the patched payload on its next pop.\n // - \"not_found\": no entry hash exists for this runId — including a\n // FAILED entry, whose hash the drainer-terminal `fail` path DELs.\n // - \"busy\": entry is DRAINING or materialised. The API\n // wait-and-bounces through PG.\n // - \"limit_exceeded\": an `append_tags` patch carrying `maxTags` would\n // push the deduped tag count over the cap; nothing is written.\n async mutateSnapshot(runId: string, patch: SnapshotPatch): Promise<MutateSnapshotResult> {\n const result = (await this.redis.mutateMollifierSnapshot(\n `mollifier:entries:${runId}`,\n JSON.stringify(patch)\n )) as string;\n if (\n result === \"applied_to_snapshot\" ||\n result === \"not_found\" ||\n result === \"busy\" ||\n result === \"limit_exceeded\"\n ) {\n return result;\n }\n throw new Error(`MollifierBuffer.mutateSnapshot: unexpected Lua return value: ${result}`);\n }\n\n // Optimistic compare-and-swap on the snapshot's metadata. Caller reads\n // the current metadataVersion via getEntry, applies operations in JS via\n // `applyMetadataOperations`, then calls this with the new metadata + the\n // expected version. Lua refuses if the version has moved (caller retries\n // up to N times). Mirrors the PG-side `UpdateMetadataService` retry\n // loop so concurrent increment/append operations don't lose deltas.\n async casSetMetadata(input: {\n runId: string;\n expectedVersion: number;\n newMetadata: string;\n newMetadataType: string;\n }): Promise<CasSetMetadataResult> {\n const entryKey = `mollifier:entries:${input.runId}`;\n const raw = (await this.redis.casSetMollifierMetadata(\n entryKey,\n String(input.expectedVersion),\n input.newMetadata,\n input.newMetadataType\n )) as string;\n if (raw === \"not_found\") return { kind: \"not_found\" };\n if (raw === \"busy\") return { kind: \"busy\" };\n if (raw.startsWith(\"conflict:\")) {\n return { kind: \"version_conflict\", currentVersion: Number(raw.slice(\"conflict:\".length)) };\n }\n if (raw.startsWith(\"applied:\")) {\n return { kind: \"applied\", newVersion: Number(raw.slice(\"applied:\".length)) };\n }\n throw new Error(`MollifierBuffer.casSetMetadata: unexpected Lua return: ${raw}`);\n }\n\n // Atomic pre-gate claim on a (env, task, idempotencyKey) tuple. One\n // call across both PG and buffer paths serialises through this claim;\n // closes the race the buffer-side SETNX leaves open during the\n // gate-transition burst window.\n //\n // The caller supplies an opaque `token` (UUID) on claim. The same token\n // MUST be passed to `publishClaim` / `releaseClaim`, which compare-and-\n // act so a late release from a previous claimant whose TTL expired\n // cannot erase a new owner's claim.\n //\n // - \"claimed\": we now own the claim, the caller proceeds with the\n // trigger pipeline and must `publishClaim` on success or\n // `releaseClaim` on failure.\n // - \"pending\": another trigger owns the claim and hasn't published\n // yet; the caller should poll.\n // - \"resolved\": the claim already holds a runId; the caller can\n // return that runId as a cached hit.\n async claimIdempotency(\n input: IdempotencyLookupInput & { token: string; ttlSeconds: number }\n ): Promise<IdempotencyClaimResult> {\n const claimKey = makeIdempotencyClaimKey(input);\n const raw = (await this.redis.claimMollifierIdempotency(\n claimKey,\n `${PENDING_PREFIX}${input.token}`,\n PENDING_PREFIX,\n String(input.ttlSeconds)\n )) as string;\n if (raw === \"claimed\") return { kind: \"claimed\" };\n if (raw === \"pending\") return { kind: \"pending\" };\n if (raw.startsWith(\"resolved:\")) {\n return { kind: \"resolved\", runId: raw.slice(\"resolved:\".length) };\n }\n throw new Error(`MollifierBuffer.claimIdempotency: unexpected return: ${raw}`);\n }\n\n // Publish the winning runId to the claim so subsequent claimants /\n // waiters see \"resolved\". TTL bounded by the customer's\n // `idempotencyKeyExpiresAt` minus now; caller computes.\n //\n // Compare-and-set on the caller's token: if the current value isn't\n // our pending marker (TTL expired and another claimant moved in, or\n // someone else already published), the publish is a no-op. The caller\n // can treat any such case as \"we lost the claim\" and re-read.\n // Returns true if we published; false if the claim slot was no longer\n // ours.\n async publishClaim(\n input: IdempotencyLookupInput & { token: string; runId: string; ttlSeconds: number }\n ): Promise<boolean> {\n const claimKey = makeIdempotencyClaimKey(input);\n const result = (await this.redis.publishMollifierClaim(\n claimKey,\n `${PENDING_PREFIX}${input.token}`,\n input.runId,\n String(input.ttlSeconds)\n )) as number;\n return result === 1;\n }\n\n // Release the claim on pipeline error so waiters can re-claim and\n // retry. Idempotent.\n //\n // Compare-and-delete on the caller's token: only deletes if the\n // current value is exactly our pending marker. A late release from a\n // claimant whose TTL expired is a no-op, so a new owner's claim is\n // never wiped by a slow predecessor.\n async releaseClaim(input: IdempotencyLookupInput & { token: string }): Promise<void> {\n const claimKey = makeIdempotencyClaimKey(input);\n await this.redis.releaseMollifierClaim(claimKey, `${PENDING_PREFIX}${input.token}`);\n }\n\n // Reopen a RESOLVED claim slot whose winner was cleared, so the claim-loser\n // reacquire path can re-serialise a cross-DB recreate through a fresh claim.\n // Compare-and-delete on the observed `expectedRunId` (never an unconditional\n // DEL) so a concurrent reacquirer that already re-published a NEW winner is\n // never wiped. Reuses the lookup self-heal's compare-and-delete Lua. Returns\n // true if the stale slot was cleared.\n async resetResolvedClaim(\n input: IdempotencyLookupInput & { expectedRunId: string }\n ): Promise<boolean> {\n const claimKey = makeIdempotencyClaimKey(input);\n const deleted = (await this.redis.delMollifierKeyIfEquals(\n claimKey,\n input.expectedRunId\n )) as number;\n return deleted === 1;\n }\n\n // Read the current claim value, used by the wait/poll loop on losers\n // to detect \"pending\" → \"resolved\" transitions and timeouts.\n async readClaim(input: IdempotencyLookupInput): Promise<IdempotencyClaimResult | null> {\n const claimKey = makeIdempotencyClaimKey(input);\n const value = await this.redis.get(claimKey);\n if (value === null) return null;\n if (value.startsWith(PENDING_PREFIX)) return { kind: \"pending\" };\n return { kind: \"resolved\", runId: value };\n }\n\n // Resolve a buffered run by (env, task, idempotencyKey) tuple. Used by\n // `IdempotencyKeyConcern.handleTriggerRequest` after the PG check\n // misses — same key may belong to a buffered run waiting to drain. The\n // lookup self-heals: if the lookup points at an entry hash that's gone,\n // we clear the lookup and report a miss. The clear is a compare-and-\n // delete (only if the key still holds the stale runId we observed) so a\n // fresh accept that rebinds the key between our GET and DEL isn't wiped.\n async lookupIdempotency(input: IdempotencyLookupInput): Promise<string | null> {\n const lookupKey = idempotencyLookupKeyFor(input);\n const runId = await this.redis.get(lookupKey);\n if (!runId) return null;\n const entry = await this.getEntry(runId);\n if (!entry) {\n await this.redis.delMollifierKeyIfEquals(lookupKey, runId);\n return null;\n }\n return runId;\n }\n\n // Clear the idempotency binding from a buffered run. Used by\n // `ResetIdempotencyKeyService` alongside the existing PG-side\n // `updateMany`. Returns the runId that was cleared, or null if no\n // buffered run held this key.\n async resetIdempotency(input: IdempotencyLookupInput): Promise<{ clearedRunId: string | null }> {\n const lookupKey = idempotencyLookupKeyFor(input);\n const claimKey = makeIdempotencyClaimKey(input);\n const clearedRunId = (await this.redis.resetMollifierIdempotency(\n lookupKey,\n \"mollifier:entries:\",\n claimKey\n )) as string;\n return { clearedRunId: clearedRunId.length > 0 ? clearedRunId : null };\n }\n\n // Marks the entry as materialised (PG row written) and resets its TTL to\n // the grace window. Entry hash persists past ack as a read-fallback\n // safety net for the brief PG replica-lag window between drainer-side\n // write and reader-side visibility. Also clears the associated\n // idempotency lookup if one was set on accept.\n async ack(runId: string): Promise<void> {\n await this.redis.ackMollifierEntry(\n `mollifier:entries:${runId}`,\n DRAINING_SET_KEY,\n String(this.ackGraceTtlSeconds),\n runId\n );\n }\n\n async requeue(runId: string): Promise<void> {\n await this.redis.requeueMollifierEntry(\n `mollifier:entries:${runId}`,\n \"mollifier:orgs\",\n DRAINING_SET_KEY,\n \"mollifier:queue:\",\n runId,\n \"mollifier:org-envs:\"\n );\n }\n\n // Returns true if a live entry was torn down; false if the entry no\n // longer existed (a concurrent ack or manual cleanup removed it between\n // pop and fail — there is no accept-time TTL). Note FAILED is not an\n // observable state: the Lua marks the hash FAILED then DELs it in the\n // same atomic script, so a subsequent getEntry returns null. Caller can\n // use the boolean to skip downstream FAILED handling for ghost entries.\n async fail(runId: string, error: { code: string; message: string }): Promise<boolean> {\n const result = await this.redis.failMollifierEntry(\n `mollifier:entries:${runId}`,\n DRAINING_SET_KEY,\n JSON.stringify(error),\n runId\n );\n return result === 1;\n }\n\n // Observability-only: number of entries currently in DRAINING state\n // (popped, not yet acked/failed/requeued). The gauge in the webapp\n // drainer worker polls this on a short interval and emits it as\n // `mollifier.draining.current` for ops dashboards and post-crash\n // forensics. Cheap (single ZCARD).\n async getDrainingCount(): Promise<number> {\n return this.redis.zcard(DRAINING_SET_KEY);\n }\n\n // Observability-only: list runIds that have been DRAINING longer than\n // `olderThanMs` (i.e. popped before `now - olderThanMs`). Bounded by\n // `limit` to keep the result set tractable when something has gone\n // very wrong. ZRANGEBYSCORE is O(log N + K). Score is the pop wall-clock\n // in milliseconds as written by the popAndMarkDraining Lua.\n async listStaleDraining(olderThanMs: number, limit: number): Promise<string[]> {\n const maxScore = Date.now() - Math.max(0, olderThanMs);\n return this.redis.zrangebyscore(\n DRAINING_SET_KEY,\n \"-inf\",\n String(maxScore),\n \"LIMIT\",\n 0,\n Math.max(0, limit)\n );\n }\n\n // Returns Redis-side TTL on the entry hash. Returns -1 for entries\n // with no TTL — the steady state under the current design, where\n // entries persist until drainer ack/fail. The ack grace TTL (30s\n // post-materialise) is the only context where this returns a\n // positive value; tests around the grace TTL still rely on it.\n async getEntryTtlSeconds(runId: string): Promise<number> {\n return this.redis.ttl(`mollifier:entries:${runId}`);\n }\n\n async evaluateTrip(\n envId: string,\n options: { windowMs: number; threshold: number; holdMs: number }\n ): Promise<{ tripped: boolean; count: number }> {\n const rateKey = `mollifier:rate:${envId}`;\n const trippedKey = `mollifier:tripped:${envId}`;\n const result = (await this.redis.mollifierEvaluateTrip(\n rateKey,\n trippedKey,\n String(options.windowMs),\n String(options.threshold),\n String(options.holdMs)\n )) as [number, number];\n\n return { count: result[0], tripped: result[1] === 1 };\n }\n\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n #registerCommands() {\n this.redis.defineCommand(\"acceptMollifierEntry\", {\n numberOfKeys: 3,\n lua: `\n local entryKey = KEYS[1]\n local queueKey = KEYS[2]\n local orgsKey = KEYS[3]\n local runId = ARGV[1]\n local envId = ARGV[2]\n local orgId = ARGV[3]\n local payload = ARGV[4]\n local createdAt = ARGV[5]\n local createdAtMicros = ARGV[6]\n local orgEnvsPrefix = ARGV[7]\n local idempotencyLookupKey = ARGV[8] or ''\n local entryPrefix = ARGV[9]\n\n -- Idempotent: refuse if an entry for this runId already exists in any\n -- state. Caller-side dedup is also enforced via API idempotency keys,\n -- but the buffer must not double-enqueue if a caller retries.\n if redis.call('EXISTS', entryKey) == 1 then\n return 0\n end\n\n -- Idempotency-key dedup. If the caller passed a lookup key\n -- and it's already bound to another buffered run, return the\n -- winner's runId so the loser's API response can echo it as a\n -- cached hit. Otherwise SET the lookup (no TTL — lifecycle is\n -- paired with the entry hash; drainer ack/fail clear it\n -- explicitly).\n if idempotencyLookupKey ~= '' then\n local existing = redis.call('GET', idempotencyLookupKey)\n if existing then\n -- Self-heal: only honour the binding if its entry hash still\n -- exists. If the entry was evicted (maxmemory) but the lookup\n -- survived, the binding is stale — fall through and rebind to\n -- this run rather than returning a dead runId that would block\n -- the key indefinitely. Mirrors lookupIdempotency's self-heal.\n if redis.call('EXISTS', entryPrefix .. existing) == 1 then\n return existing\n end\n end\n redis.call('SET', idempotencyLookupKey, runId)\n end\n\n redis.call('HSET', entryKey,\n 'runId', runId,\n 'envId', envId,\n 'orgId', orgId,\n 'payload', payload,\n 'status', 'QUEUED',\n 'attempts', '0',\n 'createdAt', createdAt,\n 'createdAtMicros', createdAtMicros,\n 'idempotencyLookupKey', idempotencyLookupKey,\n 'metadataVersion', '0')\n -- No EXPIRE on the entry hash. Buffer entries persist until the\n -- drainer ACKs (post-materialise grace) or FAILs them — the\n -- drainer is the only recovery mechanism, so silent TTL-based\n -- eviction would lose runs with no customer-visible signal.\n -- Memory pressure from an offline drainer is the alertable\n -- failure mode instead; see _ops/mollifier-ops.md.\n -- LIST queue: LPUSH at the head, drainer RPOPs from the tail, so\n -- insertion order == drain order (FIFO). createdAtMicros is kept\n -- as a hash field for dwell metrics only — it is no longer a sort\n -- key now that the buffer has no list/pagination surface.\n redis.call('LPUSH', queueKey, runId)\n -- Org-level membership: maintained atomically with the per-env\n -- queue so the drainer can walk orgs → envs-for-org and\n -- schedule one env per org per tick. SADDs are idempotent if the\n -- org/env are already tracked.\n redis.call('SADD', orgsKey, orgId)\n redis.call('SADD', orgEnvsPrefix .. orgId, envId)\n return 1\n `,\n });\n\n this.redis.defineCommand(\"requeueMollifierEntry\", {\n numberOfKeys: 3,\n lua: `\n local entryKey = KEYS[1]\n local orgsKey = KEYS[2]\n local drainingSetKey = KEYS[3]\n local queuePrefix = ARGV[1]\n local runId = ARGV[2]\n local orgEnvsPrefix = ARGV[3]\n\n local envId = redis.call('HGET', entryKey, 'envId')\n local orgId = redis.call('HGET', entryKey, 'orgId')\n if not envId then\n return 0\n end\n\n local currentAttempts = redis.call('HGET', entryKey, 'attempts')\n local nextAttempts = tonumber(currentAttempts or '0') + 1\n\n redis.call('HSET', entryKey, 'status', 'QUEUED', 'attempts', tostring(nextAttempts))\n -- Requeue RPUSHes to the tail (the RPOP end) so a transiently\n -- failed entry pops next rather than going to the back of the\n -- line behind a fresh backlog. createdAt is immutable across\n -- retries; the drainer's maxAttempts caps the\n -- retry loop so a poisoned entry doesn't head-of-line forever.\n redis.call('RPUSH', queuePrefix .. envId, runId)\n -- Re-track the org/env: pop may have SREM'd them when the queue\n -- last emptied. SADDs are idempotent if the values are still\n -- present.\n if orgId then\n redis.call('SADD', orgsKey, orgId)\n redis.call('SADD', orgEnvsPrefix .. orgId, envId)\n end\n -- Observability-only: leaving DRAINING state, so drop the\n -- entry from the draining-tracker set. ZREM on absent member\n -- is a no-op.\n redis.call('ZREM', drainingSetKey, runId)\n return 1\n `,\n });\n\n this.redis.defineCommand(\"popAndMarkDraining\", {\n numberOfKeys: 3,\n lua: `\n local queueKey = KEYS[1]\n local orgsKey = KEYS[2]\n local drainingSetKey = KEYS[3]\n local entryPrefix = ARGV[1]\n local envId = ARGV[2]\n local orgEnvsPrefix = ARGV[3]\n\n -- Wall-clock millis used as the ZADD score on the draining-tracker\n -- set. Computed once per script invocation so all observers see\n -- the same pop instant. redis.call('TIME') is deterministic per\n -- script execution (Lua sees it as a single read), satisfying the\n -- write-determinism contract on replicas/AOF replay.\n local timeArr = redis.call('TIME')\n local nowMs = tonumber(timeArr[1]) * 1000 + math.floor(tonumber(timeArr[2]) / 1000)\n\n -- Helper: prune org-level membership when an env's queue empties.\n -- Called only from the success branch where we know orgId from the\n -- popped entry. The no-runId branch below can't reach this because\n -- it has no entry to read orgId from — accept any stale org-envs\n -- entries that result (bounded by env count, recovered next accept).\n local function pruneOrgMembership(orgId)\n if not orgId then return end\n local orgEnvsKey = orgEnvsPrefix .. orgId\n redis.call('SREM', orgEnvsKey, envId)\n if redis.call('SCARD', orgEnvsKey) == 0 then\n redis.call('SREM', orgsKey, orgId)\n end\n end\n\n -- Loop to skip orphan queue references — runIds whose entry hash is\n -- gone (e.g. Redis maxmemory eviction, since QUEUED entries carry\n -- no TTL of their own). HSET on a missing key would CREATE a\n -- partial hash without a TTL, leaking memory. The loop is bounded\n -- by queue length; entire Lua script remains atomic.\n while true do\n -- RPOP returns the tail member (oldest, FIFO), or false when empty.\n local runId = redis.call('RPOP', queueKey)\n if not runId then\n -- Queue is empty AND we have no entry to read orgId from, so\n -- skip org-level cleanup. Stale org-envs entries are bounded\n -- by env count and recovered on the next accept.\n return nil\n end\n\n local entryKey = entryPrefix .. runId\n if redis.call('EXISTS', entryKey) == 1 then\n redis.call('HSET', entryKey, 'status', 'DRAINING')\n -- Observability-only: track the runId in the draining set\n -- with the pop wall-clock as score. Acked/failed/requeued\n -- in the corresponding Lua scripts. The set is NOT\n -- load-bearing for correctness — the per-entry hash carries\n -- status — so a missed ZREM on a partial Lua execution is\n -- recoverable via the stale-sweep + entry hash, not a\n -- correctness bug.\n redis.call('ZADD', drainingSetKey, nowMs, runId)\n local raw = redis.call('HGETALL', entryKey)\n local result = {}\n for i = 1, #raw, 2 do\n result[raw[i]] = raw[i + 1]\n end\n -- Prune org-level membership if this pop drained the queue.\n -- Atomic with the RPOP above — a concurrent accept AFTER\n -- this script will SADD both back along with its LPUSH.\n if redis.call('LLEN', queueKey) == 0 then\n pruneOrgMembership(result['orgId'])\n end\n return cjson.encode(result)\n end\n -- Orphan queue reference: entry hash gone (evicted) while runId\n -- was queued. Discard the reference and loop to the next.\n end\n `,\n });\n\n this.redis.defineCommand(\"casSetMollifierMetadata\", {\n numberOfKeys: 1,\n lua: `\n local entryKey = KEYS[1]\n local expectedVersion = tonumber(ARGV[1])\n local newMetadata = ARGV[2]\n local newMetadataType = ARGV[3]\n\n if redis.call('EXISTS', entryKey) == 0 then\n return 'not_found'\n end\n\n local status = redis.call('HGET', entryKey, 'status')\n local materialised = redis.call('HGET', entryKey, 'materialised')\n if status ~= 'QUEUED' or materialised == 'true' then\n return 'busy'\n end\n\n local currentVersionStr = redis.call('HGET', entryKey, 'metadataVersion') or '0'\n local currentVersion = tonumber(currentVersionStr) or 0\n if currentVersion ~= expectedVersion then\n return 'conflict:' .. tostring(currentVersion)\n end\n\n -- Write the new metadata onto the snapshot's payload JSON. We\n -- keep the rest of the payload intact — only metadata/metadataType\n -- change. metadataVersion is denormalised on the hash for cheap\n -- CAS reads; it's intentionally NOT stored inside the payload\n -- itself (PG-side metadataVersion is a column, not a JSON field).\n local payloadJson = redis.call('HGET', entryKey, 'payload')\n local ok, payload = pcall(cjson.decode, payloadJson)\n if not ok then return 'busy' end\n payload.metadata = newMetadata\n payload.metadataType = newMetadataType\n\n local newVersion = currentVersion + 1\n redis.call('HSET', entryKey,\n 'payload', cjson.encode(payload),\n 'metadataVersion', tostring(newVersion))\n return 'applied:' .. tostring(newVersion)\n `,\n });\n\n this.redis.defineCommand(\"claimMollifierIdempotency\", {\n numberOfKeys: 1,\n lua: `\n local claimKey = KEYS[1]\n local pendingMarker = ARGV[1] -- \"pending:<caller-token>\"\n local pendingPrefix = ARGV[2] -- \"pending:\"\n local ttl = tonumber(ARGV[3])\n\n -- SETNX-with-TTL: atomic; only one caller can win.\n local won = redis.call('SET', claimKey, pendingMarker, 'NX', 'EX', ttl)\n if won then\n return 'claimed'\n end\n\n local existing = redis.call('GET', claimKey)\n if not existing then\n -- The slot expired in the race window between the SET NX\n -- failing and this GET. It's free now — claim it so we don't\n -- string.sub a nil and error out.\n redis.call('SET', claimKey, pendingMarker, 'EX', ttl)\n return 'claimed'\n end\n -- Any \"pending:*\" value is a live claim — the caller-supplied\n -- token differentiates ownership but is opaque to losers.\n if string.sub(existing, 1, string.len(pendingPrefix)) == pendingPrefix then\n return 'pending'\n end\n return 'resolved:' .. existing\n `,\n });\n\n // Publish a winning runId to a claim slot we own. Compare-and-set on\n // the caller's pending marker: if the slot is no longer ours (TTL\n // expired and another claimant moved in, or already resolved by\n // someone else), we no-op. Returns 1 on publish, 0 on no-op.\n this.redis.defineCommand(\"publishMollifierClaim\", {\n numberOfKeys: 1,\n lua: `\n local claimKey = KEYS[1]\n local ownerMarker = ARGV[1] -- \"pending:<our-token>\"\n local runId = ARGV[2]\n local ttl = tonumber(ARGV[3])\n\n local existing = redis.call('GET', claimKey)\n if existing == ownerMarker then\n redis.call('SET', claimKey, runId, 'EX', ttl)\n return 1\n end\n return 0\n `,\n });\n\n // Release a claim slot we own. Compare-and-delete on the caller's\n // pending marker: a late release from a previous claimant whose TTL\n // expired is a no-op, so a new owner's claim is never wiped.\n this.redis.defineCommand(\"releaseMollifierClaim\", {\n numberOfKeys: 1,\n lua: `\n local claimKey = KEYS[1]\n local ownerMarker = ARGV[1] -- \"pending:<our-token>\"\n\n local existing = redis.call('GET', claimKey)\n if existing == ownerMarker then\n redis.call('DEL', claimKey)\n return 1\n end\n return 0\n `,\n });\n\n this.redis.defineCommand(\"resetMollifierIdempotency\", {\n numberOfKeys: 1,\n lua: `\n local lookupKey = KEYS[1]\n local entryPrefix = ARGV[1]\n local claimKey = ARGV[2]\n\n -- Reset reopens the key across BOTH the buffer lookup and the\n -- cross-store pre-gate claim pointer. Without clearing the claim,\n -- a resolved/pending claim would keep deduping new triggers for\n -- the rest of its TTL even though the binding was reset. DEL is\n -- unconditional — the claim is gone regardless of whether a\n -- buffered run currently holds the lookup.\n redis.call('DEL', claimKey)\n\n local runId = redis.call('GET', lookupKey)\n if not runId then\n return ''\n end\n\n local entryKey = entryPrefix .. runId\n if redis.call('EXISTS', entryKey) == 0 then\n -- Stale lookup. Lazy cleanup.\n redis.call('DEL', lookupKey)\n return ''\n end\n\n -- Clear the idempotency fields on the snapshot payload so the\n -- drainer's eventual engine.trigger call inserts a PG row\n -- without the key set.\n local payloadJson = redis.call('HGET', entryKey, 'payload')\n if payloadJson then\n local ok, payload = pcall(cjson.decode, payloadJson)\n if ok then\n payload.idempotencyKey = cjson.null\n payload.idempotencyKeyExpiresAt = cjson.null\n redis.call('HSET', entryKey, 'payload', cjson.encode(payload))\n end\n end\n -- Clear the denormalised lookup pointer on the hash so a later\n -- ack doesn't try to DEL a key that's already gone.\n redis.call('HSET', entryKey, 'idempotencyLookupKey', '')\n redis.call('DEL', lookupKey)\n return runId\n `,\n });\n\n this.redis.defineCommand(\"mutateMollifierSnapshot\", {\n numberOfKeys: 1,\n lua: `\n local entryKey = KEYS[1]\n local patchJson = ARGV[1]\n\n if redis.call('EXISTS', entryKey) == 0 then\n return 'not_found'\n end\n\n local status = redis.call('HGET', entryKey, 'status')\n local materialised = redis.call('HGET', entryKey, 'materialised')\n if status ~= 'QUEUED' or materialised == 'true' then\n return 'busy'\n end\n\n local payloadJson = redis.call('HGET', entryKey, 'payload')\n local ok, payload = pcall(cjson.decode, payloadJson)\n if not ok then return 'busy' end\n\n local patch = cjson.decode(patchJson)\n\n if patch.type == 'append_tags' then\n -- cjson decode of an absent or empty-array field gives nil or\n -- an empty table; we rebuild as a dense array. Existing tags\n -- are preserved; new tags are appended only if not present.\n local existing = payload.tags or {}\n local seen = {}\n local merged = {}\n for _, t in ipairs(existing) do\n if not seen[t] then\n seen[t] = true\n table.insert(merged, t)\n end\n end\n for _, t in ipairs(patch.tags or {}) do\n if not seen[t] then\n seen[t] = true\n table.insert(merged, t)\n end\n end\n -- Cap the deduped count when the caller supplies a limit, so a\n -- buffered run can't exceed MAX_TAGS_PER_RUN via the tags API.\n -- Reject the whole patch (write nothing) rather than truncating.\n if patch.maxTags ~= nil and #merged > patch.maxTags then\n return 'limit_exceeded'\n end\n payload.tags = merged\n elseif patch.type == 'set_metadata' then\n payload.metadata = patch.metadata\n payload.metadataType = patch.metadataType\n -- Bump the denormalised metadataVersion so an in-flight\n -- casSetMetadata (optimistic CAS keyed on this counter) sees\n -- the concurrent write as a version conflict and retries,\n -- instead of clobbering it under a now-stale expectedVersion.\n local currentVersion = tonumber(redis.call('HGET', entryKey, 'metadataVersion') or '0') or 0\n redis.call('HSET', entryKey, 'metadataVersion', tostring(currentVersion + 1))\n elseif patch.type == 'set_delay' then\n payload.delayUntil = patch.delayUntil\n elseif patch.type == 'mark_cancelled' then\n payload.cancelledAt = patch.cancelledAt\n payload.cancelReason = patch.cancelReason\n else\n return 'busy'\n end\n\n redis.call('HSET', entryKey, 'payload', cjson.encode(payload))\n return 'applied_to_snapshot'\n `,\n });\n\n this.redis.defineCommand(\"ackMollifierEntry\", {\n numberOfKeys: 2,\n lua: `\n local entryKey = KEYS[1]\n local drainingSetKey = KEYS[2]\n local graceTtlSeconds = tonumber(ARGV[1])\n local runId = ARGV[2]\n\n -- Always ZREM from the draining-tracker — even if the entry hash\n -- has been concurrently torn down, the runId might still be in\n -- the set (e.g. fail() ran first and cleared the hash but a\n -- delayed ack races in). Idempotent: ZREM on absent is a no-op.\n redis.call('ZREM', drainingSetKey, runId)\n\n -- Guard: never create a partial entry. If the hash is gone between\n -- pop and ack (concurrent fail or eviction — QUEUED entries carry\n -- no TTL), the run is gone, nothing to mark materialised.\n if redis.call('EXISTS', entryKey) == 0 then\n return 0\n end\n\n -- If the entry was accepted with an idempotency key, the lookup\n -- string was stored on the hash at accept time. Clear it now —\n -- PG becomes canonical for the key post-materialisation.\n local lookupKey = redis.call('HGET', entryKey, 'idempotencyLookupKey')\n if lookupKey and lookupKey ~= '' then\n redis.call('DEL', lookupKey)\n end\n\n redis.call('HSET', entryKey, 'materialised', 'true')\n redis.call('EXPIRE', entryKey, graceTtlSeconds)\n return 1\n `,\n });\n\n this.redis.defineCommand(\"failMollifierEntry\", {\n numberOfKeys: 2,\n lua: `\n local entryKey = KEYS[1]\n local drainingSetKey = KEYS[2]\n local errorPayload = ARGV[1]\n local runId = ARGV[2]\n\n -- Always ZREM from the draining-tracker (idempotent on absent).\n -- Mirrors ack: the runId may be in the set even if the entry hash\n -- has been raced away.\n redis.call('ZREM', drainingSetKey, runId)\n\n -- Guard: nothing to mark FAILED if the hash is gone (concurrent\n -- ack/manual cleanup). Returning 0 lets the caller distinguish\n -- \"marked failed\" from \"no-op\".\n if redis.call('EXISTS', entryKey) == 0 then\n return 0\n end\n\n redis.call('HSET', entryKey, 'status', 'FAILED', 'lastError', errorPayload)\n\n -- Terminal-failure contract: the drainer's onTerminalFailure\n -- callback (see MollifierDrainer.processEntry) has been\n -- invoked before this fail() and has either written a\n -- SYSTEM_FAILURE PG row (for both non-retryable AND\n -- max-attempts-exhausted retryable errors) or chosen to fall\n -- through (genuinely bad snapshot the engine can't materialise\n -- a row from). Either way the buffer entry is no longer\n -- load-bearing here. Clear the idempotency lookup -- PG's\n -- unique constraint is the canonical dedup mechanism\n -- post-materialise -- and drop the entry hash so failed runs\n -- don't accrete forever now that there's no accept-time TTL.\n local lookupKey = redis.call('HGET', entryKey, 'idempotencyLookupKey')\n if lookupKey and lookupKey ~= '' then\n redis.call('DEL', lookupKey)\n end\n redis.call('DEL', entryKey)\n return 1\n `,\n });\n\n // Compare-and-delete: DEL the key only if it still holds the expected\n // value. Used by lookupIdempotency's stale-lookup self-heal so a\n // concurrent accept that rebinds the key between the reader's GET and\n // this DEL isn't clobbered.\n this.redis.defineCommand(\"delMollifierKeyIfEquals\", {\n numberOfKeys: 1,\n lua: `\n if redis.call('GET', KEYS[1]) == ARGV[1] then\n return redis.call('DEL', KEYS[1])\n end\n return 0\n `,\n });\n\n this.redis.defineCommand(\"mollifierEvaluateTrip\", {\n numberOfKeys: 2,\n lua: `\n local rateKey = KEYS[1]\n local trippedKey = KEYS[2]\n local windowMs = tonumber(ARGV[1])\n local threshold = tonumber(ARGV[2])\n local holdMs = tonumber(ARGV[3])\n\n local count = redis.call('INCR', rateKey)\n if count == 1 then\n redis.call('PEXPIRE', rateKey, windowMs)\n end\n\n if count > threshold then\n redis.call('PSETEX', trippedKey, holdMs, '1')\n end\n\n local tripped = redis.call('EXISTS', trippedKey)\n return {count, tripped}\n `,\n });\n }\n}\n\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n acceptMollifierEntry(\n entryKey: string,\n queueKey: string,\n orgsKey: string,\n runId: string,\n envId: string,\n orgId: string,\n payload: string,\n createdAt: string,\n createdAtMicros: string,\n orgEnvsPrefix: string,\n idempotencyLookupKey: string,\n entryPrefix: string,\n callback?: Callback<number | string>\n ): Result<number | string, Context>;\n popAndMarkDraining(\n queueKey: string,\n orgsKey: string,\n drainingSetKey: string,\n entryPrefix: string,\n envId: string,\n orgEnvsPrefix: string,\n callback?: Callback<string | null>\n ): Result<string | null, Context>;\n requeueMollifierEntry(\n entryKey: string,\n orgsKey: string,\n drainingSetKey: string,\n queuePrefix: string,\n runId: string,\n orgEnvsPrefix: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n mutateMollifierSnapshot(\n entryKey: string,\n patchJson: string,\n callback?: Callback<string>\n ): Result<string, Context>;\n casSetMollifierMetadata(\n entryKey: string,\n expectedVersion: string,\n newMetadata: string,\n newMetadataType: string,\n callback?: Callback<string>\n ): Result<string, Context>;\n resetMollifierIdempotency(\n lookupKey: string,\n entryPrefix: string,\n claimKey: string,\n callback?: Callback<string>\n ): Result<string, Context>;\n claimMollifierIdempotency(\n claimKey: string,\n pendingMarker: string,\n pendingPrefix: string,\n ttlSeconds: string,\n callback?: Callback<string>\n ): Result<string, Context>;\n publishMollifierClaim(\n claimKey: string,\n ownerMarker: string,\n runId: string,\n ttlSeconds: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n releaseMollifierClaim(\n claimKey: string,\n ownerMarker: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n ackMollifierEntry(\n entryKey: string,\n drainingSetKey: string,\n graceTtlSeconds: string,\n runId: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n failMollifierEntry(\n entryKey: string,\n drainingSetKey: string,\n errorPayload: string,\n runId: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n delMollifierKeyIfEquals(\n key: string,\n expected: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n mollifierEvaluateTrip(\n rateKey: string,\n trippedKey: string,\n windowMs: string,\n threshold: string,\n holdMs: string,\n callback?: Callback<[number, number]>\n ): Result<[number, number], Context>;\n }\n}\n","import { Logger } from \"@trigger.dev/core/logger\";\nimport type { MollifierBuffer } from \"./buffer.js\";\nimport type { BufferEntry } from \"./schemas.js\";\nimport { deserialiseSnapshot } from \"./schemas.js\";\n\nexport type MollifierDrainerHandler<TPayload> = (input: {\n runId: string;\n envId: string;\n orgId: string;\n payload: TPayload;\n attempts: number;\n createdAt: Date;\n}) => Promise<void>;\n\n// Invoked once per entry before `buffer.fail()` on any terminal path —\n// non-retryable error OR retryable error after maxAttempts. Lets the caller\n// land a SYSTEM_FAILURE PG row so the customer sees the run instead of it\n// silently disappearing alongside the buffer entry. Throwing a retryable\n// error from the callback causes the drainer to requeue rather than fail\n// (so the PG write itself gets another chance once PG recovers); throwing\n// anything else falls through to `buffer.fail()` to avoid an infinite loop\n// on a genuinely bad payload.\nexport type MollifierDrainerTerminalFailureCause = \"non-retryable\" | \"max-attempts-exhausted\";\nexport type MollifierDrainerTerminalFailureHandler<TPayload> = (input: {\n runId: string;\n envId: string;\n orgId: string;\n payload: TPayload;\n attempts: number;\n createdAt: Date;\n error: { code: string; message: string };\n cause: MollifierDrainerTerminalFailureCause;\n}) => Promise<void>;\n\nexport type MollifierDrainerOptions<TPayload> = {\n buffer: MollifierBuffer;\n handler: MollifierDrainerHandler<TPayload>;\n onTerminalFailure?: MollifierDrainerTerminalFailureHandler<TPayload>;\n concurrency: number;\n maxAttempts: number;\n isRetryable: (err: unknown) => boolean;\n pollIntervalMs?: number;\n // Cap on how many ORGS `runOnce` processes per tick. The drainer rotates\n // through orgs at the top level and picks one env per org per tick, so\n // the actual per-tick pop count is at most `maxOrgsPerTick`. Tune for\n // \"typical orgs with pending entries\" rather than total system org\n // count. Defaults to 500.\n //\n // The buffer maintains `mollifier:orgs` and `mollifier:org-envs:${orgId}`\n // atomically with per-env queues, so the drainer can walk orgs → envs\n // directly. An org with N envs gets the same per-tick scheduling slot\n // as an org with 1 env — tenant-level drainage throughput is determined\n // by org count, not env count.\n maxOrgsPerTick?: number;\n // Per-env per-tick pop cap. Default 1 preserves the original\n // one-pop-per-env-per-tick behaviour. Setting it higher lets a single\n // env drain at handler-parallelism speed: each tick the drainer pops\n // up to `drainBatchSize` entries from the env's queue, then dispatches\n // them all through the shared `concurrency`-bounded pLimit. For a\n // single-env burst this turns N sequential ticks into one tick of N\n // parallel handler calls, capped by `concurrency`. Org/env fairness\n // still holds — each org still contributes exactly one env per tick.\n //\n // Memory: per-tick in-flight entries ≤ `maxOrgsPerTick × drainBatchSize`.\n // Operators sizing this should ensure their PG pool / engine handler\n // can sustain `concurrency` parallel writes; popping more than the\n // handler can process per tick just queues entries in JS waiting on\n // pLimit.\n drainBatchSize?: number;\n // Cap on the exponential backoff applied after consecutive `runOnce`\n // errors. Defaults to 5000ms. The backoff base is `max(pollIntervalMs,\n // backoffFloorMs)` and doubles per consecutive error up to this cap.\n maxBackoffMs?: number;\n // Floor for the exponential-backoff base, so a tiny `pollIntervalMs`\n // doesn't collapse the backoff to near-zero on a sustained outage.\n // Defaults to 100ms.\n backoffFloorMs?: number;\n logger?: Logger;\n};\n\nexport type DrainResult = {\n drained: number;\n failed: number;\n};\n\nexport class MollifierDrainer<TPayload = unknown> {\n private readonly buffer: MollifierBuffer;\n private readonly handler: MollifierDrainerHandler<TPayload>;\n private readonly onTerminalFailure?: MollifierDrainerTerminalFailureHandler<TPayload>;\n private readonly maxAttempts: number;\n private readonly isRetryable: (err: unknown) => boolean;\n private readonly pollIntervalMs: number;\n private readonly maxOrgsPerTick: number;\n private readonly drainBatchSize: number;\n private readonly concurrency: number;\n private readonly maxBackoffMs: number;\n private readonly backoffFloorMs: number;\n private readonly logger: Logger;\n // Rotation state. `orgCursor` advances through the active-orgs list.\n // Each org has its own internal cursor in `perOrgEnvCursors` for\n // cycling through that org's envs. Both reset on `start()`.\n private orgCursor = 0;\n private perOrgEnvCursors = new Map<string, number>();\n private isRunning = false;\n private stopping = false;\n private loopPromise: Promise<void> | null = null;\n\n constructor(options: MollifierDrainerOptions<TPayload>) {\n this.buffer = options.buffer;\n this.handler = options.handler;\n this.onTerminalFailure = options.onTerminalFailure;\n this.maxAttempts = options.maxAttempts;\n this.isRetryable = options.isRetryable;\n this.pollIntervalMs = options.pollIntervalMs ?? 100;\n this.maxOrgsPerTick = options.maxOrgsPerTick ?? 500;\n this.drainBatchSize = Math.max(1, options.drainBatchSize ?? 1);\n this.concurrency = Math.max(1, options.concurrency);\n this.maxBackoffMs = options.maxBackoffMs ?? 5_000;\n this.backoffFloorMs = Math.max(1, options.backoffFloorMs ?? 100);\n this.logger = options.logger ?? new Logger(\"MollifierDrainer\", \"debug\");\n }\n\n async runOnce(): Promise<DrainResult> {\n const orgs = await this.buffer.listOrgs();\n if (orgs.length === 0) return { drained: 0, failed: 0 };\n\n const orgSlice = this.takeOrgSlice(orgs);\n\n // Fan the per-org SMEMBERS out in a single pipelined round-trip. Serial\n // awaits would otherwise add `orgSlice.length × RTT` of dead time before\n // pops start — at the default `maxOrgsPerTick=500` and a ~1ms ElastiCache\n // RTT that's a ~500ms per-tick floor. ioredis auto-pipelines concurrent\n // commands into one batch, so the burst is cheap; SMEMBERS on a small set\n // is O(N) per org and trivial at this scale. `Promise.all` preserves\n // order, so the org→envs pairing below stays deterministic.\n const envsByOrg = await Promise.all(orgSlice.map((orgId) => this.buffer.listEnvsForOrg(orgId)));\n const targets: string[] = [];\n for (let i = 0; i < orgSlice.length; i++) {\n const orgId = orgSlice[i]!;\n const envsForOrg = envsByOrg[i]!;\n if (envsForOrg.length === 0) continue;\n const envId = this.pickEnvForOrg(orgId, envsForOrg);\n targets.push(envId);\n }\n\n if (targets.length === 0) return { drained: 0, failed: 0 };\n\n // Worker-pool draining. We spawn up to `concurrency` workers; each\n // worker repeatedly:\n // 1. Picks the next env with budget remaining (round-robin),\n // atomically claiming one slot of that env's per-tick budget.\n // 2. Pops one entry and processes it.\n // 3. Repeats until pickNextEnv returns null.\n //\n // This pattern gives us both invariants the prior two designs traded\n // off:\n // - Single-env bursts use the full `concurrency` budget. All\n // workers can pull from one env, processing `concurrency` entries\n // in parallel.\n // - The number of entries in \"popped-but-not-acked\" (DRAINING)\n // state at any moment is bounded by the worker count, i.e.\n // `concurrency` — same blast radius as the pre-batch\n // one-pop-per-env model. A process crash mid-tick strands at\n // most `concurrency` entries for stale-sweep to recover, not\n // `maxOrgsPerTick × drainBatchSize`.\n //\n // Fairness: pickNextEnv advances a cursor by 1 each successful pick,\n // so workers round-robin across envs at the entry level. Combined\n // with the per-env budget cap, an env contributes at most\n // `drainBatchSize` entries per tick regardless of how many workers\n // are free — a heavy env can't starve siblings within a tick.\n const remaining = new Map<string, number>();\n const skip = new Set<string>(); // envs with empty queue or pop failure this tick\n for (const envId of targets) remaining.set(envId, this.drainBatchSize);\n\n let cursor = 0;\n const pickNextEnv = (): string | null => {\n for (let i = 0; i < targets.length; i++) {\n const idx = (cursor + i) % targets.length;\n const envId = targets[idx]!;\n if (skip.has(envId)) continue;\n const r = remaining.get(envId) ?? 0;\n if (r > 0) {\n remaining.set(envId, r - 1);\n cursor = (idx + 1) % targets.length;\n return envId;\n }\n }\n return null;\n };\n\n let drained = 0;\n let failed = 0;\n\n const worker = async (): Promise<void> => {\n while (true) {\n const envId = pickNextEnv();\n if (envId === null) return;\n let entry: BufferEntry | null;\n try {\n entry = await this.buffer.pop(envId);\n } catch (err) {\n // A pop failure on one env aborts that env's batch for this\n // tick (don't keep hammering a broken Redis) and counts as\n // exactly one failure — same as the pre-batch path on a pop\n // blowup. Other envs continue.\n //\n // `pickNextEnv` decrements `remaining` before the pop settles,\n // so multiple workers can race into the same env and all hit\n // a throwing pop before the first catch lands. Guarding the\n // failure increment on `!skip.has(envId)` keeps the per-env\n // failure count at exactly one even under that race —\n // matching the documented contract.\n this.logger.error(\"MollifierDrainer.pop failed\", { envId, err });\n if (!skip.has(envId)) {\n skip.add(envId);\n failed += 1;\n }\n continue;\n }\n if (!entry) {\n // Queue exhausted between scheduling and this pop. Mark the\n // env skipped so siblings aren't held up by repeated empty pops.\n skip.add(envId);\n continue;\n }\n try {\n const outcome = await this.processEntry(entry);\n if (outcome === \"drained\") drained += 1;\n else failed += 1;\n } catch (err) {\n this.logger.error(\"MollifierDrainer.processEntry failed\", {\n envId,\n runId: entry.runId,\n err,\n });\n failed += 1;\n }\n }\n };\n\n const totalBudget = targets.length * this.drainBatchSize;\n const workerCount = Math.min(this.concurrency, totalBudget);\n await Promise.all(Array.from({ length: workerCount }, () => worker()));\n\n return { drained, failed };\n }\n\n start(): void {\n if (this.isRunning) return;\n this.isRunning = true;\n this.stopping = false;\n // Reset rotation state on each (re)start. A stop+start cycle means\n // operator intent to \"begin clean\" — between-restart cursor drift\n // would otherwise carry implicit state across what should look like\n // a fresh boot.\n this.orgCursor = 0;\n this.perOrgEnvCursors = new Map();\n this.loopPromise = this.loop();\n }\n\n // Signal the loop to exit (`stopping = true`) and wait for it. With no\n // timeout, wait indefinitely for the in-flight `runOnce` and its handlers\n // to settle — same semantic as FairQueue / BatchQueue's `stop()`. With a\n // timeout, race the loop promise against a deadline so a hung handler\n // can't wedge the process past its termination grace period.\n async stop(options: { timeoutMs?: number } = {}): Promise<void> {\n if (!this.isRunning || !this.loopPromise) return;\n this.stopping = true;\n if (options.timeoutMs == null) {\n await this.loopPromise;\n return;\n }\n // Hold the timer handle so we can clearTimeout() it after the race.\n // Without this, when the loop wins the race, the discarded timer is\n // still ref'd and pins the Node event loop for up to `timeoutMs`,\n // delaying process shutdown by exactly the slack we were trying to\n // bound. try/finally clears the handle in every exit path (loop-won,\n // timeout-won, or exception).\n const timeoutSentinel = Symbol(\"mollifier.stop.timeout\");\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<typeof timeoutSentinel>((resolve) => {\n timeoutHandle = setTimeout(() => resolve(timeoutSentinel), options.timeoutMs);\n });\n try {\n const winner = await Promise.race([\n this.loopPromise.then(() => \"done\" as const),\n timeoutPromise,\n ]);\n if (winner === timeoutSentinel) {\n this.logger.warn(\n \"MollifierDrainer.stop: deadline exceeded; returning while loop iteration is in flight\",\n { timeoutMs: options.timeoutMs }\n );\n }\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n\n // Transient Redis errors (e.g. a connection blip in `listOrgs` /\n // `listEnvsForOrg` / `pop`) must not kill the polling loop permanently.\n // We log each `runOnce` failure, back off so we don't spin tight on a\n // sustained outage, and resume. The loop only exits when `stop()` flips\n // `stopping`.\n private async loop(): Promise<void> {\n try {\n let consecutiveErrors = 0;\n while (!this.stopping) {\n try {\n const result = await this.runOnce();\n consecutiveErrors = 0;\n if (result.drained === 0 && result.failed === 0) {\n await this.delay(this.pollIntervalMs);\n }\n } catch (err) {\n consecutiveErrors += 1;\n this.logger.error(\"MollifierDrainer.runOnce failed; backing off\", {\n err,\n consecutiveErrors,\n });\n await this.delay(this.backoffMs(consecutiveErrors));\n }\n }\n } finally {\n this.isRunning = false;\n }\n }\n\n // Exponential backoff capped at 5s. Keeps the loop responsive after a\n // brief blip while preventing a tight retry loop during a long Redis\n // outage. 1 → 200ms, 2 → 400ms, 3 → 800ms, 4 → 1.6s, 5 → 3.2s, 6+ → 5s.\n private backoffMs(consecutiveErrors: number): number {\n const base = Math.max(this.pollIntervalMs, this.backoffFloorMs);\n const capped = Math.min(base * 2 ** (consecutiveErrors - 1), this.maxBackoffMs);\n return capped;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // Take up to `maxOrgsPerTick` orgs starting at the current cursor, with\n // wrap-around. Cursor advances by 1 each tick so every org reaches\n // every slot position (0..sliceSize-1) over a full cycle — no\n // head-of-line bias within the slice. Orgs are sorted before slicing\n // so rotation is deterministic regardless of Redis SET iteration order.\n private takeOrgSlice(orgs: string[]): string[] {\n const sorted = [...orgs].sort();\n const n = sorted.length;\n const sliceSize = Math.min(this.maxOrgsPerTick, n);\n const start = this.orgCursor % n;\n this.orgCursor = (this.orgCursor + 1) % Math.max(n, 1);\n const end = start + sliceSize;\n if (end <= n) return sorted.slice(start, end);\n return [...sorted.slice(start), ...sorted.slice(0, end - n)];\n }\n\n // Pick one env from the org's active-envs list, rotating per org via\n // the per-org cursor. Each org's cursor advances by 1 each visit, so\n // an org with N envs cycles through them across N visits.\n private pickEnvForOrg(orgId: string, envsForOrg: string[]): string {\n const sorted = [...envsForOrg].sort();\n const cursor = this.perOrgEnvCursors.get(orgId) ?? 0;\n const idx = cursor % sorted.length;\n this.perOrgEnvCursors.set(orgId, (cursor + 1) % sorted.length);\n return sorted[idx]!;\n }\n\n private async processEntry(entry: BufferEntry): Promise<\"drained\" | \"failed\"> {\n try {\n const payload = deserialiseSnapshot<TPayload>(entry.payload);\n await this.handler({\n runId: entry.runId,\n envId: entry.envId,\n orgId: entry.orgId,\n payload,\n attempts: entry.attempts,\n createdAt: entry.createdAt,\n });\n await this.buffer.ack(entry.runId);\n return \"drained\";\n } catch (err) {\n const nextAttempts = entry.attempts + 1;\n if (this.isRetryable(err) && nextAttempts < this.maxAttempts) {\n await this.buffer.requeue(entry.runId);\n this.logger.warn(\"MollifierDrainer: retryable error, requeued\", {\n runId: entry.runId,\n attempts: nextAttempts,\n });\n return \"failed\";\n }\n const cause: MollifierDrainerTerminalFailureCause = this.isRetryable(err)\n ? \"max-attempts-exhausted\"\n : \"non-retryable\";\n const code = err instanceof Error ? err.name : \"Unknown\";\n const message = err instanceof Error ? err.message : String(err);\n // Run the terminal-failure callback BEFORE buffer.fail() so a\n // SYSTEM_FAILURE PG row can land while the entry is still around to\n // read from (and so we don't lose the run if the callback's own\n // write itself needs a retry). If the callback throws a retryable\n // error, requeue the entry instead of fail()ing — PG is still\n // unreachable, give it another tick. Any other callback failure\n // falls through to buffer.fail() so a genuinely bad snapshot\n // doesn't loop forever.\n if (this.onTerminalFailure) {\n try {\n await this.onTerminalFailure({\n runId: entry.runId,\n envId: entry.envId,\n orgId: entry.orgId,\n payload: deserialiseSnapshot<TPayload>(entry.payload),\n attempts: nextAttempts,\n createdAt: entry.createdAt,\n error: { code, message },\n cause,\n });\n } catch (writeErr) {\n if (this.isRetryable(writeErr)) {\n await this.buffer.requeue(entry.runId);\n this.logger.warn(\"MollifierDrainer: terminal-failure callback retryable; requeued\", {\n runId: entry.runId,\n attempts: nextAttempts,\n writeErr,\n });\n return \"failed\";\n }\n this.logger.error(\"MollifierDrainer: terminal-failure callback failed\", {\n runId: entry.runId,\n writeErr,\n });\n }\n }\n await this.buffer.fail(entry.runId, { code, message });\n this.logger.error(\"MollifierDrainer: terminal failure\", {\n runId: entry.runId,\n code,\n message,\n cause,\n });\n return \"failed\";\n }\n }\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,55,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
1
+ {"version":3,"file":"index.cjs","names":["assert","util","process","os","tty","net_1","events_1","events_1","net_1","tls_1","Buffer","Logger","Redis","scopedUrlAlphabet","Logger","#registerCommands","API_NAME","API_NAME","API_NAME","#head","#tail","#size","z","Logger","#updateQueueSizeMetric","#updateDeadLetterQueueSizeMetric","#updateConcurrencyLimitActiveMetric","#updateConcurrencyLimitPendingMetric","#updateOldestMessageAgeMetric","#logSuperseded","cronParser","Cluster","#registerCommands","#assertPipelineSucceeded","#sweepScopes","#registerCommands","#hashToShard","#initializeMetrics","#registerCommands","#getShardForQueue","#removeFromInflight","#makeMember","#parseMember","#registerCommands","#buildKey","#tag","#queueTag","#registerCommands","#getQueuesFromShard","#addQuantumToTenants","#getTenantsFromDispatch","#decrementDeficit","#decrementDeficitBatch","#deficitKey","#getOrCreateSnapshot","#shuffleTenantsByWeight","#orderQueuesForTenant","#createSnapshot","#getQueuesFromShard","#selectTopTenantQueues","#shuffle","#weightedShuffle","#getQueuesFromShard","#getLastServedIndex","#rotateArray","#setLastServedIndex","#lastServedKey","#validateLayout","Logger","#registerCommands","#runMasterQueueConsumerLoop","#runReclaimLoop","#runReconcileLoop","#processShardIteration","#processDispatchShard","#drainLegacyMasterQueueShard","#createSchedulerContext","#fallbackDispatchToLegacyScheduler","#processSelectedQueues","#isInCooloff","#claimAndPushToWorkerQueue","#updateAllIndexesAfterDequeue","#resetCooloff","#releaseConcurrencySafely","#completeInVisibility","#releaseOrphanedConcurrency","#handleMessageFailure","#moveToDeadLetterQueue","#reclaimTimedOutMessages","#releaseReclaimedConcurrency","#reconcileConcurrency","z","Logger","#registerCommands","Logger"],"sources":["../../../node_modules/.pnpm/@ioredis+commands@1.2.0/node_modules/@ioredis/commands/built/commands.json","../../../node_modules/.pnpm/@ioredis+commands@1.2.0/node_modules/@ioredis/commands/built/index.js","../../../node_modules/.pnpm/standard-as-callback@2.1.0/node_modules/standard-as-callback/built/utils.js","../../../node_modules/.pnpm/standard-as-callback@2.1.0/node_modules/standard-as-callback/built/index.js","../../../node_modules/.pnpm/redis-errors@1.2.0/node_modules/redis-errors/lib/old.js","../../../node_modules/.pnpm/redis-errors@1.2.0/node_modules/redis-errors/lib/modern.js","../../../node_modules/.pnpm/redis-errors@1.2.0/node_modules/redis-errors/index.js","../../../node_modules/.pnpm/cluster-key-slot@1.1.2/node_modules/cluster-key-slot/lib/index.js","../../../node_modules/.pnpm/lodash.defaults@4.2.0/node_modules/lodash.defaults/index.js","../../../node_modules/.pnpm/lodash.isarguments@3.1.0/node_modules/lodash.isarguments/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/lodash.js","../../../node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js","../../../node_modules/.pnpm/debug@4.4.3_supports-color@10.0.0/node_modules/debug/src/common.js","../../../node_modules/.pnpm/debug@4.4.3_supports-color@10.0.0/node_modules/debug/src/browser.js","../../../node_modules/.pnpm/supports-color@10.0.0/node_modules/supports-color/index.js","../../../node_modules/.pnpm/debug@4.4.3_supports-color@10.0.0/node_modules/debug/src/node.js","../../../node_modules/.pnpm/debug@4.4.3_supports-color@10.0.0/node_modules/debug/src/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/debug.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/constants/TLSProfiles.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/Command.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/errors/ClusterAllFailedError.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/ScanStream.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/autoPipelining.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/Script.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/Commander.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/Pipeline.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/transaction.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/utils/applyMixin.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/ClusterOptions.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/util.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/ClusterSubscriber.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/ConnectionPool.js","../../../node_modules/.pnpm/denque@2.1.0/node_modules/denque/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/DelayQueue.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/cluster/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/AbstractConnector.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/StandaloneConnector.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/SentinelConnector/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/connectors/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/errors/index.js","../../../node_modules/.pnpm/redis-parser@3.0.0/node_modules/redis-parser/lib/parser.js","../../../node_modules/.pnpm/redis-parser@3.0.0/node_modules/redis-parser/index.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/SubscriptionSet.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/DataHandler.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/redis/event_handler.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/redis/RedisOptions.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/Redis.js","../../../node_modules/.pnpm/ioredis@5.6.1/node_modules/ioredis/built/index.js","../../../internal-packages/redis/src/index.ts","../../../node_modules/.pnpm/nanoid@5.1.16/node_modules/nanoid/url-alphabet/index.js","../../../node_modules/.pnpm/nanoid@5.1.16/node_modules/nanoid/index.js","../src/queue.ts","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/version.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/internal/semver.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/diag/ComponentLogger.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/diag/types.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/diag/internal/logLevelLogger.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/api/diag.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/context/context.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeter.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics/Metric.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/context/NoopContextManager.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/api/context.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/trace_flags.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/invalid-span-constants.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/NonRecordingSpan.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/context-utils.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/spancontext-utils.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/NoopTracer.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracer.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/ProxyTracerProvider.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/span_kind.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/status.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/context-api.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/api/metrics.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics-api.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/api/trace.js","../../../node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace-api.js","../../../internal-packages/tracing/src/index.ts","../../../node_modules/.pnpm/yocto-queue@1.1.1/node_modules/yocto-queue/index.js","../../../node_modules/.pnpm/p-limit@6.2.0/node_modules/p-limit/index.js","../src/worker.ts","../src/utils.ts","../src/fair-queue/connection.ts","../src/fair-queue/concurrency.ts","../src/fair-queue/masterQueue.ts","../src/fair-queue/telemetry.ts","../src/fair-queue/tenantDispatch.ts","../src/fair-queue/visibility.ts","../src/fair-queue/workerQueue.ts","../src/fair-queue/keyProducer.ts","../src/fair-queue/retry.ts","../src/fair-queue/scheduler.ts","../src/fair-queue/schedulers/drr.ts","../src/fair-queue/schedulers/weighted.ts","../src/fair-queue/schedulers/roundRobin.ts","../src/fair-queue/index.ts","../src/mollifier/schemas.ts","../src/mollifier/buffer.ts","../src/mollifier/drainer.ts"],"sourcesContent":["","\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getKeyIndexes = exports.hasFlag = exports.exists = exports.list = void 0;\nconst commands_json_1 = __importDefault(require(\"./commands.json\"));\n/**\n * Redis command list\n *\n * All commands are lowercased.\n */\nexports.list = Object.keys(commands_json_1.default);\nconst flags = {};\nexports.list.forEach((commandName) => {\n flags[commandName] = commands_json_1.default[commandName].flags.reduce(function (flags, flag) {\n flags[flag] = true;\n return flags;\n }, {});\n});\n/**\n * Check if the command exists\n */\nfunction exists(commandName) {\n return Boolean(commands_json_1.default[commandName]);\n}\nexports.exists = exists;\n/**\n * Check if the command has the flag\n *\n * Some of possible flags: readonly, noscript, loading\n */\nfunction hasFlag(commandName, flag) {\n if (!flags[commandName]) {\n throw new Error(\"Unknown command \" + commandName);\n }\n return Boolean(flags[commandName][flag]);\n}\nexports.hasFlag = hasFlag;\n/**\n * Get indexes of keys in the command arguments\n *\n * @example\n * ```javascript\n * getKeyIndexes('set', ['key', 'value']) // [0]\n * getKeyIndexes('mget', ['key1', 'key2']) // [0, 1]\n * ```\n */\nfunction getKeyIndexes(commandName, args, options) {\n const command = commands_json_1.default[commandName];\n if (!command) {\n throw new Error(\"Unknown command \" + commandName);\n }\n if (!Array.isArray(args)) {\n throw new Error(\"Expect args to be an array\");\n }\n const keys = [];\n const parseExternalKey = Boolean(options && options.parseExternalKey);\n const takeDynamicKeys = (args, startIndex) => {\n const keys = [];\n const keyStop = Number(args[startIndex]);\n for (let i = 0; i < keyStop; i++) {\n keys.push(i + startIndex + 1);\n }\n return keys;\n };\n const takeKeyAfterToken = (args, startIndex, token) => {\n for (let i = startIndex; i < args.length - 1; i += 1) {\n if (String(args[i]).toLowerCase() === token.toLowerCase()) {\n return i + 1;\n }\n }\n return null;\n };\n switch (commandName) {\n case \"zunionstore\":\n case \"zinterstore\":\n case \"zdiffstore\":\n keys.push(0, ...takeDynamicKeys(args, 1));\n break;\n case \"eval\":\n case \"evalsha\":\n case \"eval_ro\":\n case \"evalsha_ro\":\n case \"fcall\":\n case \"fcall_ro\":\n case \"blmpop\":\n case \"bzmpop\":\n keys.push(...takeDynamicKeys(args, 1));\n break;\n case \"sintercard\":\n case \"lmpop\":\n case \"zunion\":\n case \"zinter\":\n case \"zmpop\":\n case \"zintercard\":\n case \"zdiff\": {\n keys.push(...takeDynamicKeys(args, 0));\n break;\n }\n case \"georadius\": {\n keys.push(0);\n const storeKey = takeKeyAfterToken(args, 5, \"STORE\");\n if (storeKey)\n keys.push(storeKey);\n const distKey = takeKeyAfterToken(args, 5, \"STOREDIST\");\n if (distKey)\n keys.push(distKey);\n break;\n }\n case \"georadiusbymember\": {\n keys.push(0);\n const storeKey = takeKeyAfterToken(args, 4, \"STORE\");\n if (storeKey)\n keys.push(storeKey);\n const distKey = takeKeyAfterToken(args, 4, \"STOREDIST\");\n if (distKey)\n keys.push(distKey);\n break;\n }\n case \"sort\":\n case \"sort_ro\":\n keys.push(0);\n for (let i = 1; i < args.length - 1; i++) {\n let arg = args[i];\n if (typeof arg !== \"string\") {\n continue;\n }\n const directive = arg.toUpperCase();\n if (directive === \"GET\") {\n i += 1;\n arg = args[i];\n if (arg !== \"#\") {\n if (parseExternalKey) {\n keys.push([i, getExternalKeyNameLength(arg)]);\n }\n else {\n keys.push(i);\n }\n }\n }\n else if (directive === \"BY\") {\n i += 1;\n if (parseExternalKey) {\n keys.push([i, getExternalKeyNameLength(args[i])]);\n }\n else {\n keys.push(i);\n }\n }\n else if (directive === \"STORE\") {\n i += 1;\n keys.push(i);\n }\n }\n break;\n case \"migrate\":\n if (args[2] === \"\") {\n for (let i = 5; i < args.length - 1; i++) {\n const arg = args[i];\n if (typeof arg === \"string\" && arg.toUpperCase() === \"KEYS\") {\n for (let j = i + 1; j < args.length; j++) {\n keys.push(j);\n }\n break;\n }\n }\n }\n else {\n keys.push(2);\n }\n break;\n case \"xreadgroup\":\n case \"xread\":\n // Keys are 1st half of the args after STREAMS argument.\n for (let i = commandName === \"xread\" ? 0 : 3; i < args.length - 1; i++) {\n if (String(args[i]).toUpperCase() === \"STREAMS\") {\n for (let j = i + 1; j <= i + (args.length - 1 - i) / 2; j++) {\n keys.push(j);\n }\n break;\n }\n }\n break;\n default:\n // Step has to be at least one in this case, otherwise the command does\n // not contain a key.\n if (command.step > 0) {\n const keyStart = command.keyStart - 1;\n const keyStop = command.keyStop > 0\n ? command.keyStop\n : args.length + command.keyStop + 1;\n for (let i = keyStart; i < keyStop; i += command.step) {\n keys.push(i);\n }\n }\n break;\n }\n return keys;\n}\nexports.getKeyIndexes = getKeyIndexes;\nfunction getExternalKeyNameLength(key) {\n if (typeof key !== \"string\") {\n key = String(key);\n }\n const hashPos = key.indexOf(\"->\");\n return hashPos === -1 ? key.length : hashPos;\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.tryCatch = exports.errorObj = void 0;\n//Try catch is not supported in optimizing\n//compiler, so it is isolated\nexports.errorObj = { e: {} };\nlet tryCatchTarget;\nfunction tryCatcher(err, val) {\n try {\n const target = tryCatchTarget;\n tryCatchTarget = null;\n return target.apply(this, arguments);\n }\n catch (e) {\n exports.errorObj.e = e;\n return exports.errorObj;\n }\n}\nfunction tryCatch(fn) {\n tryCatchTarget = fn;\n return tryCatcher;\n}\nexports.tryCatch = tryCatch;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst utils_1 = require(\"./utils\");\nfunction throwLater(e) {\n setTimeout(function () {\n throw e;\n }, 0);\n}\nfunction asCallback(promise, nodeback, options) {\n if (typeof nodeback === \"function\") {\n promise.then((val) => {\n let ret;\n if (options !== undefined &&\n Object(options).spread &&\n Array.isArray(val)) {\n ret = utils_1.tryCatch(nodeback).apply(undefined, [null].concat(val));\n }\n else {\n ret =\n val === undefined\n ? utils_1.tryCatch(nodeback)(null)\n : utils_1.tryCatch(nodeback)(null, val);\n }\n if (ret === utils_1.errorObj) {\n throwLater(ret.e);\n }\n }, (cause) => {\n if (!cause) {\n const newReason = new Error(cause + \"\");\n Object.assign(newReason, { cause });\n cause = newReason;\n }\n const ret = utils_1.tryCatch(nodeback)(cause);\n if (ret === utils_1.errorObj) {\n throwLater(ret.e);\n }\n });\n }\n return promise;\n}\nexports.default = asCallback;\n","'use strict'\n\nconst assert = require('assert')\nconst util = require('util')\n\n// RedisError\n\nfunction RedisError (message) {\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n Error.captureStackTrace(this, this.constructor)\n}\n\nutil.inherits(RedisError, Error)\n\nObject.defineProperty(RedisError.prototype, 'name', {\n value: 'RedisError',\n configurable: true,\n writable: true\n})\n\n// ParserError\n\nfunction ParserError (message, buffer, offset) {\n assert(buffer)\n assert.strictEqual(typeof offset, 'number')\n\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n\n const tmp = Error.stackTraceLimit\n Error.stackTraceLimit = 2\n Error.captureStackTrace(this, this.constructor)\n Error.stackTraceLimit = tmp\n this.offset = offset\n this.buffer = buffer\n}\n\nutil.inherits(ParserError, RedisError)\n\nObject.defineProperty(ParserError.prototype, 'name', {\n value: 'ParserError',\n configurable: true,\n writable: true\n})\n\n// ReplyError\n\nfunction ReplyError (message) {\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n const tmp = Error.stackTraceLimit\n Error.stackTraceLimit = 2\n Error.captureStackTrace(this, this.constructor)\n Error.stackTraceLimit = tmp\n}\n\nutil.inherits(ReplyError, RedisError)\n\nObject.defineProperty(ReplyError.prototype, 'name', {\n value: 'ReplyError',\n configurable: true,\n writable: true\n})\n\n// AbortError\n\nfunction AbortError (message) {\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n Error.captureStackTrace(this, this.constructor)\n}\n\nutil.inherits(AbortError, RedisError)\n\nObject.defineProperty(AbortError.prototype, 'name', {\n value: 'AbortError',\n configurable: true,\n writable: true\n})\n\n// InterruptError\n\nfunction InterruptError (message) {\n Object.defineProperty(this, 'message', {\n value: message || '',\n configurable: true,\n writable: true\n })\n Error.captureStackTrace(this, this.constructor)\n}\n\nutil.inherits(InterruptError, AbortError)\n\nObject.defineProperty(InterruptError.prototype, 'name', {\n value: 'InterruptError',\n configurable: true,\n writable: true\n})\n\nmodule.exports = {\n RedisError,\n ParserError,\n ReplyError,\n AbortError,\n InterruptError\n}\n","'use strict'\n\nconst assert = require('assert')\n\nclass RedisError extends Error {\n get name () {\n return this.constructor.name\n }\n}\n\nclass ParserError extends RedisError {\n constructor (message, buffer, offset) {\n assert(buffer)\n assert.strictEqual(typeof offset, 'number')\n\n const tmp = Error.stackTraceLimit\n Error.stackTraceLimit = 2\n super(message)\n Error.stackTraceLimit = tmp\n this.offset = offset\n this.buffer = buffer\n }\n\n get name () {\n return this.constructor.name\n }\n}\n\nclass ReplyError extends RedisError {\n constructor (message) {\n const tmp = Error.stackTraceLimit\n Error.stackTraceLimit = 2\n super(message)\n Error.stackTraceLimit = tmp\n }\n get name () {\n return this.constructor.name\n }\n}\n\nclass AbortError extends RedisError {\n get name () {\n return this.constructor.name\n }\n}\n\nclass InterruptError extends AbortError {\n get name () {\n return this.constructor.name\n }\n}\n\nmodule.exports = {\n RedisError,\n ParserError,\n ReplyError,\n AbortError,\n InterruptError\n}\n","'use strict'\n\nconst Errors = process.version.charCodeAt(1) < 55 && process.version.charCodeAt(2) === 46\n ? require('./lib/old') // Node.js < 7\n : require('./lib/modern')\n\nmodule.exports = Errors\n","/*\n * Copyright 2001-2010 Georges Menie (www.menie.org)\n * Copyright 2010 Salvatore Sanfilippo (adapted to Redis coding style)\n * Copyright 2015 Zihua Li (http://zihua.li) (ported to JavaScript)\n * Copyright 2016 Mike Diarmid (http://github.com/salakar) (re-write for performance, ~700% perf inc)\n * All rights reserved.\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * * Neither the name of the University of California, Berkeley nor the\n * names of its contributors may be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* CRC16 implementation according to CCITT standards.\n *\n * Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the\n * following parameters:\n *\n * Name : \"XMODEM\", also known as \"ZMODEM\", \"CRC-16/ACORN\"\n * Width : 16 bit\n * Poly : 1021 (That is actually x^16 + x^12 + x^5 + 1)\n * Initialization : 0000\n * Reflect Input byte : False\n * Reflect Output CRC : False\n * Xor constant to output CRC : 0000\n * Output for \"123456789\" : 31C3\n */\n\nvar lookup = [\n 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,\n 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,\n 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,\n 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,\n 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,\n 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,\n 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,\n 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,\n 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,\n 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,\n 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,\n 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,\n 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,\n 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,\n 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,\n 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,\n 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,\n 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,\n 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,\n 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,\n 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,\n 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,\n 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,\n 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,\n 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,\n 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,\n 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,\n 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,\n 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,\n 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,\n 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,\n 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0\n];\n\n/**\n * Convert a string to a UTF8 array - faster than via buffer\n * @param str\n * @returns {Array}\n */\nvar toUTF8Array = function toUTF8Array(str) {\n var char;\n var i = 0;\n var p = 0;\n var utf8 = [];\n var len = str.length;\n\n for (; i < len; i++) {\n char = str.charCodeAt(i);\n if (char < 128) {\n utf8[p++] = char;\n } else if (char < 2048) {\n utf8[p++] = (char >> 6) | 192;\n utf8[p++] = (char & 63) | 128;\n } else if (\n ((char & 0xFC00) === 0xD800) && (i + 1) < str.length &&\n ((str.charCodeAt(i + 1) & 0xFC00) === 0xDC00)) {\n char = 0x10000 + ((char & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);\n utf8[p++] = (char >> 18) | 240;\n utf8[p++] = ((char >> 12) & 63) | 128;\n utf8[p++] = ((char >> 6) & 63) | 128;\n utf8[p++] = (char & 63) | 128;\n } else {\n utf8[p++] = (char >> 12) | 224;\n utf8[p++] = ((char >> 6) & 63) | 128;\n utf8[p++] = (char & 63) | 128;\n }\n }\n\n return utf8;\n};\n\n/**\n * Convert a string into a redis slot hash.\n * @param str\n * @returns {number}\n */\nvar generate = module.exports = function generate(str) {\n var char;\n var i = 0;\n var start = -1;\n var result = 0;\n var resultHash = 0;\n var utf8 = typeof str === 'string' ? toUTF8Array(str) : str;\n var len = utf8.length;\n\n while (i < len) {\n char = utf8[i++];\n if (start === -1) {\n if (char === 0x7B) {\n start = i;\n }\n } else if (char !== 0x7D) {\n resultHash = lookup[(char ^ (resultHash >> 8)) & 0xFF] ^ (resultHash << 8);\n } else if (i - 1 !== start) {\n return resultHash & 0x3FFF;\n }\n\n result = lookup[(char ^ (result >> 8)) & 0xFF] ^ (result << 8);\n }\n\n return result & 0x3FFF;\n};\n\n/**\n * Convert an array of multiple strings into a redis slot hash.\n * Returns -1 if one of the keys is not for the same slot as the others\n * @param keys\n * @returns {number}\n */\nmodule.exports.generateMulti = function generateMulti(keys) {\n var i = 1;\n var len = keys.length;\n var base = generate(keys[0]);\n\n while (i < len) {\n if (generate(keys[i++]) !== base) return -1;\n }\n\n return base;\n};\n","/**\n * lodash (Custom Build) <https://lodash.com/>\n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors <https://jquery.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]';\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\n/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n // Safari 9 makes `arguments.length` enumerable in strict mode.\n var result = (isArray(value) || isArguments(value))\n ? baseTimes(value.length, String)\n : [];\n\n var length = result.length,\n skipIndexes = !!length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (key == 'length' || isIndex(key, length)))) {\n result.push(key);\n }\n }\n return result;\n}\n\n/**\n * Used by `_.defaults` to customize its `_.assignIn` use.\n *\n * @private\n * @param {*} objValue The destination value.\n * @param {*} srcValue The source value.\n * @param {string} key The key of the property to assign.\n * @param {Object} object The parent object of `objValue`.\n * @returns {*} Returns the value to assign.\n */\nfunction assignInDefaults(objValue, srcValue, key, object) {\n if (objValue === undefined ||\n (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n return srcValue;\n }\n return objValue;\n}\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n object[key] = value;\n }\n}\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n}\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = array;\n return apply(func, this, otherArgs);\n };\n}\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n assignValue(object, key, newValue === undefined ? source[key] : newValue);\n }\n return object;\n}\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n length = length == null ? MAX_SAFE_INTEGER : length;\n return !!length &&\n (typeof value == 'number' || reIsUint.test(value)) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\n/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\n/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nfunction isArguments(value) {\n // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&\n (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);\n}\n\n/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 8-9 which returns 'object' for typed array and other constructors.\n var tag = isObject(value) ? objectToString.call(value) : '';\n return tag == funcTag || tag == genTag;\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/**\n * This method is like `_.assignIn` except that it accepts `customizer`\n * which is invoked to produce the assigned values. If `customizer` returns\n * `undefined`, assignment is handled by the method instead. The `customizer`\n * is invoked with five arguments: (objValue, srcValue, key, object, source).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extendWith\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @see _.assignWith\n * @example\n *\n * function customizer(objValue, srcValue) {\n * return _.isUndefined(objValue) ? srcValue : objValue;\n * }\n *\n * var defaults = _.partialRight(_.assignInWith, customizer);\n *\n * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\nvar assignInWith = createAssigner(function(object, source, srcIndex, customizer) {\n copyObject(source, keysIn(source), object, customizer);\n});\n\n/**\n * Assigns own and inherited enumerable string keyed properties of source\n * objects to the destination object for all destination properties that\n * resolve to `undefined`. Source objects are applied from left to right.\n * Once a property is set, additional values of the same property are ignored.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaultsDeep\n * @example\n *\n * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\nvar defaults = baseRest(function(args) {\n args.push(undefined, assignInDefaults);\n return apply(assignInWith, undefined, args);\n});\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nmodule.exports = defaults;\n","/**\n * lodash (Custom Build) <https://lodash.com/>\n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors <https://jquery.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nfunction isArguments(value) {\n // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&\n (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);\n}\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 8-9 which returns 'object' for typed array and other constructors.\n var tag = isObject(value) ? objectToString.call(value) : '';\n return tag == funcTag || tag == genTag;\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\nmodule.exports = isArguments;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.isArguments = exports.defaults = exports.noop = void 0;\nconst defaults = require(\"lodash.defaults\");\nexports.defaults = defaults;\nconst isArguments = require(\"lodash.isarguments\");\nexports.isArguments = isArguments;\nfunction noop() { }\nexports.noop = noop;\n","/**\n * Helpers.\n */\n\nvar s = 1000;\nvar m = s * 60;\nvar h = m * 60;\nvar d = h * 24;\nvar w = d * 7;\nvar y = d * 365.25;\n\n/**\n * Parse or format the given `val`.\n *\n * Options:\n *\n * - `long` verbose formatting [false]\n *\n * @param {String|Number} val\n * @param {Object} [options]\n * @throws {Error} throw an error if val is not a non-empty string or a number\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function (val, options) {\n options = options || {};\n var type = typeof val;\n if (type === 'string' && val.length > 0) {\n return parse(val);\n } else if (type === 'number' && isFinite(val)) {\n return options.long ? fmtLong(val) : fmtShort(val);\n }\n throw new Error(\n 'val is not a non-empty string or a valid number. val=' +\n JSON.stringify(val)\n );\n};\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n str = String(str);\n if (str.length > 100) {\n return;\n }\n var match = /^(-?(?:\\d+)?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(\n str\n );\n if (!match) {\n return;\n }\n var n = parseFloat(match[1]);\n var type = (match[2] || 'ms').toLowerCase();\n switch (type) {\n case 'years':\n case 'year':\n case 'yrs':\n case 'yr':\n case 'y':\n return n * y;\n case 'weeks':\n case 'week':\n case 'w':\n return n * w;\n case 'days':\n case 'day':\n case 'd':\n return n * d;\n case 'hours':\n case 'hour':\n case 'hrs':\n case 'hr':\n case 'h':\n return n * h;\n case 'minutes':\n case 'minute':\n case 'mins':\n case 'min':\n case 'm':\n return n * m;\n case 'seconds':\n case 'second':\n case 'secs':\n case 'sec':\n case 's':\n return n * s;\n case 'milliseconds':\n case 'millisecond':\n case 'msecs':\n case 'msec':\n case 'ms':\n return n;\n default:\n return undefined;\n }\n}\n\n/**\n * Short format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtShort(ms) {\n var msAbs = Math.abs(ms);\n if (msAbs >= d) {\n return Math.round(ms / d) + 'd';\n }\n if (msAbs >= h) {\n return Math.round(ms / h) + 'h';\n }\n if (msAbs >= m) {\n return Math.round(ms / m) + 'm';\n }\n if (msAbs >= s) {\n return Math.round(ms / s) + 's';\n }\n return ms + 'ms';\n}\n\n/**\n * Long format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtLong(ms) {\n var msAbs = Math.abs(ms);\n if (msAbs >= d) {\n return plural(ms, msAbs, d, 'day');\n }\n if (msAbs >= h) {\n return plural(ms, msAbs, h, 'hour');\n }\n if (msAbs >= m) {\n return plural(ms, msAbs, m, 'minute');\n }\n if (msAbs >= s) {\n return plural(ms, msAbs, s, 'second');\n }\n return ms + ' ms';\n}\n\n/**\n * Pluralization helper.\n */\n\nfunction plural(ms, msAbs, n, name) {\n var isPlural = msAbs >= n * 1.5;\n return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');\n}\n","\n/**\n * This is the common logic for both the Node.js and web browser\n * implementations of `debug()`.\n */\n\nfunction setup(env) {\n\tcreateDebug.debug = createDebug;\n\tcreateDebug.default = createDebug;\n\tcreateDebug.coerce = coerce;\n\tcreateDebug.disable = disable;\n\tcreateDebug.enable = enable;\n\tcreateDebug.enabled = enabled;\n\tcreateDebug.humanize = require('ms');\n\tcreateDebug.destroy = destroy;\n\n\tObject.keys(env).forEach(key => {\n\t\tcreateDebug[key] = env[key];\n\t});\n\n\t/**\n\t* The currently active debug mode names, and names to skip.\n\t*/\n\n\tcreateDebug.names = [];\n\tcreateDebug.skips = [];\n\n\t/**\n\t* Map of special \"%n\" handling functions, for the debug \"format\" argument.\n\t*\n\t* Valid key names are a single, lower or upper-case letter, i.e. \"n\" and \"N\".\n\t*/\n\tcreateDebug.formatters = {};\n\n\t/**\n\t* Selects a color for a debug namespace\n\t* @param {String} namespace The namespace string for the debug instance to be colored\n\t* @return {Number|String} An ANSI color code for the given namespace\n\t* @api private\n\t*/\n\tfunction selectColor(namespace) {\n\t\tlet hash = 0;\n\n\t\tfor (let i = 0; i < namespace.length; i++) {\n\t\t\thash = ((hash << 5) - hash) + namespace.charCodeAt(i);\n\t\t\thash |= 0; // Convert to 32bit integer\n\t\t}\n\n\t\treturn createDebug.colors[Math.abs(hash) % createDebug.colors.length];\n\t}\n\tcreateDebug.selectColor = selectColor;\n\n\t/**\n\t* Create a debugger with the given `namespace`.\n\t*\n\t* @param {String} namespace\n\t* @return {Function}\n\t* @api public\n\t*/\n\tfunction createDebug(namespace) {\n\t\tlet prevTime;\n\t\tlet enableOverride = null;\n\t\tlet namespacesCache;\n\t\tlet enabledCache;\n\n\t\tfunction debug(...args) {\n\t\t\t// Disabled?\n\t\t\tif (!debug.enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst self = debug;\n\n\t\t\t// Set `diff` timestamp\n\t\t\tconst curr = Number(new Date());\n\t\t\tconst ms = curr - (prevTime || curr);\n\t\t\tself.diff = ms;\n\t\t\tself.prev = prevTime;\n\t\t\tself.curr = curr;\n\t\t\tprevTime = curr;\n\n\t\t\targs[0] = createDebug.coerce(args[0]);\n\n\t\t\tif (typeof args[0] !== 'string') {\n\t\t\t\t// Anything else let's inspect with %O\n\t\t\t\targs.unshift('%O');\n\t\t\t}\n\n\t\t\t// Apply any `formatters` transformations\n\t\t\tlet index = 0;\n\t\t\targs[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {\n\t\t\t\t// If we encounter an escaped % then don't increase the array index\n\t\t\t\tif (match === '%%') {\n\t\t\t\t\treturn '%';\n\t\t\t\t}\n\t\t\t\tindex++;\n\t\t\t\tconst formatter = createDebug.formatters[format];\n\t\t\t\tif (typeof formatter === 'function') {\n\t\t\t\t\tconst val = args[index];\n\t\t\t\t\tmatch = formatter.call(self, val);\n\n\t\t\t\t\t// Now we need to remove `args[index]` since it's inlined in the `format`\n\t\t\t\t\targs.splice(index, 1);\n\t\t\t\t\tindex--;\n\t\t\t\t}\n\t\t\t\treturn match;\n\t\t\t});\n\n\t\t\t// Apply env-specific formatting (colors, etc.)\n\t\t\tcreateDebug.formatArgs.call(self, args);\n\n\t\t\tconst logFn = self.log || createDebug.log;\n\t\t\tlogFn.apply(self, args);\n\t\t}\n\n\t\tdebug.namespace = namespace;\n\t\tdebug.useColors = createDebug.useColors();\n\t\tdebug.color = createDebug.selectColor(namespace);\n\t\tdebug.extend = extend;\n\t\tdebug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.\n\n\t\tObject.defineProperty(debug, 'enabled', {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: false,\n\t\t\tget: () => {\n\t\t\t\tif (enableOverride !== null) {\n\t\t\t\t\treturn enableOverride;\n\t\t\t\t}\n\t\t\t\tif (namespacesCache !== createDebug.namespaces) {\n\t\t\t\t\tnamespacesCache = createDebug.namespaces;\n\t\t\t\t\tenabledCache = createDebug.enabled(namespace);\n\t\t\t\t}\n\n\t\t\t\treturn enabledCache;\n\t\t\t},\n\t\t\tset: v => {\n\t\t\t\tenableOverride = v;\n\t\t\t}\n\t\t});\n\n\t\t// Env-specific initialization logic for debug instances\n\t\tif (typeof createDebug.init === 'function') {\n\t\t\tcreateDebug.init(debug);\n\t\t}\n\n\t\treturn debug;\n\t}\n\n\tfunction extend(namespace, delimiter) {\n\t\tconst newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);\n\t\tnewDebug.log = this.log;\n\t\treturn newDebug;\n\t}\n\n\t/**\n\t* Enables a debug mode by namespaces. This can include modes\n\t* separated by a colon and wildcards.\n\t*\n\t* @param {String} namespaces\n\t* @api public\n\t*/\n\tfunction enable(namespaces) {\n\t\tcreateDebug.save(namespaces);\n\t\tcreateDebug.namespaces = namespaces;\n\n\t\tcreateDebug.names = [];\n\t\tcreateDebug.skips = [];\n\n\t\tconst split = (typeof namespaces === 'string' ? namespaces : '')\n\t\t\t.trim()\n\t\t\t.replace(/\\s+/g, ',')\n\t\t\t.split(',')\n\t\t\t.filter(Boolean);\n\n\t\tfor (const ns of split) {\n\t\t\tif (ns[0] === '-') {\n\t\t\t\tcreateDebug.skips.push(ns.slice(1));\n\t\t\t} else {\n\t\t\t\tcreateDebug.names.push(ns);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given string matches a namespace template, honoring\n\t * asterisks as wildcards.\n\t *\n\t * @param {String} search\n\t * @param {String} template\n\t * @return {Boolean}\n\t */\n\tfunction matchesTemplate(search, template) {\n\t\tlet searchIndex = 0;\n\t\tlet templateIndex = 0;\n\t\tlet starIndex = -1;\n\t\tlet matchIndex = 0;\n\n\t\twhile (searchIndex < search.length) {\n\t\t\tif (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {\n\t\t\t\t// Match character or proceed with wildcard\n\t\t\t\tif (template[templateIndex] === '*') {\n\t\t\t\t\tstarIndex = templateIndex;\n\t\t\t\t\tmatchIndex = searchIndex;\n\t\t\t\t\ttemplateIndex++; // Skip the '*'\n\t\t\t\t} else {\n\t\t\t\t\tsearchIndex++;\n\t\t\t\t\ttemplateIndex++;\n\t\t\t\t}\n\t\t\t} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition\n\t\t\t\t// Backtrack to the last '*' and try to match more characters\n\t\t\t\ttemplateIndex = starIndex + 1;\n\t\t\t\tmatchIndex++;\n\t\t\t\tsearchIndex = matchIndex;\n\t\t\t} else {\n\t\t\t\treturn false; // No match\n\t\t\t}\n\t\t}\n\n\t\t// Handle trailing '*' in template\n\t\twhile (templateIndex < template.length && template[templateIndex] === '*') {\n\t\t\ttemplateIndex++;\n\t\t}\n\n\t\treturn templateIndex === template.length;\n\t}\n\n\t/**\n\t* Disable debug output.\n\t*\n\t* @return {String} namespaces\n\t* @api public\n\t*/\n\tfunction disable() {\n\t\tconst namespaces = [\n\t\t\t...createDebug.names,\n\t\t\t...createDebug.skips.map(namespace => '-' + namespace)\n\t\t].join(',');\n\t\tcreateDebug.enable('');\n\t\treturn namespaces;\n\t}\n\n\t/**\n\t* Returns true if the given mode name is enabled, false otherwise.\n\t*\n\t* @param {String} name\n\t* @return {Boolean}\n\t* @api public\n\t*/\n\tfunction enabled(name) {\n\t\tfor (const skip of createDebug.skips) {\n\t\t\tif (matchesTemplate(name, skip)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfor (const ns of createDebug.names) {\n\t\t\tif (matchesTemplate(name, ns)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t* Coerce `val`.\n\t*\n\t* @param {Mixed} val\n\t* @return {Mixed}\n\t* @api private\n\t*/\n\tfunction coerce(val) {\n\t\tif (val instanceof Error) {\n\t\t\treturn val.stack || val.message;\n\t\t}\n\t\treturn val;\n\t}\n\n\t/**\n\t* XXX DO NOT USE. This is a temporary stub function.\n\t* XXX It WILL be removed in the next major release.\n\t*/\n\tfunction destroy() {\n\t\tconsole.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');\n\t}\n\n\tcreateDebug.enable(createDebug.load());\n\n\treturn createDebug;\n}\n\nmodule.exports = setup;\n","/* eslint-env browser */\n\n/**\n * This is the web browser implementation of `debug()`.\n */\n\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\nexports.storage = localstorage();\nexports.destroy = (() => {\n\tlet warned = false;\n\n\treturn () => {\n\t\tif (!warned) {\n\t\t\twarned = true;\n\t\t\tconsole.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');\n\t\t}\n\t};\n})();\n\n/**\n * Colors.\n */\n\nexports.colors = [\n\t'#0000CC',\n\t'#0000FF',\n\t'#0033CC',\n\t'#0033FF',\n\t'#0066CC',\n\t'#0066FF',\n\t'#0099CC',\n\t'#0099FF',\n\t'#00CC00',\n\t'#00CC33',\n\t'#00CC66',\n\t'#00CC99',\n\t'#00CCCC',\n\t'#00CCFF',\n\t'#3300CC',\n\t'#3300FF',\n\t'#3333CC',\n\t'#3333FF',\n\t'#3366CC',\n\t'#3366FF',\n\t'#3399CC',\n\t'#3399FF',\n\t'#33CC00',\n\t'#33CC33',\n\t'#33CC66',\n\t'#33CC99',\n\t'#33CCCC',\n\t'#33CCFF',\n\t'#6600CC',\n\t'#6600FF',\n\t'#6633CC',\n\t'#6633FF',\n\t'#66CC00',\n\t'#66CC33',\n\t'#9900CC',\n\t'#9900FF',\n\t'#9933CC',\n\t'#9933FF',\n\t'#99CC00',\n\t'#99CC33',\n\t'#CC0000',\n\t'#CC0033',\n\t'#CC0066',\n\t'#CC0099',\n\t'#CC00CC',\n\t'#CC00FF',\n\t'#CC3300',\n\t'#CC3333',\n\t'#CC3366',\n\t'#CC3399',\n\t'#CC33CC',\n\t'#CC33FF',\n\t'#CC6600',\n\t'#CC6633',\n\t'#CC9900',\n\t'#CC9933',\n\t'#CCCC00',\n\t'#CCCC33',\n\t'#FF0000',\n\t'#FF0033',\n\t'#FF0066',\n\t'#FF0099',\n\t'#FF00CC',\n\t'#FF00FF',\n\t'#FF3300',\n\t'#FF3333',\n\t'#FF3366',\n\t'#FF3399',\n\t'#FF33CC',\n\t'#FF33FF',\n\t'#FF6600',\n\t'#FF6633',\n\t'#FF9900',\n\t'#FF9933',\n\t'#FFCC00',\n\t'#FFCC33'\n];\n\n/**\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\n * and the Firebug extension (any Firefox version) are known\n * to support \"%c\" CSS customizations.\n *\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\n */\n\n// eslint-disable-next-line complexity\nfunction useColors() {\n\t// NB: In an Electron preload script, document will be defined but not fully\n\t// initialized. Since we know we're in Chrome, we'll just detect this case\n\t// explicitly\n\tif (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {\n\t\treturn true;\n\t}\n\n\t// Internet Explorer and Edge do not support colors.\n\tif (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\\/(\\d+)/)) {\n\t\treturn false;\n\t}\n\n\tlet m;\n\n\t// Is webkit? http://stackoverflow.com/a/16459606/376773\n\t// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\n\t// eslint-disable-next-line no-return-assign\n\treturn (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||\n\t\t// Is firebug? http://stackoverflow.com/a/398120/376773\n\t\t(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||\n\t\t// Is firefox >= v31?\n\t\t// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\n\t\t(typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/)) && parseInt(m[1], 10) >= 31) ||\n\t\t// Double check webkit in userAgent just in case we are in a worker\n\t\t(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\/(\\d+)/));\n}\n\n/**\n * Colorize log arguments if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n\targs[0] = (this.useColors ? '%c' : '') +\n\t\tthis.namespace +\n\t\t(this.useColors ? ' %c' : ' ') +\n\t\targs[0] +\n\t\t(this.useColors ? '%c ' : ' ') +\n\t\t'+' + module.exports.humanize(this.diff);\n\n\tif (!this.useColors) {\n\t\treturn;\n\t}\n\n\tconst c = 'color: ' + this.color;\n\targs.splice(1, 0, c, 'color: inherit');\n\n\t// The final \"%c\" is somewhat tricky, because there could be other\n\t// arguments passed either before or after the %c, so we need to\n\t// figure out the correct index to insert the CSS into\n\tlet index = 0;\n\tlet lastC = 0;\n\targs[0].replace(/%[a-zA-Z%]/g, match => {\n\t\tif (match === '%%') {\n\t\t\treturn;\n\t\t}\n\t\tindex++;\n\t\tif (match === '%c') {\n\t\t\t// We only are interested in the *last* %c\n\t\t\t// (the user may have provided their own)\n\t\t\tlastC = index;\n\t\t}\n\t});\n\n\targs.splice(lastC, 0, c);\n}\n\n/**\n * Invokes `console.debug()` when available.\n * No-op when `console.debug` is not a \"function\".\n * If `console.debug` is not available, falls back\n * to `console.log`.\n *\n * @api public\n */\nexports.log = console.debug || console.log || (() => {});\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\nfunction save(namespaces) {\n\ttry {\n\t\tif (namespaces) {\n\t\t\texports.storage.setItem('debug', namespaces);\n\t\t} else {\n\t\t\texports.storage.removeItem('debug');\n\t\t}\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\nfunction load() {\n\tlet r;\n\ttry {\n\t\tr = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n\n\t// If debug isn't set in LS, and we're in Electron, try to load $DEBUG\n\tif (!r && typeof process !== 'undefined' && 'env' in process) {\n\t\tr = process.env.DEBUG;\n\t}\n\n\treturn r;\n}\n\n/**\n * Localstorage attempts to return the localstorage.\n *\n * This is necessary because safari throws\n * when a user disables cookies/localstorage\n * and you attempt to access it.\n *\n * @return {LocalStorage}\n * @api private\n */\n\nfunction localstorage() {\n\ttry {\n\t\t// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context\n\t\t// The Browser also has localStorage in the global context.\n\t\treturn localStorage;\n\t} catch (error) {\n\t\t// Swallow\n\t\t// XXX (@Qix-) should we be logging these?\n\t}\n}\n\nmodule.exports = require('./common')(exports);\n\nconst {formatters} = module.exports;\n\n/**\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\n */\n\nformatters.j = function (v) {\n\ttry {\n\t\treturn JSON.stringify(v);\n\t} catch (error) {\n\t\treturn '[UnexpectedJSONParseError]: ' + error.message;\n\t}\n};\n","import process from 'node:process';\nimport os from 'node:os';\nimport tty from 'node:tty';\n\n// From: https://github.com/sindresorhus/has-flag/blob/main/index.js\n/// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {\nfunction hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {\n\tconst prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');\n\tconst position = argv.indexOf(prefix + flag);\n\tconst terminatorPosition = argv.indexOf('--');\n\treturn position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);\n}\n\nconst {env} = process;\n\nlet flagForceColor;\nif (\n\thasFlag('no-color')\n\t|| hasFlag('no-colors')\n\t|| hasFlag('color=false')\n\t|| hasFlag('color=never')\n) {\n\tflagForceColor = 0;\n} else if (\n\thasFlag('color')\n\t|| hasFlag('colors')\n\t|| hasFlag('color=true')\n\t|| hasFlag('color=always')\n) {\n\tflagForceColor = 1;\n}\n\nfunction envForceColor() {\n\tif (!('FORCE_COLOR' in env)) {\n\t\treturn;\n\t}\n\n\tif (env.FORCE_COLOR === 'true') {\n\t\treturn 1;\n\t}\n\n\tif (env.FORCE_COLOR === 'false') {\n\t\treturn 0;\n\t}\n\n\tif (env.FORCE_COLOR.length === 0) {\n\t\treturn 1;\n\t}\n\n\tconst level = Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);\n\n\tif (![0, 1, 2, 3].includes(level)) {\n\t\treturn;\n\t}\n\n\treturn level;\n}\n\nfunction translateLevel(level) {\n\tif (level === 0) {\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tlevel,\n\t\thasBasic: true,\n\t\thas256: level >= 2,\n\t\thas16m: level >= 3,\n\t};\n}\n\nfunction _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {\n\tconst noFlagForceColor = envForceColor();\n\tif (noFlagForceColor !== undefined) {\n\t\tflagForceColor = noFlagForceColor;\n\t}\n\n\tconst forceColor = sniffFlags ? flagForceColor : noFlagForceColor;\n\n\tif (forceColor === 0) {\n\t\treturn 0;\n\t}\n\n\tif (sniffFlags) {\n\t\tif (hasFlag('color=16m')\n\t\t\t|| hasFlag('color=full')\n\t\t\t|| hasFlag('color=truecolor')) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (hasFlag('color=256')) {\n\t\t\treturn 2;\n\t\t}\n\t}\n\n\t// Check for Azure DevOps pipelines.\n\t// Has to be above the `!streamIsTTY` check.\n\tif ('TF_BUILD' in env && 'AGENT_NAME' in env) {\n\t\treturn 1;\n\t}\n\n\tif (haveStream && !streamIsTTY && forceColor === undefined) {\n\t\treturn 0;\n\t}\n\n\tconst min = forceColor || 0;\n\n\tif (env.TERM === 'dumb') {\n\t\treturn min;\n\t}\n\n\tif (process.platform === 'win32') {\n\t\t// Windows 10 build 10586 is the first Windows release that supports 256 colors.\n\t\t// Windows 10 build 14931 is the first release that supports 16m/TrueColor.\n\t\tconst osRelease = os.release().split('.');\n\t\tif (\n\t\t\tNumber(osRelease[0]) >= 10\n\t\t\t&& Number(osRelease[2]) >= 10_586\n\t\t) {\n\t\t\treturn Number(osRelease[2]) >= 14_931 ? 3 : 2;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\tif ('CI' in env) {\n\t\tif (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn min;\n\t}\n\n\tif ('TEAMCITY_VERSION' in env) {\n\t\treturn /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;\n\t}\n\n\tif (env.COLORTERM === 'truecolor') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-kitty') {\n\t\treturn 3;\n\t}\n\n\tif ('TERM_PROGRAM' in env) {\n\t\tconst version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);\n\n\t\tswitch (env.TERM_PROGRAM) {\n\t\t\tcase 'iTerm.app': {\n\t\t\t\treturn version >= 3 ? 3 : 2;\n\t\t\t}\n\n\t\t\tcase 'Apple_Terminal': {\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t}\n\n\tif (/-256(color)?$/i.test(env.TERM)) {\n\t\treturn 2;\n\t}\n\n\tif (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {\n\t\treturn 1;\n\t}\n\n\tif ('COLORTERM' in env) {\n\t\treturn 1;\n\t}\n\n\treturn min;\n}\n\nexport function createSupportsColor(stream, options = {}) {\n\tconst level = _supportsColor(stream, {\n\t\tstreamIsTTY: stream && stream.isTTY,\n\t\t...options,\n\t});\n\n\treturn translateLevel(level);\n}\n\nconst supportsColor = {\n\tstdout: createSupportsColor({isTTY: tty.isatty(1)}),\n\tstderr: createSupportsColor({isTTY: tty.isatty(2)}),\n};\n\nexport default supportsColor;\n","/**\n * Module dependencies.\n */\n\nconst tty = require('tty');\nconst util = require('util');\n\n/**\n * This is the Node.js implementation of `debug()`.\n */\n\nexports.init = init;\nexports.log = log;\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\nexports.destroy = util.deprecate(\n\t() => {},\n\t'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'\n);\n\n/**\n * Colors.\n */\n\nexports.colors = [6, 2, 3, 4, 5, 1];\n\ntry {\n\t// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)\n\t// eslint-disable-next-line import/no-extraneous-dependencies\n\tconst supportsColor = require('supports-color');\n\n\tif (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {\n\t\texports.colors = [\n\t\t\t20,\n\t\t\t21,\n\t\t\t26,\n\t\t\t27,\n\t\t\t32,\n\t\t\t33,\n\t\t\t38,\n\t\t\t39,\n\t\t\t40,\n\t\t\t41,\n\t\t\t42,\n\t\t\t43,\n\t\t\t44,\n\t\t\t45,\n\t\t\t56,\n\t\t\t57,\n\t\t\t62,\n\t\t\t63,\n\t\t\t68,\n\t\t\t69,\n\t\t\t74,\n\t\t\t75,\n\t\t\t76,\n\t\t\t77,\n\t\t\t78,\n\t\t\t79,\n\t\t\t80,\n\t\t\t81,\n\t\t\t92,\n\t\t\t93,\n\t\t\t98,\n\t\t\t99,\n\t\t\t112,\n\t\t\t113,\n\t\t\t128,\n\t\t\t129,\n\t\t\t134,\n\t\t\t135,\n\t\t\t148,\n\t\t\t149,\n\t\t\t160,\n\t\t\t161,\n\t\t\t162,\n\t\t\t163,\n\t\t\t164,\n\t\t\t165,\n\t\t\t166,\n\t\t\t167,\n\t\t\t168,\n\t\t\t169,\n\t\t\t170,\n\t\t\t171,\n\t\t\t172,\n\t\t\t173,\n\t\t\t178,\n\t\t\t179,\n\t\t\t184,\n\t\t\t185,\n\t\t\t196,\n\t\t\t197,\n\t\t\t198,\n\t\t\t199,\n\t\t\t200,\n\t\t\t201,\n\t\t\t202,\n\t\t\t203,\n\t\t\t204,\n\t\t\t205,\n\t\t\t206,\n\t\t\t207,\n\t\t\t208,\n\t\t\t209,\n\t\t\t214,\n\t\t\t215,\n\t\t\t220,\n\t\t\t221\n\t\t];\n\t}\n} catch (error) {\n\t// Swallow - we only care if `supports-color` is available; it doesn't have to be.\n}\n\n/**\n * Build up the default `inspectOpts` object from the environment variables.\n *\n * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js\n */\n\nexports.inspectOpts = Object.keys(process.env).filter(key => {\n\treturn /^debug_/i.test(key);\n}).reduce((obj, key) => {\n\t// Camel-case\n\tconst prop = key\n\t\t.substring(6)\n\t\t.toLowerCase()\n\t\t.replace(/_([a-z])/g, (_, k) => {\n\t\t\treturn k.toUpperCase();\n\t\t});\n\n\t// Coerce string value into JS value\n\tlet val = process.env[key];\n\tif (/^(yes|on|true|enabled)$/i.test(val)) {\n\t\tval = true;\n\t} else if (/^(no|off|false|disabled)$/i.test(val)) {\n\t\tval = false;\n\t} else if (val === 'null') {\n\t\tval = null;\n\t} else {\n\t\tval = Number(val);\n\t}\n\n\tobj[prop] = val;\n\treturn obj;\n}, {});\n\n/**\n * Is stdout a TTY? Colored output is enabled when `true`.\n */\n\nfunction useColors() {\n\treturn 'colors' in exports.inspectOpts ?\n\t\tBoolean(exports.inspectOpts.colors) :\n\t\ttty.isatty(process.stderr.fd);\n}\n\n/**\n * Adds ANSI color escape codes if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n\tconst {namespace: name, useColors} = this;\n\n\tif (useColors) {\n\t\tconst c = this.color;\n\t\tconst colorCode = '\\u001B[3' + (c < 8 ? c : '8;5;' + c);\n\t\tconst prefix = ` ${colorCode};1m${name} \\u001B[0m`;\n\n\t\targs[0] = prefix + args[0].split('\\n').join('\\n' + prefix);\n\t\targs.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\\u001B[0m');\n\t} else {\n\t\targs[0] = getDate() + name + ' ' + args[0];\n\t}\n}\n\nfunction getDate() {\n\tif (exports.inspectOpts.hideDate) {\n\t\treturn '';\n\t}\n\treturn new Date().toISOString() + ' ';\n}\n\n/**\n * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr.\n */\n\nfunction log(...args) {\n\treturn process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\\n');\n}\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\nfunction save(namespaces) {\n\tif (namespaces) {\n\t\tprocess.env.DEBUG = namespaces;\n\t} else {\n\t\t// If you set a process.env field to null or undefined, it gets cast to the\n\t\t// string 'null' or 'undefined'. Just delete instead.\n\t\tdelete process.env.DEBUG;\n\t}\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\n\nfunction load() {\n\treturn process.env.DEBUG;\n}\n\n/**\n * Init logic for `debug` instances.\n *\n * Create a new `inspectOpts` object in case `useColors` is set\n * differently for a particular `debug` instance.\n */\n\nfunction init(debug) {\n\tdebug.inspectOpts = {};\n\n\tconst keys = Object.keys(exports.inspectOpts);\n\tfor (let i = 0; i < keys.length; i++) {\n\t\tdebug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];\n\t}\n}\n\nmodule.exports = require('./common')(exports);\n\nconst {formatters} = module.exports;\n\n/**\n * Map %o to `util.inspect()`, all on a single line.\n */\n\nformatters.o = function (v) {\n\tthis.inspectOpts.colors = this.useColors;\n\treturn util.inspect(v, this.inspectOpts)\n\t\t.split('\\n')\n\t\t.map(str => str.trim())\n\t\t.join(' ');\n};\n\n/**\n * Map %O to `util.inspect()`, allowing multiple lines if needed.\n */\n\nformatters.O = function (v) {\n\tthis.inspectOpts.colors = this.useColors;\n\treturn util.inspect(v, this.inspectOpts);\n};\n","/**\n * Detect Electron renderer / nwjs process, which is node, but we should\n * treat as a browser.\n */\n\nif (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {\n\tmodule.exports = require('./browser.js');\n} else {\n\tmodule.exports = require('./node.js');\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.genRedactedString = exports.getStringValue = exports.MAX_ARGUMENT_LENGTH = void 0;\nconst debug_1 = require(\"debug\");\nconst MAX_ARGUMENT_LENGTH = 200;\nexports.MAX_ARGUMENT_LENGTH = MAX_ARGUMENT_LENGTH;\nconst NAMESPACE_PREFIX = \"ioredis\";\n/**\n * helper function that tried to get a string value for\n * arbitrary \"debug\" arg\n */\nfunction getStringValue(v) {\n if (v === null) {\n return;\n }\n switch (typeof v) {\n case \"boolean\":\n return;\n case \"number\":\n return;\n case \"object\":\n if (Buffer.isBuffer(v)) {\n return v.toString(\"hex\");\n }\n if (Array.isArray(v)) {\n return v.join(\",\");\n }\n try {\n return JSON.stringify(v);\n }\n catch (e) {\n return;\n }\n case \"string\":\n return v;\n }\n}\nexports.getStringValue = getStringValue;\n/**\n * helper function that redacts a string representation of a \"debug\" arg\n */\nfunction genRedactedString(str, maxLen) {\n const { length } = str;\n return length <= maxLen\n ? str\n : str.slice(0, maxLen) + ' ... <REDACTED full-length=\"' + length + '\">';\n}\nexports.genRedactedString = genRedactedString;\n/**\n * a wrapper for the `debug` module, used to generate\n * \"debug functions\" that trim the values in their output\n */\nfunction genDebugFunction(namespace) {\n const fn = (0, debug_1.default)(`${NAMESPACE_PREFIX}:${namespace}`);\n function wrappedDebug(...args) {\n if (!fn.enabled) {\n return; // no-op\n }\n // we skip the first arg because that is the message\n for (let i = 1; i < args.length; i++) {\n const str = getStringValue(args[i]);\n if (typeof str === \"string\" && str.length > MAX_ARGUMENT_LENGTH) {\n args[i] = genRedactedString(str, MAX_ARGUMENT_LENGTH);\n }\n }\n return fn.apply(null, args);\n }\n Object.defineProperties(wrappedDebug, {\n namespace: {\n get() {\n return fn.namespace;\n },\n },\n enabled: {\n get() {\n return fn.enabled;\n },\n },\n destroy: {\n get() {\n return fn.destroy;\n },\n },\n log: {\n get() {\n return fn.log;\n },\n set(l) {\n fn.log = l;\n },\n },\n });\n return wrappedDebug;\n}\nexports.default = genDebugFunction;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n/**\n * TLS settings for Redis Cloud. Updated on 2022-08-19.\n */\nconst RedisCloudCA = `-----BEGIN CERTIFICATE-----\nMIIDTzCCAjegAwIBAgIJAKSVpiDswLcwMA0GCSqGSIb3DQEBBQUAMD4xFjAUBgNV\nBAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTAeFw0xMzEwMDExMjE0NTVaFw0yMzA5MjkxMjE0NTVaMD4xFjAUBgNV\nBAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZqkh/DczWP\nJnxnHLQ7QL0T4B4CDKWBKCcisriGbA6ZePWVNo4hfKQC6JrzfR+081NeD6VcWUiz\nrmd+jtPhIY4c+WVQYm5PKaN6DT1imYdxQw7aqO5j2KUCEh/cznpLxeSHoTxlR34E\nQwF28Wl3eg2vc5ct8LjU3eozWVk3gb7alx9mSA2SgmuX5lEQawl++rSjsBStemY2\nBDwOpAMXIrdEyP/cVn8mkvi/BDs5M5G+09j0gfhyCzRWMQ7Hn71u1eolRxwVxgi3\nTMn+/vTaFSqxKjgck6zuAYjBRPaHe7qLxHNr1So/Mc9nPy+3wHebFwbIcnUojwbp\n4nctkWbjb2cCAwEAAaNQME4wHQYDVR0OBBYEFP1whtcrydmW3ZJeuSoKZIKjze3w\nMB8GA1UdIwQYMBaAFP1whtcrydmW3ZJeuSoKZIKjze3wMAwGA1UdEwQFMAMBAf8w\nDQYJKoZIhvcNAQEFBQADggEBAG2erXhwRAa7+ZOBs0B6X57Hwyd1R4kfmXcs0rta\nlbPpvgULSiB+TCbf3EbhJnHGyvdCY1tvlffLjdA7HJ0PCOn+YYLBA0pTU/dyvrN6\nSu8NuS5yubnt9mb13nDGYo1rnt0YRfxN+8DM3fXIVr038A30UlPX2Ou1ExFJT0MZ\nuFKY6ZvLdI6/1cbgmguMlAhM+DhKyV6Sr5699LM3zqeI816pZmlREETYkGr91q7k\nBpXJu/dtHaGxg1ZGu6w/PCsYGUcECWENYD4VQPd8N32JjOfu6vEgoEAwfPP+3oGp\nZ4m3ewACcWOAenqflb+cQYC4PsF7qbXDmRaWrbKntOlZ3n0=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIGMTCCBBmgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCVVMx\nCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJDQTESMBAGA1UECgwJUmVkaXNMYWJzMS0w\nKwYDVQQDDCRSZWRpc0xhYnMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN\nMTgwMjI1MTUzNzM3WhcNMjgwMjIzMTUzNzM3WjBfMQswCQYDVQQGEwJVUzELMAkG\nA1UECAwCQ0ExEjAQBgNVBAoMCVJlZGlzTGFiczEvMC0GA1UEAwwmUkNQIEludGVy\nbWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA\nA4ICDwAwggIKAoICAQDf9dqbxc8Bq7Ctq9rWcxrGNKKHivqLAFpPq02yLPx6fsOv\nTq7GsDChAYBBc4v7Y2Ap9RD5Vs3dIhEANcnolf27QwrG9RMnnvzk8pCvp1o6zSU4\nVuOE1W66/O1/7e2rVxyrnTcP7UgK43zNIXu7+tiAqWsO92uSnuMoGPGpeaUm1jym\nhjWKtkAwDFSqvHY+XL5qDVBEjeUe+WHkYUg40cAXjusAqgm2hZt29c2wnVrxW25W\nP0meNlzHGFdA2AC5z54iRiqj57dTfBTkHoBczQxcyw6hhzxZQ4e5I5zOKjXXEhZN\nr0tA3YC14CTabKRus/JmZieyZzRgEy2oti64tmLYTqSlAD78pRL40VNoaSYetXLw\nhhNsXCHgWaY6d5bLOc/aIQMAV5oLvZQKvuXAF1IDmhPA+bZbpWipp0zagf1P1H3s\nUzsMdn2KM0ejzgotbtNlj5TcrVwpmvE3ktvUAuA+hi3FkVx1US+2Gsp5x4YOzJ7u\nP1WPk6ShF0JgnJH2ILdj6kttTWwFzH17keSFICWDfH/+kM+k7Y1v3EXMQXE7y0T9\nMjvJskz6d/nv+sQhY04xt64xFMGTnZjlJMzfQNi7zWFLTZnDD0lPowq7l3YiPoTT\nt5Xky83lu0KZsZBo0WlWaDG00gLVdtRgVbcuSWxpi5BdLb1kRab66JptWjxwXQID\nAQABo4HrMIHoMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHBzOi8vcmwtY2Etc2VydmVy\nLnJlZGlzbGFicy5jb20vdjEvY3JsMEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcw\nAYYqaHR0cHM6Ly9ybC1jYS1zZXJ2ZXIucmVkaXNsYWJzLmNvbS92MS9vY3NwMB0G\nA1UdDgQWBBQHar5OKvQUpP2qWt6mckzToeCOHDAfBgNVHSMEGDAWgBQi42wH6hM4\nL2sujEvLM0/u8lRXTzASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIB\nhjANBgkqhkiG9w0BAQsFAAOCAgEAirEn/iTsAKyhd+pu2W3Z5NjCko4NPU0EYUbr\nAP7+POK2rzjIrJO3nFYQ/LLuC7KCXG+2qwan2SAOGmqWst13Y+WHp44Kae0kaChW\nvcYLXXSoGQGC8QuFSNUdaeg3RbMDYFT04dOkqufeWVccoHVxyTSg9eD8LZuHn5jw\n7QDLiEECBmIJHk5Eeo2TAZrx4Yx6ufSUX5HeVjlAzqwtAqdt99uCJ/EL8bgpWbe+\nXoSpvUv0SEC1I1dCAhCKAvRlIOA6VBcmzg5Am12KzkqTul12/VEFIgzqu0Zy2Jbc\nAUPrYVu/+tOGXQaijy7YgwH8P8n3s7ZeUa1VABJHcxrxYduDDJBLZi+MjheUDaZ1\njQRHYevI2tlqeSBqdPKG4zBY5lS0GiAlmuze5oENt0P3XboHoZPHiqcK3VECgTVh\n/BkJcuudETSJcZDmQ8YfoKfBzRQNg2sv/hwvUv73Ss51Sco8GEt2lD8uEdib1Q6z\nzDT5lXJowSzOD5ZA9OGDjnSRL+2riNtKWKEqvtEG3VBJoBzu9GoxbAc7wIZLxmli\niF5a/Zf5X+UXD3s4TMmy6C4QZJpAA2egsSQCnraWO2ULhh7iXMysSkF/nzVfZn43\niqpaB8++9a37hWq14ZmOv0TJIDz//b2+KC4VFXWQ5W5QC6whsjT+OlG4p5ZYG0jo\n616pxqo=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n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\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIEjzCCA3egAwIBAgIQe55B/ALCKJDZtdNT8kD6hTANBgkqhkiG9w0BAQsFADBM\nMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv\nYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMjAxMjYxMjAwMDBaFw0y\nNTAxMjYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu\nIG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIE9WIFRMUyBDQSAy\nMDIyIFEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmGmg1LW9b7Lf\n8zDD83yBDTEkt+FOxKJZqF4veWc5KZsQj9HfnUS2e5nj/E+JImlGPsQuoiosLuXD\nBVBNAMcUFa11buFMGMeEMwiTmCXoXRrXQmH0qjpOfKgYc5gHG3BsRGaRrf7VR4eg\nofNMG9wUBw4/g/TT7+bQJdA4NfE7Y4d5gEryZiBGB/swaX6Jp/8MF4TgUmOWmalK\ndZCKyb4sPGQFRTtElk67F7vU+wdGcrcOx1tDcIB0ncjLPMnaFicagl+daWGsKqTh\ncounQb6QJtYHa91KvCfKWocMxQ7OIbB5UARLPmC4CJ1/f8YFm35ebfzAeULYdGXu\njE9CLor0OwIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG\nCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW\nBBSH5Zq7a7B/t95GfJWkDBpA8HHqdjAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj\nmove4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw\nMi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1\ncmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w\nK6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwIQYD\nVR0gBBowGDAIBgZngQwBAgIwDAYKKwYBBAGgMgoBAjANBgkqhkiG9w0BAQsFAAOC\nAQEAKRic9/f+nmhQU/wz04APZLjgG5OgsuUOyUEZjKVhNGDwxGTvKhyXGGAMW2B/\n3bRi+aElpXwoxu3pL6fkElbX3B0BeS5LoDtxkyiVEBMZ8m+sXbocwlPyxrPbX6mY\n0rVIvnuUeBH8X0L5IwfpNVvKnBIilTbcebfHyXkPezGwz7E1yhUULjJFm2bt0SdX\ny+4X/WeiiYIv+fTVgZZgl+/2MKIsu/qdBJc3f3TvJ8nz+Eax1zgZmww+RSQWeOj3\n15Iw6Z5FX+NwzY/Ab+9PosR5UosSeq+9HhtaxZttXG1nVh+avYPGYddWmiMT90J5\nZgKnO/Fx2hBgTxhOTMYaD312kg==\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\nA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\nZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\nMTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\nA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\nRgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\ngHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\nKPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\nQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\nXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\nDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\nLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\nRUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\njjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\n6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\nmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\nMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\nWD9f\n-----END CERTIFICATE-----`;\nconst TLSProfiles = {\n RedisCloudFixed: { ca: RedisCloudCA },\n RedisCloudFlexible: { ca: RedisCloudCA },\n};\nexports.default = TLSProfiles;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.noop = exports.defaults = exports.Debug = exports.zipMap = exports.CONNECTION_CLOSED_ERROR_MSG = exports.shuffle = exports.sample = exports.resolveTLSProfile = exports.parseURL = exports.optimizeErrorStack = exports.toArg = exports.convertMapToArray = exports.convertObjectToArray = exports.timeout = exports.packObject = exports.isInt = exports.wrapMultiResult = exports.convertBufferToString = void 0;\nconst url_1 = require(\"url\");\nconst lodash_1 = require(\"./lodash\");\nObject.defineProperty(exports, \"defaults\", { enumerable: true, get: function () { return lodash_1.defaults; } });\nObject.defineProperty(exports, \"noop\", { enumerable: true, get: function () { return lodash_1.noop; } });\nconst debug_1 = require(\"./debug\");\nexports.Debug = debug_1.default;\nconst TLSProfiles_1 = require(\"../constants/TLSProfiles\");\n/**\n * Convert a buffer to string, supports buffer array\n *\n * @example\n * ```js\n * const input = [Buffer.from('foo'), [Buffer.from('bar')]]\n * const res = convertBufferToString(input, 'utf8')\n * expect(res).to.eql(['foo', ['bar']])\n * ```\n */\nfunction convertBufferToString(value, encoding) {\n if (value instanceof Buffer) {\n return value.toString(encoding);\n }\n if (Array.isArray(value)) {\n const length = value.length;\n const res = Array(length);\n for (let i = 0; i < length; ++i) {\n res[i] =\n value[i] instanceof Buffer && encoding === \"utf8\"\n ? value[i].toString()\n : convertBufferToString(value[i], encoding);\n }\n return res;\n }\n return value;\n}\nexports.convertBufferToString = convertBufferToString;\n/**\n * Convert a list of results to node-style\n *\n * @example\n * ```js\n * const input = ['a', 'b', new Error('c'), 'd']\n * const output = exports.wrapMultiResult(input)\n * expect(output).to.eql([[null, 'a'], [null, 'b'], [new Error('c')], [null, 'd'])\n * ```\n */\nfunction wrapMultiResult(arr) {\n // When using WATCH/EXEC transactions, the EXEC will return\n // a null instead of an array\n if (!arr) {\n return null;\n }\n const result = [];\n const length = arr.length;\n for (let i = 0; i < length; ++i) {\n const item = arr[i];\n if (item instanceof Error) {\n result.push([item]);\n }\n else {\n result.push([null, item]);\n }\n }\n return result;\n}\nexports.wrapMultiResult = wrapMultiResult;\n/**\n * Detect if the argument is a int\n * @example\n * ```js\n * > isInt('123')\n * true\n * > isInt('123.3')\n * false\n * > isInt('1x')\n * false\n * > isInt(123)\n * true\n * > isInt(true)\n * false\n * ```\n */\nfunction isInt(value) {\n const x = parseFloat(value);\n return !isNaN(value) && (x | 0) === x;\n}\nexports.isInt = isInt;\n/**\n * Pack an array to an Object\n *\n * @example\n * ```js\n * > packObject(['a', 'b', 'c', 'd'])\n * { a: 'b', c: 'd' }\n * ```\n */\nfunction packObject(array) {\n const result = {};\n const length = array.length;\n for (let i = 1; i < length; i += 2) {\n result[array[i - 1]] = array[i];\n }\n return result;\n}\nexports.packObject = packObject;\n/**\n * Return a callback with timeout\n */\nfunction timeout(callback, timeout) {\n let timer = null;\n const run = function () {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n callback.apply(this, arguments);\n }\n };\n timer = setTimeout(run, timeout, new Error(\"timeout\"));\n return run;\n}\nexports.timeout = timeout;\n/**\n * Convert an object to an array\n * @example\n * ```js\n * > convertObjectToArray({ a: '1' })\n * ['a', '1']\n * ```\n */\nfunction convertObjectToArray(obj) {\n const result = [];\n const keys = Object.keys(obj); // Object.entries requires node 7+\n for (let i = 0, l = keys.length; i < l; i++) {\n result.push(keys[i], obj[keys[i]]);\n }\n return result;\n}\nexports.convertObjectToArray = convertObjectToArray;\n/**\n * Convert a map to an array\n * @example\n * ```js\n * > convertMapToArray(new Map([[1, '2']]))\n * [1, '2']\n * ```\n */\nfunction convertMapToArray(map) {\n const result = [];\n let pos = 0;\n map.forEach(function (value, key) {\n result[pos] = key;\n result[pos + 1] = value;\n pos += 2;\n });\n return result;\n}\nexports.convertMapToArray = convertMapToArray;\n/**\n * Convert a non-string arg to a string\n */\nfunction toArg(arg) {\n if (arg === null || typeof arg === \"undefined\") {\n return \"\";\n }\n return String(arg);\n}\nexports.toArg = toArg;\n/**\n * Optimize error stack\n *\n * @param error actually error\n * @param friendlyStack the stack that more meaningful\n * @param filterPath only show stacks with the specified path\n */\nfunction optimizeErrorStack(error, friendlyStack, filterPath) {\n const stacks = friendlyStack.split(\"\\n\");\n let lines = \"\";\n let i;\n for (i = 1; i < stacks.length; ++i) {\n if (stacks[i].indexOf(filterPath) === -1) {\n break;\n }\n }\n for (let j = i; j < stacks.length; ++j) {\n lines += \"\\n\" + stacks[j];\n }\n if (error.stack) {\n const pos = error.stack.indexOf(\"\\n\");\n error.stack = error.stack.slice(0, pos) + lines;\n }\n return error;\n}\nexports.optimizeErrorStack = optimizeErrorStack;\n/**\n * Parse the redis protocol url\n */\nfunction parseURL(url) {\n if (isInt(url)) {\n return { port: url };\n }\n let parsed = (0, url_1.parse)(url, true, true);\n if (!parsed.slashes && url[0] !== \"/\") {\n url = \"//\" + url;\n parsed = (0, url_1.parse)(url, true, true);\n }\n const options = parsed.query || {};\n const result = {};\n if (parsed.auth) {\n const index = parsed.auth.indexOf(\":\");\n result.username = index === -1 ? parsed.auth : parsed.auth.slice(0, index);\n result.password = index === -1 ? \"\" : parsed.auth.slice(index + 1);\n }\n if (parsed.pathname) {\n if (parsed.protocol === \"redis:\" || parsed.protocol === \"rediss:\") {\n if (parsed.pathname.length > 1) {\n result.db = parsed.pathname.slice(1);\n }\n }\n else {\n result.path = parsed.pathname;\n }\n }\n if (parsed.host) {\n result.host = parsed.hostname;\n }\n if (parsed.port) {\n result.port = parsed.port;\n }\n if (typeof options.family === \"string\") {\n const intFamily = Number.parseInt(options.family, 10);\n if (!Number.isNaN(intFamily)) {\n result.family = intFamily;\n }\n }\n (0, lodash_1.defaults)(result, options);\n return result;\n}\nexports.parseURL = parseURL;\n/**\n * Resolve TLS profile shortcut in connection options\n */\nfunction resolveTLSProfile(options) {\n let tls = options === null || options === void 0 ? void 0 : options.tls;\n if (typeof tls === \"string\")\n tls = { profile: tls };\n const profile = TLSProfiles_1.default[tls === null || tls === void 0 ? void 0 : tls.profile];\n if (profile) {\n tls = Object.assign({}, profile, tls);\n delete tls.profile;\n options = Object.assign({}, options, { tls });\n }\n return options;\n}\nexports.resolveTLSProfile = resolveTLSProfile;\n/**\n * Get a random element from `array`\n */\nfunction sample(array, from = 0) {\n const length = array.length;\n if (from >= length) {\n return null;\n }\n return array[from + Math.floor(Math.random() * (length - from))];\n}\nexports.sample = sample;\n/**\n * Shuffle the array using the Fisher-Yates Shuffle.\n * This method will mutate the original array.\n */\nfunction shuffle(array) {\n let counter = array.length;\n // While there are elements in the array\n while (counter > 0) {\n // Pick a random index\n const index = Math.floor(Math.random() * counter);\n // Decrease counter by 1\n counter--;\n // And swap the last element with it\n [array[counter], array[index]] = [array[index], array[counter]];\n }\n return array;\n}\nexports.shuffle = shuffle;\n/**\n * Error message for connection being disconnected\n */\nexports.CONNECTION_CLOSED_ERROR_MSG = \"Connection is closed.\";\nfunction zipMap(keys, values) {\n const map = new Map();\n keys.forEach((key, index) => {\n map.set(key, values[index]);\n });\n return map;\n}\nexports.zipMap = zipMap;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst commands_1 = require(\"@ioredis/commands\");\nconst calculateSlot = require(\"cluster-key-slot\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst utils_1 = require(\"./utils\");\n/**\n * Command instance\n *\n * It's rare that you need to create a Command instance yourself.\n *\n * ```js\n * var infoCommand = new Command('info', null, function (err, result) {\n * console.log('result', result);\n * });\n *\n * redis.sendCommand(infoCommand);\n *\n * // When no callback provided, Command instance will have a `promise` property,\n * // which will resolve/reject with the result of the command.\n * var getCommand = new Command('get', ['foo']);\n * getCommand.promise.then(function (result) {\n * console.log('result', result);\n * });\n * ```\n */\nclass Command {\n /**\n * Creates an instance of Command.\n * @param name Command name\n * @param args An array of command arguments\n * @param options\n * @param callback The callback that handles the response.\n * If omit, the response will be handled via Promise\n */\n constructor(name, args = [], options = {}, callback) {\n this.name = name;\n this.inTransaction = false;\n this.isResolved = false;\n this.transformed = false;\n this.replyEncoding = options.replyEncoding;\n this.errorStack = options.errorStack;\n this.args = args.flat();\n this.callback = callback;\n this.initPromise();\n if (options.keyPrefix) {\n // @ts-expect-error\n const isBufferKeyPrefix = options.keyPrefix instanceof Buffer;\n // @ts-expect-error\n let keyPrefixBuffer = isBufferKeyPrefix\n ? options.keyPrefix\n : null;\n this._iterateKeys((key) => {\n if (key instanceof Buffer) {\n if (keyPrefixBuffer === null) {\n keyPrefixBuffer = Buffer.from(options.keyPrefix);\n }\n return Buffer.concat([keyPrefixBuffer, key]);\n }\n else if (isBufferKeyPrefix) {\n // @ts-expect-error\n return Buffer.concat([options.keyPrefix, Buffer.from(String(key))]);\n }\n return options.keyPrefix + key;\n });\n }\n if (options.readOnly) {\n this.isReadOnly = true;\n }\n }\n /**\n * Check whether the command has the flag\n */\n static checkFlag(flagName, commandName) {\n return !!this.getFlagMap()[flagName][commandName];\n }\n static setArgumentTransformer(name, func) {\n this._transformer.argument[name] = func;\n }\n static setReplyTransformer(name, func) {\n this._transformer.reply[name] = func;\n }\n static getFlagMap() {\n if (!this.flagMap) {\n this.flagMap = Object.keys(Command.FLAGS).reduce((map, flagName) => {\n map[flagName] = {};\n Command.FLAGS[flagName].forEach((commandName) => {\n map[flagName][commandName] = true;\n });\n return map;\n }, {});\n }\n return this.flagMap;\n }\n getSlot() {\n if (typeof this.slot === \"undefined\") {\n const key = this.getKeys()[0];\n this.slot = key == null ? null : calculateSlot(key);\n }\n return this.slot;\n }\n getKeys() {\n return this._iterateKeys();\n }\n /**\n * Convert command to writable buffer or string\n */\n toWritable(_socket) {\n let result;\n const commandStr = \"*\" +\n (this.args.length + 1) +\n \"\\r\\n$\" +\n Buffer.byteLength(this.name) +\n \"\\r\\n\" +\n this.name +\n \"\\r\\n\";\n if (this.bufferMode) {\n const buffers = new MixedBuffers();\n buffers.push(commandStr);\n for (let i = 0; i < this.args.length; ++i) {\n const arg = this.args[i];\n if (arg instanceof Buffer) {\n if (arg.length === 0) {\n buffers.push(\"$0\\r\\n\\r\\n\");\n }\n else {\n buffers.push(\"$\" + arg.length + \"\\r\\n\");\n buffers.push(arg);\n buffers.push(\"\\r\\n\");\n }\n }\n else {\n buffers.push(\"$\" +\n Buffer.byteLength(arg) +\n \"\\r\\n\" +\n arg +\n \"\\r\\n\");\n }\n }\n result = buffers.toBuffer();\n }\n else {\n result = commandStr;\n for (let i = 0; i < this.args.length; ++i) {\n const arg = this.args[i];\n result +=\n \"$\" +\n Buffer.byteLength(arg) +\n \"\\r\\n\" +\n arg +\n \"\\r\\n\";\n }\n }\n return result;\n }\n stringifyArguments() {\n for (let i = 0; i < this.args.length; ++i) {\n const arg = this.args[i];\n if (typeof arg === \"string\") {\n // buffers and strings don't need any transformation\n }\n else if (arg instanceof Buffer) {\n this.bufferMode = true;\n }\n else {\n this.args[i] = (0, utils_1.toArg)(arg);\n }\n }\n }\n /**\n * Convert buffer/buffer[] to string/string[],\n * and apply reply transformer.\n */\n transformReply(result) {\n if (this.replyEncoding) {\n result = (0, utils_1.convertBufferToString)(result, this.replyEncoding);\n }\n const transformer = Command._transformer.reply[this.name];\n if (transformer) {\n result = transformer(result);\n }\n return result;\n }\n /**\n * Set the wait time before terminating the attempt to execute a command\n * and generating an error.\n */\n setTimeout(ms) {\n if (!this._commandTimeoutTimer) {\n this._commandTimeoutTimer = setTimeout(() => {\n if (!this.isResolved) {\n this.reject(new Error(\"Command timed out\"));\n }\n }, ms);\n }\n }\n initPromise() {\n const promise = new Promise((resolve, reject) => {\n if (!this.transformed) {\n this.transformed = true;\n const transformer = Command._transformer.argument[this.name];\n if (transformer) {\n this.args = transformer(this.args);\n }\n this.stringifyArguments();\n }\n this.resolve = this._convertValue(resolve);\n if (this.errorStack) {\n this.reject = (err) => {\n reject((0, utils_1.optimizeErrorStack)(err, this.errorStack.stack, __dirname));\n };\n }\n else {\n this.reject = reject;\n }\n });\n this.promise = (0, standard_as_callback_1.default)(promise, this.callback);\n }\n /**\n * Iterate through the command arguments that are considered keys.\n */\n _iterateKeys(transform = (key) => key) {\n if (typeof this.keys === \"undefined\") {\n this.keys = [];\n if ((0, commands_1.exists)(this.name)) {\n // @ts-expect-error\n const keyIndexes = (0, commands_1.getKeyIndexes)(this.name, this.args);\n for (const index of keyIndexes) {\n this.args[index] = transform(this.args[index]);\n this.keys.push(this.args[index]);\n }\n }\n }\n return this.keys;\n }\n /**\n * Convert the value from buffer to the target encoding.\n */\n _convertValue(resolve) {\n return (value) => {\n try {\n const existingTimer = this._commandTimeoutTimer;\n if (existingTimer) {\n clearTimeout(existingTimer);\n delete this._commandTimeoutTimer;\n }\n resolve(this.transformReply(value));\n this.isResolved = true;\n }\n catch (err) {\n this.reject(err);\n }\n return this.promise;\n };\n }\n}\nexports.default = Command;\nCommand.FLAGS = {\n VALID_IN_SUBSCRIBER_MODE: [\n \"subscribe\",\n \"psubscribe\",\n \"unsubscribe\",\n \"punsubscribe\",\n \"ssubscribe\",\n \"sunsubscribe\",\n \"ping\",\n \"quit\",\n ],\n VALID_IN_MONITOR_MODE: [\"monitor\", \"auth\"],\n ENTER_SUBSCRIBER_MODE: [\"subscribe\", \"psubscribe\", \"ssubscribe\"],\n EXIT_SUBSCRIBER_MODE: [\"unsubscribe\", \"punsubscribe\", \"sunsubscribe\"],\n WILL_DISCONNECT: [\"quit\"],\n};\nCommand._transformer = {\n argument: {},\n reply: {},\n};\nconst msetArgumentTransformer = function (args) {\n if (args.length === 1) {\n if (args[0] instanceof Map) {\n return (0, utils_1.convertMapToArray)(args[0]);\n }\n if (typeof args[0] === \"object\" && args[0] !== null) {\n return (0, utils_1.convertObjectToArray)(args[0]);\n }\n }\n return args;\n};\nconst hsetArgumentTransformer = function (args) {\n if (args.length === 2) {\n if (args[1] instanceof Map) {\n return [args[0]].concat((0, utils_1.convertMapToArray)(args[1]));\n }\n if (typeof args[1] === \"object\" && args[1] !== null) {\n return [args[0]].concat((0, utils_1.convertObjectToArray)(args[1]));\n }\n }\n return args;\n};\nCommand.setArgumentTransformer(\"mset\", msetArgumentTransformer);\nCommand.setArgumentTransformer(\"msetnx\", msetArgumentTransformer);\nCommand.setArgumentTransformer(\"hset\", hsetArgumentTransformer);\nCommand.setArgumentTransformer(\"hmset\", hsetArgumentTransformer);\nCommand.setReplyTransformer(\"hgetall\", function (result) {\n if (Array.isArray(result)) {\n const obj = {};\n for (let i = 0; i < result.length; i += 2) {\n const key = result[i];\n const value = result[i + 1];\n if (key in obj) {\n // can only be truthy if the property is special somehow, like '__proto__' or 'constructor'\n // https://github.com/luin/ioredis/issues/1267\n Object.defineProperty(obj, key, {\n value,\n configurable: true,\n enumerable: true,\n writable: true,\n });\n }\n else {\n obj[key] = value;\n }\n }\n return obj;\n }\n return result;\n});\nclass MixedBuffers {\n constructor() {\n this.length = 0;\n this.items = [];\n }\n push(x) {\n this.length += Buffer.byteLength(x);\n this.items.push(x);\n }\n toBuffer() {\n const result = Buffer.allocUnsafe(this.length);\n let offset = 0;\n for (const item of this.items) {\n const length = Buffer.byteLength(item);\n Buffer.isBuffer(item)\n ? item.copy(result, offset)\n : result.write(item, offset, length);\n offset += length;\n }\n return result;\n }\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst redis_errors_1 = require(\"redis-errors\");\nclass ClusterAllFailedError extends redis_errors_1.RedisError {\n constructor(message, lastNodeError) {\n super(message);\n this.lastNodeError = lastNodeError;\n Error.captureStackTrace(this, this.constructor);\n }\n get name() {\n return this.constructor.name;\n }\n}\nexports.default = ClusterAllFailedError;\nClusterAllFailedError.defaultMessage = \"Failed to refresh slots cache.\";\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst stream_1 = require(\"stream\");\n/**\n * Convenient class to convert the process of scanning keys to a readable stream.\n */\nclass ScanStream extends stream_1.Readable {\n constructor(opt) {\n super(opt);\n this.opt = opt;\n this._redisCursor = \"0\";\n this._redisDrained = false;\n }\n _read() {\n if (this._redisDrained) {\n this.push(null);\n return;\n }\n const args = [this._redisCursor];\n if (this.opt.key) {\n args.unshift(this.opt.key);\n }\n if (this.opt.match) {\n args.push(\"MATCH\", this.opt.match);\n }\n if (this.opt.type) {\n args.push(\"TYPE\", this.opt.type);\n }\n if (this.opt.count) {\n args.push(\"COUNT\", String(this.opt.count));\n }\n if (this.opt.noValues) {\n args.push(\"NOVALUES\");\n }\n this.opt.redis[this.opt.command](args, (err, res) => {\n if (err) {\n this.emit(\"error\", err);\n return;\n }\n this._redisCursor = res[0] instanceof Buffer ? res[0].toString() : res[0];\n if (this._redisCursor === \"0\") {\n this._redisDrained = true;\n }\n this.push(res[1]);\n });\n }\n close() {\n this._redisDrained = true;\n }\n}\nexports.default = ScanStream;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.executeWithAutoPipelining = exports.getFirstValueInFlattenedArray = exports.shouldUseAutoPipelining = exports.notAllowedAutoPipelineCommands = exports.kCallbacks = exports.kExec = void 0;\nconst lodash_1 = require(\"./utils/lodash\");\nconst calculateSlot = require(\"cluster-key-slot\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nexports.kExec = Symbol(\"exec\");\nexports.kCallbacks = Symbol(\"callbacks\");\nexports.notAllowedAutoPipelineCommands = [\n \"auth\",\n \"info\",\n \"script\",\n \"quit\",\n \"cluster\",\n \"pipeline\",\n \"multi\",\n \"subscribe\",\n \"psubscribe\",\n \"unsubscribe\",\n \"unpsubscribe\",\n \"select\",\n];\nfunction executeAutoPipeline(client, slotKey) {\n /*\n If a pipeline is already executing, keep queueing up commands\n since ioredis won't serve two pipelines at the same time\n */\n if (client._runningAutoPipelines.has(slotKey)) {\n return;\n }\n if (!client._autoPipelines.has(slotKey)) {\n /*\n Rare edge case. Somehow, something has deleted this running autopipeline in an immediate\n call to executeAutoPipeline.\n \n Maybe the callback in the pipeline.exec is sometimes called in the same tick,\n e.g. if redis is disconnected?\n */\n return;\n }\n client._runningAutoPipelines.add(slotKey);\n // Get the pipeline and immediately delete it so that new commands are queued on a new pipeline\n const pipeline = client._autoPipelines.get(slotKey);\n client._autoPipelines.delete(slotKey);\n const callbacks = pipeline[exports.kCallbacks];\n // Stop keeping a reference to callbacks immediately after the callbacks stop being used.\n // This allows the GC to reclaim objects referenced by callbacks, especially with 16384 slots\n // in Redis.Cluster\n pipeline[exports.kCallbacks] = null;\n // Perform the call\n pipeline.exec(function (err, results) {\n client._runningAutoPipelines.delete(slotKey);\n /*\n Invoke all callback in nextTick so the stack is cleared\n and callbacks can throw errors without affecting other callbacks.\n */\n if (err) {\n for (let i = 0; i < callbacks.length; i++) {\n process.nextTick(callbacks[i], err);\n }\n }\n else {\n for (let i = 0; i < callbacks.length; i++) {\n process.nextTick(callbacks[i], ...results[i]);\n }\n }\n // If there is another pipeline on the same node, immediately execute it without waiting for nextTick\n if (client._autoPipelines.has(slotKey)) {\n executeAutoPipeline(client, slotKey);\n }\n });\n}\nfunction shouldUseAutoPipelining(client, functionName, commandName) {\n return (functionName &&\n client.options.enableAutoPipelining &&\n !client.isPipeline &&\n !exports.notAllowedAutoPipelineCommands.includes(commandName) &&\n !client.options.autoPipeliningIgnoredCommands.includes(commandName));\n}\nexports.shouldUseAutoPipelining = shouldUseAutoPipelining;\nfunction getFirstValueInFlattenedArray(args) {\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (typeof arg === \"string\") {\n return arg;\n }\n else if (Array.isArray(arg) || (0, lodash_1.isArguments)(arg)) {\n if (arg.length === 0) {\n continue;\n }\n return arg[0];\n }\n const flattened = [arg].flat();\n if (flattened.length > 0) {\n return flattened[0];\n }\n }\n return undefined;\n}\nexports.getFirstValueInFlattenedArray = getFirstValueInFlattenedArray;\nfunction executeWithAutoPipelining(client, functionName, commandName, args, callback) {\n // On cluster mode let's wait for slots to be available\n if (client.isCluster && !client.slots.length) {\n if (client.status === \"wait\")\n client.connect().catch(lodash_1.noop);\n return (0, standard_as_callback_1.default)(new Promise(function (resolve, reject) {\n client.delayUntilReady((err) => {\n if (err) {\n reject(err);\n return;\n }\n executeWithAutoPipelining(client, functionName, commandName, args, null).then(resolve, reject);\n });\n }), callback);\n }\n // If we have slot information, we can improve routing by grouping slots served by the same subset of nodes\n // Note that the first value in args may be a (possibly empty) array.\n // ioredis will only flatten one level of the array, in the Command constructor.\n const prefix = client.options.keyPrefix || \"\";\n const slotKey = client.isCluster\n ? client.slots[calculateSlot(`${prefix}${getFirstValueInFlattenedArray(args)}`)].join(\",\")\n : \"main\";\n if (!client._autoPipelines.has(slotKey)) {\n const pipeline = client.pipeline();\n pipeline[exports.kExec] = false;\n pipeline[exports.kCallbacks] = [];\n client._autoPipelines.set(slotKey, pipeline);\n }\n const pipeline = client._autoPipelines.get(slotKey);\n /*\n Mark the pipeline as scheduled.\n The symbol will make sure that the pipeline is only scheduled once per tick.\n New commands are appended to an already scheduled pipeline.\n */\n if (!pipeline[exports.kExec]) {\n pipeline[exports.kExec] = true;\n /*\n Deferring with setImmediate so we have a chance to capture multiple\n commands that can be scheduled by I/O events already in the event loop queue.\n */\n setImmediate(executeAutoPipeline, client, slotKey);\n }\n // Create the promise which will execute the command in the pipeline.\n const autoPipelinePromise = new Promise(function (resolve, reject) {\n pipeline[exports.kCallbacks].push(function (err, value) {\n if (err) {\n reject(err);\n return;\n }\n resolve(value);\n });\n if (functionName === \"call\") {\n args.unshift(commandName);\n }\n pipeline[functionName](...args);\n });\n return (0, standard_as_callback_1.default)(autoPipelinePromise, callback);\n}\nexports.executeWithAutoPipelining = executeWithAutoPipelining;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst crypto_1 = require(\"crypto\");\nconst Command_1 = require(\"./Command\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nclass Script {\n constructor(lua, numberOfKeys = null, keyPrefix = \"\", readOnly = false) {\n this.lua = lua;\n this.numberOfKeys = numberOfKeys;\n this.keyPrefix = keyPrefix;\n this.readOnly = readOnly;\n this.sha = (0, crypto_1.createHash)(\"sha1\").update(lua).digest(\"hex\");\n const sha = this.sha;\n const socketHasScriptLoaded = new WeakSet();\n this.Command = class CustomScriptCommand extends Command_1.default {\n toWritable(socket) {\n const origReject = this.reject;\n this.reject = (err) => {\n if (err.message.indexOf(\"NOSCRIPT\") !== -1) {\n socketHasScriptLoaded.delete(socket);\n }\n origReject.call(this, err);\n };\n if (!socketHasScriptLoaded.has(socket)) {\n socketHasScriptLoaded.add(socket);\n this.name = \"eval\";\n this.args[0] = lua;\n }\n else if (this.name === \"eval\") {\n this.name = \"evalsha\";\n this.args[0] = sha;\n }\n return super.toWritable(socket);\n }\n };\n }\n execute(container, args, options, callback) {\n if (typeof this.numberOfKeys === \"number\") {\n args.unshift(this.numberOfKeys);\n }\n if (this.keyPrefix) {\n options.keyPrefix = this.keyPrefix;\n }\n if (this.readOnly) {\n options.readOnly = true;\n }\n const evalsha = new this.Command(\"evalsha\", [this.sha, ...args], options);\n evalsha.promise = evalsha.promise.catch((err) => {\n if (err.message.indexOf(\"NOSCRIPT\") === -1) {\n throw err;\n }\n // Resend the same custom evalsha command that gets transformed\n // to an eval in case it's not loaded yet on the connection.\n const resend = new this.Command(\"evalsha\", [this.sha, ...args], options);\n const client = container.isPipeline ? container.redis : container;\n return client.sendCommand(resend);\n });\n (0, standard_as_callback_1.default)(evalsha.promise, callback);\n return container.sendCommand(evalsha);\n }\n}\nexports.default = Script;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst commands_1 = require(\"@ioredis/commands\");\nconst autoPipelining_1 = require(\"../autoPipelining\");\nconst Command_1 = require(\"../Command\");\nconst Script_1 = require(\"../Script\");\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nclass Commander {\n constructor() {\n this.options = {};\n /**\n * @ignore\n */\n this.scriptsSet = {};\n /**\n * @ignore\n */\n this.addedBuiltinSet = new Set();\n }\n /**\n * Return supported builtin commands\n */\n getBuiltinCommands() {\n return commands.slice(0);\n }\n /**\n * Create a builtin command\n */\n createBuiltinCommand(commandName) {\n return {\n string: generateFunction(null, commandName, \"utf8\"),\n buffer: generateFunction(null, commandName, null),\n };\n }\n /**\n * Create add builtin command\n */\n addBuiltinCommand(commandName) {\n this.addedBuiltinSet.add(commandName);\n this[commandName] = generateFunction(commandName, commandName, \"utf8\");\n this[commandName + \"Buffer\"] = generateFunction(commandName + \"Buffer\", commandName, null);\n }\n /**\n * Define a custom command using lua script\n */\n defineCommand(name, definition) {\n const script = new Script_1.default(definition.lua, definition.numberOfKeys, this.options.keyPrefix, definition.readOnly);\n this.scriptsSet[name] = script;\n this[name] = generateScriptingFunction(name, name, script, \"utf8\");\n this[name + \"Buffer\"] = generateScriptingFunction(name + \"Buffer\", name, script, null);\n }\n /**\n * @ignore\n */\n sendCommand(command, stream, node) {\n throw new Error('\"sendCommand\" is not implemented');\n }\n}\nconst commands = commands_1.list.filter((command) => command !== \"monitor\");\ncommands.push(\"sentinel\");\ncommands.forEach(function (commandName) {\n Commander.prototype[commandName] = generateFunction(commandName, commandName, \"utf8\");\n Commander.prototype[commandName + \"Buffer\"] = generateFunction(commandName + \"Buffer\", commandName, null);\n});\nCommander.prototype.call = generateFunction(\"call\", \"utf8\");\nCommander.prototype.callBuffer = generateFunction(\"callBuffer\", null);\n// @ts-expect-error\nCommander.prototype.send_command = Commander.prototype.call;\nfunction generateFunction(functionName, _commandName, _encoding) {\n if (typeof _encoding === \"undefined\") {\n _encoding = _commandName;\n _commandName = null;\n }\n return function (...args) {\n const commandName = (_commandName || args.shift());\n let callback = args[args.length - 1];\n if (typeof callback === \"function\") {\n args.pop();\n }\n else {\n callback = undefined;\n }\n const options = {\n errorStack: this.options.showFriendlyErrorStack ? new Error() : undefined,\n keyPrefix: this.options.keyPrefix,\n replyEncoding: _encoding,\n };\n // No auto pipeline, use regular command sending\n if (!(0, autoPipelining_1.shouldUseAutoPipelining)(this, functionName, commandName)) {\n return this.sendCommand(\n // @ts-expect-error\n new Command_1.default(commandName, args, options, callback));\n }\n // Create a new pipeline and make sure it's scheduled\n return (0, autoPipelining_1.executeWithAutoPipelining)(this, functionName, commandName, \n // @ts-expect-error\n args, callback);\n };\n}\nfunction generateScriptingFunction(functionName, commandName, script, encoding) {\n return function (...args) {\n const callback = typeof args[args.length - 1] === \"function\" ? args.pop() : undefined;\n const options = {\n replyEncoding: encoding,\n };\n if (this.options.showFriendlyErrorStack) {\n options.errorStack = new Error();\n }\n // No auto pipeline, use regular command sending\n if (!(0, autoPipelining_1.shouldUseAutoPipelining)(this, functionName, commandName)) {\n return script.execute(this, args, options, callback);\n }\n // Create a new pipeline and make sure it's scheduled\n return (0, autoPipelining_1.executeWithAutoPipelining)(this, functionName, commandName, args, callback);\n };\n}\nexports.default = Commander;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst calculateSlot = require(\"cluster-key-slot\");\nconst commands_1 = require(\"@ioredis/commands\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst util_1 = require(\"util\");\nconst Command_1 = require(\"./Command\");\nconst utils_1 = require(\"./utils\");\nconst Commander_1 = require(\"./utils/Commander\");\n/*\n This function derives from the cluster-key-slot implementation.\n Instead of checking that all keys have the same slot, it checks that all slots are served by the same set of nodes.\n If this is satisfied, it returns the first key's slot.\n*/\nfunction generateMultiWithNodes(redis, keys) {\n const slot = calculateSlot(keys[0]);\n const target = redis._groupsBySlot[slot];\n for (let i = 1; i < keys.length; i++) {\n if (redis._groupsBySlot[calculateSlot(keys[i])] !== target) {\n return -1;\n }\n }\n return slot;\n}\nclass Pipeline extends Commander_1.default {\n constructor(redis) {\n super();\n this.redis = redis;\n this.isPipeline = true;\n this.replyPending = 0;\n this._queue = [];\n this._result = [];\n this._transactions = 0;\n this._shaToScript = {};\n this.isCluster =\n this.redis.constructor.name === \"Cluster\" || this.redis.isCluster;\n this.options = redis.options;\n Object.keys(redis.scriptsSet).forEach((name) => {\n const script = redis.scriptsSet[name];\n this._shaToScript[script.sha] = script;\n this[name] = redis[name];\n this[name + \"Buffer\"] = redis[name + \"Buffer\"];\n });\n redis.addedBuiltinSet.forEach((name) => {\n this[name] = redis[name];\n this[name + \"Buffer\"] = redis[name + \"Buffer\"];\n });\n this.promise = new Promise((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n const _this = this;\n Object.defineProperty(this, \"length\", {\n get: function () {\n return _this._queue.length;\n },\n });\n }\n fillResult(value, position) {\n if (this._queue[position].name === \"exec\" && Array.isArray(value[1])) {\n const execLength = value[1].length;\n for (let i = 0; i < execLength; i++) {\n if (value[1][i] instanceof Error) {\n continue;\n }\n const cmd = this._queue[position - (execLength - i)];\n try {\n value[1][i] = cmd.transformReply(value[1][i]);\n }\n catch (err) {\n value[1][i] = err;\n }\n }\n }\n this._result[position] = value;\n if (--this.replyPending) {\n return;\n }\n if (this.isCluster) {\n let retriable = true;\n let commonError;\n for (let i = 0; i < this._result.length; ++i) {\n const error = this._result[i][0];\n const command = this._queue[i];\n if (error) {\n if (command.name === \"exec\" &&\n error.message ===\n \"EXECABORT Transaction discarded because of previous errors.\") {\n continue;\n }\n if (!commonError) {\n commonError = {\n name: error.name,\n message: error.message,\n };\n }\n else if (commonError.name !== error.name ||\n commonError.message !== error.message) {\n retriable = false;\n break;\n }\n }\n else if (!command.inTransaction) {\n const isReadOnly = (0, commands_1.exists)(command.name) && (0, commands_1.hasFlag)(command.name, \"readonly\");\n if (!isReadOnly) {\n retriable = false;\n break;\n }\n }\n }\n if (commonError && retriable) {\n const _this = this;\n const errv = commonError.message.split(\" \");\n const queue = this._queue;\n let inTransaction = false;\n this._queue = [];\n for (let i = 0; i < queue.length; ++i) {\n if (errv[0] === \"ASK\" &&\n !inTransaction &&\n queue[i].name !== \"asking\" &&\n (!queue[i - 1] || queue[i - 1].name !== \"asking\")) {\n const asking = new Command_1.default(\"asking\");\n asking.ignore = true;\n this.sendCommand(asking);\n }\n queue[i].initPromise();\n this.sendCommand(queue[i]);\n inTransaction = queue[i].inTransaction;\n }\n let matched = true;\n if (typeof this.leftRedirections === \"undefined\") {\n this.leftRedirections = {};\n }\n const exec = function () {\n _this.exec();\n };\n const cluster = this.redis;\n cluster.handleError(commonError, this.leftRedirections, {\n moved: function (_slot, key) {\n _this.preferKey = key;\n cluster.slots[errv[1]] = [key];\n cluster._groupsBySlot[errv[1]] =\n cluster._groupsIds[cluster.slots[errv[1]].join(\";\")];\n cluster.refreshSlotsCache();\n _this.exec();\n },\n ask: function (_slot, key) {\n _this.preferKey = key;\n _this.exec();\n },\n tryagain: exec,\n clusterDown: exec,\n connectionClosed: exec,\n maxRedirections: () => {\n matched = false;\n },\n defaults: () => {\n matched = false;\n },\n });\n if (matched) {\n return;\n }\n }\n }\n let ignoredCount = 0;\n for (let i = 0; i < this._queue.length - ignoredCount; ++i) {\n if (this._queue[i + ignoredCount].ignore) {\n ignoredCount += 1;\n }\n this._result[i] = this._result[i + ignoredCount];\n }\n this.resolve(this._result.slice(0, this._result.length - ignoredCount));\n }\n sendCommand(command) {\n if (this._transactions > 0) {\n command.inTransaction = true;\n }\n const position = this._queue.length;\n command.pipelineIndex = position;\n command.promise\n .then((result) => {\n this.fillResult([null, result], position);\n })\n .catch((error) => {\n this.fillResult([error], position);\n });\n this._queue.push(command);\n return this;\n }\n addBatch(commands) {\n let command, commandName, args;\n for (let i = 0; i < commands.length; ++i) {\n command = commands[i];\n commandName = command[0];\n args = command.slice(1);\n this[commandName].apply(this, args);\n }\n return this;\n }\n}\nexports.default = Pipeline;\n// @ts-expect-error\nconst multi = Pipeline.prototype.multi;\n// @ts-expect-error\nPipeline.prototype.multi = function () {\n this._transactions += 1;\n return multi.apply(this, arguments);\n};\n// @ts-expect-error\nconst execBuffer = Pipeline.prototype.execBuffer;\n// @ts-expect-error\nPipeline.prototype.execBuffer = (0, util_1.deprecate)(function () {\n if (this._transactions > 0) {\n this._transactions -= 1;\n }\n return execBuffer.apply(this, arguments);\n}, \"Pipeline#execBuffer: Use Pipeline#exec instead\");\n// NOTE: To avoid an unhandled promise rejection, this will unconditionally always return this.promise,\n// which always has the rejection handled by standard-as-callback\n// adding the provided rejection callback.\n//\n// If a different promise instance were returned, that promise would cause its own unhandled promise rejection\n// errors, even if that promise unconditionally resolved to **the resolved value of** this.promise.\nPipeline.prototype.exec = function (callback) {\n // Wait for the cluster to be connected, since we need nodes information before continuing\n if (this.isCluster && !this.redis.slots.length) {\n if (this.redis.status === \"wait\")\n this.redis.connect().catch(utils_1.noop);\n if (callback && !this.nodeifiedPromise) {\n this.nodeifiedPromise = true;\n (0, standard_as_callback_1.default)(this.promise, callback);\n }\n this.redis.delayUntilReady((err) => {\n if (err) {\n this.reject(err);\n return;\n }\n this.exec(callback);\n });\n return this.promise;\n }\n if (this._transactions > 0) {\n this._transactions -= 1;\n return execBuffer.apply(this, arguments);\n }\n if (!this.nodeifiedPromise) {\n this.nodeifiedPromise = true;\n (0, standard_as_callback_1.default)(this.promise, callback);\n }\n if (!this._queue.length) {\n this.resolve([]);\n }\n let pipelineSlot;\n if (this.isCluster) {\n // List of the first key for each command\n const sampleKeys = [];\n for (let i = 0; i < this._queue.length; i++) {\n const keys = this._queue[i].getKeys();\n if (keys.length) {\n sampleKeys.push(keys[0]);\n }\n // For each command, check that the keys belong to the same slot\n if (keys.length && calculateSlot.generateMulti(keys) < 0) {\n this.reject(new Error(\"All the keys in a pipeline command should belong to the same slot\"));\n return this.promise;\n }\n }\n if (sampleKeys.length) {\n pipelineSlot = generateMultiWithNodes(this.redis, sampleKeys);\n if (pipelineSlot < 0) {\n this.reject(new Error(\"All keys in the pipeline should belong to the same slots allocation group\"));\n return this.promise;\n }\n }\n else {\n // Send the pipeline to a random node\n pipelineSlot = (Math.random() * 16384) | 0;\n }\n }\n const _this = this;\n execPipeline();\n return this.promise;\n function execPipeline() {\n let writePending = (_this.replyPending = _this._queue.length);\n let node;\n if (_this.isCluster) {\n node = {\n slot: pipelineSlot,\n redis: _this.redis.connectionPool.nodes.all[_this.preferKey],\n };\n }\n let data = \"\";\n let buffers;\n const stream = {\n isPipeline: true,\n destination: _this.isCluster ? node : { redis: _this.redis },\n write(writable) {\n if (typeof writable !== \"string\") {\n if (!buffers) {\n buffers = [];\n }\n if (data) {\n buffers.push(Buffer.from(data, \"utf8\"));\n data = \"\";\n }\n buffers.push(writable);\n }\n else {\n data += writable;\n }\n if (!--writePending) {\n if (buffers) {\n if (data) {\n buffers.push(Buffer.from(data, \"utf8\"));\n }\n stream.destination.redis.stream.write(Buffer.concat(buffers));\n }\n else {\n stream.destination.redis.stream.write(data);\n }\n // Reset writePending for resending\n writePending = _this._queue.length;\n data = \"\";\n buffers = undefined;\n }\n },\n };\n for (let i = 0; i < _this._queue.length; ++i) {\n _this.redis.sendCommand(_this._queue[i], stream, node);\n }\n return _this.promise;\n }\n};\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.addTransactionSupport = void 0;\nconst utils_1 = require(\"./utils\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst Pipeline_1 = require(\"./Pipeline\");\nfunction addTransactionSupport(redis) {\n redis.pipeline = function (commands) {\n const pipeline = new Pipeline_1.default(this);\n if (Array.isArray(commands)) {\n pipeline.addBatch(commands);\n }\n return pipeline;\n };\n const { multi } = redis;\n redis.multi = function (commands, options) {\n if (typeof options === \"undefined\" && !Array.isArray(commands)) {\n options = commands;\n commands = null;\n }\n if (options && options.pipeline === false) {\n return multi.call(this);\n }\n const pipeline = new Pipeline_1.default(this);\n // @ts-expect-error\n pipeline.multi();\n if (Array.isArray(commands)) {\n pipeline.addBatch(commands);\n }\n const exec = pipeline.exec;\n pipeline.exec = function (callback) {\n // Wait for the cluster to be connected, since we need nodes information before continuing\n if (this.isCluster && !this.redis.slots.length) {\n if (this.redis.status === \"wait\")\n this.redis.connect().catch(utils_1.noop);\n return (0, standard_as_callback_1.default)(new Promise((resolve, reject) => {\n this.redis.delayUntilReady((err) => {\n if (err) {\n reject(err);\n return;\n }\n this.exec(pipeline).then(resolve, reject);\n });\n }), callback);\n }\n if (this._transactions > 0) {\n exec.call(pipeline);\n }\n // Returns directly when the pipeline\n // has been called multiple times (retries).\n if (this.nodeifiedPromise) {\n return exec.call(pipeline);\n }\n const promise = exec.call(pipeline);\n return (0, standard_as_callback_1.default)(promise.then(function (result) {\n const execResult = result[result.length - 1];\n if (typeof execResult === \"undefined\") {\n throw new Error(\"Pipeline cannot be used to send any commands when the `exec()` has been called on it.\");\n }\n if (execResult[0]) {\n execResult[0].previousErrors = [];\n for (let i = 0; i < result.length - 1; ++i) {\n if (result[i][0]) {\n execResult[0].previousErrors.push(result[i][0]);\n }\n }\n throw execResult[0];\n }\n return (0, utils_1.wrapMultiResult)(execResult[1]);\n }), callback);\n };\n // @ts-expect-error\n const { execBuffer } = pipeline;\n // @ts-expect-error\n pipeline.execBuffer = function (callback) {\n if (this._transactions > 0) {\n execBuffer.call(pipeline);\n }\n return pipeline.exec(callback);\n };\n return pipeline;\n };\n const { exec } = redis;\n redis.exec = function (callback) {\n return (0, standard_as_callback_1.default)(exec.call(this).then(function (results) {\n if (Array.isArray(results)) {\n results = (0, utils_1.wrapMultiResult)(results);\n }\n return results;\n }), callback);\n };\n}\nexports.addTransactionSupport = addTransactionSupport;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction applyMixin(derivedConstructor, mixinConstructor) {\n Object.getOwnPropertyNames(mixinConstructor.prototype).forEach((name) => {\n Object.defineProperty(derivedConstructor.prototype, name, Object.getOwnPropertyDescriptor(mixinConstructor.prototype, name));\n });\n}\nexports.default = applyMixin;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.DEFAULT_CLUSTER_OPTIONS = void 0;\nconst dns_1 = require(\"dns\");\nexports.DEFAULT_CLUSTER_OPTIONS = {\n clusterRetryStrategy: (times) => Math.min(100 + times * 2, 2000),\n enableOfflineQueue: true,\n enableReadyCheck: true,\n scaleReads: \"master\",\n maxRedirections: 16,\n retryDelayOnMoved: 0,\n retryDelayOnFailover: 100,\n retryDelayOnClusterDown: 100,\n retryDelayOnTryAgain: 100,\n slotsRefreshTimeout: 1000,\n useSRVRecords: false,\n resolveSrv: dns_1.resolveSrv,\n dnsLookup: dns_1.lookup,\n enableAutoPipelining: false,\n autoPipeliningIgnoredCommands: [],\n shardedSubscribers: false,\n};\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getConnectionName = exports.weightSrvRecords = exports.groupSrvRecords = exports.getUniqueHostnamesFromOptions = exports.normalizeNodeOptions = exports.nodeKeyToRedisOptions = exports.getNodeKey = void 0;\nconst utils_1 = require(\"../utils\");\nconst net_1 = require(\"net\");\nfunction getNodeKey(node) {\n node.port = node.port || 6379;\n node.host = node.host || \"127.0.0.1\";\n return node.host + \":\" + node.port;\n}\nexports.getNodeKey = getNodeKey;\nfunction nodeKeyToRedisOptions(nodeKey) {\n const portIndex = nodeKey.lastIndexOf(\":\");\n if (portIndex === -1) {\n throw new Error(`Invalid node key ${nodeKey}`);\n }\n return {\n host: nodeKey.slice(0, portIndex),\n port: Number(nodeKey.slice(portIndex + 1)),\n };\n}\nexports.nodeKeyToRedisOptions = nodeKeyToRedisOptions;\nfunction normalizeNodeOptions(nodes) {\n return nodes.map((node) => {\n const options = {};\n if (typeof node === \"object\") {\n Object.assign(options, node);\n }\n else if (typeof node === \"string\") {\n Object.assign(options, (0, utils_1.parseURL)(node));\n }\n else if (typeof node === \"number\") {\n options.port = node;\n }\n else {\n throw new Error(\"Invalid argument \" + node);\n }\n if (typeof options.port === \"string\") {\n options.port = parseInt(options.port, 10);\n }\n // Cluster mode only support db 0\n delete options.db;\n if (!options.port) {\n options.port = 6379;\n }\n if (!options.host) {\n options.host = \"127.0.0.1\";\n }\n return (0, utils_1.resolveTLSProfile)(options);\n });\n}\nexports.normalizeNodeOptions = normalizeNodeOptions;\nfunction getUniqueHostnamesFromOptions(nodes) {\n const uniqueHostsMap = {};\n nodes.forEach((node) => {\n uniqueHostsMap[node.host] = true;\n });\n return Object.keys(uniqueHostsMap).filter((host) => !(0, net_1.isIP)(host));\n}\nexports.getUniqueHostnamesFromOptions = getUniqueHostnamesFromOptions;\nfunction groupSrvRecords(records) {\n const recordsByPriority = {};\n for (const record of records) {\n if (!recordsByPriority.hasOwnProperty(record.priority)) {\n recordsByPriority[record.priority] = {\n totalWeight: record.weight,\n records: [record],\n };\n }\n else {\n recordsByPriority[record.priority].totalWeight += record.weight;\n recordsByPriority[record.priority].records.push(record);\n }\n }\n return recordsByPriority;\n}\nexports.groupSrvRecords = groupSrvRecords;\nfunction weightSrvRecords(recordsGroup) {\n if (recordsGroup.records.length === 1) {\n recordsGroup.totalWeight = 0;\n return recordsGroup.records.shift();\n }\n // + `recordsGroup.records.length` to support `weight` 0\n const random = Math.floor(Math.random() * (recordsGroup.totalWeight + recordsGroup.records.length));\n let total = 0;\n for (const [i, record] of recordsGroup.records.entries()) {\n total += 1 + record.weight;\n if (total > random) {\n recordsGroup.totalWeight -= record.weight;\n recordsGroup.records.splice(i, 1);\n return record;\n }\n }\n}\nexports.weightSrvRecords = weightSrvRecords;\nfunction getConnectionName(component, nodeConnectionName) {\n const prefix = `ioredis-cluster(${component})`;\n return nodeConnectionName ? `${prefix}:${nodeConnectionName}` : prefix;\n}\nexports.getConnectionName = getConnectionName;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst util_1 = require(\"./util\");\nconst utils_1 = require(\"../utils\");\nconst Redis_1 = require(\"../Redis\");\nconst debug = (0, utils_1.Debug)(\"cluster:subscriber\");\nclass ClusterSubscriber {\n constructor(connectionPool, emitter, isSharded = false) {\n this.connectionPool = connectionPool;\n this.emitter = emitter;\n this.isSharded = isSharded;\n this.started = false;\n //There is only one connection for the entire pool\n this.subscriber = null;\n //The slot range for which this subscriber is responsible\n this.slotRange = [];\n this.onSubscriberEnd = () => {\n if (!this.started) {\n debug(\"subscriber has disconnected, but ClusterSubscriber is not started, so not reconnecting.\");\n return;\n }\n // If the subscriber closes whilst it's still the active connection,\n // we might as well try to connecting to a new node if possible to\n // minimise the number of missed publishes.\n debug(\"subscriber has disconnected, selecting a new one...\");\n this.selectSubscriber();\n };\n // If the current node we're using as the subscriber disappears\n // from the node pool for some reason, we will select a new one\n // to connect to.\n // Note that this event is only triggered if the connection to\n // the node has been used; cluster subscriptions are setup with\n // lazyConnect = true. It's possible for the subscriber node to\n // disappear without this method being called!\n // See https://github.com/luin/ioredis/pull/1589\n this.connectionPool.on(\"-node\", (_, key) => {\n if (!this.started || !this.subscriber) {\n return;\n }\n if ((0, util_1.getNodeKey)(this.subscriber.options) === key) {\n debug(\"subscriber has left, selecting a new one...\");\n this.selectSubscriber();\n }\n });\n this.connectionPool.on(\"+node\", () => {\n if (!this.started || this.subscriber) {\n return;\n }\n debug(\"a new node is discovered and there is no subscriber, selecting a new one...\");\n this.selectSubscriber();\n });\n }\n getInstance() {\n return this.subscriber;\n }\n /**\n * Associate this subscriber to a specific slot range.\n *\n * Returns the range or an empty array if the slot range couldn't be associated.\n *\n * BTW: This is more for debugging and testing purposes.\n *\n * @param range\n */\n associateSlotRange(range) {\n if (this.isSharded) {\n this.slotRange = range;\n }\n return this.slotRange;\n }\n start() {\n this.started = true;\n this.selectSubscriber();\n debug(\"started\");\n }\n stop() {\n this.started = false;\n if (this.subscriber) {\n this.subscriber.disconnect();\n this.subscriber = null;\n }\n }\n isStarted() {\n return this.started;\n }\n selectSubscriber() {\n const lastActiveSubscriber = this.lastActiveSubscriber;\n // Disconnect the previous subscriber even if there\n // will not be a new one.\n if (lastActiveSubscriber) {\n lastActiveSubscriber.off(\"end\", this.onSubscriberEnd);\n lastActiveSubscriber.disconnect();\n }\n if (this.subscriber) {\n this.subscriber.off(\"end\", this.onSubscriberEnd);\n this.subscriber.disconnect();\n }\n const sampleNode = (0, utils_1.sample)(this.connectionPool.getNodes());\n if (!sampleNode) {\n debug(\"selecting subscriber failed since there is no node discovered in the cluster yet\");\n this.subscriber = null;\n return;\n }\n const { options } = sampleNode;\n debug(\"selected a subscriber %s:%s\", options.host, options.port);\n /*\n * Create a specialized Redis connection for the subscription.\n * Note that auto reconnection is enabled here.\n *\n * `enableReadyCheck` is also enabled because although subscription is allowed\n * while redis is loading data from the disk, we can check if the password\n * provided for the subscriber is correct, and if not, the current subscriber\n * will be disconnected and a new subscriber will be selected.\n */\n let connectionPrefix = \"subscriber\";\n if (this.isSharded)\n connectionPrefix = \"ssubscriber\";\n this.subscriber = new Redis_1.default({\n port: options.port,\n host: options.host,\n username: options.username,\n password: options.password,\n enableReadyCheck: true,\n connectionName: (0, util_1.getConnectionName)(connectionPrefix, options.connectionName),\n lazyConnect: true,\n tls: options.tls,\n // Don't try to reconnect the subscriber connection. If the connection fails\n // we will get an end event (handled below), at which point we'll pick a new\n // node from the pool and try to connect to that as the subscriber connection.\n retryStrategy: null,\n });\n // Ignore the errors since they're handled in the connection pool.\n this.subscriber.on(\"error\", utils_1.noop);\n // The node we lost connection to may not come back up in a\n // reasonable amount of time (e.g. a slave that's taken down\n // for maintainence), we could potentially miss many published\n // messages so we should reconnect as quickly as possible, to\n // a different node if needed.\n this.subscriber.once(\"end\", this.onSubscriberEnd);\n // Re-subscribe previous channels\n const previousChannels = { subscribe: [], psubscribe: [], ssubscribe: [] };\n if (lastActiveSubscriber) {\n const condition = lastActiveSubscriber.condition || lastActiveSubscriber.prevCondition;\n if (condition && condition.subscriber) {\n previousChannels.subscribe = condition.subscriber.channels(\"subscribe\");\n previousChannels.psubscribe =\n condition.subscriber.channels(\"psubscribe\");\n previousChannels.ssubscribe =\n condition.subscriber.channels(\"ssubscribe\");\n }\n }\n if (previousChannels.subscribe.length ||\n previousChannels.psubscribe.length ||\n previousChannels.ssubscribe.length) {\n let pending = 0;\n for (const type of [\"subscribe\", \"psubscribe\", \"ssubscribe\"]) {\n const channels = previousChannels[type];\n if (channels.length) {\n pending += 1;\n debug(\"%s %d channels\", type, channels.length);\n this.subscriber[type](channels)\n .then(() => {\n if (!--pending) {\n this.lastActiveSubscriber = this.subscriber;\n }\n })\n .catch(() => {\n // TODO: should probably disconnect the subscriber and try again.\n debug(\"failed to %s %d channels\", type, channels.length);\n });\n }\n }\n }\n else {\n this.lastActiveSubscriber = this.subscriber;\n }\n for (const event of [\n \"message\",\n \"messageBuffer\",\n ]) {\n this.subscriber.on(event, (arg1, arg2) => {\n this.emitter.emit(event, arg1, arg2);\n });\n }\n for (const event of [\"pmessage\", \"pmessageBuffer\"]) {\n this.subscriber.on(event, (arg1, arg2, arg3) => {\n this.emitter.emit(event, arg1, arg2, arg3);\n });\n }\n if (this.isSharded == true) {\n for (const event of [\n \"smessage\",\n \"smessageBuffer\",\n ]) {\n this.subscriber.on(event, (arg1, arg2) => {\n this.emitter.emit(event, arg1, arg2);\n });\n }\n }\n }\n}\nexports.default = ClusterSubscriber;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst events_1 = require(\"events\");\nconst utils_1 = require(\"../utils\");\nconst util_1 = require(\"./util\");\nconst Redis_1 = require(\"../Redis\");\nconst debug = (0, utils_1.Debug)(\"cluster:connectionPool\");\nclass ConnectionPool extends events_1.EventEmitter {\n constructor(redisOptions) {\n super();\n this.redisOptions = redisOptions;\n // master + slave = all\n this.nodes = {\n all: {},\n master: {},\n slave: {},\n };\n this.specifiedOptions = {};\n }\n getNodes(role = \"all\") {\n const nodes = this.nodes[role];\n return Object.keys(nodes).map((key) => nodes[key]);\n }\n getInstanceByKey(key) {\n return this.nodes.all[key];\n }\n getSampleInstance(role) {\n const keys = Object.keys(this.nodes[role]);\n const sampleKey = (0, utils_1.sample)(keys);\n return this.nodes[role][sampleKey];\n }\n /**\n * Add a master node to the pool\n * @param node\n */\n addMasterNode(node) {\n const key = (0, util_1.getNodeKey)(node.options);\n const redis = this.createRedisFromOptions(node, node.options.readOnly);\n //Master nodes aren't read-only\n if (!node.options.readOnly) {\n this.nodes.all[key] = redis;\n this.nodes.master[key] = redis;\n return true;\n }\n return false;\n }\n /**\n * Creates a Redis connection instance from the node options\n * @param node\n * @param readOnly\n */\n createRedisFromOptions(node, readOnly) {\n const redis = new Redis_1.default((0, utils_1.defaults)({\n // Never try to reconnect when a node is lose,\n // instead, waiting for a `MOVED` error and\n // fetch the slots again.\n retryStrategy: null,\n // Offline queue should be enabled so that\n // we don't need to wait for the `ready` event\n // before sending commands to the node.\n enableOfflineQueue: true,\n readOnly: readOnly,\n }, node, this.redisOptions, { lazyConnect: true }));\n return redis;\n }\n /**\n * Find or create a connection to the node\n */\n findOrCreate(node, readOnly = false) {\n const key = (0, util_1.getNodeKey)(node);\n readOnly = Boolean(readOnly);\n if (this.specifiedOptions[key]) {\n Object.assign(node, this.specifiedOptions[key]);\n }\n else {\n this.specifiedOptions[key] = node;\n }\n let redis;\n if (this.nodes.all[key]) {\n redis = this.nodes.all[key];\n if (redis.options.readOnly !== readOnly) {\n redis.options.readOnly = readOnly;\n debug(\"Change role of %s to %s\", key, readOnly ? \"slave\" : \"master\");\n redis[readOnly ? \"readonly\" : \"readwrite\"]().catch(utils_1.noop);\n if (readOnly) {\n delete this.nodes.master[key];\n this.nodes.slave[key] = redis;\n }\n else {\n delete this.nodes.slave[key];\n this.nodes.master[key] = redis;\n }\n }\n }\n else {\n debug(\"Connecting to %s as %s\", key, readOnly ? \"slave\" : \"master\");\n redis = this.createRedisFromOptions(node, readOnly);\n this.nodes.all[key] = redis;\n this.nodes[readOnly ? \"slave\" : \"master\"][key] = redis;\n redis.once(\"end\", () => {\n this.removeNode(key);\n this.emit(\"-node\", redis, key);\n if (!Object.keys(this.nodes.all).length) {\n this.emit(\"drain\");\n }\n });\n this.emit(\"+node\", redis, key);\n redis.on(\"error\", function (error) {\n this.emit(\"nodeError\", error, key);\n });\n }\n return redis;\n }\n /**\n * Reset the pool with a set of nodes.\n * The old node will be removed.\n */\n reset(nodes) {\n debug(\"Reset with %O\", nodes);\n const newNodes = {};\n nodes.forEach((node) => {\n const key = (0, util_1.getNodeKey)(node);\n // Don't override the existing (master) node\n // when the current one is slave.\n if (!(node.readOnly && newNodes[key])) {\n newNodes[key] = node;\n }\n });\n Object.keys(this.nodes.all).forEach((key) => {\n if (!newNodes[key]) {\n debug(\"Disconnect %s because the node does not hold any slot\", key);\n this.nodes.all[key].disconnect();\n this.removeNode(key);\n }\n });\n Object.keys(newNodes).forEach((key) => {\n const node = newNodes[key];\n this.findOrCreate(node, node.readOnly);\n });\n }\n /**\n * Remove a node from the pool.\n */\n removeNode(key) {\n const { nodes } = this;\n if (nodes.all[key]) {\n debug(\"Remove %s from the pool\", key);\n delete nodes.all[key];\n }\n delete nodes.master[key];\n delete nodes.slave[key];\n }\n}\nexports.default = ConnectionPool;\n","'use strict';\n\n/**\n * Custom implementation of a double ended queue.\n */\nfunction Denque(array, options) {\n var options = options || {};\n this._capacity = options.capacity;\n\n this._head = 0;\n this._tail = 0;\n\n if (Array.isArray(array)) {\n this._fromArray(array);\n } else {\n this._capacityMask = 0x3;\n this._list = new Array(4);\n }\n}\n\n/**\n * --------------\n * PUBLIC API\n * -------------\n */\n\n/**\n * Returns the item at the specified index from the list.\n * 0 is the first element, 1 is the second, and so on...\n * Elements at negative values are that many from the end: -1 is one before the end\n * (the last element), -2 is two before the end (one before last), etc.\n * @param index\n * @returns {*}\n */\nDenque.prototype.peekAt = function peekAt(index) {\n var i = index;\n // expect a number or return undefined\n if ((i !== (i | 0))) {\n return void 0;\n }\n var len = this.size();\n if (i >= len || i < -len) return undefined;\n if (i < 0) i += len;\n i = (this._head + i) & this._capacityMask;\n return this._list[i];\n};\n\n/**\n * Alias for peekAt()\n * @param i\n * @returns {*}\n */\nDenque.prototype.get = function get(i) {\n return this.peekAt(i);\n};\n\n/**\n * Returns the first item in the list without removing it.\n * @returns {*}\n */\nDenque.prototype.peek = function peek() {\n if (this._head === this._tail) return undefined;\n return this._list[this._head];\n};\n\n/**\n * Alias for peek()\n * @returns {*}\n */\nDenque.prototype.peekFront = function peekFront() {\n return this.peek();\n};\n\n/**\n * Returns the item that is at the back of the queue without removing it.\n * Uses peekAt(-1)\n */\nDenque.prototype.peekBack = function peekBack() {\n return this.peekAt(-1);\n};\n\n/**\n * Returns the current length of the queue\n * @return {Number}\n */\nObject.defineProperty(Denque.prototype, 'length', {\n get: function length() {\n return this.size();\n }\n});\n\n/**\n * Return the number of items on the list, or 0 if empty.\n * @returns {number}\n */\nDenque.prototype.size = function size() {\n if (this._head === this._tail) return 0;\n if (this._head < this._tail) return this._tail - this._head;\n else return this._capacityMask + 1 - (this._head - this._tail);\n};\n\n/**\n * Add an item at the beginning of the list.\n * @param item\n */\nDenque.prototype.unshift = function unshift(item) {\n if (arguments.length === 0) return this.size();\n var len = this._list.length;\n this._head = (this._head - 1 + len) & this._capacityMask;\n this._list[this._head] = item;\n if (this._tail === this._head) this._growArray();\n if (this._capacity && this.size() > this._capacity) this.pop();\n if (this._head < this._tail) return this._tail - this._head;\n else return this._capacityMask + 1 - (this._head - this._tail);\n};\n\n/**\n * Remove and return the first item on the list,\n * Returns undefined if the list is empty.\n * @returns {*}\n */\nDenque.prototype.shift = function shift() {\n var head = this._head;\n if (head === this._tail) return undefined;\n var item = this._list[head];\n this._list[head] = undefined;\n this._head = (head + 1) & this._capacityMask;\n if (head < 2 && this._tail > 10000 && this._tail <= this._list.length >>> 2) this._shrinkArray();\n return item;\n};\n\n/**\n * Add an item to the bottom of the list.\n * @param item\n */\nDenque.prototype.push = function push(item) {\n if (arguments.length === 0) return this.size();\n var tail = this._tail;\n this._list[tail] = item;\n this._tail = (tail + 1) & this._capacityMask;\n if (this._tail === this._head) {\n this._growArray();\n }\n if (this._capacity && this.size() > this._capacity) {\n this.shift();\n }\n if (this._head < this._tail) return this._tail - this._head;\n else return this._capacityMask + 1 - (this._head - this._tail);\n};\n\n/**\n * Remove and return the last item on the list.\n * Returns undefined if the list is empty.\n * @returns {*}\n */\nDenque.prototype.pop = function pop() {\n var tail = this._tail;\n if (tail === this._head) return undefined;\n var len = this._list.length;\n this._tail = (tail - 1 + len) & this._capacityMask;\n var item = this._list[this._tail];\n this._list[this._tail] = undefined;\n if (this._head < 2 && tail > 10000 && tail <= len >>> 2) this._shrinkArray();\n return item;\n};\n\n/**\n * Remove and return the item at the specified index from the list.\n * Returns undefined if the list is empty.\n * @param index\n * @returns {*}\n */\nDenque.prototype.removeOne = function removeOne(index) {\n var i = index;\n // expect a number or return undefined\n if ((i !== (i | 0))) {\n return void 0;\n }\n if (this._head === this._tail) return void 0;\n var size = this.size();\n var len = this._list.length;\n if (i >= size || i < -size) return void 0;\n if (i < 0) i += size;\n i = (this._head + i) & this._capacityMask;\n var item = this._list[i];\n var k;\n if (index < size / 2) {\n for (k = index; k > 0; k--) {\n this._list[i] = this._list[i = (i - 1 + len) & this._capacityMask];\n }\n this._list[i] = void 0;\n this._head = (this._head + 1 + len) & this._capacityMask;\n } else {\n for (k = size - 1 - index; k > 0; k--) {\n this._list[i] = this._list[i = (i + 1 + len) & this._capacityMask];\n }\n this._list[i] = void 0;\n this._tail = (this._tail - 1 + len) & this._capacityMask;\n }\n return item;\n};\n\n/**\n * Remove number of items from the specified index from the list.\n * Returns array of removed items.\n * Returns undefined if the list is empty.\n * @param index\n * @param count\n * @returns {array}\n */\nDenque.prototype.remove = function remove(index, count) {\n var i = index;\n var removed;\n var del_count = count;\n // expect a number or return undefined\n if ((i !== (i | 0))) {\n return void 0;\n }\n if (this._head === this._tail) return void 0;\n var size = this.size();\n var len = this._list.length;\n if (i >= size || i < -size || count < 1) return void 0;\n if (i < 0) i += size;\n if (count === 1 || !count) {\n removed = new Array(1);\n removed[0] = this.removeOne(i);\n return removed;\n }\n if (i === 0 && i + count >= size) {\n removed = this.toArray();\n this.clear();\n return removed;\n }\n if (i + count > size) count = size - i;\n var k;\n removed = new Array(count);\n for (k = 0; k < count; k++) {\n removed[k] = this._list[(this._head + i + k) & this._capacityMask];\n }\n i = (this._head + i) & this._capacityMask;\n if (index + count === size) {\n this._tail = (this._tail - count + len) & this._capacityMask;\n for (k = count; k > 0; k--) {\n this._list[i = (i + 1 + len) & this._capacityMask] = void 0;\n }\n return removed;\n }\n if (index === 0) {\n this._head = (this._head + count + len) & this._capacityMask;\n for (k = count - 1; k > 0; k--) {\n this._list[i = (i + 1 + len) & this._capacityMask] = void 0;\n }\n return removed;\n }\n if (i < size / 2) {\n this._head = (this._head + index + count + len) & this._capacityMask;\n for (k = index; k > 0; k--) {\n this.unshift(this._list[i = (i - 1 + len) & this._capacityMask]);\n }\n i = (this._head - 1 + len) & this._capacityMask;\n while (del_count > 0) {\n this._list[i = (i - 1 + len) & this._capacityMask] = void 0;\n del_count--;\n }\n if (index < 0) this._tail = i;\n } else {\n this._tail = i;\n i = (i + count + len) & this._capacityMask;\n for (k = size - (count + index); k > 0; k--) {\n this.push(this._list[i++]);\n }\n i = this._tail;\n while (del_count > 0) {\n this._list[i = (i + 1 + len) & this._capacityMask] = void 0;\n del_count--;\n }\n }\n if (this._head < 2 && this._tail > 10000 && this._tail <= len >>> 2) this._shrinkArray();\n return removed;\n};\n\n/**\n * Native splice implementation.\n * Remove number of items from the specified index from the list and/or add new elements.\n * Returns array of removed items or empty array if count == 0.\n * Returns undefined if the list is empty.\n *\n * @param index\n * @param count\n * @param {...*} [elements]\n * @returns {array}\n */\nDenque.prototype.splice = function splice(index, count) {\n var i = index;\n // expect a number or return undefined\n if ((i !== (i | 0))) {\n return void 0;\n }\n var size = this.size();\n if (i < 0) i += size;\n if (i > size) return void 0;\n if (arguments.length > 2) {\n var k;\n var temp;\n var removed;\n var arg_len = arguments.length;\n var len = this._list.length;\n var arguments_index = 2;\n if (!size || i < size / 2) {\n temp = new Array(i);\n for (k = 0; k < i; k++) {\n temp[k] = this._list[(this._head + k) & this._capacityMask];\n }\n if (count === 0) {\n removed = [];\n if (i > 0) {\n this._head = (this._head + i + len) & this._capacityMask;\n }\n } else {\n removed = this.remove(i, count);\n this._head = (this._head + i + len) & this._capacityMask;\n }\n while (arg_len > arguments_index) {\n this.unshift(arguments[--arg_len]);\n }\n for (k = i; k > 0; k--) {\n this.unshift(temp[k - 1]);\n }\n } else {\n temp = new Array(size - (i + count));\n var leng = temp.length;\n for (k = 0; k < leng; k++) {\n temp[k] = this._list[(this._head + i + count + k) & this._capacityMask];\n }\n if (count === 0) {\n removed = [];\n if (i != size) {\n this._tail = (this._head + i + len) & this._capacityMask;\n }\n } else {\n removed = this.remove(i, count);\n this._tail = (this._tail - leng + len) & this._capacityMask;\n }\n while (arguments_index < arg_len) {\n this.push(arguments[arguments_index++]);\n }\n for (k = 0; k < leng; k++) {\n this.push(temp[k]);\n }\n }\n return removed;\n } else {\n return this.remove(i, count);\n }\n};\n\n/**\n * Soft clear - does not reset capacity.\n */\nDenque.prototype.clear = function clear() {\n this._list = new Array(this._list.length);\n this._head = 0;\n this._tail = 0;\n};\n\n/**\n * Returns true or false whether the list is empty.\n * @returns {boolean}\n */\nDenque.prototype.isEmpty = function isEmpty() {\n return this._head === this._tail;\n};\n\n/**\n * Returns an array of all queue items.\n * @returns {Array}\n */\nDenque.prototype.toArray = function toArray() {\n return this._copyArray(false);\n};\n\n/**\n * -------------\n * INTERNALS\n * -------------\n */\n\n/**\n * Fills the queue with items from an array\n * For use in the constructor\n * @param array\n * @private\n */\nDenque.prototype._fromArray = function _fromArray(array) {\n var length = array.length;\n var capacity = this._nextPowerOf2(length);\n\n this._list = new Array(capacity);\n this._capacityMask = capacity - 1;\n this._tail = length;\n\n for (var i = 0; i < length; i++) this._list[i] = array[i];\n};\n\n/**\n *\n * @param fullCopy\n * @param size Initialize the array with a specific size. Will default to the current list size\n * @returns {Array}\n * @private\n */\nDenque.prototype._copyArray = function _copyArray(fullCopy, size) {\n var src = this._list;\n var capacity = src.length;\n var length = this.length;\n size = size | length;\n\n // No prealloc requested and the buffer is contiguous\n if (size == length && this._head < this._tail) {\n // Simply do a fast slice copy\n return this._list.slice(this._head, this._tail);\n }\n\n var dest = new Array(size);\n\n var k = 0;\n var i;\n if (fullCopy || this._head > this._tail) {\n for (i = this._head; i < capacity; i++) dest[k++] = src[i];\n for (i = 0; i < this._tail; i++) dest[k++] = src[i];\n } else {\n for (i = this._head; i < this._tail; i++) dest[k++] = src[i];\n }\n\n return dest;\n}\n\n/**\n * Grows the internal list array.\n * @private\n */\nDenque.prototype._growArray = function _growArray() {\n if (this._head != 0) {\n // double array size and copy existing data, head to end, then beginning to tail.\n var newList = this._copyArray(true, this._list.length << 1);\n\n this._tail = this._list.length;\n this._head = 0;\n\n this._list = newList;\n } else {\n this._tail = this._list.length;\n this._list.length <<= 1;\n }\n\n this._capacityMask = (this._capacityMask << 1) | 1;\n};\n\n/**\n * Shrinks the internal list array.\n * @private\n */\nDenque.prototype._shrinkArray = function _shrinkArray() {\n this._list.length >>>= 1;\n this._capacityMask >>>= 1;\n};\n\n/**\n * Find the next power of 2, at least 4\n * @private\n * @param {number} num \n * @returns {number}\n */\nDenque.prototype._nextPowerOf2 = function _nextPowerOf2(num) {\n var log2 = Math.log(num) / Math.log(2);\n var nextPow2 = 1 << (log2 + 1);\n\n return Math.max(nextPow2, 4);\n}\n\nmodule.exports = Denque;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst utils_1 = require(\"../utils\");\nconst Deque = require(\"denque\");\nconst debug = (0, utils_1.Debug)(\"delayqueue\");\n/**\n * Queue that runs items after specified duration\n */\nclass DelayQueue {\n constructor() {\n this.queues = {};\n this.timeouts = {};\n }\n /**\n * Add a new item to the queue\n *\n * @param bucket bucket name\n * @param item function that will run later\n * @param options\n */\n push(bucket, item, options) {\n const callback = options.callback || process.nextTick;\n if (!this.queues[bucket]) {\n this.queues[bucket] = new Deque();\n }\n const queue = this.queues[bucket];\n queue.push(item);\n if (!this.timeouts[bucket]) {\n this.timeouts[bucket] = setTimeout(() => {\n callback(() => {\n this.timeouts[bucket] = null;\n this.execute(bucket);\n });\n }, options.timeout);\n }\n }\n execute(bucket) {\n const queue = this.queues[bucket];\n if (!queue) {\n return;\n }\n const { length } = queue;\n if (!length) {\n return;\n }\n debug(\"send %d commands in %s queue\", length, bucket);\n this.queues[bucket] = null;\n while (queue.length > 0) {\n queue.shift()();\n }\n }\n}\nexports.default = DelayQueue;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst utils_1 = require(\"../utils\");\nconst ClusterSubscriber_1 = require(\"./ClusterSubscriber\");\nconst ConnectionPool_1 = require(\"./ConnectionPool\");\nconst util_1 = require(\"./util\");\nconst calculateSlot = require(\"cluster-key-slot\");\nconst debug = (0, utils_1.Debug)(\"cluster:subscriberGroup\");\n/**\n * Redis differs between \"normal\" and sharded PubSub. If using the \"normal\" PubSub feature, exactly one\n * ClusterSubscriber exists per cluster instance. This works because the Redis cluster bus forwards m\n * messages between shards. However, this has scalability limitations, which is the reason why the sharded\n * PubSub feature was added to Redis. With sharded PubSub, each shard is responsible for its own messages.\n * Given that, we need at least one ClusterSubscriber per master endpoint/node.\n *\n * This class leverages the previously exising ClusterSubscriber by adding support for multiple such subscribers\n * in alignment to the master nodes of the cluster. The ClusterSubscriber class was extended in a non-breaking way\n * to support this feature.\n */\nclass ClusterSubscriberGroup {\n /**\n * Register callbacks\n *\n * @param cluster\n */\n constructor(cluster) {\n this.cluster = cluster;\n this.shardedSubscribers = new Map();\n this.clusterSlots = [];\n //Simple [min, max] slot ranges aren't enough because you can migrate single slots\n this.subscriberToSlotsIndex = new Map();\n this.channels = new Map();\n cluster.on(\"+node\", (redis) => {\n this._addSubscriber(redis);\n });\n cluster.on(\"-node\", (redis) => {\n this._removeSubscriber(redis);\n });\n cluster.on(\"refresh\", () => {\n this._refreshSlots(cluster);\n });\n }\n /**\n * Get the responsible subscriber.\n *\n * Returns null if no subscriber was found\n *\n * @param slot\n */\n getResponsibleSubscriber(slot) {\n const nodeKey = this.clusterSlots[slot][0];\n return this.shardedSubscribers.get(nodeKey);\n }\n /**\n * Adds a channel for which this subscriber group is responsible\n *\n * @param channels\n */\n addChannels(channels) {\n const slot = calculateSlot(channels[0]);\n //Check if the all channels belong to the same slot and otherwise reject the operation\n channels.forEach((c) => {\n if (calculateSlot(c) != slot)\n return -1;\n });\n const currChannels = this.channels.get(slot);\n if (!currChannels) {\n this.channels.set(slot, channels);\n }\n else {\n this.channels.set(slot, currChannels.concat(channels));\n }\n return [...this.channels.values()].flatMap(v => v).length;\n }\n /**\n * Removes channels for which the subscriber group is responsible by optionally unsubscribing\n * @param channels\n */\n removeChannels(channels) {\n const slot = calculateSlot(channels[0]);\n //Check if the all channels belong to the same slot and otherwise reject the operation\n channels.forEach((c) => {\n if (calculateSlot(c) != slot)\n return -1;\n });\n const slotChannels = this.channels.get(slot);\n if (slotChannels) {\n const updatedChannels = slotChannels.filter(c => !channels.includes(c));\n this.channels.set(slot, updatedChannels);\n }\n return [...this.channels.values()].flatMap(v => v).length;\n }\n /**\n * Disconnect all subscribers\n */\n stop() {\n for (const s of this.shardedSubscribers.values()) {\n s.stop();\n }\n }\n /**\n * Start all not yet started subscribers\n */\n start() {\n for (const s of this.shardedSubscribers.values()) {\n if (!s.isStarted()) {\n s.start();\n }\n }\n }\n /**\n * Add a subscriber to the group of subscribers\n *\n * @param redis\n */\n _addSubscriber(redis) {\n const pool = new ConnectionPool_1.default(redis.options);\n if (pool.addMasterNode(redis)) {\n const sub = new ClusterSubscriber_1.default(pool, this.cluster, true);\n const nodeKey = (0, util_1.getNodeKey)(redis.options);\n this.shardedSubscribers.set(nodeKey, sub);\n sub.start();\n // We need to attempt to resubscribe them in case the new node serves their slot\n this._resubscribe();\n this.cluster.emit(\"+subscriber\");\n return sub;\n }\n return null;\n }\n /**\n * Removes a subscriber from the group\n * @param redis\n */\n _removeSubscriber(redis) {\n const nodeKey = (0, util_1.getNodeKey)(redis.options);\n const sub = this.shardedSubscribers.get(nodeKey);\n if (sub) {\n sub.stop();\n this.shardedSubscribers.delete(nodeKey);\n // Even though the subscriber to this node is going down, we might have another subscriber\n // handling the same slots, so we need to attempt to subscribe the orphaned channels\n this._resubscribe();\n this.cluster.emit(\"-subscriber\");\n }\n return this.shardedSubscribers;\n }\n /**\n * Refreshes the subscriber-related slot ranges\n *\n * Returns false if no refresh was needed\n *\n * @param cluster\n */\n _refreshSlots(cluster) {\n //If there was an actual change, then reassign the slot ranges\n if (this._slotsAreEqual(cluster.slots)) {\n debug(\"Nothing to refresh because the new cluster map is equal to the previous one.\");\n }\n else {\n debug(\"Refreshing the slots of the subscriber group.\");\n //Rebuild the slots index\n this.subscriberToSlotsIndex = new Map();\n for (let slot = 0; slot < cluster.slots.length; slot++) {\n const node = cluster.slots[slot][0];\n if (!this.subscriberToSlotsIndex.has(node)) {\n this.subscriberToSlotsIndex.set(node, []);\n }\n this.subscriberToSlotsIndex.get(node).push(Number(slot));\n }\n //Update the subscribers from the index\n this._resubscribe();\n //Update the cached slots map\n this.clusterSlots = JSON.parse(JSON.stringify(cluster.slots));\n this.cluster.emit(\"subscribersReady\");\n return true;\n }\n return false;\n }\n /**\n * Resubscribes to the previous channels\n *\n * @private\n */\n _resubscribe() {\n if (this.shardedSubscribers) {\n this.shardedSubscribers.forEach((s, nodeKey) => {\n const subscriberSlots = this.subscriberToSlotsIndex.get(nodeKey);\n if (subscriberSlots) {\n //More for debugging purposes\n s.associateSlotRange(subscriberSlots);\n //Resubscribe on the underlying connection\n subscriberSlots.forEach((ss) => {\n //Might return null if being disconnected\n const redis = s.getInstance();\n const channels = this.channels.get(ss);\n if (channels && channels.length > 0) {\n //Try to subscribe now\n if (redis) {\n redis.ssubscribe(channels);\n //If the instance isn't ready yet, then register the re-subscription for later\n redis.on(\"ready\", () => {\n redis.ssubscribe(channels);\n });\n }\n }\n });\n }\n });\n }\n }\n /**\n * Deep equality of the cluster slots objects\n *\n * @param other\n * @private\n */\n _slotsAreEqual(other) {\n if (this.clusterSlots === undefined)\n return false;\n else\n return JSON.stringify(this.clusterSlots) === JSON.stringify(other);\n }\n}\nexports.default = ClusterSubscriberGroup;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst commands_1 = require(\"@ioredis/commands\");\nconst events_1 = require(\"events\");\nconst redis_errors_1 = require(\"redis-errors\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst Command_1 = require(\"../Command\");\nconst ClusterAllFailedError_1 = require(\"../errors/ClusterAllFailedError\");\nconst Redis_1 = require(\"../Redis\");\nconst ScanStream_1 = require(\"../ScanStream\");\nconst transaction_1 = require(\"../transaction\");\nconst utils_1 = require(\"../utils\");\nconst applyMixin_1 = require(\"../utils/applyMixin\");\nconst Commander_1 = require(\"../utils/Commander\");\nconst ClusterOptions_1 = require(\"./ClusterOptions\");\nconst ClusterSubscriber_1 = require(\"./ClusterSubscriber\");\nconst ConnectionPool_1 = require(\"./ConnectionPool\");\nconst DelayQueue_1 = require(\"./DelayQueue\");\nconst util_1 = require(\"./util\");\nconst Deque = require(\"denque\");\nconst ClusterSubscriberGroup_1 = require(\"./ClusterSubscriberGroup\");\nconst debug = (0, utils_1.Debug)(\"cluster\");\nconst REJECT_OVERWRITTEN_COMMANDS = new WeakSet();\n/**\n * Client for the official Redis Cluster\n */\nclass Cluster extends Commander_1.default {\n /**\n * Creates an instance of Cluster.\n */\n //TODO: Add an option that enables or disables sharded PubSub\n constructor(startupNodes, options = {}) {\n super();\n this.slots = [];\n /**\n * @ignore\n */\n this._groupsIds = {};\n /**\n * @ignore\n */\n this._groupsBySlot = Array(16384);\n /**\n * @ignore\n */\n this.isCluster = true;\n this.retryAttempts = 0;\n this.delayQueue = new DelayQueue_1.default();\n this.offlineQueue = new Deque();\n this.isRefreshing = false;\n this._refreshSlotsCacheCallbacks = [];\n this._autoPipelines = new Map();\n this._runningAutoPipelines = new Set();\n this._readyDelayedCallbacks = [];\n /**\n * Every time Cluster#connect() is called, this value will be\n * auto-incrementing. The purpose of this value is used for\n * discarding previous connect attampts when creating a new\n * connection.\n */\n this.connectionEpoch = 0;\n events_1.EventEmitter.call(this);\n this.startupNodes = startupNodes;\n this.options = (0, utils_1.defaults)({}, options, ClusterOptions_1.DEFAULT_CLUSTER_OPTIONS, this.options);\n if (this.options.shardedSubscribers == true)\n this.shardedSubscribers = new ClusterSubscriberGroup_1.default(this);\n if (this.options.redisOptions &&\n this.options.redisOptions.keyPrefix &&\n !this.options.keyPrefix) {\n this.options.keyPrefix = this.options.redisOptions.keyPrefix;\n }\n // validate options\n if (typeof this.options.scaleReads !== \"function\" &&\n [\"all\", \"master\", \"slave\"].indexOf(this.options.scaleReads) === -1) {\n throw new Error('Invalid option scaleReads \"' +\n this.options.scaleReads +\n '\". Expected \"all\", \"master\", \"slave\" or a custom function');\n }\n this.connectionPool = new ConnectionPool_1.default(this.options.redisOptions);\n this.connectionPool.on(\"-node\", (redis, key) => {\n this.emit(\"-node\", redis);\n });\n this.connectionPool.on(\"+node\", (redis) => {\n this.emit(\"+node\", redis);\n });\n this.connectionPool.on(\"drain\", () => {\n this.setStatus(\"close\");\n });\n this.connectionPool.on(\"nodeError\", (error, key) => {\n this.emit(\"node error\", error, key);\n });\n this.subscriber = new ClusterSubscriber_1.default(this.connectionPool, this);\n if (this.options.scripts) {\n Object.entries(this.options.scripts).forEach(([name, definition]) => {\n this.defineCommand(name, definition);\n });\n }\n if (this.options.lazyConnect) {\n this.setStatus(\"wait\");\n }\n else {\n this.connect().catch((err) => {\n debug(\"connecting failed: %s\", err);\n });\n }\n }\n /**\n * Connect to a cluster\n */\n connect() {\n return new Promise((resolve, reject) => {\n if (this.status === \"connecting\" ||\n this.status === \"connect\" ||\n this.status === \"ready\") {\n reject(new Error(\"Redis is already connecting/connected\"));\n return;\n }\n const epoch = ++this.connectionEpoch;\n this.setStatus(\"connecting\");\n this.resolveStartupNodeHostnames()\n .then((nodes) => {\n if (this.connectionEpoch !== epoch) {\n debug(\"discard connecting after resolving startup nodes because epoch not match: %d != %d\", epoch, this.connectionEpoch);\n reject(new redis_errors_1.RedisError(\"Connection is discarded because a new connection is made\"));\n return;\n }\n if (this.status !== \"connecting\") {\n debug(\"discard connecting after resolving startup nodes because the status changed to %s\", this.status);\n reject(new redis_errors_1.RedisError(\"Connection is aborted\"));\n return;\n }\n this.connectionPool.reset(nodes);\n const readyHandler = () => {\n this.setStatus(\"ready\");\n this.retryAttempts = 0;\n this.executeOfflineCommands();\n this.resetNodesRefreshInterval();\n resolve();\n };\n let closeListener = undefined;\n const refreshListener = () => {\n this.invokeReadyDelayedCallbacks(undefined);\n this.removeListener(\"close\", closeListener);\n this.manuallyClosing = false;\n this.setStatus(\"connect\");\n if (this.options.enableReadyCheck) {\n this.readyCheck((err, fail) => {\n if (err || fail) {\n debug(\"Ready check failed (%s). Reconnecting...\", err || fail);\n if (this.status === \"connect\") {\n this.disconnect(true);\n }\n }\n else {\n readyHandler();\n }\n });\n }\n else {\n readyHandler();\n }\n };\n closeListener = () => {\n const error = new Error(\"None of startup nodes is available\");\n this.removeListener(\"refresh\", refreshListener);\n this.invokeReadyDelayedCallbacks(error);\n reject(error);\n };\n this.once(\"refresh\", refreshListener);\n this.once(\"close\", closeListener);\n this.once(\"close\", this.handleCloseEvent.bind(this));\n this.refreshSlotsCache((err) => {\n if (err && err.message === ClusterAllFailedError_1.default.defaultMessage) {\n Redis_1.default.prototype.silentEmit.call(this, \"error\", err);\n this.connectionPool.reset([]);\n }\n });\n this.subscriber.start();\n if (this.options.shardedSubscribers) {\n this.shardedSubscribers.start();\n }\n })\n .catch((err) => {\n this.setStatus(\"close\");\n this.handleCloseEvent(err);\n this.invokeReadyDelayedCallbacks(err);\n reject(err);\n });\n });\n }\n /**\n * Disconnect from every node in the cluster.\n */\n disconnect(reconnect = false) {\n const status = this.status;\n this.setStatus(\"disconnecting\");\n if (!reconnect) {\n this.manuallyClosing = true;\n }\n if (this.reconnectTimeout && !reconnect) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n debug(\"Canceled reconnecting attempts\");\n }\n this.clearNodesRefreshInterval();\n this.subscriber.stop();\n if (this.options.shardedSubscribers) {\n this.shardedSubscribers.stop();\n }\n if (status === \"wait\") {\n this.setStatus(\"close\");\n this.handleCloseEvent();\n }\n else {\n this.connectionPool.reset([]);\n }\n }\n /**\n * Quit the cluster gracefully.\n */\n quit(callback) {\n const status = this.status;\n this.setStatus(\"disconnecting\");\n this.manuallyClosing = true;\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n this.clearNodesRefreshInterval();\n this.subscriber.stop();\n if (this.options.shardedSubscribers) {\n this.shardedSubscribers.stop();\n }\n if (status === \"wait\") {\n const ret = (0, standard_as_callback_1.default)(Promise.resolve(\"OK\"), callback);\n // use setImmediate to make sure \"close\" event\n // being emitted after quit() is returned\n setImmediate(function () {\n this.setStatus(\"close\");\n this.handleCloseEvent();\n }.bind(this));\n return ret;\n }\n return (0, standard_as_callback_1.default)(Promise.all(this.nodes().map((node) => node.quit().catch((err) => {\n // Ignore the error caused by disconnecting since\n // we're disconnecting...\n if (err.message === utils_1.CONNECTION_CLOSED_ERROR_MSG) {\n return \"OK\";\n }\n throw err;\n }))).then(() => \"OK\"), callback);\n }\n /**\n * Create a new instance with the same startup nodes and options as the current one.\n *\n * @example\n * ```js\n * var cluster = new Redis.Cluster([{ host: \"127.0.0.1\", port: \"30001\" }]);\n * var anotherCluster = cluster.duplicate();\n * ```\n */\n duplicate(overrideStartupNodes = [], overrideOptions = {}) {\n const startupNodes = overrideStartupNodes.length > 0\n ? overrideStartupNodes\n : this.startupNodes.slice(0);\n const options = Object.assign({}, this.options, overrideOptions);\n return new Cluster(startupNodes, options);\n }\n /**\n * Get nodes with the specified role\n */\n nodes(role = \"all\") {\n if (role !== \"all\" && role !== \"master\" && role !== \"slave\") {\n throw new Error('Invalid role \"' + role + '\". Expected \"all\", \"master\" or \"slave\"');\n }\n return this.connectionPool.getNodes(role);\n }\n /**\n * This is needed in order not to install a listener for each auto pipeline\n *\n * @ignore\n */\n delayUntilReady(callback) {\n this._readyDelayedCallbacks.push(callback);\n }\n /**\n * Get the number of commands queued in automatic pipelines.\n *\n * This is not available (and returns 0) until the cluster is connected and slots information have been received.\n */\n get autoPipelineQueueSize() {\n let queued = 0;\n for (const pipeline of this._autoPipelines.values()) {\n queued += pipeline.length;\n }\n return queued;\n }\n /**\n * Refresh the slot cache\n *\n * @ignore\n */\n refreshSlotsCache(callback) {\n if (callback) {\n this._refreshSlotsCacheCallbacks.push(callback);\n }\n if (this.isRefreshing) {\n return;\n }\n this.isRefreshing = true;\n const _this = this;\n const wrapper = (error) => {\n this.isRefreshing = false;\n for (const callback of this._refreshSlotsCacheCallbacks) {\n callback(error);\n }\n this._refreshSlotsCacheCallbacks = [];\n };\n const nodes = (0, utils_1.shuffle)(this.connectionPool.getNodes());\n let lastNodeError = null;\n function tryNode(index) {\n if (index === nodes.length) {\n const error = new ClusterAllFailedError_1.default(ClusterAllFailedError_1.default.defaultMessage, lastNodeError);\n return wrapper(error);\n }\n const node = nodes[index];\n const key = `${node.options.host}:${node.options.port}`;\n debug(\"getting slot cache from %s\", key);\n _this.getInfoFromNode(node, function (err) {\n switch (_this.status) {\n case \"close\":\n case \"end\":\n return wrapper(new Error(\"Cluster is disconnected.\"));\n case \"disconnecting\":\n return wrapper(new Error(\"Cluster is disconnecting.\"));\n }\n if (err) {\n _this.emit(\"node error\", err, key);\n lastNodeError = err;\n tryNode(index + 1);\n }\n else {\n _this.emit(\"refresh\");\n wrapper();\n }\n });\n }\n tryNode(0);\n }\n /**\n * @ignore\n */\n sendCommand(command, stream, node) {\n if (this.status === \"wait\") {\n this.connect().catch(utils_1.noop);\n }\n if (this.status === \"end\") {\n command.reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n return command.promise;\n }\n let to = this.options.scaleReads;\n if (to !== \"master\") {\n const isCommandReadOnly = command.isReadOnly ||\n ((0, commands_1.exists)(command.name) && (0, commands_1.hasFlag)(command.name, \"readonly\"));\n if (!isCommandReadOnly) {\n to = \"master\";\n }\n }\n let targetSlot = node ? node.slot : command.getSlot();\n const ttl = {};\n const _this = this;\n if (!node && !REJECT_OVERWRITTEN_COMMANDS.has(command)) {\n REJECT_OVERWRITTEN_COMMANDS.add(command);\n const reject = command.reject;\n command.reject = function (err) {\n const partialTry = tryConnection.bind(null, true);\n _this.handleError(err, ttl, {\n moved: function (slot, key) {\n debug(\"command %s is moved to %s\", command.name, key);\n targetSlot = Number(slot);\n if (_this.slots[slot]) {\n _this.slots[slot][0] = key;\n }\n else {\n _this.slots[slot] = [key];\n }\n _this._groupsBySlot[slot] =\n _this._groupsIds[_this.slots[slot].join(\";\")];\n _this.connectionPool.findOrCreate(_this.natMapper(key));\n tryConnection();\n debug(\"refreshing slot caches... (triggered by MOVED error)\");\n _this.refreshSlotsCache();\n },\n ask: function (slot, key) {\n debug(\"command %s is required to ask %s:%s\", command.name, key);\n const mapped = _this.natMapper(key);\n _this.connectionPool.findOrCreate(mapped);\n tryConnection(false, `${mapped.host}:${mapped.port}`);\n },\n tryagain: partialTry,\n clusterDown: partialTry,\n connectionClosed: partialTry,\n maxRedirections: function (redirectionError) {\n reject.call(command, redirectionError);\n },\n defaults: function () {\n reject.call(command, err);\n },\n });\n };\n }\n tryConnection();\n function tryConnection(random, asking) {\n if (_this.status === \"end\") {\n command.reject(new redis_errors_1.AbortError(\"Cluster is ended.\"));\n return;\n }\n let redis;\n if (_this.status === \"ready\" || command.name === \"cluster\") {\n if (node && node.redis) {\n redis = node.redis;\n }\n else if (Command_1.default.checkFlag(\"ENTER_SUBSCRIBER_MODE\", command.name) ||\n Command_1.default.checkFlag(\"EXIT_SUBSCRIBER_MODE\", command.name)) {\n if (_this.options.shardedSubscribers == true &&\n (command.name == \"ssubscribe\" || command.name == \"sunsubscribe\")) {\n const sub = _this.shardedSubscribers.getResponsibleSubscriber(targetSlot);\n let status = -1;\n if (command.name == \"ssubscribe\")\n status = _this.shardedSubscribers.addChannels(command.getKeys());\n if (command.name == \"sunsubscribe\")\n status = _this.shardedSubscribers.removeChannels(command.getKeys());\n if (status !== -1) {\n redis = sub.getInstance();\n }\n else {\n command.reject(new redis_errors_1.AbortError(\"Can't add or remove the given channels. Are they in the same slot?\"));\n }\n }\n else {\n redis = _this.subscriber.getInstance();\n }\n if (!redis) {\n command.reject(new redis_errors_1.AbortError(\"No subscriber for the cluster\"));\n return;\n }\n }\n else {\n if (!random) {\n if (typeof targetSlot === \"number\" && _this.slots[targetSlot]) {\n const nodeKeys = _this.slots[targetSlot];\n if (typeof to === \"function\") {\n const nodes = nodeKeys.map(function (key) {\n return _this.connectionPool.getInstanceByKey(key);\n });\n redis = to(nodes, command);\n if (Array.isArray(redis)) {\n redis = (0, utils_1.sample)(redis);\n }\n if (!redis) {\n redis = nodes[0];\n }\n }\n else {\n let key;\n if (to === \"all\") {\n key = (0, utils_1.sample)(nodeKeys);\n }\n else if (to === \"slave\" && nodeKeys.length > 1) {\n key = (0, utils_1.sample)(nodeKeys, 1);\n }\n else {\n key = nodeKeys[0];\n }\n redis = _this.connectionPool.getInstanceByKey(key);\n }\n }\n if (asking) {\n redis = _this.connectionPool.getInstanceByKey(asking);\n redis.asking();\n }\n }\n if (!redis) {\n redis =\n (typeof to === \"function\"\n ? null\n : _this.connectionPool.getSampleInstance(to)) ||\n _this.connectionPool.getSampleInstance(\"all\");\n }\n }\n if (node && !node.redis) {\n node.redis = redis;\n }\n }\n if (redis) {\n redis.sendCommand(command, stream);\n }\n else if (_this.options.enableOfflineQueue) {\n _this.offlineQueue.push({\n command: command,\n stream: stream,\n node: node,\n });\n }\n else {\n command.reject(new Error(\"Cluster isn't ready and enableOfflineQueue options is false\"));\n }\n }\n return command.promise;\n }\n sscanStream(key, options) {\n return this.createScanStream(\"sscan\", { key, options });\n }\n sscanBufferStream(key, options) {\n return this.createScanStream(\"sscanBuffer\", { key, options });\n }\n hscanStream(key, options) {\n return this.createScanStream(\"hscan\", { key, options });\n }\n hscanBufferStream(key, options) {\n return this.createScanStream(\"hscanBuffer\", { key, options });\n }\n zscanStream(key, options) {\n return this.createScanStream(\"zscan\", { key, options });\n }\n zscanBufferStream(key, options) {\n return this.createScanStream(\"zscanBuffer\", { key, options });\n }\n /**\n * @ignore\n */\n handleError(error, ttl, handlers) {\n if (typeof ttl.value === \"undefined\") {\n ttl.value = this.options.maxRedirections;\n }\n else {\n ttl.value -= 1;\n }\n if (ttl.value <= 0) {\n handlers.maxRedirections(new Error(\"Too many Cluster redirections. Last error: \" + error));\n return;\n }\n const errv = error.message.split(\" \");\n if (errv[0] === \"MOVED\") {\n const timeout = this.options.retryDelayOnMoved;\n if (timeout && typeof timeout === \"number\") {\n this.delayQueue.push(\"moved\", handlers.moved.bind(null, errv[1], errv[2]), { timeout });\n }\n else {\n handlers.moved(errv[1], errv[2]);\n }\n }\n else if (errv[0] === \"ASK\") {\n handlers.ask(errv[1], errv[2]);\n }\n else if (errv[0] === \"TRYAGAIN\") {\n this.delayQueue.push(\"tryagain\", handlers.tryagain, {\n timeout: this.options.retryDelayOnTryAgain,\n });\n }\n else if (errv[0] === \"CLUSTERDOWN\" &&\n this.options.retryDelayOnClusterDown > 0) {\n this.delayQueue.push(\"clusterdown\", handlers.connectionClosed, {\n timeout: this.options.retryDelayOnClusterDown,\n callback: this.refreshSlotsCache.bind(this),\n });\n }\n else if (error.message === utils_1.CONNECTION_CLOSED_ERROR_MSG &&\n this.options.retryDelayOnFailover > 0 &&\n this.status === \"ready\") {\n this.delayQueue.push(\"failover\", handlers.connectionClosed, {\n timeout: this.options.retryDelayOnFailover,\n callback: this.refreshSlotsCache.bind(this),\n });\n }\n else {\n handlers.defaults();\n }\n }\n resetOfflineQueue() {\n this.offlineQueue = new Deque();\n }\n clearNodesRefreshInterval() {\n if (this.slotsTimer) {\n clearTimeout(this.slotsTimer);\n this.slotsTimer = null;\n }\n }\n resetNodesRefreshInterval() {\n if (this.slotsTimer || !this.options.slotsRefreshInterval) {\n return;\n }\n const nextRound = () => {\n this.slotsTimer = setTimeout(() => {\n debug('refreshing slot caches... (triggered by \"slotsRefreshInterval\" option)');\n this.refreshSlotsCache(() => {\n nextRound();\n });\n }, this.options.slotsRefreshInterval);\n };\n nextRound();\n }\n /**\n * Change cluster instance's status\n */\n setStatus(status) {\n debug(\"status: %s -> %s\", this.status || \"[empty]\", status);\n this.status = status;\n process.nextTick(() => {\n this.emit(status);\n });\n }\n /**\n * Called when closed to check whether a reconnection should be made\n */\n handleCloseEvent(reason) {\n if (reason) {\n debug(\"closed because %s\", reason);\n }\n let retryDelay;\n if (!this.manuallyClosing &&\n typeof this.options.clusterRetryStrategy === \"function\") {\n retryDelay = this.options.clusterRetryStrategy.call(this, ++this.retryAttempts, reason);\n }\n if (typeof retryDelay === \"number\") {\n this.setStatus(\"reconnecting\");\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectTimeout = null;\n debug(\"Cluster is disconnected. Retrying after %dms\", retryDelay);\n this.connect().catch(function (err) {\n debug(\"Got error %s when reconnecting. Ignoring...\", err);\n });\n }, retryDelay);\n }\n else {\n this.setStatus(\"end\");\n this.flushQueue(new Error(\"None of startup nodes is available\"));\n }\n }\n /**\n * Flush offline queue with error.\n */\n flushQueue(error) {\n let item;\n while ((item = this.offlineQueue.shift())) {\n item.command.reject(error);\n }\n }\n executeOfflineCommands() {\n if (this.offlineQueue.length) {\n debug(\"send %d commands in offline queue\", this.offlineQueue.length);\n const offlineQueue = this.offlineQueue;\n this.resetOfflineQueue();\n let item;\n while ((item = offlineQueue.shift())) {\n this.sendCommand(item.command, item.stream, item.node);\n }\n }\n }\n natMapper(nodeKey) {\n const key = typeof nodeKey === \"string\"\n ? nodeKey\n : `${nodeKey.host}:${nodeKey.port}`;\n let mapped = null;\n if (this.options.natMap && typeof this.options.natMap === \"function\") {\n mapped = this.options.natMap(key);\n }\n else if (this.options.natMap && typeof this.options.natMap === \"object\") {\n mapped = this.options.natMap[key];\n }\n if (mapped) {\n debug(\"NAT mapping %s -> %O\", key, mapped);\n return Object.assign({}, mapped);\n }\n return typeof nodeKey === \"string\"\n ? (0, util_1.nodeKeyToRedisOptions)(nodeKey)\n : nodeKey;\n }\n getInfoFromNode(redis, callback) {\n if (!redis) {\n return callback(new Error(\"Node is disconnected\"));\n }\n // Use a duplication of the connection to avoid\n // timeouts when the connection is in the blocking\n // mode (e.g. waiting for BLPOP).\n const duplicatedConnection = redis.duplicate({\n enableOfflineQueue: true,\n enableReadyCheck: false,\n retryStrategy: null,\n connectionName: (0, util_1.getConnectionName)(\"refresher\", this.options.redisOptions && this.options.redisOptions.connectionName),\n });\n // Ignore error events since we will handle\n // exceptions for the CLUSTER SLOTS command.\n duplicatedConnection.on(\"error\", utils_1.noop);\n duplicatedConnection.cluster(\"SLOTS\", (0, utils_1.timeout)((err, result) => {\n duplicatedConnection.disconnect();\n if (err) {\n debug(\"error encountered running CLUSTER.SLOTS: %s\", err);\n return callback(err);\n }\n if (this.status === \"disconnecting\" ||\n this.status === \"close\" ||\n this.status === \"end\") {\n debug(\"ignore CLUSTER.SLOTS results (count: %d) since cluster status is %s\", result.length, this.status);\n callback();\n return;\n }\n const nodes = [];\n debug(\"cluster slots result count: %d\", result.length);\n for (let i = 0; i < result.length; ++i) {\n const items = result[i];\n const slotRangeStart = items[0];\n const slotRangeEnd = items[1];\n const keys = [];\n for (let j = 2; j < items.length; j++) {\n if (!items[j][0]) {\n continue;\n }\n const node = this.natMapper({\n host: items[j][0],\n port: items[j][1],\n });\n node.readOnly = j !== 2;\n nodes.push(node);\n keys.push(node.host + \":\" + node.port);\n }\n debug(\"cluster slots result [%d]: slots %d~%d served by %s\", i, slotRangeStart, slotRangeEnd, keys);\n for (let slot = slotRangeStart; slot <= slotRangeEnd; slot++) {\n this.slots[slot] = keys;\n }\n }\n // Assign to each node keys a numeric value to make autopipeline comparison faster.\n this._groupsIds = Object.create(null);\n let j = 0;\n for (let i = 0; i < 16384; i++) {\n const target = (this.slots[i] || []).join(\";\");\n if (!target.length) {\n this._groupsBySlot[i] = undefined;\n continue;\n }\n if (!this._groupsIds[target]) {\n this._groupsIds[target] = ++j;\n }\n this._groupsBySlot[i] = this._groupsIds[target];\n }\n this.connectionPool.reset(nodes);\n callback();\n }, this.options.slotsRefreshTimeout));\n }\n invokeReadyDelayedCallbacks(err) {\n for (const c of this._readyDelayedCallbacks) {\n process.nextTick(c, err);\n }\n this._readyDelayedCallbacks = [];\n }\n /**\n * Check whether Cluster is able to process commands\n */\n readyCheck(callback) {\n this.cluster(\"INFO\", (err, res) => {\n if (err) {\n return callback(err);\n }\n if (typeof res !== \"string\") {\n return callback();\n }\n let state;\n const lines = res.split(\"\\r\\n\");\n for (let i = 0; i < lines.length; ++i) {\n const parts = lines[i].split(\":\");\n if (parts[0] === \"cluster_state\") {\n state = parts[1];\n break;\n }\n }\n if (state === \"fail\") {\n debug(\"cluster state not ok (%s)\", state);\n callback(null, state);\n }\n else {\n callback();\n }\n });\n }\n resolveSrv(hostname) {\n return new Promise((resolve, reject) => {\n this.options.resolveSrv(hostname, (err, records) => {\n if (err) {\n return reject(err);\n }\n const self = this, groupedRecords = (0, util_1.groupSrvRecords)(records), sortedKeys = Object.keys(groupedRecords).sort((a, b) => parseInt(a) - parseInt(b));\n function tryFirstOne(err) {\n if (!sortedKeys.length) {\n return reject(err);\n }\n const key = sortedKeys[0], group = groupedRecords[key], record = (0, util_1.weightSrvRecords)(group);\n if (!group.records.length) {\n sortedKeys.shift();\n }\n self.dnsLookup(record.name).then((host) => resolve({\n host,\n port: record.port,\n }), tryFirstOne);\n }\n tryFirstOne();\n });\n });\n }\n dnsLookup(hostname) {\n return new Promise((resolve, reject) => {\n this.options.dnsLookup(hostname, (err, address) => {\n if (err) {\n debug(\"failed to resolve hostname %s to IP: %s\", hostname, err.message);\n reject(err);\n }\n else {\n debug(\"resolved hostname %s to IP %s\", hostname, address);\n resolve(address);\n }\n });\n });\n }\n /**\n * Normalize startup nodes, and resolving hostnames to IPs.\n *\n * This process happens every time when #connect() is called since\n * #startupNodes and DNS records may chanage.\n */\n async resolveStartupNodeHostnames() {\n if (!Array.isArray(this.startupNodes) || this.startupNodes.length === 0) {\n throw new Error(\"`startupNodes` should contain at least one node.\");\n }\n const startupNodes = (0, util_1.normalizeNodeOptions)(this.startupNodes);\n const hostnames = (0, util_1.getUniqueHostnamesFromOptions)(startupNodes);\n if (hostnames.length === 0) {\n return startupNodes;\n }\n const configs = await Promise.all(hostnames.map((this.options.useSRVRecords ? this.resolveSrv : this.dnsLookup).bind(this)));\n const hostnameToConfig = (0, utils_1.zipMap)(hostnames, configs);\n return startupNodes.map((node) => {\n const config = hostnameToConfig.get(node.host);\n if (!config) {\n return node;\n }\n if (this.options.useSRVRecords) {\n return Object.assign({}, node, config);\n }\n return Object.assign({}, node, { host: config });\n });\n }\n createScanStream(command, { key, options = {} }) {\n return new ScanStream_1.default({\n objectMode: true,\n key: key,\n redis: this,\n command: command,\n ...options,\n });\n }\n}\n(0, applyMixin_1.default)(Cluster, events_1.EventEmitter);\n(0, transaction_1.addTransactionSupport)(Cluster.prototype);\nexports.default = Cluster;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst utils_1 = require(\"../utils\");\nconst debug = (0, utils_1.Debug)(\"AbstractConnector\");\nclass AbstractConnector {\n constructor(disconnectTimeout) {\n this.connecting = false;\n this.disconnectTimeout = disconnectTimeout;\n }\n check(info) {\n return true;\n }\n disconnect() {\n this.connecting = false;\n if (this.stream) {\n const stream = this.stream; // Make sure callbacks refer to the same instance\n const timeout = setTimeout(() => {\n debug(\"stream %s:%s still open, destroying it\", stream.remoteAddress, stream.remotePort);\n stream.destroy();\n }, this.disconnectTimeout);\n stream.on(\"close\", () => clearTimeout(timeout));\n stream.end();\n }\n }\n}\nexports.default = AbstractConnector;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst net_1 = require(\"net\");\nconst tls_1 = require(\"tls\");\nconst utils_1 = require(\"../utils\");\nconst AbstractConnector_1 = require(\"./AbstractConnector\");\nclass StandaloneConnector extends AbstractConnector_1.default {\n constructor(options) {\n super(options.disconnectTimeout);\n this.options = options;\n }\n connect(_) {\n const { options } = this;\n this.connecting = true;\n let connectionOptions;\n if (\"path\" in options && options.path) {\n connectionOptions = {\n path: options.path,\n };\n }\n else {\n connectionOptions = {};\n if (\"port\" in options && options.port != null) {\n connectionOptions.port = options.port;\n }\n if (\"host\" in options && options.host != null) {\n connectionOptions.host = options.host;\n }\n if (\"family\" in options && options.family != null) {\n connectionOptions.family = options.family;\n }\n }\n if (options.tls) {\n Object.assign(connectionOptions, options.tls);\n }\n // TODO:\n // We use native Promise here since other Promise\n // implementation may use different schedulers that\n // cause issue when the stream is resolved in the\n // next tick.\n // Should use the provided promise in the next major\n // version and do not connect before resolved.\n return new Promise((resolve, reject) => {\n process.nextTick(() => {\n if (!this.connecting) {\n reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n return;\n }\n try {\n if (options.tls) {\n this.stream = (0, tls_1.connect)(connectionOptions);\n }\n else {\n this.stream = (0, net_1.createConnection)(connectionOptions);\n }\n }\n catch (err) {\n reject(err);\n return;\n }\n this.stream.once(\"error\", (err) => {\n this.firstError = err;\n });\n resolve(this.stream);\n });\n });\n }\n}\nexports.default = StandaloneConnector;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction isSentinelEql(a, b) {\n return ((a.host || \"127.0.0.1\") === (b.host || \"127.0.0.1\") &&\n (a.port || 26379) === (b.port || 26379));\n}\nclass SentinelIterator {\n constructor(sentinels) {\n this.cursor = 0;\n this.sentinels = sentinels.slice(0);\n }\n next() {\n const done = this.cursor >= this.sentinels.length;\n return { done, value: done ? undefined : this.sentinels[this.cursor++] };\n }\n reset(moveCurrentEndpointToFirst) {\n if (moveCurrentEndpointToFirst &&\n this.sentinels.length > 1 &&\n this.cursor !== 1) {\n this.sentinels.unshift(...this.sentinels.splice(this.cursor - 1));\n }\n this.cursor = 0;\n }\n add(sentinel) {\n for (let i = 0; i < this.sentinels.length; i++) {\n if (isSentinelEql(sentinel, this.sentinels[i])) {\n return false;\n }\n }\n this.sentinels.push(sentinel);\n return true;\n }\n toString() {\n return `${JSON.stringify(this.sentinels)} @${this.cursor}`;\n }\n}\nexports.default = SentinelIterator;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.FailoverDetector = void 0;\nconst utils_1 = require(\"../../utils\");\nconst debug = (0, utils_1.Debug)(\"FailoverDetector\");\nconst CHANNEL_NAME = \"+switch-master\";\nclass FailoverDetector {\n // sentinels can't be used for regular commands after this\n constructor(connector, sentinels) {\n this.isDisconnected = false;\n this.connector = connector;\n this.sentinels = sentinels;\n }\n cleanup() {\n this.isDisconnected = true;\n for (const sentinel of this.sentinels) {\n sentinel.client.disconnect();\n }\n }\n async subscribe() {\n debug(\"Starting FailoverDetector\");\n const promises = [];\n for (const sentinel of this.sentinels) {\n const promise = sentinel.client.subscribe(CHANNEL_NAME).catch((err) => {\n debug(\"Failed to subscribe to failover messages on sentinel %s:%s (%s)\", sentinel.address.host || \"127.0.0.1\", sentinel.address.port || 26739, err.message);\n });\n promises.push(promise);\n sentinel.client.on(\"message\", (channel) => {\n if (!this.isDisconnected && channel === CHANNEL_NAME) {\n this.disconnect();\n }\n });\n }\n await Promise.all(promises);\n }\n disconnect() {\n // Avoid disconnecting more than once per failover.\n // A new FailoverDetector will be created after reconnecting.\n this.isDisconnected = true;\n debug(\"Failover detected, disconnecting\");\n // Will call this.cleanup()\n this.connector.disconnect();\n }\n}\nexports.FailoverDetector = FailoverDetector;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.SentinelIterator = void 0;\nconst net_1 = require(\"net\");\nconst utils_1 = require(\"../../utils\");\nconst tls_1 = require(\"tls\");\nconst SentinelIterator_1 = require(\"./SentinelIterator\");\nexports.SentinelIterator = SentinelIterator_1.default;\nconst AbstractConnector_1 = require(\"../AbstractConnector\");\nconst Redis_1 = require(\"../../Redis\");\nconst FailoverDetector_1 = require(\"./FailoverDetector\");\nconst debug = (0, utils_1.Debug)(\"SentinelConnector\");\nclass SentinelConnector extends AbstractConnector_1.default {\n constructor(options) {\n super(options.disconnectTimeout);\n this.options = options;\n this.emitter = null;\n this.failoverDetector = null;\n if (!this.options.sentinels.length) {\n throw new Error(\"Requires at least one sentinel to connect to.\");\n }\n if (!this.options.name) {\n throw new Error(\"Requires the name of master.\");\n }\n this.sentinelIterator = new SentinelIterator_1.default(this.options.sentinels);\n }\n check(info) {\n const roleMatches = !info.role || this.options.role === info.role;\n if (!roleMatches) {\n debug(\"role invalid, expected %s, but got %s\", this.options.role, info.role);\n // Start from the next item.\n // Note that `reset` will move the cursor to the previous element,\n // so we advance two steps here.\n this.sentinelIterator.next();\n this.sentinelIterator.next();\n this.sentinelIterator.reset(true);\n }\n return roleMatches;\n }\n disconnect() {\n super.disconnect();\n if (this.failoverDetector) {\n this.failoverDetector.cleanup();\n }\n }\n connect(eventEmitter) {\n this.connecting = true;\n this.retryAttempts = 0;\n let lastError;\n const connectToNext = async () => {\n const endpoint = this.sentinelIterator.next();\n if (endpoint.done) {\n this.sentinelIterator.reset(false);\n const retryDelay = typeof this.options.sentinelRetryStrategy === \"function\"\n ? this.options.sentinelRetryStrategy(++this.retryAttempts)\n : null;\n let errorMsg = typeof retryDelay !== \"number\"\n ? \"All sentinels are unreachable and retry is disabled.\"\n : `All sentinels are unreachable. Retrying from scratch after ${retryDelay}ms.`;\n if (lastError) {\n errorMsg += ` Last error: ${lastError.message}`;\n }\n debug(errorMsg);\n const error = new Error(errorMsg);\n if (typeof retryDelay === \"number\") {\n eventEmitter(\"error\", error);\n await new Promise((resolve) => setTimeout(resolve, retryDelay));\n return connectToNext();\n }\n else {\n throw error;\n }\n }\n let resolved = null;\n let err = null;\n try {\n resolved = await this.resolve(endpoint.value);\n }\n catch (error) {\n err = error;\n }\n if (!this.connecting) {\n throw new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG);\n }\n const endpointAddress = endpoint.value.host + \":\" + endpoint.value.port;\n if (resolved) {\n debug(\"resolved: %s:%s from sentinel %s\", resolved.host, resolved.port, endpointAddress);\n if (this.options.enableTLSForSentinelMode && this.options.tls) {\n Object.assign(resolved, this.options.tls);\n this.stream = (0, tls_1.connect)(resolved);\n this.stream.once(\"secureConnect\", this.initFailoverDetector.bind(this));\n }\n else {\n this.stream = (0, net_1.createConnection)(resolved);\n this.stream.once(\"connect\", this.initFailoverDetector.bind(this));\n }\n this.stream.once(\"error\", (err) => {\n this.firstError = err;\n });\n return this.stream;\n }\n else {\n const errorMsg = err\n ? \"failed to connect to sentinel \" +\n endpointAddress +\n \" because \" +\n err.message\n : \"connected to sentinel \" +\n endpointAddress +\n \" successfully, but got an invalid reply: \" +\n resolved;\n debug(errorMsg);\n eventEmitter(\"sentinelError\", new Error(errorMsg));\n if (err) {\n lastError = err;\n }\n return connectToNext();\n }\n };\n return connectToNext();\n }\n async updateSentinels(client) {\n if (!this.options.updateSentinels) {\n return;\n }\n const result = await client.sentinel(\"sentinels\", this.options.name);\n if (!Array.isArray(result)) {\n return;\n }\n result\n .map(utils_1.packObject)\n .forEach((sentinel) => {\n const flags = sentinel.flags ? sentinel.flags.split(\",\") : [];\n if (flags.indexOf(\"disconnected\") === -1 &&\n sentinel.ip &&\n sentinel.port) {\n const endpoint = this.sentinelNatResolve(addressResponseToAddress(sentinel));\n if (this.sentinelIterator.add(endpoint)) {\n debug(\"adding sentinel %s:%s\", endpoint.host, endpoint.port);\n }\n }\n });\n debug(\"Updated internal sentinels: %s\", this.sentinelIterator);\n }\n async resolveMaster(client) {\n const result = await client.sentinel(\"get-master-addr-by-name\", this.options.name);\n await this.updateSentinels(client);\n return this.sentinelNatResolve(Array.isArray(result)\n ? { host: result[0], port: Number(result[1]) }\n : null);\n }\n async resolveSlave(client) {\n const result = await client.sentinel(\"slaves\", this.options.name);\n if (!Array.isArray(result)) {\n return null;\n }\n const availableSlaves = result\n .map(utils_1.packObject)\n .filter((slave) => slave.flags && !slave.flags.match(/(disconnected|s_down|o_down)/));\n return this.sentinelNatResolve(selectPreferredSentinel(availableSlaves, this.options.preferredSlaves));\n }\n sentinelNatResolve(item) {\n if (!item || !this.options.natMap)\n return item;\n const key = `${item.host}:${item.port}`;\n let result = item;\n if (typeof this.options.natMap === \"function\") {\n result = this.options.natMap(key) || item;\n }\n else if (typeof this.options.natMap === \"object\") {\n result = this.options.natMap[key] || item;\n }\n return result;\n }\n connectToSentinel(endpoint, options) {\n const redis = new Redis_1.default({\n port: endpoint.port || 26379,\n host: endpoint.host,\n username: this.options.sentinelUsername || null,\n password: this.options.sentinelPassword || null,\n family: endpoint.family ||\n // @ts-expect-error\n (\"path\" in this.options && this.options.path\n ? undefined\n : // @ts-expect-error\n this.options.family),\n tls: this.options.sentinelTLS,\n retryStrategy: null,\n enableReadyCheck: false,\n connectTimeout: this.options.connectTimeout,\n commandTimeout: this.options.sentinelCommandTimeout,\n ...options,\n });\n // @ts-expect-error\n return redis;\n }\n async resolve(endpoint) {\n const client = this.connectToSentinel(endpoint);\n // ignore the errors since resolve* methods will handle them\n client.on(\"error\", noop);\n try {\n if (this.options.role === \"slave\") {\n return await this.resolveSlave(client);\n }\n else {\n return await this.resolveMaster(client);\n }\n }\n finally {\n client.disconnect();\n }\n }\n async initFailoverDetector() {\n var _a;\n if (!this.options.failoverDetector) {\n return;\n }\n // Move the current sentinel to the first position\n this.sentinelIterator.reset(true);\n const sentinels = [];\n // In case of a large amount of sentinels, limit the number of concurrent connections\n while (sentinels.length < this.options.sentinelMaxConnections) {\n const { done, value } = this.sentinelIterator.next();\n if (done) {\n break;\n }\n const client = this.connectToSentinel(value, {\n lazyConnect: true,\n retryStrategy: this.options.sentinelReconnectStrategy,\n });\n client.on(\"reconnecting\", () => {\n var _a;\n // Tests listen to this event\n (_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit(\"sentinelReconnecting\");\n });\n sentinels.push({ address: value, client });\n }\n this.sentinelIterator.reset(false);\n if (this.failoverDetector) {\n // Clean up previous detector\n this.failoverDetector.cleanup();\n }\n this.failoverDetector = new FailoverDetector_1.FailoverDetector(this, sentinels);\n await this.failoverDetector.subscribe();\n // Tests listen to this event\n (_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit(\"failoverSubscribed\");\n }\n}\nexports.default = SentinelConnector;\nfunction selectPreferredSentinel(availableSlaves, preferredSlaves) {\n if (availableSlaves.length === 0) {\n return null;\n }\n let selectedSlave;\n if (typeof preferredSlaves === \"function\") {\n selectedSlave = preferredSlaves(availableSlaves);\n }\n else if (preferredSlaves !== null && typeof preferredSlaves === \"object\") {\n const preferredSlavesArray = Array.isArray(preferredSlaves)\n ? preferredSlaves\n : [preferredSlaves];\n // sort by priority\n preferredSlavesArray.sort((a, b) => {\n // default the priority to 1\n if (!a.prio) {\n a.prio = 1;\n }\n if (!b.prio) {\n b.prio = 1;\n }\n // lowest priority first\n if (a.prio < b.prio) {\n return -1;\n }\n if (a.prio > b.prio) {\n return 1;\n }\n return 0;\n });\n // loop over preferred slaves and return the first match\n for (let p = 0; p < preferredSlavesArray.length; p++) {\n for (let a = 0; a < availableSlaves.length; a++) {\n const slave = availableSlaves[a];\n if (slave.ip === preferredSlavesArray[p].ip) {\n if (slave.port === preferredSlavesArray[p].port) {\n selectedSlave = slave;\n break;\n }\n }\n }\n if (selectedSlave) {\n break;\n }\n }\n }\n // if none of the preferred slaves are available, a random available slave is returned\n if (!selectedSlave) {\n selectedSlave = (0, utils_1.sample)(availableSlaves);\n }\n return addressResponseToAddress(selectedSlave);\n}\nfunction addressResponseToAddress(input) {\n return { host: input.ip, port: Number(input.port) };\n}\nfunction noop() { }\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.SentinelConnector = exports.StandaloneConnector = void 0;\nconst StandaloneConnector_1 = require(\"./StandaloneConnector\");\nexports.StandaloneConnector = StandaloneConnector_1.default;\nconst SentinelConnector_1 = require(\"./SentinelConnector\");\nexports.SentinelConnector = SentinelConnector_1.default;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst redis_errors_1 = require(\"redis-errors\");\nclass MaxRetriesPerRequestError extends redis_errors_1.AbortError {\n constructor(maxRetriesPerRequest) {\n const message = `Reached the max retries per request limit (which is ${maxRetriesPerRequest}). Refer to \"maxRetriesPerRequest\" option for details.`;\n super(message);\n Error.captureStackTrace(this, this.constructor);\n }\n get name() {\n return this.constructor.name;\n }\n}\nexports.default = MaxRetriesPerRequestError;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.MaxRetriesPerRequestError = void 0;\nconst MaxRetriesPerRequestError_1 = require(\"./MaxRetriesPerRequestError\");\nexports.MaxRetriesPerRequestError = MaxRetriesPerRequestError_1.default;\n","'use strict'\n\nconst Buffer = require('buffer').Buffer\nconst StringDecoder = require('string_decoder').StringDecoder\nconst decoder = new StringDecoder()\nconst errors = require('redis-errors')\nconst ReplyError = errors.ReplyError\nconst ParserError = errors.ParserError\nvar bufferPool = Buffer.allocUnsafe(32 * 1024)\nvar bufferOffset = 0\nvar interval = null\nvar counter = 0\nvar notDecreased = 0\n\n/**\n * Used for integer numbers only\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|number}\n */\nfunction parseSimpleNumbers (parser) {\n const length = parser.buffer.length - 1\n var offset = parser.offset\n var number = 0\n var sign = 1\n\n if (parser.buffer[offset] === 45) {\n sign = -1\n offset++\n }\n\n while (offset < length) {\n const c1 = parser.buffer[offset++]\n if (c1 === 13) { // \\r\\n\n parser.offset = offset + 1\n return sign * number\n }\n number = (number * 10) + (c1 - 48)\n }\n}\n\n/**\n * Used for integer numbers in case of the returnNumbers option\n *\n * Reading the string as parts of n SMI is more efficient than\n * using a string directly.\n *\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|string}\n */\nfunction parseStringNumbers (parser) {\n const length = parser.buffer.length - 1\n var offset = parser.offset\n var number = 0\n var res = ''\n\n if (parser.buffer[offset] === 45) {\n res += '-'\n offset++\n }\n\n while (offset < length) {\n var c1 = parser.buffer[offset++]\n if (c1 === 13) { // \\r\\n\n parser.offset = offset + 1\n if (number !== 0) {\n res += number\n }\n return res\n } else if (number > 429496728) {\n res += (number * 10) + (c1 - 48)\n number = 0\n } else if (c1 === 48 && number === 0) {\n res += 0\n } else {\n number = (number * 10) + (c1 - 48)\n }\n }\n}\n\n/**\n * Parse a '+' redis simple string response but forward the offsets\n * onto convertBufferRange to generate a string.\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|string|Buffer}\n */\nfunction parseSimpleString (parser) {\n const start = parser.offset\n const buffer = parser.buffer\n const length = buffer.length - 1\n var offset = start\n\n while (offset < length) {\n if (buffer[offset++] === 13) { // \\r\\n\n parser.offset = offset + 1\n if (parser.optionReturnBuffers === true) {\n return parser.buffer.slice(start, offset - 1)\n }\n return parser.buffer.toString('utf8', start, offset - 1)\n }\n }\n}\n\n/**\n * Returns the read length\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|number}\n */\nfunction parseLength (parser) {\n const length = parser.buffer.length - 1\n var offset = parser.offset\n var number = 0\n\n while (offset < length) {\n const c1 = parser.buffer[offset++]\n if (c1 === 13) {\n parser.offset = offset + 1\n return number\n }\n number = (number * 10) + (c1 - 48)\n }\n}\n\n/**\n * Parse a ':' redis integer response\n *\n * If stringNumbers is activated the parser always returns numbers as string\n * This is important for big numbers (number > Math.pow(2, 53)) as js numbers\n * are 64bit floating point numbers with reduced precision\n *\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|number|string}\n */\nfunction parseInteger (parser) {\n if (parser.optionStringNumbers === true) {\n return parseStringNumbers(parser)\n }\n return parseSimpleNumbers(parser)\n}\n\n/**\n * Parse a '$' redis bulk string response\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|null|string}\n */\nfunction parseBulkString (parser) {\n const length = parseLength(parser)\n if (length === undefined) {\n return\n }\n if (length < 0) {\n return null\n }\n const offset = parser.offset + length\n if (offset + 2 > parser.buffer.length) {\n parser.bigStrSize = offset + 2\n parser.totalChunkSize = parser.buffer.length\n parser.bufferCache.push(parser.buffer)\n return\n }\n const start = parser.offset\n parser.offset = offset + 2\n if (parser.optionReturnBuffers === true) {\n return parser.buffer.slice(start, offset)\n }\n return parser.buffer.toString('utf8', start, offset)\n}\n\n/**\n * Parse a '-' redis error response\n * @param {JavascriptRedisParser} parser\n * @returns {ReplyError}\n */\nfunction parseError (parser) {\n var string = parseSimpleString(parser)\n if (string !== undefined) {\n if (parser.optionReturnBuffers === true) {\n string = string.toString()\n }\n return new ReplyError(string)\n }\n}\n\n/**\n * Parsing error handler, resets parser buffer\n * @param {JavascriptRedisParser} parser\n * @param {number} type\n * @returns {undefined}\n */\nfunction handleError (parser, type) {\n const err = new ParserError(\n 'Protocol error, got ' + JSON.stringify(String.fromCharCode(type)) + ' as reply type byte',\n JSON.stringify(parser.buffer),\n parser.offset\n )\n parser.buffer = null\n parser.returnFatalError(err)\n}\n\n/**\n * Parse a '*' redis array response\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|null|any[]}\n */\nfunction parseArray (parser) {\n const length = parseLength(parser)\n if (length === undefined) {\n return\n }\n if (length < 0) {\n return null\n }\n const responses = new Array(length)\n return parseArrayElements(parser, responses, 0)\n}\n\n/**\n * Push a partly parsed array to the stack\n *\n * @param {JavascriptRedisParser} parser\n * @param {any[]} array\n * @param {number} pos\n * @returns {undefined}\n */\nfunction pushArrayCache (parser, array, pos) {\n parser.arrayCache.push(array)\n parser.arrayPos.push(pos)\n}\n\n/**\n * Parse chunked redis array response\n * @param {JavascriptRedisParser} parser\n * @returns {undefined|any[]}\n */\nfunction parseArrayChunks (parser) {\n const tmp = parser.arrayCache.pop()\n var pos = parser.arrayPos.pop()\n if (parser.arrayCache.length) {\n const res = parseArrayChunks(parser)\n if (res === undefined) {\n pushArrayCache(parser, tmp, pos)\n return\n }\n tmp[pos++] = res\n }\n return parseArrayElements(parser, tmp, pos)\n}\n\n/**\n * Parse redis array response elements\n * @param {JavascriptRedisParser} parser\n * @param {Array} responses\n * @param {number} i\n * @returns {undefined|null|any[]}\n */\nfunction parseArrayElements (parser, responses, i) {\n const bufferLength = parser.buffer.length\n while (i < responses.length) {\n const offset = parser.offset\n if (parser.offset >= bufferLength) {\n pushArrayCache(parser, responses, i)\n return\n }\n const response = parseType(parser, parser.buffer[parser.offset++])\n if (response === undefined) {\n if (!(parser.arrayCache.length || parser.bufferCache.length)) {\n parser.offset = offset\n }\n pushArrayCache(parser, responses, i)\n return\n }\n responses[i] = response\n i++\n }\n\n return responses\n}\n\n/**\n * Called the appropriate parser for the specified type.\n *\n * 36: $\n * 43: +\n * 42: *\n * 58: :\n * 45: -\n *\n * @param {JavascriptRedisParser} parser\n * @param {number} type\n * @returns {*}\n */\nfunction parseType (parser, type) {\n switch (type) {\n case 36:\n return parseBulkString(parser)\n case 43:\n return parseSimpleString(parser)\n case 42:\n return parseArray(parser)\n case 58:\n return parseInteger(parser)\n case 45:\n return parseError(parser)\n default:\n return handleError(parser, type)\n }\n}\n\n/**\n * Decrease the bufferPool size over time\n *\n * Balance between increasing and decreasing the bufferPool.\n * Decrease the bufferPool by 10% by removing the first 10% of the current pool.\n * @returns {undefined}\n */\nfunction decreaseBufferPool () {\n if (bufferPool.length > 50 * 1024) {\n if (counter === 1 || notDecreased > counter * 2) {\n const minSliceLen = Math.floor(bufferPool.length / 10)\n const sliceLength = minSliceLen < bufferOffset\n ? bufferOffset\n : minSliceLen\n bufferOffset = 0\n bufferPool = bufferPool.slice(sliceLength, bufferPool.length)\n } else {\n notDecreased++\n counter--\n }\n } else {\n clearInterval(interval)\n counter = 0\n notDecreased = 0\n interval = null\n }\n}\n\n/**\n * Check if the requested size fits in the current bufferPool.\n * If it does not, reset and increase the bufferPool accordingly.\n *\n * @param {number} length\n * @returns {undefined}\n */\nfunction resizeBuffer (length) {\n if (bufferPool.length < length + bufferOffset) {\n const multiplier = length > 1024 * 1024 * 75 ? 2 : 3\n if (bufferOffset > 1024 * 1024 * 111) {\n bufferOffset = 1024 * 1024 * 50\n }\n bufferPool = Buffer.allocUnsafe(length * multiplier + bufferOffset)\n bufferOffset = 0\n counter++\n if (interval === null) {\n interval = setInterval(decreaseBufferPool, 50)\n }\n }\n}\n\n/**\n * Concat a bulk string containing multiple chunks\n *\n * Notes:\n * 1) The first chunk might contain the whole bulk string including the \\r\n * 2) We are only safe to fully add up elements that are neither the first nor any of the last two elements\n *\n * @param {JavascriptRedisParser} parser\n * @returns {String}\n */\nfunction concatBulkString (parser) {\n const list = parser.bufferCache\n const oldOffset = parser.offset\n var chunks = list.length\n var offset = parser.bigStrSize - parser.totalChunkSize\n parser.offset = offset\n if (offset <= 2) {\n if (chunks === 2) {\n return list[0].toString('utf8', oldOffset, list[0].length + offset - 2)\n }\n chunks--\n offset = list[list.length - 2].length + offset\n }\n var res = decoder.write(list[0].slice(oldOffset))\n for (var i = 1; i < chunks - 1; i++) {\n res += decoder.write(list[i])\n }\n res += decoder.end(list[i].slice(0, offset - 2))\n return res\n}\n\n/**\n * Concat the collected chunks from parser.bufferCache.\n *\n * Increases the bufferPool size beforehand if necessary.\n *\n * @param {JavascriptRedisParser} parser\n * @returns {Buffer}\n */\nfunction concatBulkBuffer (parser) {\n const list = parser.bufferCache\n const oldOffset = parser.offset\n const length = parser.bigStrSize - oldOffset - 2\n var chunks = list.length\n var offset = parser.bigStrSize - parser.totalChunkSize\n parser.offset = offset\n if (offset <= 2) {\n if (chunks === 2) {\n return list[0].slice(oldOffset, list[0].length + offset - 2)\n }\n chunks--\n offset = list[list.length - 2].length + offset\n }\n resizeBuffer(length)\n const start = bufferOffset\n list[0].copy(bufferPool, start, oldOffset, list[0].length)\n bufferOffset += list[0].length - oldOffset\n for (var i = 1; i < chunks - 1; i++) {\n list[i].copy(bufferPool, bufferOffset)\n bufferOffset += list[i].length\n }\n list[i].copy(bufferPool, bufferOffset, 0, offset - 2)\n bufferOffset += offset - 2\n return bufferPool.slice(start, bufferOffset)\n}\n\nclass JavascriptRedisParser {\n /**\n * Javascript Redis Parser constructor\n * @param {{returnError: Function, returnReply: Function, returnFatalError?: Function, returnBuffers: boolean, stringNumbers: boolean }} options\n * @constructor\n */\n constructor (options) {\n if (!options) {\n throw new TypeError('Options are mandatory.')\n }\n if (typeof options.returnError !== 'function' || typeof options.returnReply !== 'function') {\n throw new TypeError('The returnReply and returnError options have to be functions.')\n }\n this.setReturnBuffers(!!options.returnBuffers)\n this.setStringNumbers(!!options.stringNumbers)\n this.returnError = options.returnError\n this.returnFatalError = options.returnFatalError || options.returnError\n this.returnReply = options.returnReply\n this.reset()\n }\n\n /**\n * Reset the parser values to the initial state\n *\n * @returns {undefined}\n */\n reset () {\n this.offset = 0\n this.buffer = null\n this.bigStrSize = 0\n this.totalChunkSize = 0\n this.bufferCache = []\n this.arrayCache = []\n this.arrayPos = []\n }\n\n /**\n * Set the returnBuffers option\n *\n * @param {boolean} returnBuffers\n * @returns {undefined}\n */\n setReturnBuffers (returnBuffers) {\n if (typeof returnBuffers !== 'boolean') {\n throw new TypeError('The returnBuffers argument has to be a boolean')\n }\n this.optionReturnBuffers = returnBuffers\n }\n\n /**\n * Set the stringNumbers option\n *\n * @param {boolean} stringNumbers\n * @returns {undefined}\n */\n setStringNumbers (stringNumbers) {\n if (typeof stringNumbers !== 'boolean') {\n throw new TypeError('The stringNumbers argument has to be a boolean')\n }\n this.optionStringNumbers = stringNumbers\n }\n\n /**\n * Parse the redis buffer\n * @param {Buffer} buffer\n * @returns {undefined}\n */\n execute (buffer) {\n if (this.buffer === null) {\n this.buffer = buffer\n this.offset = 0\n } else if (this.bigStrSize === 0) {\n const oldLength = this.buffer.length\n const remainingLength = oldLength - this.offset\n const newBuffer = Buffer.allocUnsafe(remainingLength + buffer.length)\n this.buffer.copy(newBuffer, 0, this.offset, oldLength)\n buffer.copy(newBuffer, remainingLength, 0, buffer.length)\n this.buffer = newBuffer\n this.offset = 0\n if (this.arrayCache.length) {\n const arr = parseArrayChunks(this)\n if (arr === undefined) {\n return\n }\n this.returnReply(arr)\n }\n } else if (this.totalChunkSize + buffer.length >= this.bigStrSize) {\n this.bufferCache.push(buffer)\n var tmp = this.optionReturnBuffers ? concatBulkBuffer(this) : concatBulkString(this)\n this.bigStrSize = 0\n this.bufferCache = []\n this.buffer = buffer\n if (this.arrayCache.length) {\n this.arrayCache[0][this.arrayPos[0]++] = tmp\n tmp = parseArrayChunks(this)\n if (tmp === undefined) {\n return\n }\n }\n this.returnReply(tmp)\n } else {\n this.bufferCache.push(buffer)\n this.totalChunkSize += buffer.length\n return\n }\n\n while (this.offset < this.buffer.length) {\n const offset = this.offset\n const type = this.buffer[this.offset++]\n const response = parseType(this, type)\n if (response === undefined) {\n if (!(this.arrayCache.length || this.bufferCache.length)) {\n this.offset = offset\n }\n return\n }\n\n if (type === 45) {\n this.returnError(response)\n } else {\n this.returnReply(response)\n }\n }\n\n this.buffer = null\n }\n}\n\nmodule.exports = JavascriptRedisParser\n","'use strict'\n\nmodule.exports = require('./lib/parser')\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n/**\n * Tiny class to simplify dealing with subscription set\n */\nclass SubscriptionSet {\n constructor() {\n this.set = {\n subscribe: {},\n psubscribe: {},\n ssubscribe: {},\n };\n }\n add(set, channel) {\n this.set[mapSet(set)][channel] = true;\n }\n del(set, channel) {\n delete this.set[mapSet(set)][channel];\n }\n channels(set) {\n return Object.keys(this.set[mapSet(set)]);\n }\n isEmpty() {\n return (this.channels(\"subscribe\").length === 0 &&\n this.channels(\"psubscribe\").length === 0 &&\n this.channels(\"ssubscribe\").length === 0);\n }\n}\nexports.default = SubscriptionSet;\nfunction mapSet(set) {\n if (set === \"unsubscribe\") {\n return \"subscribe\";\n }\n if (set === \"punsubscribe\") {\n return \"psubscribe\";\n }\n if (set === \"sunsubscribe\") {\n return \"ssubscribe\";\n }\n return set;\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst Command_1 = require(\"./Command\");\nconst utils_1 = require(\"./utils\");\nconst RedisParser = require(\"redis-parser\");\nconst SubscriptionSet_1 = require(\"./SubscriptionSet\");\nconst debug = (0, utils_1.Debug)(\"dataHandler\");\nclass DataHandler {\n constructor(redis, parserOptions) {\n this.redis = redis;\n const parser = new RedisParser({\n stringNumbers: parserOptions.stringNumbers,\n returnBuffers: true,\n returnError: (err) => {\n this.returnError(err);\n },\n returnFatalError: (err) => {\n this.returnFatalError(err);\n },\n returnReply: (reply) => {\n this.returnReply(reply);\n },\n });\n // prependListener ensures the parser receives and processes data before socket timeout checks are performed\n redis.stream.prependListener(\"data\", (data) => {\n parser.execute(data);\n });\n // prependListener() doesn't enable flowing mode automatically - we need to resume the stream manually\n redis.stream.resume();\n }\n returnFatalError(err) {\n err.message += \". Please report this.\";\n this.redis.recoverFromFatalError(err, err, { offlineQueue: false });\n }\n returnError(err) {\n const item = this.shiftCommand(err);\n if (!item) {\n return;\n }\n err.command = {\n name: item.command.name,\n args: item.command.args,\n };\n this.redis.handleReconnection(err, item);\n }\n returnReply(reply) {\n if (this.handleMonitorReply(reply)) {\n return;\n }\n if (this.handleSubscriberReply(reply)) {\n return;\n }\n const item = this.shiftCommand(reply);\n if (!item) {\n return;\n }\n if (Command_1.default.checkFlag(\"ENTER_SUBSCRIBER_MODE\", item.command.name)) {\n this.redis.condition.subscriber = new SubscriptionSet_1.default();\n this.redis.condition.subscriber.add(item.command.name, reply[1].toString());\n if (!fillSubCommand(item.command, reply[2])) {\n this.redis.commandQueue.unshift(item);\n }\n }\n else if (Command_1.default.checkFlag(\"EXIT_SUBSCRIBER_MODE\", item.command.name)) {\n if (!fillUnsubCommand(item.command, reply[2])) {\n this.redis.commandQueue.unshift(item);\n }\n }\n else {\n item.command.resolve(reply);\n }\n }\n handleSubscriberReply(reply) {\n if (!this.redis.condition.subscriber) {\n return false;\n }\n const replyType = Array.isArray(reply) ? reply[0].toString() : null;\n debug('receive reply \"%s\" in subscriber mode', replyType);\n switch (replyType) {\n case \"message\":\n if (this.redis.listeners(\"message\").length > 0) {\n // Check if there're listeners to avoid unnecessary `toString()`.\n this.redis.emit(\"message\", reply[1].toString(), reply[2] ? reply[2].toString() : \"\");\n }\n this.redis.emit(\"messageBuffer\", reply[1], reply[2]);\n break;\n case \"pmessage\": {\n const pattern = reply[1].toString();\n if (this.redis.listeners(\"pmessage\").length > 0) {\n this.redis.emit(\"pmessage\", pattern, reply[2].toString(), reply[3].toString());\n }\n this.redis.emit(\"pmessageBuffer\", pattern, reply[2], reply[3]);\n break;\n }\n case \"smessage\": {\n if (this.redis.listeners(\"smessage\").length > 0) {\n this.redis.emit(\"smessage\", reply[1].toString(), reply[2] ? reply[2].toString() : \"\");\n }\n this.redis.emit(\"smessageBuffer\", reply[1], reply[2]);\n break;\n }\n case \"ssubscribe\":\n case \"subscribe\":\n case \"psubscribe\": {\n const channel = reply[1].toString();\n this.redis.condition.subscriber.add(replyType, channel);\n const item = this.shiftCommand(reply);\n if (!item) {\n return;\n }\n if (!fillSubCommand(item.command, reply[2])) {\n this.redis.commandQueue.unshift(item);\n }\n break;\n }\n case \"sunsubscribe\":\n case \"unsubscribe\":\n case \"punsubscribe\": {\n const channel = reply[1] ? reply[1].toString() : null;\n if (channel) {\n this.redis.condition.subscriber.del(replyType, channel);\n }\n const count = reply[2];\n if (Number(count) === 0) {\n this.redis.condition.subscriber = false;\n }\n const item = this.shiftCommand(reply);\n if (!item) {\n return;\n }\n if (!fillUnsubCommand(item.command, count)) {\n this.redis.commandQueue.unshift(item);\n }\n break;\n }\n default: {\n const item = this.shiftCommand(reply);\n if (!item) {\n return;\n }\n item.command.resolve(reply);\n }\n }\n return true;\n }\n handleMonitorReply(reply) {\n if (this.redis.status !== \"monitoring\") {\n return false;\n }\n const replyStr = reply.toString();\n if (replyStr === \"OK\") {\n // Valid commands in the monitoring mode are AUTH and MONITOR,\n // both of which always reply with 'OK'.\n // So if we got an 'OK', we can make certain that\n // the reply is made to AUTH & MONITOR.\n return false;\n }\n // Since commands sent in the monitoring mode will trigger an exception,\n // any replies we received in the monitoring mode should consider to be\n // realtime monitor data instead of result of commands.\n const len = replyStr.indexOf(\" \");\n const timestamp = replyStr.slice(0, len);\n const argIndex = replyStr.indexOf('\"');\n const args = replyStr\n .slice(argIndex + 1, -1)\n .split('\" \"')\n .map((elem) => elem.replace(/\\\\\"/g, '\"'));\n const dbAndSource = replyStr.slice(len + 2, argIndex - 2).split(\" \");\n this.redis.emit(\"monitor\", timestamp, args, dbAndSource[1], dbAndSource[0]);\n return true;\n }\n shiftCommand(reply) {\n const item = this.redis.commandQueue.shift();\n if (!item) {\n const message = \"Command queue state error. If you can reproduce this, please report it.\";\n const error = new Error(message +\n (reply instanceof Error\n ? ` Last error: ${reply.message}`\n : ` Last reply: ${reply.toString()}`));\n this.redis.emit(\"error\", error);\n return null;\n }\n return item;\n }\n}\nexports.default = DataHandler;\nconst remainingRepliesMap = new WeakMap();\nfunction fillSubCommand(command, count) {\n let remainingReplies = remainingRepliesMap.has(command)\n ? remainingRepliesMap.get(command)\n : command.args.length;\n remainingReplies -= 1;\n if (remainingReplies <= 0) {\n command.resolve(count);\n remainingRepliesMap.delete(command);\n return true;\n }\n remainingRepliesMap.set(command, remainingReplies);\n return false;\n}\nfunction fillUnsubCommand(command, count) {\n let remainingReplies = remainingRepliesMap.has(command)\n ? remainingRepliesMap.get(command)\n : command.args.length;\n if (remainingReplies === 0) {\n if (Number(count) === 0) {\n remainingRepliesMap.delete(command);\n command.resolve(count);\n return true;\n }\n return false;\n }\n remainingReplies -= 1;\n if (remainingReplies <= 0) {\n command.resolve(count);\n return true;\n }\n remainingRepliesMap.set(command, remainingReplies);\n return false;\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.readyHandler = exports.errorHandler = exports.closeHandler = exports.connectHandler = void 0;\nconst redis_errors_1 = require(\"redis-errors\");\nconst Command_1 = require(\"../Command\");\nconst errors_1 = require(\"../errors\");\nconst utils_1 = require(\"../utils\");\nconst DataHandler_1 = require(\"../DataHandler\");\nconst debug = (0, utils_1.Debug)(\"connection\");\nfunction connectHandler(self) {\n return function () {\n self.setStatus(\"connect\");\n self.resetCommandQueue();\n // AUTH command should be processed before any other commands\n let flushed = false;\n const { connectionEpoch } = self;\n if (self.condition.auth) {\n self.auth(self.condition.auth, function (err) {\n if (connectionEpoch !== self.connectionEpoch) {\n return;\n }\n if (err) {\n if (err.message.indexOf(\"no password is set\") !== -1) {\n console.warn(\"[WARN] Redis server does not require a password, but a password was supplied.\");\n }\n else if (err.message.indexOf(\"without any password configured for the default user\") !== -1) {\n console.warn(\"[WARN] This Redis server's `default` user does not require a password, but a password was supplied\");\n }\n else if (err.message.indexOf(\"wrong number of arguments for 'auth' command\") !== -1) {\n console.warn(`[ERROR] The server returned \"wrong number of arguments for 'auth' command\". You are probably passing both username and password to Redis version 5 or below. You should only pass the 'password' option for Redis version 5 and under.`);\n }\n else {\n flushed = true;\n self.recoverFromFatalError(err, err);\n }\n }\n });\n }\n if (self.condition.select) {\n self.select(self.condition.select).catch((err) => {\n // If the node is in cluster mode, select is disallowed.\n // In this case, reconnect won't help.\n self.silentEmit(\"error\", err);\n });\n }\n if (!self.options.enableReadyCheck) {\n exports.readyHandler(self)();\n }\n /*\n No need to keep the reference of DataHandler here\n because we don't need to do the cleanup.\n `Stream#end()` will remove all listeners for us.\n */\n new DataHandler_1.default(self, {\n stringNumbers: self.options.stringNumbers,\n });\n if (self.options.enableReadyCheck) {\n self._readyCheck(function (err, info) {\n if (connectionEpoch !== self.connectionEpoch) {\n return;\n }\n if (err) {\n if (!flushed) {\n self.recoverFromFatalError(new Error(\"Ready check failed: \" + err.message), err);\n }\n }\n else {\n if (self.connector.check(info)) {\n exports.readyHandler(self)();\n }\n else {\n self.disconnect(true);\n }\n }\n });\n }\n };\n}\nexports.connectHandler = connectHandler;\nfunction abortError(command) {\n const err = new redis_errors_1.AbortError(\"Command aborted due to connection close\");\n err.command = {\n name: command.name,\n args: command.args,\n };\n return err;\n}\n// If a contiguous set of pipeline commands starts from index zero then they\n// can be safely reattempted. If however we have a chain of pipelined commands\n// starting at index 1 or more it means we received a partial response before\n// the connection close and those pipelined commands must be aborted. For\n// example, if the queue looks like this: [2, 3, 4, 0, 1, 2] then after\n// aborting and purging we'll have a queue that looks like this: [0, 1, 2]\nfunction abortIncompletePipelines(commandQueue) {\n var _a;\n let expectedIndex = 0;\n for (let i = 0; i < commandQueue.length;) {\n const command = (_a = commandQueue.peekAt(i)) === null || _a === void 0 ? void 0 : _a.command;\n const pipelineIndex = command.pipelineIndex;\n if (pipelineIndex === undefined || pipelineIndex === 0) {\n expectedIndex = 0;\n }\n if (pipelineIndex !== undefined && pipelineIndex !== expectedIndex++) {\n commandQueue.remove(i, 1);\n command.reject(abortError(command));\n continue;\n }\n i++;\n }\n}\n// If only a partial transaction result was received before connection close,\n// we have to abort any transaction fragments that may have ended up in the\n// offline queue\nfunction abortTransactionFragments(commandQueue) {\n var _a;\n for (let i = 0; i < commandQueue.length;) {\n const command = (_a = commandQueue.peekAt(i)) === null || _a === void 0 ? void 0 : _a.command;\n if (command.name === \"multi\") {\n break;\n }\n if (command.name === \"exec\") {\n commandQueue.remove(i, 1);\n command.reject(abortError(command));\n break;\n }\n if (command.inTransaction) {\n commandQueue.remove(i, 1);\n command.reject(abortError(command));\n }\n else {\n i++;\n }\n }\n}\nfunction closeHandler(self) {\n return function () {\n const prevStatus = self.status;\n self.setStatus(\"close\");\n if (self.commandQueue.length) {\n abortIncompletePipelines(self.commandQueue);\n }\n if (self.offlineQueue.length) {\n abortTransactionFragments(self.offlineQueue);\n }\n if (prevStatus === \"ready\") {\n if (!self.prevCondition) {\n self.prevCondition = self.condition;\n }\n if (self.commandQueue.length) {\n self.prevCommandQueue = self.commandQueue;\n }\n }\n if (self.manuallyClosing) {\n self.manuallyClosing = false;\n debug(\"skip reconnecting since the connection is manually closed.\");\n return close();\n }\n if (typeof self.options.retryStrategy !== \"function\") {\n debug(\"skip reconnecting because `retryStrategy` is not a function\");\n return close();\n }\n const retryDelay = self.options.retryStrategy(++self.retryAttempts);\n if (typeof retryDelay !== \"number\") {\n debug(\"skip reconnecting because `retryStrategy` doesn't return a number\");\n return close();\n }\n debug(\"reconnect in %sms\", retryDelay);\n self.setStatus(\"reconnecting\", retryDelay);\n self.reconnectTimeout = setTimeout(function () {\n self.reconnectTimeout = null;\n self.connect().catch(utils_1.noop);\n }, retryDelay);\n const { maxRetriesPerRequest } = self.options;\n if (typeof maxRetriesPerRequest === \"number\") {\n if (maxRetriesPerRequest < 0) {\n debug(\"maxRetriesPerRequest is negative, ignoring...\");\n }\n else {\n const remainder = self.retryAttempts % (maxRetriesPerRequest + 1);\n if (remainder === 0) {\n debug(\"reach maxRetriesPerRequest limitation, flushing command queue...\");\n self.flushQueue(new errors_1.MaxRetriesPerRequestError(maxRetriesPerRequest));\n }\n }\n }\n };\n function close() {\n self.setStatus(\"end\");\n self.flushQueue(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n }\n}\nexports.closeHandler = closeHandler;\nfunction errorHandler(self) {\n return function (error) {\n debug(\"error: %s\", error);\n self.silentEmit(\"error\", error);\n };\n}\nexports.errorHandler = errorHandler;\nfunction readyHandler(self) {\n return function () {\n self.setStatus(\"ready\");\n self.retryAttempts = 0;\n if (self.options.monitor) {\n self.call(\"monitor\").then(() => self.setStatus(\"monitoring\"), (error) => self.emit(\"error\", error));\n const { sendCommand } = self;\n self.sendCommand = function (command) {\n if (Command_1.default.checkFlag(\"VALID_IN_MONITOR_MODE\", command.name)) {\n return sendCommand.call(self, command);\n }\n command.reject(new Error(\"Connection is in monitoring mode, can't process commands.\"));\n return command.promise;\n };\n self.once(\"close\", function () {\n delete self.sendCommand;\n });\n return;\n }\n const finalSelect = self.prevCondition\n ? self.prevCondition.select\n : self.condition.select;\n if (self.options.connectionName) {\n debug(\"set the connection name [%s]\", self.options.connectionName);\n self.client(\"setname\", self.options.connectionName).catch(utils_1.noop);\n }\n if (self.options.readOnly) {\n debug(\"set the connection to readonly mode\");\n self.readonly().catch(utils_1.noop);\n }\n if (self.prevCondition) {\n const condition = self.prevCondition;\n self.prevCondition = null;\n if (condition.subscriber && self.options.autoResubscribe) {\n // We re-select the previous db first since\n // `SELECT` command is not valid in sub mode.\n if (self.condition.select !== finalSelect) {\n debug(\"connect to db [%d]\", finalSelect);\n self.select(finalSelect);\n }\n const subscribeChannels = condition.subscriber.channels(\"subscribe\");\n if (subscribeChannels.length) {\n debug(\"subscribe %d channels\", subscribeChannels.length);\n self.subscribe(subscribeChannels);\n }\n const psubscribeChannels = condition.subscriber.channels(\"psubscribe\");\n if (psubscribeChannels.length) {\n debug(\"psubscribe %d channels\", psubscribeChannels.length);\n self.psubscribe(psubscribeChannels);\n }\n const ssubscribeChannels = condition.subscriber.channels(\"ssubscribe\");\n if (ssubscribeChannels.length) {\n debug(\"ssubscribe %d channels\", ssubscribeChannels.length);\n self.ssubscribe(ssubscribeChannels);\n }\n }\n }\n if (self.prevCommandQueue) {\n if (self.options.autoResendUnfulfilledCommands) {\n debug(\"resend %d unfulfilled commands\", self.prevCommandQueue.length);\n while (self.prevCommandQueue.length > 0) {\n const item = self.prevCommandQueue.shift();\n if (item.select !== self.condition.select &&\n item.command.name !== \"select\") {\n self.select(item.select);\n }\n self.sendCommand(item.command, item.stream);\n }\n }\n else {\n self.prevCommandQueue = null;\n }\n }\n if (self.offlineQueue.length) {\n debug(\"send %d commands in offline queue\", self.offlineQueue.length);\n const offlineQueue = self.offlineQueue;\n self.resetOfflineQueue();\n while (offlineQueue.length > 0) {\n const item = offlineQueue.shift();\n if (item.select !== self.condition.select &&\n item.command.name !== \"select\") {\n self.select(item.select);\n }\n self.sendCommand(item.command, item.stream);\n }\n }\n if (self.condition.select !== finalSelect) {\n debug(\"connect to db [%d]\", finalSelect);\n self.select(finalSelect);\n }\n };\n}\nexports.readyHandler = readyHandler;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.DEFAULT_REDIS_OPTIONS = void 0;\nexports.DEFAULT_REDIS_OPTIONS = {\n // Connection\n port: 6379,\n host: \"localhost\",\n family: 4,\n connectTimeout: 10000,\n disconnectTimeout: 2000,\n retryStrategy: function (times) {\n return Math.min(times * 50, 2000);\n },\n keepAlive: 0,\n noDelay: true,\n connectionName: null,\n // Sentinel\n sentinels: null,\n name: null,\n role: \"master\",\n sentinelRetryStrategy: function (times) {\n return Math.min(times * 10, 1000);\n },\n sentinelReconnectStrategy: function () {\n // This strategy only applies when sentinels are used for detecting\n // a failover, not during initial master resolution.\n // The deployment can still function when some of the sentinels are down\n // for a long period of time, so we may not want to attempt reconnection\n // very often. Therefore the default interval is fairly long (1 minute).\n return 60000;\n },\n natMap: null,\n enableTLSForSentinelMode: false,\n updateSentinels: true,\n failoverDetector: false,\n // Status\n username: null,\n password: null,\n db: 0,\n // Others\n enableOfflineQueue: true,\n enableReadyCheck: true,\n autoResubscribe: true,\n autoResendUnfulfilledCommands: true,\n lazyConnect: false,\n keyPrefix: \"\",\n reconnectOnError: null,\n readOnly: false,\n stringNumbers: false,\n maxRetriesPerRequest: 20,\n maxLoadingRetryTime: 10000,\n enableAutoPipelining: false,\n autoPipeliningIgnoredCommands: [],\n sentinelMaxConnections: 10,\n};\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst commands_1 = require(\"@ioredis/commands\");\nconst events_1 = require(\"events\");\nconst standard_as_callback_1 = require(\"standard-as-callback\");\nconst cluster_1 = require(\"./cluster\");\nconst Command_1 = require(\"./Command\");\nconst connectors_1 = require(\"./connectors\");\nconst SentinelConnector_1 = require(\"./connectors/SentinelConnector\");\nconst eventHandler = require(\"./redis/event_handler\");\nconst RedisOptions_1 = require(\"./redis/RedisOptions\");\nconst ScanStream_1 = require(\"./ScanStream\");\nconst transaction_1 = require(\"./transaction\");\nconst utils_1 = require(\"./utils\");\nconst applyMixin_1 = require(\"./utils/applyMixin\");\nconst Commander_1 = require(\"./utils/Commander\");\nconst lodash_1 = require(\"./utils/lodash\");\nconst Deque = require(\"denque\");\nconst debug = (0, utils_1.Debug)(\"redis\");\n/**\n * This is the major component of ioredis.\n * Use it to connect to a standalone Redis server or Sentinels.\n *\n * ```typescript\n * const redis = new Redis(); // Default port is 6379\n * async function main() {\n * redis.set(\"foo\", \"bar\");\n * redis.get(\"foo\", (err, result) => {\n * // `result` should be \"bar\"\n * console.log(err, result);\n * });\n * // Or use Promise\n * const result = await redis.get(\"foo\");\n * }\n * ```\n */\nclass Redis extends Commander_1.default {\n constructor(arg1, arg2, arg3) {\n super();\n this.status = \"wait\";\n /**\n * @ignore\n */\n this.isCluster = false;\n this.reconnectTimeout = null;\n this.connectionEpoch = 0;\n this.retryAttempts = 0;\n this.manuallyClosing = false;\n // Prepare autopipelines structures\n this._autoPipelines = new Map();\n this._runningAutoPipelines = new Set();\n this.parseOptions(arg1, arg2, arg3);\n events_1.EventEmitter.call(this);\n this.resetCommandQueue();\n this.resetOfflineQueue();\n if (this.options.Connector) {\n this.connector = new this.options.Connector(this.options);\n }\n else if (this.options.sentinels) {\n const sentinelConnector = new SentinelConnector_1.default(this.options);\n sentinelConnector.emitter = this;\n this.connector = sentinelConnector;\n }\n else {\n this.connector = new connectors_1.StandaloneConnector(this.options);\n }\n if (this.options.scripts) {\n Object.entries(this.options.scripts).forEach(([name, definition]) => {\n this.defineCommand(name, definition);\n });\n }\n // end(or wait) -> connecting -> connect -> ready -> end\n if (this.options.lazyConnect) {\n this.setStatus(\"wait\");\n }\n else {\n this.connect().catch(lodash_1.noop);\n }\n }\n /**\n * Create a Redis instance.\n * This is the same as `new Redis()` but is included for compatibility with node-redis.\n */\n static createClient(...args) {\n return new Redis(...args);\n }\n get autoPipelineQueueSize() {\n let queued = 0;\n for (const pipeline of this._autoPipelines.values()) {\n queued += pipeline.length;\n }\n return queued;\n }\n /**\n * Create a connection to Redis.\n * This method will be invoked automatically when creating a new Redis instance\n * unless `lazyConnect: true` is passed.\n *\n * When calling this method manually, a Promise is returned, which will\n * be resolved when the connection status is ready.\n */\n connect(callback) {\n const promise = new Promise((resolve, reject) => {\n if (this.status === \"connecting\" ||\n this.status === \"connect\" ||\n this.status === \"ready\") {\n reject(new Error(\"Redis is already connecting/connected\"));\n return;\n }\n this.connectionEpoch += 1;\n this.setStatus(\"connecting\");\n const { options } = this;\n this.condition = {\n select: options.db,\n auth: options.username\n ? [options.username, options.password]\n : options.password,\n subscriber: false,\n };\n const _this = this;\n (0, standard_as_callback_1.default)(this.connector.connect(function (type, err) {\n _this.silentEmit(type, err);\n }), function (err, stream) {\n if (err) {\n _this.flushQueue(err);\n _this.silentEmit(\"error\", err);\n reject(err);\n _this.setStatus(\"end\");\n return;\n }\n let CONNECT_EVENT = options.tls ? \"secureConnect\" : \"connect\";\n if (\"sentinels\" in options &&\n options.sentinels &&\n !options.enableTLSForSentinelMode) {\n CONNECT_EVENT = \"connect\";\n }\n _this.stream = stream;\n if (options.noDelay) {\n stream.setNoDelay(true);\n }\n // Node ignores setKeepAlive before connect, therefore we wait for the event:\n // https://github.com/nodejs/node/issues/31663\n if (typeof options.keepAlive === \"number\") {\n if (stream.connecting) {\n stream.once(CONNECT_EVENT, () => {\n stream.setKeepAlive(true, options.keepAlive);\n });\n }\n else {\n stream.setKeepAlive(true, options.keepAlive);\n }\n }\n if (stream.connecting) {\n stream.once(CONNECT_EVENT, eventHandler.connectHandler(_this));\n if (options.connectTimeout) {\n /*\n * Typically, Socket#setTimeout(0) will clear the timer\n * set before. However, in some platforms (Electron 3.x~4.x),\n * the timer will not be cleared. So we introduce a variable here.\n *\n * See https://github.com/electron/electron/issues/14915\n */\n let connectTimeoutCleared = false;\n stream.setTimeout(options.connectTimeout, function () {\n if (connectTimeoutCleared) {\n return;\n }\n stream.setTimeout(0);\n stream.destroy();\n const err = new Error(\"connect ETIMEDOUT\");\n // @ts-expect-error\n err.errorno = \"ETIMEDOUT\";\n // @ts-expect-error\n err.code = \"ETIMEDOUT\";\n // @ts-expect-error\n err.syscall = \"connect\";\n eventHandler.errorHandler(_this)(err);\n });\n stream.once(CONNECT_EVENT, function () {\n connectTimeoutCleared = true;\n stream.setTimeout(0);\n });\n }\n }\n else if (stream.destroyed) {\n const firstError = _this.connector.firstError;\n if (firstError) {\n process.nextTick(() => {\n eventHandler.errorHandler(_this)(firstError);\n });\n }\n process.nextTick(eventHandler.closeHandler(_this));\n }\n else {\n process.nextTick(eventHandler.connectHandler(_this));\n }\n if (!stream.destroyed) {\n stream.once(\"error\", eventHandler.errorHandler(_this));\n stream.once(\"close\", eventHandler.closeHandler(_this));\n }\n const connectionReadyHandler = function () {\n _this.removeListener(\"close\", connectionCloseHandler);\n resolve();\n };\n var connectionCloseHandler = function () {\n _this.removeListener(\"ready\", connectionReadyHandler);\n reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n };\n _this.once(\"ready\", connectionReadyHandler);\n _this.once(\"close\", connectionCloseHandler);\n });\n });\n return (0, standard_as_callback_1.default)(promise, callback);\n }\n /**\n * Disconnect from Redis.\n *\n * This method closes the connection immediately,\n * and may lose some pending replies that haven't written to client.\n * If you want to wait for the pending replies, use Redis#quit instead.\n */\n disconnect(reconnect = false) {\n if (!reconnect) {\n this.manuallyClosing = true;\n }\n if (this.reconnectTimeout && !reconnect) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n if (this.status === \"wait\") {\n eventHandler.closeHandler(this)();\n }\n else {\n this.connector.disconnect();\n }\n }\n /**\n * Disconnect from Redis.\n *\n * @deprecated\n */\n end() {\n this.disconnect();\n }\n /**\n * Create a new instance with the same options as the current one.\n *\n * @example\n * ```js\n * var redis = new Redis(6380);\n * var anotherRedis = redis.duplicate();\n * ```\n */\n duplicate(override) {\n return new Redis({ ...this.options, ...override });\n }\n /**\n * Mode of the connection.\n *\n * One of `\"normal\"`, `\"subscriber\"`, or `\"monitor\"`. When the connection is\n * not in `\"normal\"` mode, certain commands are not allowed.\n */\n get mode() {\n var _a;\n return this.options.monitor\n ? \"monitor\"\n : ((_a = this.condition) === null || _a === void 0 ? void 0 : _a.subscriber)\n ? \"subscriber\"\n : \"normal\";\n }\n /**\n * Listen for all requests received by the server in real time.\n *\n * This command will create a new connection to Redis and send a\n * MONITOR command via the new connection in order to avoid disturbing\n * the current connection.\n *\n * @param callback The callback function. If omit, a promise will be returned.\n * @example\n * ```js\n * var redis = new Redis();\n * redis.monitor(function (err, monitor) {\n * // Entering monitoring mode.\n * monitor.on('monitor', function (time, args, source, database) {\n * console.log(time + \": \" + util.inspect(args));\n * });\n * });\n *\n * // supports promise as well as other commands\n * redis.monitor().then(function (monitor) {\n * monitor.on('monitor', function (time, args, source, database) {\n * console.log(time + \": \" + util.inspect(args));\n * });\n * });\n * ```\n */\n monitor(callback) {\n const monitorInstance = this.duplicate({\n monitor: true,\n lazyConnect: false,\n });\n return (0, standard_as_callback_1.default)(new Promise(function (resolve, reject) {\n monitorInstance.once(\"error\", reject);\n monitorInstance.once(\"monitoring\", function () {\n resolve(monitorInstance);\n });\n }), callback);\n }\n /**\n * Send a command to Redis\n *\n * This method is used internally and in most cases you should not\n * use it directly. If you need to send a command that is not supported\n * by the library, you can use the `call` method:\n *\n * ```js\n * const redis = new Redis();\n *\n * redis.call('set', 'foo', 'bar');\n * // or\n * redis.call(['set', 'foo', 'bar']);\n * ```\n *\n * @ignore\n */\n sendCommand(command, stream) {\n var _a, _b;\n if (this.status === \"wait\") {\n this.connect().catch(lodash_1.noop);\n }\n if (this.status === \"end\") {\n command.reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));\n return command.promise;\n }\n if (((_a = this.condition) === null || _a === void 0 ? void 0 : _a.subscriber) &&\n !Command_1.default.checkFlag(\"VALID_IN_SUBSCRIBER_MODE\", command.name)) {\n command.reject(new Error(\"Connection in subscriber mode, only subscriber commands may be used\"));\n return command.promise;\n }\n if (typeof this.options.commandTimeout === \"number\") {\n command.setTimeout(this.options.commandTimeout);\n }\n let writable = this.status === \"ready\" ||\n (!stream &&\n this.status === \"connect\" &&\n (0, commands_1.exists)(command.name) &&\n (0, commands_1.hasFlag)(command.name, \"loading\"));\n if (!this.stream) {\n writable = false;\n }\n else if (!this.stream.writable) {\n writable = false;\n // @ts-expect-error\n }\n else if (this.stream._writableState && this.stream._writableState.ended) {\n // TODO: We should be able to remove this as the PR has already been merged.\n // https://github.com/iojs/io.js/pull/1217\n writable = false;\n }\n if (!writable) {\n if (!this.options.enableOfflineQueue) {\n command.reject(new Error(\"Stream isn't writeable and enableOfflineQueue options is false\"));\n return command.promise;\n }\n if (command.name === \"quit\" && this.offlineQueue.length === 0) {\n this.disconnect();\n command.resolve(Buffer.from(\"OK\"));\n return command.promise;\n }\n // @ts-expect-error\n if (debug.enabled) {\n debug(\"queue command[%s]: %d -> %s(%o)\", this._getDescription(), this.condition.select, command.name, command.args);\n }\n this.offlineQueue.push({\n command: command,\n stream: stream,\n select: this.condition.select,\n });\n }\n else {\n // @ts-expect-error\n if (debug.enabled) {\n debug(\"write command[%s]: %d -> %s(%o)\", this._getDescription(), (_b = this.condition) === null || _b === void 0 ? void 0 : _b.select, command.name, command.args);\n }\n if (stream) {\n if (\"isPipeline\" in stream && stream.isPipeline) {\n stream.write(command.toWritable(stream.destination.redis.stream));\n }\n else {\n stream.write(command.toWritable(stream));\n }\n }\n else {\n this.stream.write(command.toWritable(this.stream));\n }\n this.commandQueue.push({\n command: command,\n stream: stream,\n select: this.condition.select,\n });\n if (Command_1.default.checkFlag(\"WILL_DISCONNECT\", command.name)) {\n this.manuallyClosing = true;\n }\n if (this.options.socketTimeout !== undefined && this.socketTimeoutTimer === undefined) {\n this.setSocketTimeout();\n }\n }\n if (command.name === \"select\" && (0, utils_1.isInt)(command.args[0])) {\n const db = parseInt(command.args[0], 10);\n if (this.condition.select !== db) {\n this.condition.select = db;\n this.emit(\"select\", db);\n debug(\"switch to db [%d]\", this.condition.select);\n }\n }\n return command.promise;\n }\n setSocketTimeout() {\n this.socketTimeoutTimer = setTimeout(() => {\n this.stream.destroy(new Error(`Socket timeout. Expecting data, but didn't receive any in ${this.options.socketTimeout}ms.`));\n this.socketTimeoutTimer = undefined;\n }, this.options.socketTimeout);\n // this handler must run after the \"data\" handler in \"DataHandler\"\n // so that `this.commandQueue.length` will be updated\n this.stream.once(\"data\", () => {\n clearTimeout(this.socketTimeoutTimer);\n this.socketTimeoutTimer = undefined;\n if (this.commandQueue.length === 0)\n return;\n this.setSocketTimeout();\n });\n }\n scanStream(options) {\n return this.createScanStream(\"scan\", { options });\n }\n scanBufferStream(options) {\n return this.createScanStream(\"scanBuffer\", { options });\n }\n sscanStream(key, options) {\n return this.createScanStream(\"sscan\", { key, options });\n }\n sscanBufferStream(key, options) {\n return this.createScanStream(\"sscanBuffer\", { key, options });\n }\n hscanStream(key, options) {\n return this.createScanStream(\"hscan\", { key, options });\n }\n hscanBufferStream(key, options) {\n return this.createScanStream(\"hscanBuffer\", { key, options });\n }\n zscanStream(key, options) {\n return this.createScanStream(\"zscan\", { key, options });\n }\n zscanBufferStream(key, options) {\n return this.createScanStream(\"zscanBuffer\", { key, options });\n }\n /**\n * Emit only when there's at least one listener.\n *\n * @ignore\n */\n silentEmit(eventName, arg) {\n let error;\n if (eventName === \"error\") {\n error = arg;\n if (this.status === \"end\") {\n return;\n }\n if (this.manuallyClosing) {\n // ignore connection related errors when manually disconnecting\n if (error instanceof Error &&\n (error.message === utils_1.CONNECTION_CLOSED_ERROR_MSG ||\n // @ts-expect-error\n error.syscall === \"connect\" ||\n // @ts-expect-error\n error.syscall === \"read\")) {\n return;\n }\n }\n }\n if (this.listeners(eventName).length > 0) {\n return this.emit.apply(this, arguments);\n }\n if (error && error instanceof Error) {\n console.error(\"[ioredis] Unhandled error event:\", error.stack);\n }\n return false;\n }\n /**\n * @ignore\n */\n recoverFromFatalError(_commandError, err, options) {\n this.flushQueue(err, options);\n this.silentEmit(\"error\", err);\n this.disconnect(true);\n }\n /**\n * @ignore\n */\n handleReconnection(err, item) {\n var _a;\n let needReconnect = false;\n if (this.options.reconnectOnError) {\n needReconnect = this.options.reconnectOnError(err);\n }\n switch (needReconnect) {\n case 1:\n case true:\n if (this.status !== \"reconnecting\") {\n this.disconnect(true);\n }\n item.command.reject(err);\n break;\n case 2:\n if (this.status !== \"reconnecting\") {\n this.disconnect(true);\n }\n if (((_a = this.condition) === null || _a === void 0 ? void 0 : _a.select) !== item.select &&\n item.command.name !== \"select\") {\n this.select(item.select);\n }\n // TODO\n // @ts-expect-error\n this.sendCommand(item.command);\n break;\n default:\n item.command.reject(err);\n }\n }\n /**\n * Get description of the connection. Used for debugging.\n */\n _getDescription() {\n let description;\n if (\"path\" in this.options && this.options.path) {\n description = this.options.path;\n }\n else if (this.stream &&\n this.stream.remoteAddress &&\n this.stream.remotePort) {\n description = this.stream.remoteAddress + \":\" + this.stream.remotePort;\n }\n else if (\"host\" in this.options && this.options.host) {\n description = this.options.host + \":\" + this.options.port;\n }\n else {\n // Unexpected\n description = \"\";\n }\n if (this.options.connectionName) {\n description += ` (${this.options.connectionName})`;\n }\n return description;\n }\n resetCommandQueue() {\n this.commandQueue = new Deque();\n }\n resetOfflineQueue() {\n this.offlineQueue = new Deque();\n }\n parseOptions(...args) {\n const options = {};\n let isTls = false;\n for (let i = 0; i < args.length; ++i) {\n const arg = args[i];\n if (arg === null || typeof arg === \"undefined\") {\n continue;\n }\n if (typeof arg === \"object\") {\n (0, lodash_1.defaults)(options, arg);\n }\n else if (typeof arg === \"string\") {\n (0, lodash_1.defaults)(options, (0, utils_1.parseURL)(arg));\n if (arg.startsWith(\"rediss://\")) {\n isTls = true;\n }\n }\n else if (typeof arg === \"number\") {\n options.port = arg;\n }\n else {\n throw new Error(\"Invalid argument \" + arg);\n }\n }\n if (isTls) {\n (0, lodash_1.defaults)(options, { tls: true });\n }\n (0, lodash_1.defaults)(options, Redis.defaultOptions);\n if (typeof options.port === \"string\") {\n options.port = parseInt(options.port, 10);\n }\n if (typeof options.db === \"string\") {\n options.db = parseInt(options.db, 10);\n }\n // @ts-expect-error\n this.options = (0, utils_1.resolveTLSProfile)(options);\n }\n /**\n * Change instance's status\n */\n setStatus(status, arg) {\n // @ts-expect-error\n if (debug.enabled) {\n debug(\"status[%s]: %s -> %s\", this._getDescription(), this.status || \"[empty]\", status);\n }\n this.status = status;\n process.nextTick(this.emit.bind(this, status, arg));\n }\n createScanStream(command, { key, options = {} }) {\n return new ScanStream_1.default({\n objectMode: true,\n key: key,\n redis: this,\n command: command,\n ...options,\n });\n }\n /**\n * Flush offline queue and command queue with error.\n *\n * @param error The error object to send to the commands\n * @param options options\n */\n flushQueue(error, options) {\n options = (0, lodash_1.defaults)({}, options, {\n offlineQueue: true,\n commandQueue: true,\n });\n let item;\n if (options.offlineQueue) {\n while ((item = this.offlineQueue.shift())) {\n item.command.reject(error);\n }\n }\n if (options.commandQueue) {\n if (this.commandQueue.length > 0) {\n if (this.stream) {\n this.stream.removeAllListeners(\"data\");\n }\n while ((item = this.commandQueue.shift())) {\n item.command.reject(error);\n }\n }\n }\n }\n /**\n * Check whether Redis has finished loading the persistent data and is able to\n * process commands.\n */\n _readyCheck(callback) {\n const _this = this;\n this.info(function (err, res) {\n if (err) {\n if (err.message && err.message.includes(\"NOPERM\")) {\n console.warn(`Skipping the ready check because INFO command fails: \"${err.message}\". You can disable ready check with \"enableReadyCheck\". More: https://github.com/luin/ioredis/wiki/Disable-ready-check.`);\n return callback(null, {});\n }\n return callback(err);\n }\n if (typeof res !== \"string\") {\n return callback(null, res);\n }\n const info = {};\n const lines = res.split(\"\\r\\n\");\n for (let i = 0; i < lines.length; ++i) {\n const [fieldName, ...fieldValueParts] = lines[i].split(\":\");\n const fieldValue = fieldValueParts.join(\":\");\n if (fieldValue) {\n info[fieldName] = fieldValue;\n }\n }\n if (!info.loading || info.loading === \"0\") {\n callback(null, info);\n }\n else {\n const loadingEtaMs = (info.loading_eta_seconds || 1) * 1000;\n const retryTime = _this.options.maxLoadingRetryTime &&\n _this.options.maxLoadingRetryTime < loadingEtaMs\n ? _this.options.maxLoadingRetryTime\n : loadingEtaMs;\n debug(\"Redis server still loading, trying again in \" + retryTime + \"ms\");\n setTimeout(function () {\n _this._readyCheck(callback);\n }, retryTime);\n }\n }).catch(lodash_1.noop);\n }\n}\nRedis.Cluster = cluster_1.default;\nRedis.Command = Command_1.default;\n/**\n * Default options\n */\nRedis.defaultOptions = RedisOptions_1.DEFAULT_REDIS_OPTIONS;\n(0, applyMixin_1.default)(Redis, events_1.EventEmitter);\n(0, transaction_1.addTransactionSupport)(Redis.prototype);\nexports.default = Redis;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.print = exports.ReplyError = exports.SentinelIterator = exports.SentinelConnector = exports.AbstractConnector = exports.Pipeline = exports.ScanStream = exports.Command = exports.Cluster = exports.Redis = exports.default = void 0;\nexports = module.exports = require(\"./Redis\").default;\nvar Redis_1 = require(\"./Redis\");\nObject.defineProperty(exports, \"default\", { enumerable: true, get: function () { return Redis_1.default; } });\nvar Redis_2 = require(\"./Redis\");\nObject.defineProperty(exports, \"Redis\", { enumerable: true, get: function () { return Redis_2.default; } });\nvar cluster_1 = require(\"./cluster\");\nObject.defineProperty(exports, \"Cluster\", { enumerable: true, get: function () { return cluster_1.default; } });\n/**\n * @ignore\n */\nvar Command_1 = require(\"./Command\");\nObject.defineProperty(exports, \"Command\", { enumerable: true, get: function () { return Command_1.default; } });\n/**\n * @ignore\n */\nvar ScanStream_1 = require(\"./ScanStream\");\nObject.defineProperty(exports, \"ScanStream\", { enumerable: true, get: function () { return ScanStream_1.default; } });\n/**\n * @ignore\n */\nvar Pipeline_1 = require(\"./Pipeline\");\nObject.defineProperty(exports, \"Pipeline\", { enumerable: true, get: function () { return Pipeline_1.default; } });\n/**\n * @ignore\n */\nvar AbstractConnector_1 = require(\"./connectors/AbstractConnector\");\nObject.defineProperty(exports, \"AbstractConnector\", { enumerable: true, get: function () { return AbstractConnector_1.default; } });\n/**\n * @ignore\n */\nvar SentinelConnector_1 = require(\"./connectors/SentinelConnector\");\nObject.defineProperty(exports, \"SentinelConnector\", { enumerable: true, get: function () { return SentinelConnector_1.default; } });\nObject.defineProperty(exports, \"SentinelIterator\", { enumerable: true, get: function () { return SentinelConnector_1.SentinelIterator; } });\n// No TS typings\nexports.ReplyError = require(\"redis-errors\").ReplyError;\n/**\n * @ignore\n */\nObject.defineProperty(exports, \"Promise\", {\n get() {\n console.warn(\"ioredis v5 does not support plugging third-party Promise library anymore. Native Promise will be used.\");\n return Promise;\n },\n set(_lib) {\n console.warn(\"ioredis v5 does not support plugging third-party Promise library anymore. Native Promise will be used.\");\n },\n});\n/**\n * @ignore\n */\nfunction print(err, reply) {\n if (err) {\n console.log(\"Error: \" + err);\n }\n else {\n console.log(\"Reply: \" + reply);\n }\n}\nexports.print = print;\n","import {\n Redis,\n type Cluster,\n type ClusterNode,\n type ClusterOptions,\n type RedisOptions,\n} from \"ioredis\";\nimport { Logger } from \"@trigger.dev/core/logger\";\n\nexport {\n Redis,\n Cluster,\n type Callback,\n type RedisOptions,\n type ClusterNode,\n type ClusterOptions,\n type Result,\n type RedisCommander,\n} from \"ioredis\";\n\n/**\n * Either endpoint shape. A component that only issues key-addressed commands works against both, so\n * it should accept this rather than pin itself to a standalone connection. Commands with no key —\n * SCAN above all — do NOT fan out across a cluster, so anything that issues one must iterate\n * `cluster.nodes(\"master\")` itself.\n */\nexport type RedisClient = Redis | Cluster;\n\n/**\n * Reply-error -> reconnect mapping. Without this hook, an ElastiCache\n * vertical scale-up surfaces tens of thousands of READONLY / LOADING\n * reply errors to caller code over a healthy TCP/TLS connection (the\n * client keeps talking to a node whose role swapped underneath it).\n *\n * UNBLOCKED is the BLPOP-shaped case: the Redis primary forcibly\n * unblocks any blocking command on a connection whose node is about\n * to be demoted, returning an UNBLOCKED reply. Surfaced 65 times on\n * engine/v1/worker-actions/dequeue at the cutover instant during the\n * TRI-8873 test-cloud scale-up dry-run.\n *\n * Returning 2 tells ioredis to disconnect, reconnect, and retry the\n * command that triggered the error. After reconnect, DNS / SG routing\n * should land on a writable primary.\n *\n * Empirical confirmation on the harness in TRI-8878: this option\n * reduced a scale-up event from ~437,000 caller-surfaced errors to 2.\n */\nexport function defaultReconnectOnError(err: Error): boolean | 1 | 2 {\n const msg = err.message ?? \"\";\n if (msg.startsWith(\"READONLY\") || msg.startsWith(\"LOADING\") || msg.startsWith(\"UNBLOCKED\")) {\n return 2;\n }\n return false;\n}\n\nconst defaultOptions: Partial<RedisOptions> = {\n retryStrategy: (times: number) => {\n const delay = Math.min(times * 50, 1000);\n return delay;\n },\n maxRetriesPerRequest: process.env.GITHUB_ACTIONS ? 50 : process.env.VITEST ? 5 : 20,\n reconnectOnError: defaultReconnectOnError,\n};\n\nconst logger = new Logger(\"Redis\", \"debug\");\n\nexport function createRedisClient(\n options: RedisOptions,\n handlers?: { onError?: (err: Error) => void }\n): Redis {\n const client = new Redis({\n ...defaultOptions,\n ...options,\n });\n\n // Skip error handling setup if running in Vitest\n if (process.env.VITEST) {\n client.on(\"error\", (error) => {\n // swallow errors\n });\n return client;\n }\n\n client.on(\"error\", (error) => {\n if (handlers?.onError) {\n handlers.onError(error);\n } else {\n logger.error(`Redis client error:`, { error, keyPrefix: options.keyPrefix });\n }\n });\n\n return client;\n}\n\nexport type RedisClusterClientOptions = {\n nodes: ClusterNode[];\n clusterOptions?: Omit<ClusterOptions, \"redisOptions\">;\n redisOptions?: RedisOptions;\n /**\n * Fail a command while the cluster is unreachable instead of queueing it. For a caller on a\n * request path, where a queued command means a hung request rather than a slow one.\n */\n failFast?: boolean;\n};\n\n/**\n * Cluster-mode client. `defaultOptions` go on the INNER per-node options, so a role swap gets the\n * same reconnect-and-retry treatment a single-node client already gets.\n */\nexport function createRedisClusterClient(\n options: RedisClusterClientOptions,\n handlers?: { onError?: (err: Error) => void }\n): Cluster {\n const client = new Redis.Cluster(options.nodes, {\n // The offline queue is a CLUSTER-level setting, separate from the per-node one below. While a\n // cluster cannot refresh its slot cache it queues commands here, so a caller that wants a\n // failure during an outage rather than a wait has to turn THIS one off. Default stays `true`,\n // matching ioredis, so only a caller that asks for it changes behaviour.\n ...(options.failFast && { enableOfflineQueue: false }),\n ...options.clusterOptions,\n redisOptions: {\n ...defaultOptions,\n ...(options.failFast && { enableOfflineQueue: false }),\n ...options.redisOptions,\n },\n });\n\n if (process.env.VITEST) {\n client.on(\"error\", () => {});\n return client;\n }\n\n client.on(\"error\", (error) => {\n if (handlers?.onError) {\n handlers.onError(error);\n } else {\n logger.error(`Redis cluster client error:`, {\n error,\n keyPrefix: options.redisOptions?.keyPrefix,\n });\n }\n });\n\n // A failed slot refresh only surfaces as ClusterAllFailedError; each node's own failure, and\n // which node it was, arrives here.\n client.on(\"node error\", (error: Error, node: string) => {\n logger.warn(`Redis cluster node error:`, { node, error: error.message });\n });\n\n return client;\n}\n","export let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\n","import { webcrypto as crypto } from 'node:crypto'\n\nimport { urlAlphabet as scopedUrlAlphabet } from './url-alphabet/index.js'\n\nexport { urlAlphabet } from './url-alphabet/index.js'\n\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\n\nfunction fillPool(bytes) {\n if (bytes < 0) throw new RangeError('Wrong ID size')\n try {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.getRandomValues(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.getRandomValues(pool)\n poolOffset = 0\n }\n } catch (e) {\n pool = undefined\n throw e\n }\n poolOffset += bytes\n}\n\nexport function random(bytes) {\n fillPool((bytes |= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\n\nexport function customRandom(alphabet, defaultSize, getRandom) {\n let safeByteCutoff = 256 - (256 % alphabet.length)\n\n if (safeByteCutoff === 256) {\n let mask = alphabet.length - 1\n\n return (size = defaultSize) => {\n if (!size) return ''\n let id = ''\n while (true) {\n let bytes = getRandom(size)\n let i = size\n while (i--) {\n id += alphabet[bytes[i] & mask]\n if (id.length >= size) return id\n }\n }\n }\n }\n\n let step = Math.ceil((1.6 * 256 * defaultSize) / safeByteCutoff)\n\n return (size = defaultSize) => {\n if (!size) return ''\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n if (bytes[i] < safeByteCutoff) {\n id += alphabet[bytes[i] % alphabet.length]\n if (id.length >= size) return id\n }\n }\n }\n }\n}\n\nexport function customAlphabet(alphabet, size = 21) {\n return customRandom(alphabet, size, random)\n}\n\nexport function nanoid(size = 21) {\n fillPool((size |= 0))\n\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += scopedUrlAlphabet[pool[i] & 63]\n }\n return id\n}\n","import {\n createRedisClient,\n type Redis,\n type Callback,\n type RedisOptions,\n type Result,\n} from \"@internal/redis\";\nimport { Logger } from \"@trigger.dev/core/logger\";\nimport type { AnyZodSchema, inferZodSchemaOutput } from \"@trigger.dev/core/v3\";\nimport { nanoid } from \"nanoid\";\n\nexport interface MessageCatalogSchema {\n [key: string]: AnyZodSchema;\n}\n\nexport type MessageCatalogKey<TMessageCatalog extends MessageCatalogSchema> = keyof TMessageCatalog;\nexport type MessageCatalogValue<\n TMessageCatalog extends MessageCatalogSchema,\n TKey extends MessageCatalogKey<TMessageCatalog>,\n> = inferZodSchemaOutput<TMessageCatalog[TKey]>;\n\nexport type AnyMessageCatalog = MessageCatalogSchema;\nexport type QueueItem<TMessageCatalog extends MessageCatalogSchema> = {\n id: string;\n job: MessageCatalogKey<TMessageCatalog>;\n item: MessageCatalogValue<TMessageCatalog, MessageCatalogKey<TMessageCatalog>>;\n visibilityTimeoutMs: number;\n attempt: number;\n timestamp: Date;\n deduplicationKey?: string;\n};\n\nexport type AnyQueueItem = {\n id: string;\n job: string;\n item: any;\n visibilityTimeoutMs: number;\n attempt: number;\n timestamp: Date;\n deduplicationKey?: string;\n};\n\nexport class SimpleQueue<TMessageCatalog extends MessageCatalogSchema> {\n name: string;\n private redis: Redis;\n private schema: TMessageCatalog;\n private logger: Logger;\n\n constructor({\n name,\n schema,\n redisOptions,\n logger,\n }: {\n name: string;\n schema: TMessageCatalog;\n redisOptions: RedisOptions;\n logger?: Logger;\n }) {\n this.name = name;\n this.logger = logger ?? new Logger(\"SimpleQueue\", \"debug\");\n\n this.redis = createRedisClient(\n {\n ...redisOptions,\n keyPrefix: `${redisOptions.keyPrefix ?? \"\"}{queue:${name}:}`,\n retryStrategy(times) {\n const delay = Math.min(times * 50, 1000);\n return delay;\n },\n maxRetriesPerRequest: 20,\n },\n {\n onError: (error) => {\n this.logger.error(`RedisWorker queue redis client error:`, {\n error,\n keyPrefix: redisOptions.keyPrefix,\n });\n },\n }\n );\n this.#registerCommands();\n this.schema = schema;\n }\n\n async cancel(cancellationKey: string): Promise<void> {\n await this.redis.set(`cancellationKey:${cancellationKey}`, \"1\", \"EX\", 60 * 60 * 24); // 1 day\n }\n\n async enqueue({\n id,\n job,\n item,\n attempt,\n availableAt,\n visibilityTimeoutMs,\n cancellationKey,\n }: {\n id?: string;\n job: MessageCatalogKey<TMessageCatalog>;\n item: MessageCatalogValue<TMessageCatalog, MessageCatalogKey<TMessageCatalog>>;\n attempt?: number;\n availableAt?: Date;\n visibilityTimeoutMs: number;\n cancellationKey?: string;\n }): Promise<void> {\n try {\n const score = availableAt ? availableAt.getTime() : Date.now();\n const deduplicationKey = nanoid();\n const serializedItem = JSON.stringify({\n job,\n item,\n visibilityTimeoutMs,\n attempt,\n deduplicationKey,\n });\n\n const result = cancellationKey\n ? await this.redis.enqueueItemWithCancellationKey(\n `queue`,\n `items`,\n `cancellationKey:${cancellationKey}`,\n id ?? nanoid(),\n score,\n serializedItem\n )\n : await this.redis.enqueueItem(`queue`, `items`, id ?? nanoid(), score, serializedItem);\n\n if (result !== 1) {\n throw new Error(\"Enqueue operation failed\");\n }\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.enqueue(): error enqueuing`, {\n queue: this.name,\n error: e,\n id,\n item,\n });\n throw e;\n }\n }\n\n /**\n * Re-enqueues an item for a retry, unless since it was dequeued a newer enqueue replaced it (its\n * stored deduplication key no longer matches) or it was removed by an ack or cancel. Returns\n * false when it skipped, so a failed attempt never overwrites the newer item or revives a removed\n * one. A newer enqueue starts its own retry budget: an item a handler re-enqueues before failing\n * restarts at attempt 0 rather than moving towards the DLQ.\n */\n async requeue({\n id,\n job,\n item,\n attempt,\n availableAt,\n visibilityTimeoutMs,\n deduplicationKey,\n }: {\n id: string;\n job: MessageCatalogKey<TMessageCatalog>;\n item: MessageCatalogValue<TMessageCatalog, MessageCatalogKey<TMessageCatalog>>;\n attempt: number;\n availableAt: Date;\n visibilityTimeoutMs: number;\n deduplicationKey?: string;\n }): Promise<boolean> {\n const serializedItem = JSON.stringify({\n job,\n item,\n visibilityTimeoutMs,\n attempt,\n deduplicationKey: nanoid(),\n });\n\n const result = await this.redis.requeueItem(\n `queue`,\n `items`,\n id,\n availableAt.getTime(),\n serializedItem,\n deduplicationKey ?? \"\"\n );\n\n return result === 1;\n }\n\n async enqueueOnce({\n id,\n job,\n item,\n attempt,\n availableAt,\n visibilityTimeoutMs,\n }: {\n id: string;\n job: MessageCatalogKey<TMessageCatalog>;\n item: MessageCatalogValue<TMessageCatalog, MessageCatalogKey<TMessageCatalog>>;\n attempt?: number;\n availableAt?: Date;\n visibilityTimeoutMs: number;\n }): Promise<boolean> {\n if (!id) {\n throw new Error(\"enqueueOnce requires an id\");\n }\n try {\n const score = availableAt ? availableAt.getTime() : Date.now();\n const deduplicationKey = nanoid();\n const serializedItem = JSON.stringify({\n job,\n item,\n visibilityTimeoutMs,\n attempt,\n deduplicationKey,\n });\n const result = await this.redis.enqueueItemOnce(`queue`, `items`, id, score, serializedItem);\n // 1 if inserted, 0 if already exists\n return result === 1;\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.enqueueOnce(): error enqueuing`, {\n queue: this.name,\n error: e,\n id,\n item,\n });\n throw e;\n }\n }\n\n async dequeue(count: number = 1): Promise<Array<QueueItem<TMessageCatalog>>> {\n const now = Date.now();\n\n try {\n const results = await this.redis.dequeueItems(`queue`, `items`, now, count);\n\n if (!results || results.length === 0) {\n return [];\n }\n\n const dequeuedItems: Array<QueueItem<TMessageCatalog>> = [];\n\n for (const [id, serializedItem, score] of results) {\n const parsedItem = JSON.parse(serializedItem) as any;\n if (typeof parsedItem.job !== \"string\") {\n this.logger.error(`Invalid item in queue`, { queue: this.name, id, item: parsedItem });\n continue;\n }\n\n const timestamp = new Date(Number(score));\n\n const schema = this.schema[parsedItem.job];\n\n if (!schema) {\n this.logger.error(`Invalid item in queue, schema not found`, {\n queue: this.name,\n id,\n item: parsedItem,\n job: parsedItem.job,\n timestamp,\n availableJobs: Object.keys(this.schema),\n });\n continue;\n }\n\n // zod v4 narrows the generic schema union here; cast to public ZodType (has safeParse in v3 & v4)\n const validatedItem = schema.safeParse(parsedItem.item);\n\n if (!validatedItem.success) {\n this.logger.error(\"Invalid item in queue\", {\n queue: this.name,\n id,\n item: parsedItem,\n errors: validatedItem.error,\n attempt: parsedItem.attempt,\n timestamp,\n });\n continue;\n }\n\n const visibilityTimeoutMs = parsedItem.visibilityTimeoutMs as number;\n\n dequeuedItems.push({\n id,\n job: parsedItem.job,\n item: validatedItem.data as QueueItem<TMessageCatalog>[\"item\"],\n visibilityTimeoutMs,\n attempt: parsedItem.attempt ?? 0,\n timestamp,\n deduplicationKey: parsedItem.deduplicationKey,\n });\n }\n\n return dequeuedItems;\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.dequeue(): error dequeuing`, {\n queue: this.name,\n error: e,\n count,\n });\n throw e;\n }\n }\n\n async ack(id: string, deduplicationKey?: string): Promise<void> {\n try {\n const result = await this.redis.ackItem(`queue`, `items`, id, deduplicationKey ?? \"\");\n if (result !== 1) {\n this.logger.debug(\n `SimpleQueue ${this.name}.ack(): ack operation returned ${result}. This means it was not removed from the queue.`,\n {\n queue: this.name,\n id,\n deduplicationKey,\n result,\n }\n );\n }\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.ack(): error acknowledging item`, {\n queue: this.name,\n error: e,\n id,\n deduplicationKey,\n });\n throw e;\n }\n }\n\n async reschedule(id: string, availableAt: Date): Promise<void> {\n await this.redis.zadd(`queue`, \"XX\", availableAt.getTime(), id);\n }\n\n async size({ includeFuture = false }: { includeFuture?: boolean } = {}): Promise<number> {\n try {\n if (includeFuture) {\n // If includeFuture is true, return the total count of all items\n return await this.redis.zcard(`queue`);\n } else {\n // If includeFuture is false, return the count of items available now\n const now = Date.now();\n return await this.redis.zcount(`queue`, \"-inf\", now);\n }\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.size(): error getting queue size`, {\n queue: this.name,\n error: e,\n includeFuture,\n });\n throw e;\n }\n }\n\n /**\n * Age (in ms) of the oldest *overdue* message — the oldest item whose scheduled\n * time has already passed (score <= now). Returns 0 when the queue is empty or\n * only holds future/delayed or in-flight (future-scored) items.\n *\n * Resolves the candidate against the `items` hash so orphaned `queue` entries\n * (a member whose payload is missing — the same stale state `dequeueItems`\n * cleans up) don't report a phantom stall for work that can't be dequeued. The\n * Lua scans due items oldest-first and returns the first score whose payload\n * still exists.\n *\n * This is the generic stall signal: it stays at 0 while a queue drains healthily\n * and rises only when due work sits undrained (poison block, dead consumer,\n * backpressure).\n */\n async oldestMessageAge(): Promise<number> {\n try {\n const now = Date.now();\n // -1 sentinel = nothing due, or every due entry is orphaned.\n const score = Number(await this.redis.getOldestDueScore(`queue`, `items`, now));\n\n if (!Number.isFinite(score) || score < 0) {\n return 0;\n }\n\n return Math.max(0, now - score);\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.oldestMessageAge(): error getting oldest age`, {\n queue: this.name,\n error: e,\n });\n // Swallow: a transient Redis error must not break observable metric collection.\n return 0;\n }\n }\n\n async getJob(id: string): Promise<QueueItem<TMessageCatalog> | null> {\n const result = await this.redis.getJob(`queue`, `items`, id);\n\n if (!result) {\n return null;\n }\n\n const [_, score, serializedItem] = result;\n const item = JSON.parse(serializedItem) as QueueItem<TMessageCatalog>;\n\n return {\n id,\n job: item.job,\n item: item.item,\n visibilityTimeoutMs: item.visibilityTimeoutMs,\n attempt: item.attempt ?? 0,\n timestamp: new Date(Number(score)),\n deduplicationKey: item.deduplicationKey ?? undefined,\n };\n }\n\n /**\n * Moves an item to the dead letter queue. With a deduplication key, an item a newer enqueue has\n * replaced is left in the queue and false is returned.\n */\n async moveToDeadLetterQueue(\n id: string,\n errorMessage: string,\n deduplicationKey?: string\n ): Promise<boolean> {\n try {\n this.logger.debug(`SimpleQueue ${this.name}.moveToDeadLetterQueue(): moving item to DLQ`, {\n queue: this.name,\n id,\n errorMessage,\n });\n\n const result = await this.redis.moveToDeadLetterQueue(\n `queue`,\n `items`,\n `dlq`,\n `dlq:items`,\n id,\n errorMessage,\n deduplicationKey ?? \"\"\n );\n\n if (result === 2) return false;\n if (result !== 1) {\n throw new Error(\"Move to Dead Letter Queue operation failed\");\n }\n return true;\n } catch (e) {\n this.logger.error(\n `SimpleQueue ${this.name}.moveToDeadLetterQueue(): error moving item to DLQ`,\n {\n queue: this.name,\n error: e,\n id,\n errorMessage,\n }\n );\n throw e;\n }\n }\n\n async sizeOfDeadLetterQueue(): Promise<number> {\n try {\n return await this.redis.zcard(`dlq`);\n } catch (e) {\n this.logger.error(`SimpleQueue ${this.name}.dlqSize(): error getting DLQ size`, {\n queue: this.name,\n error: e,\n });\n throw e;\n }\n }\n\n async redriveFromDeadLetterQueue(id: string): Promise<void> {\n try {\n const result = await this.redis.redriveFromDeadLetterQueue(\n `queue`,\n `items`,\n `dlq`,\n `dlq:items`,\n id\n );\n\n if (result !== 1) {\n throw new Error(\"Redrive from Dead Letter Queue operation failed\");\n }\n } catch (e) {\n this.logger.error(\n `SimpleQueue ${this.name}.redriveFromDeadLetterQueue(): error redriving item from DLQ`,\n {\n queue: this.name,\n error: e,\n id,\n }\n );\n throw e;\n }\n }\n\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n #registerCommands() {\n this.redis.defineCommand(\"enqueueItem\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local id = ARGV[1]\n local score = ARGV[2]\n local serializedItem = ARGV[3]\n\n redis.call('ZADD', queue, score, id)\n redis.call('HSET', items, id, serializedItem)\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"enqueueItemWithCancellationKey\", {\n numberOfKeys: 3,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local cancellationKey = KEYS[3]\n\n local id = ARGV[1]\n local score = ARGV[2]\n local serializedItem = ARGV[3]\n\n -- if the cancellation key exists, return 1\n if redis.call('EXISTS', cancellationKey) == 1 then\n return 1\n end\n\n redis.call('ZADD', queue, score, id)\n redis.call('HSET', items, id, serializedItem)\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"dequeueItems\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local now = tonumber(ARGV[1])\n local count = tonumber(ARGV[2])\n\n local result = redis.call('ZRANGEBYSCORE', queue, '-inf', now, 'WITHSCORES', 'LIMIT', 0, count)\n\n if #result == 0 then\n return {}\n end\n\n local dequeued = {}\n\n for i = 1, #result, 2 do\n local id = result[i]\n local score = tonumber(result[i + 1])\n\n if score > now then\n break\n end\n\n local serializedItem = redis.call('HGET', items, id)\n\n if serializedItem then\n local item = cjson.decode(serializedItem)\n local visibilityTimeoutMs = tonumber(item.visibilityTimeoutMs)\n local invisibleUntil = now + visibilityTimeoutMs\n\n redis.call('ZADD', queue, invisibleUntil, id)\n table.insert(dequeued, {id, serializedItem, score})\n else\n -- Remove the orphaned queue entry if no corresponding item exists\n redis.call('ZREM', queue, id)\n end\n end\n\n return dequeued\n `,\n });\n\n this.redis.defineCommand(\"getOldestDueScore\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local now = tonumber(ARGV[1])\n\n -- Oldest-first scan of due items, bounded so a long prefix of orphans can't\n -- make this O(n). Orphans are rare (dequeueItems removes them), so in the\n -- common case this returns on the first iteration. Read-only: unlike\n -- dequeueItems we don't ZREM orphans here — a metric probe must not mutate.\n local result = redis.call('ZRANGEBYSCORE', queue, '-inf', now, 'WITHSCORES', 'LIMIT', 0, 100)\n\n for i = 1, #result, 2 do\n local id = result[i]\n if redis.call('HEXISTS', items, id) == 1 then\n return result[i + 1]\n end\n end\n\n return -1\n `,\n });\n\n this.redis.defineCommand(\"getJob\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local jobId = ARGV[1]\n\n local serializedItem = redis.call('HGET', items, jobId)\n\n if serializedItem == false then\n return nil\n end\n\n -- get the score from the queue sorted set\n local score = redis.call('ZSCORE', queue, jobId)\n\n return { jobId, score, serializedItem }\n `,\n });\n\n this.redis.defineCommand(\"ackItem\", {\n numberOfKeys: 2,\n lua: `\n local queueKey = KEYS[1]\n local itemsKey = KEYS[2]\n local id = ARGV[1]\n local deduplicationKey = ARGV[2]\n\n -- Get the item from the hash\n local item = redis.call('HGET', itemsKey, id)\n if not item then\n return -1\n end\n\n -- Only check deduplicationKey if a non-empty one was passed in\n if deduplicationKey and deduplicationKey ~= \"\" then\n local success, parsed = pcall(cjson.decode, item)\n if success then\n if parsed.deduplicationKey and parsed.deduplicationKey ~= deduplicationKey then\n return 0\n end\n end\n end\n\n -- Remove from sorted set and hash\n redis.call('ZREM', queueKey, id)\n redis.call('HDEL', itemsKey, id)\n return 1\n `,\n });\n\n this.redis.defineCommand(\"requeueItem\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local id = ARGV[1]\n local score = ARGV[2]\n local serializedItem = ARGV[3]\n local deduplicationKey = ARGV[4]\n\n -- Leave the item alone if, while this attempt ran, it was removed (acked or cancelled)\n -- or a newer enqueue replaced it.\n if deduplicationKey ~= \"\" then\n local current = redis.call('HGET', items, id)\n if not current then\n return 2\n end\n local success, parsed = pcall(cjson.decode, current)\n if success and parsed.deduplicationKey and parsed.deduplicationKey ~= deduplicationKey then\n return 2\n end\n end\n\n redis.call('ZADD', queue, score, id)\n redis.call('HSET', items, id, serializedItem)\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"moveToDeadLetterQueue\", {\n numberOfKeys: 4,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local dlq = KEYS[3]\n local dlqItems = KEYS[4]\n local id = ARGV[1]\n local errorMessage = ARGV[2]\n local deduplicationKey = ARGV[3]\n\n local item = redis.call('HGET', items, id)\n if not item then\n return 0\n end\n\n local parsedItem = cjson.decode(item)\n if deduplicationKey ~= \"\" and parsedItem.deduplicationKey and parsedItem.deduplicationKey ~= deduplicationKey then\n return 2\n end\n parsedItem.errorMessage = errorMessage\n\n local time = redis.call('TIME')\n local now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)\n\n redis.call('ZREM', queue, id)\n redis.call('HDEL', items, id)\n\n redis.call('ZADD', dlq, now, id)\n redis.call('HSET', dlqItems, id, cjson.encode(parsedItem))\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"redriveFromDeadLetterQueue\", {\n numberOfKeys: 4,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local dlq = KEYS[3]\n local dlqItems = KEYS[4]\n local id = ARGV[1]\n\n local item = redis.call('HGET', dlqItems, id)\n if not item then\n return 0\n end\n\n local parsedItem = cjson.decode(item)\n parsedItem.errorMessage = nil\n\n local time = redis.call('TIME')\n local now = tonumber(time[1]) * 1000 + math.floor(tonumber(time[2]) / 1000)\n\n redis.call('ZREM', dlq, id)\n redis.call('HDEL', dlqItems, id)\n\n redis.call('ZADD', queue, now, id)\n redis.call('HSET', items, id, cjson.encode(parsedItem))\n\n return 1\n `,\n });\n\n this.redis.defineCommand(\"enqueueItemOnce\", {\n numberOfKeys: 2,\n lua: `\n local queue = KEYS[1]\n local items = KEYS[2]\n local id = ARGV[1]\n local score = ARGV[2]\n local serializedItem = ARGV[3]\n\n -- Only add if not exists\n local added = redis.call('HSETNX', items, id, serializedItem)\n if added == 1 then\n redis.call('ZADD', queue, 'NX', score, id)\n return 1\n else\n return 0\n end\n `,\n });\n }\n}\n\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n enqueueItem(\n //keys\n queue: string,\n items: string,\n //args\n id: string,\n score: number,\n serializedItem: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n enqueueItemWithCancellationKey(\n //keys\n queue: string,\n items: string,\n cancellationKey: string,\n //args\n id: string,\n score: number,\n serializedItem: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n dequeueItems(\n //keys\n queue: string,\n items: string,\n //args\n now: number,\n count: number,\n callback?: Callback<Array<[string, string, string]>>\n ): Result<Array<[string, string, string]>, Context>;\n\n ackItem(\n queue: string,\n items: string,\n id: string,\n deduplicationKey: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n redriveFromDeadLetterQueue(\n queue: string,\n items: string,\n dlq: string,\n dlqItems: string,\n id: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n moveToDeadLetterQueue(\n queue: string,\n items: string,\n dlq: string,\n dlqItems: string,\n id: string,\n errorMessage: string,\n deduplicationKey: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n requeueItem(\n queue: string,\n items: string,\n id: string,\n score: number,\n serializedItem: string,\n deduplicationKey: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n enqueueItemOnce(\n queue: string,\n items: string,\n id: string,\n score: number,\n serializedItem: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n\n getJob(\n queue: string,\n items: string,\n id: string,\n callback?: Callback<[string, string, string] | null>\n ): Result<[string, string, string] | null, Context>;\n\n getOldestDueScore(\n //keys\n queue: string,\n items: string,\n //args\n now: number,\n callback?: Callback<string | number>\n ): Result<string | number, Context>;\n }\n}\n","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n// this is autogenerated file, see scripts/version-update.js\nexport const VERSION = '1.9.1';\n//# sourceMappingURL=version.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { VERSION } from '../version';\nconst re = /^(\\d+)\\.(\\d+)\\.(\\d+)(-(.+))?$/;\n/**\n * Create a function to test an API version to see if it is compatible with the provided ownVersion.\n *\n * The returned function has the following semantics:\n * - Exact match is always compatible\n * - Major versions must match exactly\n * - 1.x package cannot use global 2.x package\n * - 2.x package cannot use global 1.x package\n * - The minor version of the API module requesting access to the global API must be less than or equal to the minor version of this API\n * - 1.3 package may use 1.4 global because the later global contains all functions 1.3 expects\n * - 1.4 package may NOT use 1.3 global because it may try to call functions which don't exist on 1.3\n * - If the major version is 0, the minor version is treated as the major and the patch is treated as the minor\n * - Patch and build tag differences are not considered at this time\n *\n * @param ownVersion version which should be checked against\n */\nexport function _makeCompatibilityCheck(ownVersion) {\n const acceptedVersions = new Set([ownVersion]);\n const rejectedVersions = new Set();\n const myVersionMatch = ownVersion.match(re);\n if (!myVersionMatch) {\n // we cannot guarantee compatibility so we always return noop\n return () => false;\n }\n const ownVersionParsed = {\n major: +myVersionMatch[1],\n minor: +myVersionMatch[2],\n patch: +myVersionMatch[3],\n prerelease: myVersionMatch[4],\n };\n // if ownVersion has a prerelease tag, versions must match exactly\n if (ownVersionParsed.prerelease != null) {\n return function isExactmatch(globalVersion) {\n return globalVersion === ownVersion;\n };\n }\n function _reject(v) {\n rejectedVersions.add(v);\n return false;\n }\n function _accept(v) {\n acceptedVersions.add(v);\n return true;\n }\n return function isCompatible(globalVersion) {\n if (acceptedVersions.has(globalVersion)) {\n return true;\n }\n if (rejectedVersions.has(globalVersion)) {\n return false;\n }\n const globalVersionMatch = globalVersion.match(re);\n if (!globalVersionMatch) {\n // cannot parse other version\n // we cannot guarantee compatibility so we always noop\n return _reject(globalVersion);\n }\n const globalVersionParsed = {\n major: +globalVersionMatch[1],\n minor: +globalVersionMatch[2],\n patch: +globalVersionMatch[3],\n prerelease: globalVersionMatch[4],\n };\n // if globalVersion has a prerelease tag, versions must match exactly\n if (globalVersionParsed.prerelease != null) {\n return _reject(globalVersion);\n }\n // major versions must match\n if (ownVersionParsed.major !== globalVersionParsed.major) {\n return _reject(globalVersion);\n }\n if (ownVersionParsed.major === 0) {\n if (ownVersionParsed.minor === globalVersionParsed.minor &&\n ownVersionParsed.patch <= globalVersionParsed.patch) {\n return _accept(globalVersion);\n }\n return _reject(globalVersion);\n }\n if (ownVersionParsed.minor <= globalVersionParsed.minor) {\n return _accept(globalVersion);\n }\n return _reject(globalVersion);\n };\n}\n/**\n * Test an API version to see if it is compatible with this API.\n *\n * - Exact match is always compatible\n * - Major versions must match exactly\n * - 1.x package cannot use global 2.x package\n * - 2.x package cannot use global 1.x package\n * - The minor version of the API module requesting access to the global API must be less than or equal to the minor version of this API\n * - 1.3 package may use 1.4 global because the later global contains all functions 1.3 expects\n * - 1.4 package may NOT use 1.3 global because it may try to call functions which don't exist on 1.3\n * - If the major version is 0, the minor version is treated as the major and the patch is treated as the minor\n * - Patch and build tag differences are not considered at this time\n *\n * @param version version of the API requesting an instance of the global API\n */\nexport const isCompatible = _makeCompatibilityCheck(VERSION);\n//# sourceMappingURL=semver.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { VERSION } from '../version';\nimport { isCompatible } from './semver';\nconst major = VERSION.split('.')[0];\nconst GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for(`opentelemetry.js.api.${major}`);\nconst _global = (typeof globalThis === 'object'\n ? globalThis\n : typeof self === 'object'\n ? self\n : typeof window === 'object'\n ? window\n : typeof global === 'object'\n ? global\n : {});\nexport function registerGlobal(type, instance, diag, allowOverride = false) {\n var _a;\n const api = (_global[GLOBAL_OPENTELEMETRY_API_KEY] = (_a = _global[GLOBAL_OPENTELEMETRY_API_KEY]) !== null && _a !== void 0 ? _a : {\n version: VERSION,\n });\n if (!allowOverride && api[type]) {\n // already registered an API of this type\n const err = new Error(`@opentelemetry/api: Attempted duplicate registration of API: ${type}`);\n diag.error(err.stack || err.message);\n return false;\n }\n if (api.version !== VERSION) {\n // All registered APIs must be of the same version exactly\n const err = new Error(`@opentelemetry/api: Registration of version v${api.version} for ${type} does not match previously registered API v${VERSION}`);\n diag.error(err.stack || err.message);\n return false;\n }\n api[type] = instance;\n diag.debug(`@opentelemetry/api: Registered a global for ${type} v${VERSION}.`);\n return true;\n}\nexport function getGlobal(type) {\n var _a, _b;\n const globalVersion = (_a = _global[GLOBAL_OPENTELEMETRY_API_KEY]) === null || _a === void 0 ? void 0 : _a.version;\n if (!globalVersion || !isCompatible(globalVersion)) {\n return;\n }\n return (_b = _global[GLOBAL_OPENTELEMETRY_API_KEY]) === null || _b === void 0 ? void 0 : _b[type];\n}\nexport function unregisterGlobal(type, diag) {\n diag.debug(`@opentelemetry/api: Unregistering a global for ${type} v${VERSION}.`);\n const api = _global[GLOBAL_OPENTELEMETRY_API_KEY];\n if (api) {\n delete api[type];\n }\n}\n//# sourceMappingURL=global-utils.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { getGlobal } from '../internal/global-utils';\n/**\n * Component Logger which is meant to be used as part of any component which\n * will add automatically additional namespace in front of the log message.\n * It will then forward all message to global diag logger\n * @example\n * const cLogger = diag.createComponentLogger({ namespace: '@opentelemetry/instrumentation-http' });\n * cLogger.debug('test');\n * // @opentelemetry/instrumentation-http test\n */\nexport class DiagComponentLogger {\n constructor(props) {\n this._namespace = props.namespace || 'DiagComponentLogger';\n }\n debug(...args) {\n return logProxy('debug', this._namespace, args);\n }\n error(...args) {\n return logProxy('error', this._namespace, args);\n }\n info(...args) {\n return logProxy('info', this._namespace, args);\n }\n warn(...args) {\n return logProxy('warn', this._namespace, args);\n }\n verbose(...args) {\n return logProxy('verbose', this._namespace, args);\n }\n}\nfunction logProxy(funcName, namespace, args) {\n const logger = getGlobal('diag');\n // shortcut if logger not set\n if (!logger) {\n return;\n }\n return logger[funcName](namespace, ...args);\n}\n//# sourceMappingURL=ComponentLogger.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * Defines the available internal logging levels for the diagnostic logger, the numeric values\n * of the levels are defined to match the original values from the initial LogLevel to avoid\n * compatibility/migration issues for any implementation that assume the numeric ordering.\n */\nexport var DiagLogLevel;\n(function (DiagLogLevel) {\n /** Diagnostic Logging level setting to disable all logging (except and forced logs) */\n DiagLogLevel[DiagLogLevel[\"NONE\"] = 0] = \"NONE\";\n /** Identifies an error scenario */\n DiagLogLevel[DiagLogLevel[\"ERROR\"] = 30] = \"ERROR\";\n /** Identifies a warning scenario */\n DiagLogLevel[DiagLogLevel[\"WARN\"] = 50] = \"WARN\";\n /** General informational log message */\n DiagLogLevel[DiagLogLevel[\"INFO\"] = 60] = \"INFO\";\n /** General debug log message */\n DiagLogLevel[DiagLogLevel[\"DEBUG\"] = 70] = \"DEBUG\";\n /**\n * Detailed trace level logging should only be used for development, should only be set\n * in a development environment.\n */\n DiagLogLevel[DiagLogLevel[\"VERBOSE\"] = 80] = \"VERBOSE\";\n /** Used to set the logging level to include all logging */\n DiagLogLevel[DiagLogLevel[\"ALL\"] = 9999] = \"ALL\";\n})(DiagLogLevel || (DiagLogLevel = {}));\n//# sourceMappingURL=types.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { DiagLogLevel } from '../types';\nexport function createLogLevelDiagLogger(maxLevel, logger) {\n if (maxLevel < DiagLogLevel.NONE) {\n maxLevel = DiagLogLevel.NONE;\n }\n else if (maxLevel > DiagLogLevel.ALL) {\n maxLevel = DiagLogLevel.ALL;\n }\n // In case the logger is null or undefined\n logger = logger || {};\n function _filterFunc(funcName, theLevel) {\n const theFunc = logger[funcName];\n if (typeof theFunc === 'function' && maxLevel >= theLevel) {\n return theFunc.bind(logger);\n }\n return function () { };\n }\n return {\n error: _filterFunc('error', DiagLogLevel.ERROR),\n warn: _filterFunc('warn', DiagLogLevel.WARN),\n info: _filterFunc('info', DiagLogLevel.INFO),\n debug: _filterFunc('debug', DiagLogLevel.DEBUG),\n verbose: _filterFunc('verbose', DiagLogLevel.VERBOSE),\n };\n}\n//# sourceMappingURL=logLevelLogger.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { DiagComponentLogger } from '../diag/ComponentLogger';\nimport { createLogLevelDiagLogger } from '../diag/internal/logLevelLogger';\nimport { DiagLogLevel } from '../diag/types';\nimport { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils';\nconst API_NAME = 'diag';\n/**\n * Singleton object which represents the entry point to the OpenTelemetry internal\n * diagnostic API\n *\n * @since 1.0.0\n */\nexport class DiagAPI {\n /** Get the singleton instance of the DiagAPI API */\n static instance() {\n if (!this._instance) {\n this._instance = new DiagAPI();\n }\n return this._instance;\n }\n /**\n * Private internal constructor\n * @private\n */\n constructor() {\n function _logProxy(funcName) {\n return function (...args) {\n const logger = getGlobal('diag');\n // shortcut if logger not set\n if (!logger)\n return;\n return logger[funcName](...args);\n };\n }\n // Using self local variable for minification purposes as 'this' cannot be minified\n const self = this;\n // DiagAPI specific functions\n const setLogger = (logger, optionsOrLogLevel = { logLevel: DiagLogLevel.INFO }) => {\n var _a, _b, _c;\n if (logger === self) {\n // There isn't much we can do here.\n // Logging to the console might break the user application.\n // Try to log to self. If a logger was previously registered it will receive the log.\n const err = new Error('Cannot use diag as the logger for itself. Please use a DiagLogger implementation like ConsoleDiagLogger or a custom implementation');\n self.error((_a = err.stack) !== null && _a !== void 0 ? _a : err.message);\n return false;\n }\n if (typeof optionsOrLogLevel === 'number') {\n optionsOrLogLevel = {\n logLevel: optionsOrLogLevel,\n };\n }\n const oldLogger = getGlobal('diag');\n const newLogger = createLogLevelDiagLogger((_b = optionsOrLogLevel.logLevel) !== null && _b !== void 0 ? _b : DiagLogLevel.INFO, logger);\n // There already is an logger registered. We'll let it know before overwriting it.\n if (oldLogger && !optionsOrLogLevel.suppressOverrideMessage) {\n const stack = (_c = new Error().stack) !== null && _c !== void 0 ? _c : '<failed to generate stacktrace>';\n oldLogger.warn(`Current logger will be overwritten from ${stack}`);\n newLogger.warn(`Current logger will overwrite one already registered from ${stack}`);\n }\n return registerGlobal('diag', newLogger, self, true);\n };\n self.setLogger = setLogger;\n self.disable = () => {\n unregisterGlobal(API_NAME, self);\n };\n self.createComponentLogger = (options) => {\n return new DiagComponentLogger(options);\n };\n self.verbose = _logProxy('verbose');\n self.debug = _logProxy('debug');\n self.info = _logProxy('info');\n self.warn = _logProxy('warn');\n self.error = _logProxy('error');\n }\n}\n//# sourceMappingURL=diag.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * Get a key to uniquely identify a context value\n *\n * @since 1.0.0\n */\nexport function createContextKey(description) {\n // The specification states that for the same input, multiple calls should\n // return different keys. Due to the nature of the JS dependency management\n // system, this creates problems where multiple versions of some package\n // could hold different keys for the same property.\n //\n // Therefore, we use Symbol.for which returns the same key for the same input.\n return Symbol.for(description);\n}\nclass BaseContext {\n /**\n * Construct a new context which inherits values from an optional parent context.\n *\n * @param parentContext a context from which to inherit values\n */\n constructor(parentContext) {\n // for minification\n const self = this;\n self._currentContext = parentContext ? new Map(parentContext) : new Map();\n self.getValue = (key) => self._currentContext.get(key);\n self.setValue = (key, value) => {\n const context = new BaseContext(self._currentContext);\n context._currentContext.set(key, value);\n return context;\n };\n self.deleteValue = (key) => {\n const context = new BaseContext(self._currentContext);\n context._currentContext.delete(key);\n return context;\n };\n }\n}\n/**\n * The root context is used as the default parent context when there is no active context\n *\n * @since 1.0.0\n */\nexport const ROOT_CONTEXT = new BaseContext();\n//# sourceMappingURL=context.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * NoopMeter is a noop implementation of the {@link Meter} interface. It reuses\n * constant NoopMetrics for all of its methods.\n */\nexport class NoopMeter {\n constructor() { }\n /**\n * @see {@link Meter.createGauge}\n */\n createGauge(_name, _options) {\n return NOOP_GAUGE_METRIC;\n }\n /**\n * @see {@link Meter.createHistogram}\n */\n createHistogram(_name, _options) {\n return NOOP_HISTOGRAM_METRIC;\n }\n /**\n * @see {@link Meter.createCounter}\n */\n createCounter(_name, _options) {\n return NOOP_COUNTER_METRIC;\n }\n /**\n * @see {@link Meter.createUpDownCounter}\n */\n createUpDownCounter(_name, _options) {\n return NOOP_UP_DOWN_COUNTER_METRIC;\n }\n /**\n * @see {@link Meter.createObservableGauge}\n */\n createObservableGauge(_name, _options) {\n return NOOP_OBSERVABLE_GAUGE_METRIC;\n }\n /**\n * @see {@link Meter.createObservableCounter}\n */\n createObservableCounter(_name, _options) {\n return NOOP_OBSERVABLE_COUNTER_METRIC;\n }\n /**\n * @see {@link Meter.createObservableUpDownCounter}\n */\n createObservableUpDownCounter(_name, _options) {\n return NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC;\n }\n /**\n * @see {@link Meter.addBatchObservableCallback}\n */\n addBatchObservableCallback(_callback, _observables) { }\n /**\n * @see {@link Meter.removeBatchObservableCallback}\n */\n removeBatchObservableCallback(_callback) { }\n}\nexport class NoopMetric {\n}\nexport class NoopCounterMetric extends NoopMetric {\n add(_value, _attributes) { }\n}\nexport class NoopUpDownCounterMetric extends NoopMetric {\n add(_value, _attributes) { }\n}\nexport class NoopGaugeMetric extends NoopMetric {\n record(_value, _attributes) { }\n}\nexport class NoopHistogramMetric extends NoopMetric {\n record(_value, _attributes) { }\n}\nexport class NoopObservableMetric {\n addCallback(_callback) { }\n removeCallback(_callback) { }\n}\nexport class NoopObservableCounterMetric extends NoopObservableMetric {\n}\nexport class NoopObservableGaugeMetric extends NoopObservableMetric {\n}\nexport class NoopObservableUpDownCounterMetric extends NoopObservableMetric {\n}\nexport const NOOP_METER = new NoopMeter();\n// Synchronous instruments\nexport const NOOP_COUNTER_METRIC = new NoopCounterMetric();\nexport const NOOP_GAUGE_METRIC = new NoopGaugeMetric();\nexport const NOOP_HISTOGRAM_METRIC = new NoopHistogramMetric();\nexport const NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric();\n// Asynchronous instruments\nexport const NOOP_OBSERVABLE_COUNTER_METRIC = new NoopObservableCounterMetric();\nexport const NOOP_OBSERVABLE_GAUGE_METRIC = new NoopObservableGaugeMetric();\nexport const NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC = new NoopObservableUpDownCounterMetric();\n/**\n * Create a no-op Meter\n *\n * @since 1.3.0\n */\nexport function createNoopMeter() {\n return NOOP_METER;\n}\n//# sourceMappingURL=NoopMeter.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * The Type of value. It describes how the data is reported.\n *\n * @since 1.3.0\n */\nexport var ValueType;\n(function (ValueType) {\n ValueType[ValueType[\"INT\"] = 0] = \"INT\";\n ValueType[ValueType[\"DOUBLE\"] = 1] = \"DOUBLE\";\n})(ValueType || (ValueType = {}));\n//# sourceMappingURL=Metric.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { ROOT_CONTEXT } from './context';\nexport class NoopContextManager {\n active() {\n return ROOT_CONTEXT;\n }\n with(_context, fn, thisArg, ...args) {\n return fn.call(thisArg, ...args);\n }\n bind(_context, target) {\n return target;\n }\n enable() {\n return this;\n }\n disable() {\n return this;\n }\n}\n//# sourceMappingURL=NoopContextManager.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NoopContextManager } from '../context/NoopContextManager';\nimport { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils';\nimport { DiagAPI } from './diag';\nconst API_NAME = 'context';\nconst NOOP_CONTEXT_MANAGER = new NoopContextManager();\n/**\n * Singleton object which represents the entry point to the OpenTelemetry Context API\n *\n * @since 1.0.0\n */\nexport class ContextAPI {\n /** Empty private constructor prevents end users from constructing a new instance of the API */\n constructor() { }\n /** Get the singleton instance of the Context API */\n static getInstance() {\n if (!this._instance) {\n this._instance = new ContextAPI();\n }\n return this._instance;\n }\n /**\n * Set the current context manager.\n *\n * @returns true if the context manager was successfully registered, else false\n */\n setGlobalContextManager(contextManager) {\n return registerGlobal(API_NAME, contextManager, DiagAPI.instance());\n }\n /**\n * Get the currently active context\n */\n active() {\n return this._getContextManager().active();\n }\n /**\n * Execute a function with an active context\n *\n * @param context context to be active during function execution\n * @param fn function to execute in a context\n * @param thisArg optional receiver to be used for calling fn\n * @param args optional arguments forwarded to fn\n */\n with(context, fn, thisArg, ...args) {\n return this._getContextManager().with(context, fn, thisArg, ...args);\n }\n /**\n * Bind a context to a target function or event emitter\n *\n * @param context context to bind to the event emitter or function. Defaults to the currently active context\n * @param target function or event emitter to bind\n */\n bind(context, target) {\n return this._getContextManager().bind(context, target);\n }\n _getContextManager() {\n return getGlobal(API_NAME) || NOOP_CONTEXT_MANAGER;\n }\n /** Disable and remove the global context manager */\n disable() {\n this._getContextManager().disable();\n unregisterGlobal(API_NAME, DiagAPI.instance());\n }\n}\n//# sourceMappingURL=context.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * @since 1.0.0\n */\nexport var TraceFlags;\n(function (TraceFlags) {\n /** Represents no flag set. */\n TraceFlags[TraceFlags[\"NONE\"] = 0] = \"NONE\";\n /** Bit to represent whether trace is sampled in trace flags. */\n TraceFlags[TraceFlags[\"SAMPLED\"] = 1] = \"SAMPLED\";\n})(TraceFlags || (TraceFlags = {}));\n//# sourceMappingURL=trace_flags.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { TraceFlags } from './trace_flags';\n/**\n * @since 1.0.0\n */\nexport const INVALID_SPANID = '0000000000000000';\n/**\n * @since 1.0.0\n */\nexport const INVALID_TRACEID = '00000000000000000000000000000000';\n/**\n * @since 1.0.0\n */\nexport const INVALID_SPAN_CONTEXT = {\n traceId: INVALID_TRACEID,\n spanId: INVALID_SPANID,\n traceFlags: TraceFlags.NONE,\n};\n//# sourceMappingURL=invalid-span-constants.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { INVALID_SPAN_CONTEXT } from './invalid-span-constants';\n/**\n * The NonRecordingSpan is the default {@link Span} that is used when no Span\n * implementation is available. All operations are no-op including context\n * propagation.\n */\nexport class NonRecordingSpan {\n constructor(spanContext = INVALID_SPAN_CONTEXT) {\n this._spanContext = spanContext;\n }\n // Returns a SpanContext.\n spanContext() {\n return this._spanContext;\n }\n // By default does nothing\n setAttribute(_key, _value) {\n return this;\n }\n // By default does nothing\n setAttributes(_attributes) {\n return this;\n }\n // By default does nothing\n addEvent(_name, _attributes) {\n return this;\n }\n addLink(_link) {\n return this;\n }\n addLinks(_links) {\n return this;\n }\n // By default does nothing\n setStatus(_status) {\n return this;\n }\n // By default does nothing\n updateName(_name) {\n return this;\n }\n // By default does nothing\n end(_endTime) { }\n // isRecording always returns false for NonRecordingSpan.\n isRecording() {\n return false;\n }\n // By default does nothing\n recordException(_exception, _time) { }\n}\n//# sourceMappingURL=NonRecordingSpan.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { createContextKey } from '../context/context';\nimport { NonRecordingSpan } from './NonRecordingSpan';\nimport { ContextAPI } from '../api/context';\n/**\n * span key\n */\nconst SPAN_KEY = createContextKey('OpenTelemetry Context Key SPAN');\n/**\n * Return the span if one exists\n *\n * @param context context to get span from\n */\nexport function getSpan(context) {\n return context.getValue(SPAN_KEY) || undefined;\n}\n/**\n * Gets the span from the current context, if one exists.\n */\nexport function getActiveSpan() {\n return getSpan(ContextAPI.getInstance().active());\n}\n/**\n * Set the span on a context\n *\n * @param context context to use as parent\n * @param span span to set active\n */\nexport function setSpan(context, span) {\n return context.setValue(SPAN_KEY, span);\n}\n/**\n * Remove current span stored in the context\n *\n * @param context context to delete span from\n */\nexport function deleteSpan(context) {\n return context.deleteValue(SPAN_KEY);\n}\n/**\n * Wrap span context in a NoopSpan and set as span in a new\n * context\n *\n * @param context context to set active span on\n * @param spanContext span context to be wrapped\n */\nexport function setSpanContext(context, spanContext) {\n return setSpan(context, new NonRecordingSpan(spanContext));\n}\n/**\n * Get the span context of the span if it exists.\n *\n * @param context context to get values from\n */\nexport function getSpanContext(context) {\n var _a;\n return (_a = getSpan(context)) === null || _a === void 0 ? void 0 : _a.spanContext();\n}\n//# sourceMappingURL=context-utils.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { INVALID_SPANID, INVALID_TRACEID } from './invalid-span-constants';\nimport { NonRecordingSpan } from './NonRecordingSpan';\n// Valid characters (0-9, a-f, A-F) are marked as 1.\nconst isHex = new Uint8Array([\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,\n 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,\n]);\nfunction isValidHex(id, length) {\n // As of 1.9.0 the id was allowed to be a non-string value,\n // even though it was not possible in the types.\n if (typeof id !== 'string' || id.length !== length)\n return false;\n let r = 0;\n for (let i = 0; i < id.length; i += 4) {\n r +=\n (isHex[id.charCodeAt(i)] | 0) +\n (isHex[id.charCodeAt(i + 1)] | 0) +\n (isHex[id.charCodeAt(i + 2)] | 0) +\n (isHex[id.charCodeAt(i + 3)] | 0);\n }\n return r === length;\n}\n/**\n * @since 1.0.0\n */\nexport function isValidTraceId(traceId) {\n return isValidHex(traceId, 32) && traceId !== INVALID_TRACEID;\n}\n/**\n * @since 1.0.0\n */\nexport function isValidSpanId(spanId) {\n return isValidHex(spanId, 16) && spanId !== INVALID_SPANID;\n}\n/**\n * Returns true if this {@link SpanContext} is valid.\n * @return true if this {@link SpanContext} is valid.\n *\n * @since 1.0.0\n */\nexport function isSpanContextValid(spanContext) {\n return (isValidTraceId(spanContext.traceId) && isValidSpanId(spanContext.spanId));\n}\n/**\n * Wrap the given {@link SpanContext} in a new non-recording {@link Span}\n *\n * @param spanContext span context to be wrapped\n * @returns a new non-recording {@link Span} with the provided context\n */\nexport function wrapSpanContext(spanContext) {\n return new NonRecordingSpan(spanContext);\n}\n//# sourceMappingURL=spancontext-utils.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { ContextAPI } from '../api/context';\nimport { getSpanContext, setSpan } from '../trace/context-utils';\nimport { NonRecordingSpan } from './NonRecordingSpan';\nimport { isSpanContextValid } from './spancontext-utils';\nconst contextApi = ContextAPI.getInstance();\n/**\n * No-op implementations of {@link Tracer}.\n */\nexport class NoopTracer {\n // startSpan starts a noop span.\n startSpan(name, options, context = contextApi.active()) {\n const root = Boolean(options === null || options === void 0 ? void 0 : options.root);\n if (root) {\n return new NonRecordingSpan();\n }\n const parentFromContext = context && getSpanContext(context);\n if (isSpanContext(parentFromContext) &&\n isSpanContextValid(parentFromContext)) {\n return new NonRecordingSpan(parentFromContext);\n }\n else {\n return new NonRecordingSpan();\n }\n }\n startActiveSpan(name, arg2, arg3, arg4) {\n let opts;\n let ctx;\n let fn;\n if (arguments.length < 2) {\n return;\n }\n else if (arguments.length === 2) {\n fn = arg2;\n }\n else if (arguments.length === 3) {\n opts = arg2;\n fn = arg3;\n }\n else {\n opts = arg2;\n ctx = arg3;\n fn = arg4;\n }\n const parentContext = ctx !== null && ctx !== void 0 ? ctx : contextApi.active();\n const span = this.startSpan(name, opts, parentContext);\n const contextWithSpanSet = setSpan(parentContext, span);\n return contextApi.with(contextWithSpanSet, fn, undefined, span);\n }\n}\nfunction isSpanContext(spanContext) {\n return (spanContext !== null &&\n typeof spanContext === 'object' &&\n 'spanId' in spanContext &&\n typeof spanContext['spanId'] === 'string' &&\n 'traceId' in spanContext &&\n typeof spanContext['traceId'] === 'string' &&\n 'traceFlags' in spanContext &&\n typeof spanContext['traceFlags'] === 'number');\n}\n//# sourceMappingURL=NoopTracer.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NoopTracer } from './NoopTracer';\nconst NOOP_TRACER = new NoopTracer();\n/**\n * Proxy tracer provided by the proxy tracer provider\n *\n * @since 1.0.0\n */\nexport class ProxyTracer {\n constructor(provider, name, version, options) {\n this._provider = provider;\n this.name = name;\n this.version = version;\n this.options = options;\n }\n startSpan(name, options, context) {\n return this._getTracer().startSpan(name, options, context);\n }\n startActiveSpan(_name, _options, _context, _fn) {\n const tracer = this._getTracer();\n return Reflect.apply(tracer.startActiveSpan, tracer, arguments);\n }\n /**\n * Try to get a tracer from the proxy tracer provider.\n * If the proxy tracer provider has no delegate, return a noop tracer.\n */\n _getTracer() {\n if (this._delegate) {\n return this._delegate;\n }\n const tracer = this._provider.getDelegateTracer(this.name, this.version, this.options);\n if (!tracer) {\n return NOOP_TRACER;\n }\n this._delegate = tracer;\n return this._delegate;\n }\n}\n//# sourceMappingURL=ProxyTracer.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NoopTracer } from './NoopTracer';\n/**\n * An implementation of the {@link TracerProvider} which returns an impotent\n * Tracer for all calls to `getTracer`.\n *\n * All operations are no-op.\n */\nexport class NoopTracerProvider {\n getTracer(_name, _version, _options) {\n return new NoopTracer();\n }\n}\n//# sourceMappingURL=NoopTracerProvider.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { ProxyTracer } from './ProxyTracer';\nimport { NoopTracerProvider } from './NoopTracerProvider';\nconst NOOP_TRACER_PROVIDER = new NoopTracerProvider();\n/**\n * Tracer provider which provides {@link ProxyTracer}s.\n *\n * Before a delegate is set, tracers provided are NoOp.\n * When a delegate is set, traces are provided from the delegate.\n * When a delegate is set after tracers have already been provided,\n * all tracers already provided will use the provided delegate implementation.\n *\n * @deprecated This will be removed in the next major version.\n * @since 1.0.0\n */\nexport class ProxyTracerProvider {\n /**\n * Get a {@link ProxyTracer}\n */\n getTracer(name, version, options) {\n var _a;\n return ((_a = this.getDelegateTracer(name, version, options)) !== null && _a !== void 0 ? _a : new ProxyTracer(this, name, version, options));\n }\n getDelegate() {\n var _a;\n return (_a = this._delegate) !== null && _a !== void 0 ? _a : NOOP_TRACER_PROVIDER;\n }\n /**\n * Set the delegate tracer provider\n */\n setDelegate(delegate) {\n this._delegate = delegate;\n }\n getDelegateTracer(name, version, options) {\n var _a;\n return (_a = this._delegate) === null || _a === void 0 ? void 0 : _a.getTracer(name, version, options);\n }\n}\n//# sourceMappingURL=ProxyTracerProvider.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * @since 1.0.0\n */\nexport var SpanKind;\n(function (SpanKind) {\n /** Default value. Indicates that the span is used internally. */\n SpanKind[SpanKind[\"INTERNAL\"] = 0] = \"INTERNAL\";\n /**\n * Indicates that the span covers server-side handling of an RPC or other\n * remote request.\n */\n SpanKind[SpanKind[\"SERVER\"] = 1] = \"SERVER\";\n /**\n * Indicates that the span covers the client-side wrapper around an RPC or\n * other remote request.\n */\n SpanKind[SpanKind[\"CLIENT\"] = 2] = \"CLIENT\";\n /**\n * Indicates that the span describes producer sending a message to a\n * broker. Unlike client and server, there is no direct critical path latency\n * relationship between producer and consumer spans.\n */\n SpanKind[SpanKind[\"PRODUCER\"] = 3] = \"PRODUCER\";\n /**\n * Indicates that the span describes consumer receiving a message from a\n * broker. Unlike client and server, there is no direct critical path latency\n * relationship between producer and consumer spans.\n */\n SpanKind[SpanKind[\"CONSUMER\"] = 4] = \"CONSUMER\";\n})(SpanKind || (SpanKind = {}));\n//# sourceMappingURL=span_kind.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n/**\n * An enumeration of status codes.\n *\n * @since 1.0.0\n */\nexport var SpanStatusCode;\n(function (SpanStatusCode) {\n /**\n * The default status.\n */\n SpanStatusCode[SpanStatusCode[\"UNSET\"] = 0] = \"UNSET\";\n /**\n * The operation has been validated by an Application developer or\n * Operator to have completed successfully.\n */\n SpanStatusCode[SpanStatusCode[\"OK\"] = 1] = \"OK\";\n /**\n * The operation contains an error.\n */\n SpanStatusCode[SpanStatusCode[\"ERROR\"] = 2] = \"ERROR\";\n})(SpanStatusCode || (SpanStatusCode = {}));\n//# sourceMappingURL=status.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n// Split module-level variable definition into separate files to allow\n// tree-shaking on each api instance.\nimport { ContextAPI } from './api/context';\n/**\n * Entrypoint for context API\n * @since 1.0.0\n */\nexport const context = ContextAPI.getInstance();\n//# sourceMappingURL=context-api.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NOOP_METER } from './NoopMeter';\n/**\n * An implementation of the {@link MeterProvider} which returns an impotent Meter\n * for all calls to `getMeter`\n */\nexport class NoopMeterProvider {\n getMeter(_name, _version, _options) {\n return NOOP_METER;\n }\n}\nexport const NOOP_METER_PROVIDER = new NoopMeterProvider();\n//# sourceMappingURL=NoopMeterProvider.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { NOOP_METER_PROVIDER } from '../metrics/NoopMeterProvider';\nimport { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils';\nimport { DiagAPI } from './diag';\nconst API_NAME = 'metrics';\n/**\n * Singleton object which represents the entry point to the OpenTelemetry Metrics API\n */\nexport class MetricsAPI {\n /** Empty private constructor prevents end users from constructing a new instance of the API */\n constructor() { }\n /** Get the singleton instance of the Metrics API */\n static getInstance() {\n if (!this._instance) {\n this._instance = new MetricsAPI();\n }\n return this._instance;\n }\n /**\n * Set the current global meter provider.\n * Returns true if the meter provider was successfully registered, else false.\n */\n setGlobalMeterProvider(provider) {\n return registerGlobal(API_NAME, provider, DiagAPI.instance());\n }\n /**\n * Returns the global meter provider.\n */\n getMeterProvider() {\n return getGlobal(API_NAME) || NOOP_METER_PROVIDER;\n }\n /**\n * Returns a meter from the global meter provider.\n */\n getMeter(name, version, options) {\n return this.getMeterProvider().getMeter(name, version, options);\n }\n /** Remove the global meter provider */\n disable() {\n unregisterGlobal(API_NAME, DiagAPI.instance());\n }\n}\n//# sourceMappingURL=metrics.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n// Split module-level variable definition into separate files to allow\n// tree-shaking on each api instance.\nimport { MetricsAPI } from './api/metrics';\n/**\n * Entrypoint for metrics API\n *\n * @since 1.3.0\n */\nexport const metrics = MetricsAPI.getInstance();\n//# sourceMappingURL=metrics-api.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils';\nimport { ProxyTracerProvider } from '../trace/ProxyTracerProvider';\nimport { isSpanContextValid, wrapSpanContext, } from '../trace/spancontext-utils';\nimport { deleteSpan, getActiveSpan, getSpan, getSpanContext, setSpan, setSpanContext, } from '../trace/context-utils';\nimport { DiagAPI } from './diag';\nconst API_NAME = 'trace';\n/**\n * Singleton object which represents the entry point to the OpenTelemetry Tracing API\n *\n * @since 1.0.0\n */\nexport class TraceAPI {\n /** Empty private constructor prevents end users from constructing a new instance of the API */\n constructor() {\n this._proxyTracerProvider = new ProxyTracerProvider();\n this.wrapSpanContext = wrapSpanContext;\n this.isSpanContextValid = isSpanContextValid;\n this.deleteSpan = deleteSpan;\n this.getSpan = getSpan;\n this.getActiveSpan = getActiveSpan;\n this.getSpanContext = getSpanContext;\n this.setSpan = setSpan;\n this.setSpanContext = setSpanContext;\n }\n /** Get the singleton instance of the Trace API */\n static getInstance() {\n if (!this._instance) {\n this._instance = new TraceAPI();\n }\n return this._instance;\n }\n /**\n * Set the current global tracer.\n *\n * @returns true if the tracer provider was successfully registered, else false\n */\n setGlobalTracerProvider(provider) {\n const success = registerGlobal(API_NAME, this._proxyTracerProvider, DiagAPI.instance());\n if (success) {\n this._proxyTracerProvider.setDelegate(provider);\n }\n return success;\n }\n /**\n * Returns the global tracer provider.\n */\n getTracerProvider() {\n return getGlobal(API_NAME) || this._proxyTracerProvider;\n }\n /**\n * Returns a tracer from the global tracer provider.\n */\n getTracer(name, version) {\n return this.getTracerProvider().getTracer(name, version);\n }\n /** Remove the global tracer provider */\n disable() {\n unregisterGlobal(API_NAME, DiagAPI.instance());\n this._proxyTracerProvider = new ProxyTracerProvider();\n }\n}\n//# sourceMappingURL=trace.js.map","/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n// Split module-level variable definition into separate files to allow\n// tree-shaking on each api instance.\nimport { TraceAPI } from './api/trace';\n/**\n * Entrypoint for trace API\n *\n * @since 1.0.0\n */\nexport const trace = TraceAPI.getInstance();\n//# sourceMappingURL=trace-api.js.map","import {\n type Meter,\n context,\n metrics,\n propagation,\n ROOT_CONTEXT,\n SpanKind,\n SpanStatusCode,\n trace,\n ValueType,\n type Attributes,\n type Context,\n type Counter,\n type Gauge,\n type Histogram,\n type Meter as MeterType,\n type MetricOptions,\n type ObservableCounter,\n type ObservableGauge,\n type ObservableResult,\n type ObservableUpDownCounter,\n type Span,\n type SpanOptions,\n type Tracer,\n type UpDownCounter,\n} from \"@opentelemetry/api\";\nimport { type Logger, SeverityNumber } from \"@opentelemetry/api-logs\";\nimport { flattenAttributes } from \"@trigger.dev/core/v3/utils/flattenAttributes\";\n\nexport * from \"@opentelemetry/semantic-conventions\";\n\nexport type {\n Attributes,\n Counter,\n Gauge,\n Histogram,\n MeterType as Meter,\n MetricOptions,\n ObservableCounter,\n ObservableGauge,\n ObservableResult,\n ObservableUpDownCounter,\n Span,\n SpanOptions,\n Tracer,\n UpDownCounter,\n};\nexport {\n context,\n metrics,\n propagation,\n ROOT_CONTEXT,\n SpanKind,\n SpanStatusCode,\n trace,\n ValueType,\n type Context,\n};\n\nexport function getTracer(name: string): Tracer {\n return trace.getTracer(name);\n}\n\nexport function getMeter(name: string): Meter {\n return metrics.getMeter(name);\n}\n\nexport async function startSpan<T>(\n tracer: Tracer | undefined,\n name: string,\n fn: (span: Span) => Promise<T>,\n options?: SpanOptions\n): Promise<T> {\n tracer ??= getTracer(\"default\");\n\n return tracer.startActiveSpan(name, options ?? {}, async (span) => {\n try {\n return await fn(span);\n } catch (error) {\n if (error instanceof Error) {\n span.recordException(error);\n } else if (typeof error === \"string\") {\n span.recordException(new Error(error));\n } else {\n span.recordException(new Error(String(error)));\n }\n\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n } finally {\n span.end();\n }\n });\n}\n\nexport function recordSpanError(span: Span, error: Error) {\n span.recordException(error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error.message,\n });\n}\n\nexport async function emitDebugLog(\n logger: Logger,\n message: string,\n params: Record<string, unknown> = {}\n) {\n logger.emit({\n severityNumber: SeverityNumber.DEBUG,\n body: message,\n attributes: { ...flattenAttributes(params, \"params\") },\n });\n}\n\nexport async function emitInfoLog(\n logger: Logger,\n message: string,\n params: Record<string, unknown> = {}\n) {\n logger.emit({\n severityNumber: SeverityNumber.INFO,\n body: message,\n attributes: { ...flattenAttributes(params, \"params\") },\n });\n}\n\nexport async function emitErrorLog(\n logger: Logger,\n message: string,\n params: Record<string, unknown> = {}\n) {\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n body: message,\n attributes: { ...flattenAttributes(params, \"params\") },\n });\n}\n\nexport async function emitWarnLog(\n logger: Logger,\n message: string,\n params: Record<string, unknown> = {}\n) {\n logger.emit({\n severityNumber: SeverityNumber.WARN,\n body: message,\n attributes: { ...flattenAttributes(params, \"params\") },\n });\n}\n","/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n}\n","import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tvalidateConcurrency(concurrency);\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tqueue.dequeue()();\n\t\t\t// Since `pendingCount` has been decreased by one, increase `activeCount` by one.\n\t\t\tactiveCount++;\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\tresolve(result);\n\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, arguments_) => {\n\t\t// Queue `internalResolve` instead of the `run` function\n\t\t// to preserve asynchronous context.\n\t\tnew Promise(internalResolve => {\n\t\t\tqueue.enqueue(internalResolve);\n\t\t}).then(\n\t\t\trun.bind(undefined, function_, resolve, arguments_),\n\t\t);\n\n\t\t(async () => {\n\t\t\t// This function needs to wait until the next microtask before comparing\n\t\t\t// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously\n\t\t\t// after the `internalResolve` function is dequeued and called. The comparison in the if-statement\n\t\t\t// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.\n\t\t\tawait Promise.resolve();\n\n\t\t\tif (activeCount < concurrency) {\n\t\t\t\tresumeNext();\n\t\t\t}\n\t\t})();\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise(resolve => {\n\t\tenqueue(function_, resolve, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tqueue.clear();\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, option) {\n\tconst {concurrency} = option;\n\tconst limit = pLimit(concurrency);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n","import { type Redis, createRedisClient, type RedisOptions } from \"@internal/redis\";\nimport {\n type Attributes,\n type Histogram,\n type Meter,\n type ObservableResult,\n type Tracer,\n metrics,\n SpanKind,\n startSpan,\n trace,\n ValueType,\n} from \"@internal/tracing\";\nimport { Logger } from \"@trigger.dev/core/logger\";\nimport {\n calculateNextRetryDelay,\n type AnyZodSchema,\n type inferZodSchemaOutput,\n} from \"@trigger.dev/core/v3\";\nimport { type RetryOptions } from \"@trigger.dev/core/v3/schemas\";\nimport { shutdownManager } from \"@trigger.dev/core/v3/serverOnly\";\nimport { nanoid } from \"nanoid\";\nimport pLimit from \"p-limit\";\nimport { z } from \"zod/v4\";\nimport { type AnyQueueItem, SimpleQueue } from \"./queue.js\";\nimport cronParser from \"cron-parser\";\n\nexport const CronSchema = z.object({\n cron: z.string(),\n lastTimestamp: z.number().optional(),\n timestamp: z.number(),\n});\n\nexport type CronSchema = z.infer<typeof CronSchema>;\n\nexport type BatchConfig = {\n maxSize: number;\n maxWaitMs: number;\n};\n\nexport type WorkerCatalog = {\n [key: string]: {\n schema: AnyZodSchema;\n visibilityTimeoutMs: number;\n retry?: RetryOptions;\n cron?: string;\n jitterInMs?: number;\n /** Defaults to true. If false, errors will not be logged. */\n logErrors?: boolean;\n /** When set, items are accumulated and delivered in batches to the handler. */\n batch?: BatchConfig;\n };\n};\n\ntype WorkerCatalogItem = WorkerCatalog[keyof WorkerCatalog];\n\ntype QueueCatalogFromWorkerCatalog<Catalog extends WorkerCatalog> = {\n [K in keyof Catalog]: Catalog[K][\"schema\"];\n};\n\nexport type JobHandlerParams<Catalog extends WorkerCatalog, K extends keyof Catalog> = {\n id: string;\n payload: inferZodSchemaOutput<Catalog[K][\"schema\"]>;\n visibilityTimeoutMs: number;\n attempt: number;\n deduplicationKey?: string;\n};\n\nexport type JobHandler<Catalog extends WorkerCatalog, K extends keyof Catalog> = (\n params: JobHandlerParams<Catalog, K>\n) => Promise<void>;\n\ntype JobHandlerFor<Catalog extends WorkerCatalog, K extends keyof Catalog> = Catalog[K] extends {\n batch: BatchConfig;\n}\n ? (items: Array<JobHandlerParams<Catalog, K>>) => Promise<void>\n : (params: JobHandlerParams<Catalog, K>) => Promise<void>;\n\nexport type WorkerConcurrencyOptions = {\n workers?: number;\n tasksPerWorker?: number;\n limit?: number;\n};\n\ntype WorkerOptions<TCatalog extends WorkerCatalog> = {\n name: string;\n redisOptions: RedisOptions;\n catalog: TCatalog;\n jobs: {\n [K in keyof TCatalog]: JobHandlerFor<TCatalog, K>;\n };\n concurrency?: WorkerConcurrencyOptions;\n pollIntervalMs?: number;\n immediatePollIntervalMs?: number;\n shutdownTimeoutMs?: number;\n logger?: Logger;\n tracer?: Tracer;\n meter?: Meter;\n};\n\n// This results in attempt 12 being a delay of 1 hour\nconst defaultRetrySettings = {\n maxAttempts: 12,\n factor: 2,\n //one second\n minTimeoutInMs: 1_000,\n //one hour\n maxTimeoutInMs: 3_600_000,\n randomize: true,\n};\n\nclass Worker<TCatalog extends WorkerCatalog> {\n private subscriber: Redis | undefined;\n private tracer: Tracer;\n private meter: Meter;\n\n private metrics: {\n enqueueDuration?: Histogram;\n dequeueDuration?: Histogram;\n jobDuration?: Histogram;\n ackDuration?: Histogram;\n redriveDuration?: Histogram;\n rescheduleDuration?: Histogram;\n } = {};\n\n queue: SimpleQueue<QueueCatalogFromWorkerCatalog<TCatalog>>;\n private jobs: WorkerOptions<TCatalog>[\"jobs\"];\n private logger: Logger;\n private workerLoops: Promise<void>[] = [];\n private isShuttingDown = false;\n private concurrency: Required<NonNullable<WorkerOptions<TCatalog>[\"concurrency\"]>>;\n private shutdownTimeoutMs: number;\n\n // The p-limit limiter to control overall concurrency.\n private limiters: Record<string, ReturnType<typeof pLimit>> = {};\n\n // Batch accumulators: one per batch-enabled job type\n private batchAccumulators: Map<\n string,\n {\n items: AnyQueueItem[];\n firstItemAt: number;\n }\n > = new Map();\n\n constructor(private options: WorkerOptions<TCatalog>) {\n this.logger = options.logger ?? new Logger(\"Worker\", \"debug\", [\"item\"]);\n this.tracer = options.tracer ?? trace.getTracer(options.name);\n this.meter = options.meter ?? metrics.getMeter(options.name);\n\n this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 60_000;\n\n const schema: QueueCatalogFromWorkerCatalog<TCatalog> = Object.fromEntries(\n Object.entries(this.options.catalog).map(([key, value]) => [key, value.schema])\n ) as QueueCatalogFromWorkerCatalog<TCatalog>;\n\n this.queue = new SimpleQueue({\n name: options.name,\n redisOptions: options.redisOptions,\n logger: this.logger,\n schema,\n });\n\n this.jobs = options.jobs;\n\n const { workers = 1, tasksPerWorker = 1, limit = 10 } = options.concurrency ?? {};\n this.concurrency = { workers, tasksPerWorker, limit };\n\n const masterQueueObservableGauge = this.meter.createObservableGauge(\"redis_worker.queue.size\", {\n description: \"The number of items in the queue\",\n unit: \"items\",\n valueType: ValueType.INT,\n });\n\n masterQueueObservableGauge.addCallback(this.#updateQueueSizeMetric.bind(this));\n\n const deadLetterQueueObservableGauge = this.meter.createObservableGauge(\n \"redis_worker.queue.dead_letter_size\",\n {\n description: \"The number of items in the dead letter queue\",\n unit: \"items\",\n valueType: ValueType.INT,\n }\n );\n\n deadLetterQueueObservableGauge.addCallback(this.#updateDeadLetterQueueSizeMetric.bind(this));\n\n const concurrencyLimitActiveObservableGauge = this.meter.createObservableGauge(\n \"redis_worker.concurrency.active\",\n {\n description: \"The number of active workers\",\n unit: \"workers\",\n valueType: ValueType.INT,\n }\n );\n\n concurrencyLimitActiveObservableGauge.addCallback(\n this.#updateConcurrencyLimitActiveMetric.bind(this)\n );\n\n const concurrencyLimitPendingObservableGauge = this.meter.createObservableGauge(\n \"redis_worker.concurrency.pending\",\n {\n description: \"The number of pending workers\",\n unit: \"workers\",\n valueType: ValueType.INT,\n }\n );\n\n concurrencyLimitPendingObservableGauge.addCallback(\n this.#updateConcurrencyLimitPendingMetric.bind(this)\n );\n\n const oldestMessageAgeObservableGauge = this.meter.createObservableGauge(\n \"redis_worker.queue.oldest_message_age\",\n {\n description: \"Age of the oldest overdue message in the queue\",\n unit: \"ms\",\n valueType: ValueType.INT,\n }\n );\n\n oldestMessageAgeObservableGauge.addCallback(this.#updateOldestMessageAgeMetric.bind(this));\n }\n\n async #updateQueueSizeMetric(observableResult: ObservableResult<Attributes>) {\n const queueSize = await this.queue.size();\n\n observableResult.observe(queueSize, {\n worker_name: this.options.name,\n });\n }\n\n async #updateDeadLetterQueueSizeMetric(observableResult: ObservableResult<Attributes>) {\n const deadLetterQueueSize = await this.queue.sizeOfDeadLetterQueue();\n observableResult.observe(deadLetterQueueSize, {\n worker_name: this.options.name,\n });\n }\n\n async #updateOldestMessageAgeMetric(observableResult: ObservableResult<Attributes>) {\n const oldestMessageAge = await this.queue.oldestMessageAge();\n\n observableResult.observe(oldestMessageAge, {\n worker_name: this.options.name,\n });\n }\n\n async #updateConcurrencyLimitActiveMetric(observableResult: ObservableResult<Attributes>) {\n for (const [workerId, limiter] of Object.entries(this.limiters)) {\n observableResult.observe(limiter.activeCount, {\n worker_name: this.options.name,\n worker_id: workerId,\n });\n }\n }\n\n async #updateConcurrencyLimitPendingMetric(observableResult: ObservableResult<Attributes>) {\n for (const [workerId, limiter] of Object.entries(this.limiters)) {\n observableResult.observe(limiter.pendingCount, {\n worker_name: this.options.name,\n worker_id: workerId,\n });\n }\n }\n\n public start() {\n const { workers, tasksPerWorker } = this.concurrency;\n\n this.logger.info(\"Starting worker\", {\n workers,\n tasksPerWorker,\n concurrency: this.concurrency,\n });\n\n // Launch a number of \"worker loops\" on the main thread.\n for (let i = 0; i < workers; i++) {\n this.workerLoops.push(this.runWorkerLoop(`worker-${nanoid(12)}`, tasksPerWorker, i, workers));\n }\n\n this.setupShutdownHandlers();\n\n this.subscriber = createRedisClient(this.options.redisOptions, {\n onError: (error) => {\n this.logger.error(`RedisWorker subscriber redis client error:`, {\n error,\n keyPrefix: this.options.redisOptions.keyPrefix,\n });\n },\n });\n\n this.setupSubscriber();\n this.setupCron();\n\n return this;\n }\n\n /**\n * Enqueues a job for processing.\n * @param options - The enqueue options.\n * @param options.id - Optional unique identifier for the job. If not provided, one will be generated. It prevents duplication.\n * @param options.job - The job type from the worker catalog.\n * @param options.payload - The job payload that matches the schema defined in the catalog.\n * @param options.visibilityTimeoutMs - Optional visibility timeout in milliseconds. Defaults to value from catalog.\n * @param options.availableAt - Optional date when the job should become available for processing. Defaults to now.\n * @returns A promise that resolves when the job is enqueued.\n */\n enqueue<K extends keyof TCatalog>({\n id,\n job,\n payload,\n visibilityTimeoutMs,\n availableAt,\n cancellationKey,\n }: {\n id?: string;\n job: K;\n payload: inferZodSchemaOutput<TCatalog[K][\"schema\"]>;\n visibilityTimeoutMs?: number;\n availableAt?: Date;\n cancellationKey?: string;\n }) {\n return startSpan(\n this.tracer,\n \"enqueue\",\n async (span) => {\n const timeout = visibilityTimeoutMs ?? this.options.catalog[job]?.visibilityTimeoutMs;\n\n if (!timeout) {\n throw new Error(`No visibility timeout found for job ${String(job)} with id ${id}`);\n }\n\n span.setAttribute(\"job_visibility_timeout_ms\", timeout);\n\n return this.withHistogram(\n this.metrics.enqueueDuration,\n this.queue.enqueue({\n id,\n job,\n item: payload,\n visibilityTimeoutMs: timeout,\n availableAt,\n cancellationKey,\n }),\n {\n job_type: String(job),\n has_available_at: availableAt ? \"true\" : \"false\",\n }\n );\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n job_type: String(job),\n job_id: id,\n },\n }\n );\n }\n\n /**\n * Enqueues a job for processing once. If the job is already in the queue, it will be ignored.\n * @param options - The enqueue options.\n * @param options.id - Required unique identifier for the job.\n * @param options.job - The job type from the worker catalog.\n * @param options.payload - The job payload that matches the schema defined in the catalog.\n * @param options.visibilityTimeoutMs - Optional visibility timeout in milliseconds. Defaults to value from catalog.\n * @param options.availableAt - Optional date when the job should become available for processing. Defaults to now.\n * @returns A promise that resolves when the job is enqueued.\n */\n enqueueOnce<K extends keyof TCatalog>({\n id,\n job,\n payload,\n visibilityTimeoutMs,\n availableAt,\n }: {\n id: string;\n job: K;\n payload: inferZodSchemaOutput<TCatalog[K][\"schema\"]>;\n visibilityTimeoutMs?: number;\n availableAt?: Date;\n }) {\n return startSpan(\n this.tracer,\n \"enqueueOnce\",\n async (span) => {\n const timeout = visibilityTimeoutMs ?? this.options.catalog[job]?.visibilityTimeoutMs;\n\n if (!timeout) {\n throw new Error(`No visibility timeout found for job ${String(job)} with id ${id}`);\n }\n\n span.setAttribute(\"job_visibility_timeout_ms\", timeout);\n\n return this.withHistogram(\n this.metrics.enqueueDuration,\n this.queue.enqueueOnce({\n id,\n job,\n item: payload,\n visibilityTimeoutMs: timeout,\n availableAt,\n }),\n {\n job_type: String(job),\n has_available_at: availableAt ? \"true\" : \"false\",\n }\n );\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n job_type: String(job),\n job_id: id,\n },\n }\n );\n }\n\n /**\n * Reschedules an existing job to a new available date.\n * If the job isn't in the queue, it will be ignored.\n */\n reschedule(id: string, availableAt: Date) {\n return startSpan(\n this.tracer,\n \"reschedule\",\n async (span) => {\n return this.withHistogram(\n this.metrics.rescheduleDuration,\n this.queue.reschedule(id, availableAt)\n );\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n job_id: id,\n },\n }\n );\n }\n\n /**\n * Cancels a job before it's enqueued.\n * @param cancellationKey - The cancellation key to cancel.\n * @returns A promise that resolves when the job is cancelled.\n *\n * Any jobs enqueued with the same cancellation key will be not be enqueued.\n */\n cancel(cancellationKey: string) {\n return startSpan(this.tracer, \"cancel\", () => this.queue.cancel(cancellationKey));\n }\n\n ack(id: string) {\n return startSpan(\n this.tracer,\n \"ack\",\n () => {\n return this.withHistogram(this.metrics.ackDuration, this.queue.ack(id));\n },\n {\n attributes: {\n job_id: id,\n },\n }\n );\n }\n\n async getJob(id: string) {\n return this.queue.getJob(id);\n }\n\n /**\n * Returns true if the given job type has batch config in the catalog.\n */\n private isBatchJob(jobType: string): boolean {\n const catalogItem = this.options.catalog[jobType as any];\n return !!catalogItem?.batch;\n }\n\n /**\n * Returns the batch config for a job type, or undefined if not batch-enabled.\n */\n private getBatchConfig(jobType: string): BatchConfig | undefined {\n const catalogItem = this.options.catalog[jobType as any];\n return catalogItem?.batch;\n }\n\n /**\n * The max dequeue count: the largest batch maxSize across catalog entries,\n * falling back to tasksPerWorker for non-batch catalogs.\n */\n private get maxDequeueCount(): number {\n const batchSizes = Object.values(this.options.catalog)\n .filter((entry): entry is typeof entry & { batch: BatchConfig } => !!entry.batch)\n .map((entry) => entry.batch.maxSize);\n\n if (batchSizes.length > 0) {\n return Math.max(...batchSizes);\n }\n return this.concurrency.tasksPerWorker;\n }\n\n /**\n * The main loop that each worker runs. It repeatedly polls for items,\n * processes them, and then waits before the next iteration.\n */\n private async runWorkerLoop(\n workerId: string,\n taskCount: number,\n workerIndex: number,\n totalWorkers: number\n ): Promise<void> {\n const limiter = pLimit(this.concurrency.limit);\n this.limiters[workerId] = limiter;\n\n const pollIntervalMs = this.options.pollIntervalMs ?? 1000;\n const immediatePollIntervalMs = this.options.immediatePollIntervalMs ?? 100;\n\n // Calculate the delay between starting each worker loop so that they don't all start at the same time.\n const delayBetweenWorkers = this.options.pollIntervalMs ?? 1000;\n const delay = delayBetweenWorkers * (totalWorkers - workerIndex);\n await Worker.delay(delay);\n\n this.logger.info(\"Starting worker loop\", {\n workerIndex,\n totalWorkers,\n delay,\n workerId,\n taskCount,\n pollIntervalMs,\n immediatePollIntervalMs,\n concurrencyOptions: this.concurrency,\n });\n\n while (!this.isShuttingDown) {\n // 1. Flush any timed-out batch accumulators\n await this.flushTimedOutBatches(workerId, limiter);\n\n // 2. Check overall load. If at capacity, wait a bit before trying to dequeue more.\n if (limiter.activeCount + limiter.pendingCount >= this.concurrency.limit) {\n this.logger.debug(\"Worker at capacity, waiting\", {\n workerId,\n concurrencyOptions: this.concurrency,\n activeCount: limiter.activeCount,\n pendingCount: limiter.pendingCount,\n });\n\n await Worker.delay(pollIntervalMs);\n\n continue;\n }\n\n // 3. Calculate dequeue count - use max batch size if we have batch jobs\n const $taskCount = Math.min(\n this.maxDequeueCount,\n this.concurrency.limit - limiter.activeCount - limiter.pendingCount\n );\n\n let itemsFound = false;\n\n try {\n const items = await this.withHistogram(\n this.metrics.dequeueDuration,\n this.queue.dequeue($taskCount),\n {\n worker_id: workerId,\n task_count: $taskCount,\n }\n );\n\n itemsFound = items.length > 0;\n\n if (items.length === 0 && this.batchAccumulators.size === 0) {\n this.logger.debug(\"No items to dequeue\", {\n workerId,\n concurrencyOptions: this.concurrency,\n activeCount: limiter.activeCount,\n pendingCount: limiter.pendingCount,\n });\n\n await Worker.delay(pollIntervalMs);\n continue;\n }\n\n if (items.length > 0) {\n this.logger.debug(\"Dequeued items\", {\n workerId,\n itemCount: items.length,\n concurrencyOptions: this.concurrency,\n activeCount: limiter.activeCount,\n pendingCount: limiter.pendingCount,\n });\n }\n\n // 4. Route items: batch-enabled go to accumulators, others processed immediately\n for (const item of items) {\n const queueItem = item as AnyQueueItem;\n\n if (this.isBatchJob(queueItem.job)) {\n this.addToAccumulator(queueItem);\n\n const batchConfig = this.getBatchConfig(queueItem.job)!;\n const accumulator = this.batchAccumulators.get(queueItem.job);\n if (accumulator && accumulator.items.length >= batchConfig.maxSize) {\n await this.flushBatch(queueItem.job, workerId, limiter);\n }\n } else {\n limiter(() => this.processItem(queueItem, items.length, workerId, limiter)).catch(\n (err) => {\n this.logger.error(\"Unhandled error in processItem:\", {\n error: err,\n workerId,\n id: queueItem.id,\n job: queueItem.job,\n });\n }\n );\n }\n }\n } catch (error) {\n this.logger.error(\"Error dequeuing items:\", { name: this.options.name, error });\n await Worker.delay(pollIntervalMs);\n continue;\n }\n\n // 5. If we found items or have pending batch items, poll quickly\n if (itemsFound || this.batchAccumulators.size > 0) {\n await Worker.delay(immediatePollIntervalMs);\n } else {\n await Worker.delay(pollIntervalMs);\n }\n }\n\n // On shutdown, flush all remaining batch accumulators\n await this.flushAllBatches(workerId, limiter);\n\n this.logger.info(\"Worker loop finished\", { workerId });\n }\n\n /**\n * Adds an item to the batch accumulator for its job type.\n */\n private addToAccumulator(item: AnyQueueItem): void {\n let accumulator = this.batchAccumulators.get(item.job);\n if (!accumulator) {\n accumulator = { items: [], firstItemAt: Date.now() };\n this.batchAccumulators.set(item.job, accumulator);\n }\n accumulator.items.push(item);\n }\n\n /**\n * Flushes any batch accumulators that have exceeded their maxWaitMs.\n */\n private async flushTimedOutBatches(\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n const now = Date.now();\n for (const [jobType, accumulator] of this.batchAccumulators) {\n const batchConfig = this.getBatchConfig(jobType);\n if (!batchConfig) continue;\n\n if (now - accumulator.firstItemAt >= batchConfig.maxWaitMs) {\n await this.flushBatch(jobType, workerId, limiter);\n }\n }\n }\n\n /**\n * Flushes all batch accumulators (used during shutdown).\n */\n private async flushAllBatches(\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n for (const jobType of this.batchAccumulators.keys()) {\n await this.flushBatch(jobType, workerId, limiter);\n }\n }\n\n /**\n * Flushes the batch accumulator for a specific job type.\n * Removes items from the accumulator and submits them to the limiter as a single batch.\n */\n private async flushBatch(\n jobType: string,\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n const accumulator = this.batchAccumulators.get(jobType);\n if (!accumulator || accumulator.items.length === 0) return;\n\n const items = accumulator.items;\n this.batchAccumulators.delete(jobType);\n\n this.logger.debug(\"Flushing batch\", {\n jobType,\n batchSize: items.length,\n workerId,\n accumulatedMs: Date.now() - accumulator.firstItemAt,\n });\n\n limiter(() => this.processBatch(items, jobType, workerId, limiter)).catch((err) => {\n this.logger.error(\"Unhandled error in processBatch:\", {\n error: err,\n workerId,\n jobType,\n batchSize: items.length,\n });\n });\n }\n\n /**\n * Processes a batch of items for a batch-enabled job type.\n */\n private async processBatch(\n items: AnyQueueItem[],\n jobType: string,\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n const catalogItem = this.options.catalog[jobType as any];\n const handler = this.jobs[jobType as any] as\n | ((items: Array<JobHandlerParams<TCatalog, any>>) => Promise<void>)\n | undefined;\n\n if (!handler) {\n this.logger.error(`Worker no handler found for batch job type: ${jobType}`);\n return;\n }\n\n if (!catalogItem) {\n this.logger.error(`Worker no catalog item found for batch job type: ${jobType}`);\n return;\n }\n\n const batchParams = items.map((item) => ({\n id: item.id,\n payload: item.item,\n visibilityTimeoutMs: item.visibilityTimeoutMs,\n attempt: item.attempt,\n deduplicationKey: item.deduplicationKey,\n }));\n\n await startSpan(\n this.tracer,\n \"processBatch\",\n async () => {\n await this.withHistogram(this.metrics.jobDuration, handler(batchParams), {\n worker_id: workerId,\n batch_size: items.length,\n job_type: jobType,\n });\n\n // On success, acknowledge all items individually.\n await Promise.all(items.map((item) => this.queue.ack(item.id, item.deduplicationKey)));\n },\n {\n kind: SpanKind.CONSUMER,\n attributes: {\n job_type: jobType,\n batch_size: items.length,\n worker_id: workerId,\n worker_name: this.options.name,\n },\n }\n ).catch(async (error) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const shouldLogError = catalogItem.logErrors ?? true;\n const errorLogLevel =\n error && typeof error === \"object\" && \"logLevel\" in error ? error.logLevel : undefined;\n\n const logAttributes = {\n name: this.options.name,\n jobType,\n batchSize: items.length,\n error,\n errorMessage,\n };\n\n if (!shouldLogError) {\n this.logger.info(`Worker failed to process batch`, logAttributes);\n } else if (errorLogLevel === \"warn\") {\n this.logger.warn(`Worker error processing batch`, logAttributes);\n } else if (errorLogLevel === \"info\") {\n this.logger.info(`Worker error processing batch`, logAttributes);\n } else {\n this.logger.error(`Worker error processing batch`, logAttributes);\n }\n\n // Re-enqueue each item individually with retry logic\n for (const item of items) {\n try {\n const newAttempt = item.attempt + 1;\n const retrySettings = {\n ...defaultRetrySettings,\n ...catalogItem?.retry,\n };\n const retryDelay = calculateNextRetryDelay(retrySettings, newAttempt);\n\n if (!retryDelay) {\n const dlqLogAttributes = {\n name: this.options.name,\n id: item.id,\n jobType,\n attempt: newAttempt,\n };\n\n if (!shouldLogError) {\n this.logger.info(\n `Worker batch item reached max attempts. Moving to DLQ.`,\n dlqLogAttributes\n );\n } else if (errorLogLevel === \"warn\") {\n this.logger.warn(\n `Worker batch item reached max attempts. Moving to DLQ.`,\n dlqLogAttributes\n );\n } else if (errorLogLevel === \"info\") {\n this.logger.info(\n `Worker batch item reached max attempts. Moving to DLQ.`,\n dlqLogAttributes\n );\n } else {\n this.logger.error(\n `Worker batch item reached max attempts. Moving to DLQ.`,\n dlqLogAttributes\n );\n }\n\n const moved = await this.queue.moveToDeadLetterQueue(\n item.id,\n errorMessage,\n item.deduplicationKey\n );\n if (!moved) this.#logSuperseded(\"dead-letter\", item.id, jobType);\n continue;\n }\n\n const retryDate = new Date(Date.now() + retryDelay);\n this.logger.info(`Worker requeuing failed batch item with delay`, {\n name: this.options.name,\n id: item.id,\n jobType,\n retryDate,\n retryDelay,\n attempt: newAttempt,\n });\n\n const requeued = await this.queue.requeue({\n id: item.id,\n job: item.job,\n item: item.item,\n availableAt: retryDate,\n attempt: newAttempt,\n visibilityTimeoutMs: item.visibilityTimeoutMs,\n deduplicationKey: item.deduplicationKey,\n });\n if (!requeued) this.#logSuperseded(\"retry\", item.id, jobType);\n } catch (requeueError) {\n this.logger.error(\n `Worker failed to requeue batch item. It will be retried after the visibility timeout.`,\n {\n name: this.options.name,\n id: item.id,\n jobType,\n visibilityTimeoutMs: item.visibilityTimeoutMs,\n error: requeueError,\n }\n );\n }\n }\n });\n }\n\n /**\n * Processes a single item.\n */\n // The failed attempt's item was replaced by a newer enqueue, or removed (acked or cancelled),\n // while it ran, so its retry or DLQ move was skipped and the newer item is left to run.\n #logSuperseded(action: \"retry\" | \"dead-letter\", id: string, job: string) {\n this.logger.info(`Worker skipped ${action} for an item replaced or removed while it ran`, {\n name: this.options.name,\n id,\n job,\n });\n }\n\n private async processItem(\n { id, job, item, visibilityTimeoutMs, attempt, timestamp, deduplicationKey }: AnyQueueItem,\n batchSize: number,\n workerId: string,\n limiter: ReturnType<typeof pLimit>\n ): Promise<void> {\n const catalogItem = this.options.catalog[job as any];\n // processItem is only called for non-batch jobs, so the handler takes a single param\n const handler = this.jobs[job as any] as\n | ((params: JobHandlerParams<TCatalog, any>) => Promise<void>)\n | undefined;\n if (!handler) {\n this.logger.error(`Worker no handler found for job type: ${job}`);\n return;\n }\n\n if (!catalogItem) {\n this.logger.error(`Worker no catalog item found for job type: ${job}`);\n return;\n }\n\n await startSpan(\n this.tracer,\n \"processItem\",\n async () => {\n await this.withHistogram(\n this.metrics.jobDuration,\n handler({ id, payload: item, visibilityTimeoutMs, attempt, deduplicationKey }),\n {\n worker_id: workerId,\n batch_size: batchSize,\n job_type: job,\n attempt,\n }\n );\n\n // On success, acknowledge the item.\n await this.queue.ack(id, deduplicationKey);\n\n if (catalogItem.cron) {\n await this.rescheduleCronJob(job, catalogItem, item);\n }\n },\n {\n kind: SpanKind.CONSUMER,\n attributes: {\n job_id: id,\n job_type: job,\n attempt,\n job_timestamp: timestamp.getTime(),\n job_age_in_ms: Date.now() - timestamp.getTime(),\n worker_id: workerId,\n worker_limit_concurrency: limiter.concurrency,\n worker_limit_active: limiter.activeCount,\n worker_limit_pending: limiter.pendingCount,\n worker_name: this.options.name,\n batch_size: batchSize,\n },\n }\n ).catch(async (error) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n const shouldLogError = catalogItem.logErrors ?? true;\n const errorLogLevel =\n error && typeof error === \"object\" && \"logLevel\" in error ? error.logLevel : undefined;\n\n // Never include the raw item/payload here: it is job data that may be\n // customer-controlled. It is retrievable via `getJob(id)` if needed for triage.\n const logAttributes = {\n name: this.options.name,\n id,\n job,\n visibilityTimeoutMs,\n error,\n errorMessage,\n };\n\n if (!shouldLogError) {\n this.logger.info(`Worker failed to process item`, logAttributes);\n } else if (errorLogLevel === \"warn\") {\n this.logger.warn(`Worker error processing item`, logAttributes);\n } else if (errorLogLevel === \"info\") {\n this.logger.info(`Worker error processing item`, logAttributes);\n } else {\n this.logger.error(`Worker error processing item`, logAttributes);\n }\n\n // Attempt requeue logic.\n try {\n const newAttempt = attempt + 1;\n const retrySettings = {\n ...defaultRetrySettings,\n ...catalogItem?.retry,\n };\n const retryDelay = calculateNextRetryDelay(retrySettings, newAttempt);\n\n if (!retryDelay) {\n if (!shouldLogError || errorLogLevel === \"info\") {\n this.logger.info(`Worker item reached max attempts. Moving to DLQ.`, {\n ...logAttributes,\n attempt: newAttempt,\n });\n } else if (errorLogLevel === \"warn\") {\n this.logger.warn(`Worker item reached max attempts. Moving to DLQ.`, {\n ...logAttributes,\n attempt: newAttempt,\n });\n } else {\n this.logger.error(`Worker item reached max attempts. Moving to DLQ.`, {\n ...logAttributes,\n attempt: newAttempt,\n });\n }\n\n const moved = await this.queue.moveToDeadLetterQueue(id, errorMessage, deduplicationKey);\n if (!moved) this.#logSuperseded(\"dead-letter\", id, job);\n\n if (catalogItem.cron) {\n await this.rescheduleCronJob(job, catalogItem, item);\n }\n\n return;\n }\n\n const retryDate = new Date(Date.now() + retryDelay);\n this.logger.info(`Worker requeuing failed item with delay`, {\n name: this.options.name,\n id,\n job,\n retryDate,\n retryDelay,\n visibilityTimeoutMs,\n attempt: newAttempt,\n });\n const requeued = await this.queue.requeue({\n id,\n job,\n item,\n availableAt: retryDate,\n attempt: newAttempt,\n visibilityTimeoutMs,\n deduplicationKey,\n });\n if (!requeued) this.#logSuperseded(\"retry\", id, job);\n } catch (requeueError) {\n this.logger.error(\n `Worker failed to requeue item. It will be retried after the visibility timeout.`,\n {\n name: this.options.name,\n id,\n job,\n visibilityTimeoutMs,\n error: requeueError,\n }\n );\n }\n });\n }\n\n private async withHistogram<T>(\n histogram: Histogram | undefined,\n promise: Promise<T>,\n labels?: Record<string, string | number>\n ): Promise<T> {\n if (!histogram) {\n return promise;\n }\n\n const start = Date.now();\n try {\n return await promise;\n } finally {\n const duration = (Date.now() - start) / 1000; // Convert to seconds\n histogram.record(duration, { worker_name: this.options.name, ...labels });\n }\n }\n\n // A simple helper to delay for a given number of milliseconds.\n private static delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private setupCron() {\n const cronJobs = Object.entries(this.options.catalog).filter(([_, value]) => value.cron);\n\n if (cronJobs.length === 0) {\n return;\n }\n\n this.logger.info(\"Setting up cron jobs\", {\n cronJobs: cronJobs.map(([job, value]) => ({\n job,\n cron: value.cron,\n jitterInMs: value.jitterInMs,\n })),\n });\n\n // For each cron job, we need to try and enqueue a job with the next timestamp of the cron job.\n const enqueuePromises = cronJobs.map(([job, value]) =>\n this.enqueueCronJob(value.cron!, job, value.jitterInMs)\n );\n\n Promise.allSettled(enqueuePromises).then((results) => {\n results.forEach((result) => {\n if (result.status === \"fulfilled\") {\n this.logger.debug(\"Enqueued cron job\", { result: result.value });\n } else {\n this.logger.error(\"Failed to enqueue cron job\", { reason: result.reason });\n }\n });\n });\n }\n\n private async enqueueCronJob(cron: string, job: string, jitter?: number, lastTimestamp?: Date) {\n const scheduledAt = this.calculateNextScheduledAt(cron, lastTimestamp);\n const identifier = [job, this.timestampIdentifier(scheduledAt)].join(\":\");\n // Calculate the availableAt date by calculating a random number between -jitter/2 and jitter/2 and adding it to the scheduledAt\n const appliedJitter = typeof jitter === \"number\" ? Math.random() * jitter - jitter / 2 : 0;\n const availableAt = new Date(scheduledAt.getTime() + appliedJitter);\n\n const enqueued = await this.enqueueOnce({\n id: identifier,\n job,\n // job is a runtime string here, so K widens and the payload can't match a\n // single catalog entry statically; the shape is correct for the cron job.\n payload: {\n timestamp: scheduledAt.getTime(),\n lastTimestamp: lastTimestamp?.getTime(),\n cron,\n } as inferZodSchemaOutput<TCatalog[string][\"schema\"]>,\n availableAt,\n });\n\n this.logger.debug(\"Enqueued cron job\", {\n identifier,\n cron,\n job,\n scheduledAt,\n enqueued,\n availableAt,\n appliedJitter,\n jitter,\n });\n\n return {\n identifier,\n cron,\n job,\n scheduledAt,\n enqueued,\n };\n }\n\n private async rescheduleCronJob(job: string, catalogItem: WorkerCatalogItem, item: CronSchema) {\n if (!catalogItem.cron) {\n return;\n }\n\n return this.enqueueCronJob(\n catalogItem.cron,\n job,\n catalogItem.jitterInMs,\n new Date(item.timestamp)\n );\n }\n\n private calculateNextScheduledAt(cron: string, lastTimestamp?: Date): Date {\n const scheduledAt = cronParser\n .parseExpression(cron, {\n currentDate: lastTimestamp,\n })\n .next()\n .toDate();\n\n // If scheduledAt is in the past, we should just calculate the next one based on the current time\n if (scheduledAt < new Date()) {\n return this.calculateNextScheduledAt(cron);\n }\n\n return scheduledAt;\n }\n\n private timestampIdentifier(timestamp: Date) {\n const year = timestamp.getUTCFullYear();\n const month = timestamp.getUTCMonth();\n const day = timestamp.getUTCDate();\n const hour = timestamp.getUTCHours();\n const minute = timestamp.getUTCMinutes();\n const second = timestamp.getUTCSeconds();\n\n return `${year}-${month}-${day}-${hour}-${minute}-${second}`;\n }\n\n private setupSubscriber() {\n const channel = `${this.options.name}:redrive`;\n this.subscriber?.subscribe(channel, (err) => {\n if (err) {\n this.logger.error(`Failed to subscribe to ${channel}`, { error: err });\n } else {\n this.logger.debug(`Subscribed to ${channel}`);\n }\n });\n\n this.subscriber?.on(\"message\", this.handleRedriveMessage.bind(this));\n }\n\n private async handleRedriveMessage(channel: string, message: string) {\n try {\n const { id } = JSON.parse(message) as any;\n if (typeof id !== \"string\") {\n throw new Error(\"Invalid message format: id must be a string\");\n }\n await this.withHistogram(\n this.metrics.redriveDuration,\n this.queue.redriveFromDeadLetterQueue(id)\n );\n this.logger.log(`Redrived item ${id} from Dead Letter Queue`);\n } catch (error) {\n this.logger.error(\"Error processing redrive message\", { error, message });\n }\n }\n\n private setupShutdownHandlers() {\n shutdownManager.register(`redis-worker:${this.options.name}`, this.shutdown.bind(this));\n }\n\n private async shutdown(signal?: NodeJS.Signals) {\n if (this.isShuttingDown) {\n this.logger.log(\"Worker already shutting down\", { signal });\n return;\n }\n\n this.isShuttingDown = true;\n this.logger.log(\"Shutting down worker loops...\", { signal });\n\n // Wait for all worker loops to finish, retaining ownership of the deadline timer so the\n // losing timeout cannot keep the process alive after a prompt shutdown.\n let shutdownDeadline: ReturnType<typeof setTimeout> | undefined;\n const deadlinePromise = new Promise<void>((resolve) => {\n shutdownDeadline = setTimeout(() => {\n this.logger.error(\"Worker shutdown timed out\", {\n signal,\n shutdownTimeoutMs: this.shutdownTimeoutMs,\n });\n resolve();\n }, this.shutdownTimeoutMs);\n });\n\n try {\n await Promise.race([Promise.all(this.workerLoops), deadlinePromise]);\n } finally {\n if (shutdownDeadline) {\n clearTimeout(shutdownDeadline);\n }\n }\n\n await this.subscriber?.unsubscribe();\n await this.subscriber?.quit();\n await this.queue.close();\n this.logger.log(\"All workers and subscribers shut down.\", { signal });\n }\n\n public async stop() {\n shutdownManager.unregister(`redis-worker:${this.options.name}`);\n await this.shutdown();\n }\n}\n\nexport { Worker };\n","/**\n * Check if an error is an AbortError.\n *\n * This handles both:\n * - Custom abort errors created with `new Error(\"AbortError\")` (sets .message)\n * - Native Node.js AbortError from timers/promises (sets .name)\n */\nexport function isAbortError(error: unknown): boolean {\n return error instanceof Error && (error.name === \"AbortError\" || error.message === \"AbortError\");\n}\n","import {\n Cluster,\n createRedisClient,\n createRedisClusterClient,\n type RedisClient,\n type RedisClusterClientOptions,\n type RedisOptions,\n} from \"@internal/redis\";\n\n/**\n * Where a fair queue keeps its state: one Redis node, or a cluster. A cluster only works with a key\n * producer that keeps every key a script touches in one slot, such as\n * `TenantShardedFairQueueKeyProducer`. The cluster's key prefix goes in `clusterOptions.keyPrefix`.\n */\nexport type FairQueueRedisOptions = RedisOptions | { cluster: RedisClusterClientOptions };\n\nexport function isClusterConnection(\n options: FairQueueRedisOptions\n): options is { cluster: RedisClusterClientOptions } {\n return \"cluster\" in options && options.cluster !== undefined;\n}\n\nexport function createFairQueueRedisClient(options: FairQueueRedisOptions): RedisClient {\n return isClusterConnection(options)\n ? createRedisClusterClient(options.cluster)\n : createRedisClient(options);\n}\n\nexport function keyPrefixOf(options: FairQueueRedisOptions): string {\n return isClusterConnection(options)\n ? (options.cluster.clusterOptions?.keyPrefix ?? \"\")\n : (options.keyPrefix ?? \"\");\n}\n\n/**\n * Every key matching `pattern` (which must include the key prefix), page by page. A cluster doesn't\n * fan SCAN out to its nodes, so this scans each primary in turn.\n */\nexport async function* scanKeys(\n client: RedisClient,\n pattern: string,\n count = 1000\n): AsyncGenerator<string[]> {\n const nodes = client instanceof Cluster ? client.nodes(\"master\") : [client];\n for (const node of nodes) {\n let cursor = \"0\";\n do {\n const [next, keys] = await node.scan(cursor, \"MATCH\", pattern, \"COUNT\", count);\n cursor = next;\n if (keys.length > 0) yield keys;\n } while (cursor !== \"0\");\n }\n}\n","import type { RedisClient } from \"@internal/redis\";\nimport {\n createFairQueueRedisClient,\n keyPrefixOf,\n scanKeys,\n type FairQueueRedisOptions,\n} from \"./connection.js\";\nimport type {\n ConcurrencyCheckResult,\n ConcurrencyGroupConfig,\n ConcurrencyState,\n FairQueueKeyProducer,\n QueueDescriptor,\n} from \"./types.js\";\n\n/**\n * Page size for iterating a concurrency set's members (SSCAN COUNT) and cap on how many\n * members one sweep script invocation checks, bounding both the snapshot reads and the\n * time the atomic Lua script can hold up Redis when a set has accumulated many leaked\n * members.\n */\nconst SWEEP_MEMBER_CHUNK_SIZE = 500;\n\nexport interface ConcurrencyManagerOptions {\n redis: FairQueueRedisOptions;\n keys: FairQueueKeyProducer;\n groups: ConcurrencyGroupConfig[];\n logger?: {\n debug: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n };\n}\n\n/**\n * ConcurrencyManager handles multi-level concurrency tracking and limiting.\n *\n * Features:\n * - Multiple concurrent concurrency groups (tenant, org, project, etc.)\n * - Atomic reserve/release operations using Lua scripts\n * - Efficient batch checking of all groups\n */\nexport class ConcurrencyManager {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private groups: ConcurrencyGroupConfig[];\n private groupsByName: Map<string, ConcurrencyGroupConfig>;\n private logger: NonNullable<ConcurrencyManagerOptions[\"logger\"]>;\n\n constructor(private options: ConcurrencyManagerOptions) {\n this.redis = createFairQueueRedisClient(options.redis);\n this.keys = options.keys;\n this.groups = options.groups;\n this.groupsByName = new Map(options.groups.map((g) => [g.name, g]));\n this.logger = options.logger ?? {\n debug: () => {},\n error: () => {},\n };\n\n this.#registerCommands();\n }\n\n // ============================================================================\n // Public Methods\n // ============================================================================\n\n /**\n * Check if a message can be processed given all concurrency constraints.\n * Checks all configured groups and returns the first one at capacity.\n */\n async canProcess(queue: QueueDescriptor): Promise<ConcurrencyCheckResult> {\n for (const group of this.groups) {\n const groupId = group.extractGroupId(queue);\n const isAtCapacity = await this.isAtCapacity(group.name, groupId);\n\n if (isAtCapacity) {\n const state = await this.getState(group.name, groupId);\n return {\n allowed: false,\n blockedBy: state,\n };\n }\n }\n\n return { allowed: true };\n }\n\n /**\n * Reserve concurrency slots for a message across all groups.\n * Atomic - either all groups are reserved or none.\n *\n * @returns true if reservation successful, false if any group is at capacity\n */\n async reserve(queue: QueueDescriptor, messageId: string): Promise<boolean> {\n // Build list of group keys and limits\n const groupData = await Promise.all(\n this.groups.map(async (group) => {\n const groupId = group.extractGroupId(queue);\n const limit = await group.getLimit(groupId);\n return {\n key: this.keys.concurrencyKey(group.name, groupId),\n limit: limit || group.defaultLimit,\n };\n })\n );\n\n // Use Lua script for atomic multi-group reservation\n // Pass keys as KEYS array so ioredis applies keyPrefix correctly\n const keys = groupData.map((g) => g.key);\n const limits = groupData.map((g) => g.limit.toString());\n\n // Args order: messageId, ...limits (keys are passed separately)\n const result = await this.redis.reserveConcurrency(keys.length, keys, messageId, ...limits);\n\n return result === 1;\n }\n\n /**\n * Release concurrency slots for a message across all groups.\n */\n async release(queue: QueueDescriptor, messageId: string): Promise<void> {\n const pipeline = this.redis.pipeline();\n\n for (const group of this.groups) {\n const groupId = group.extractGroupId(queue);\n const key = this.keys.concurrencyKey(group.name, groupId);\n pipeline.srem(key, messageId);\n }\n\n this.#assertPipelineSucceeded(await pipeline.exec(), 1);\n }\n\n /**\n * Throw if any command in a released pipeline failed. ioredis resolves `exec()` even when\n * individual commands error, so an unchecked pipeline reports success while leaving the\n * slot held, which strands it permanently once the caller drops the in-flight record.\n */\n #assertPipelineSucceeded(\n results: Array<[Error | null, unknown]> | null,\n messageCount: number\n ): void {\n if (results === null) {\n throw new Error(\n `Concurrency release pipeline for ${messageCount} message(s) was discarded without executing`\n );\n }\n\n const errors = results\n .map(([error]) => error)\n .filter((error): error is Error => Boolean(error));\n\n if (errors.length > 0) {\n throw new Error(\n `Failed to release ${errors.length} of ${\n results?.length ?? 0\n } concurrency slot commands across ${messageCount} message(s): ${errors\n .map((error) => error.message)\n .join(\"; \")}`\n );\n }\n }\n\n /**\n * Release concurrency slots for multiple messages in a single pipeline.\n * More efficient than calling release() multiple times.\n */\n async releaseBatch(\n messages: Array<{ queue: QueueDescriptor; messageId: string }>\n ): Promise<void> {\n if (messages.length === 0) {\n return;\n }\n\n const pipeline = this.redis.pipeline();\n\n for (const { queue, messageId } of messages) {\n for (const group of this.groups) {\n const groupId = group.extractGroupId(queue);\n const key = this.keys.concurrencyKey(group.name, groupId);\n pipeline.srem(key, messageId);\n }\n }\n\n this.#assertPipelineSucceeded(await pipeline.exec(), messages.length);\n }\n\n /**\n * Remove concurrency set members that no longer correspond to an in-flight message,\n * healing slots leaked by failed releases. Scans every set of every group and, per\n * member, atomically removes it unless the message id appears in one of the given\n * in-flight data hashes. Sound because a message is registered in-flight before its\n * slot is reserved, so at the moment of the atomic check a member with no in-flight\n * record can only be a leak; if the message is about to be re-claimed, reserve simply\n * re-adds the member.\n *\n * With a tenant-sharded key producer, each shard's sets are checked against that shard's\n * in-flight data only, so the check stays in one cluster slot.\n *\n * @param inflightDataKeys - The in-flight data hash keys for every shard, in shard order. The sweep\n * refuses to run when this is empty, since with nowhere to look for running messages\n * every member would look orphaned and all concurrency accounting would be erased.\n * @returns The message ids that were removed, and how many sets were checked\n */\n async sweepOrphanedSlots(\n inflightDataKeys: string[]\n ): Promise<{ scannedSets: number; removed: string[] }> {\n if (inflightDataKeys.length === 0) {\n this.logger.error(\n \"Refusing to sweep concurrency slots without any in-flight data keys: every member would look orphaned and all concurrency accounting would be erased\"\n );\n return { scannedSets: 0, removed: [] };\n }\n\n const keyPrefix = keyPrefixOf(this.options.redis);\n let scannedSets = 0;\n const removed: string[] = [];\n\n for (const scope of this.#sweepScopes(inflightDataKeys)) {\n for await (const foundKeys of scanKeys(this.redis, `${keyPrefix}${scope.pattern}`)) {\n for (const fullKey of foundKeys) {\n const key =\n keyPrefix && fullKey.startsWith(keyPrefix) ? fullKey.slice(keyPrefix.length) : fullKey;\n\n try {\n let sawMembers = false;\n let memberCursor = \"0\";\n\n do {\n const [nextMemberCursor, page] = await this.redis.sscan(\n key,\n memberCursor,\n \"COUNT\",\n SWEEP_MEMBER_CHUNK_SIZE\n );\n memberCursor = nextMemberCursor;\n\n if (page.length === 0) {\n continue;\n }\n sawMembers = true;\n\n for (let i = 0; i < page.length; i += SWEEP_MEMBER_CHUNK_SIZE) {\n const chunk = page.slice(i, i + SWEEP_MEMBER_CHUNK_SIZE);\n const removedIds = await this.redis.removeOrphanedConcurrencySlots(\n 1 + scope.inflightDataKeys.length,\n [key, ...scope.inflightDataKeys],\n ...chunk\n );\n removed.push(...removedIds);\n }\n } while (memberCursor !== \"0\");\n\n if (sawMembers) {\n scannedSets++;\n }\n } catch (error) {\n this.logger.error(\"Failed to sweep concurrency set, skipping it\", {\n key,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n }\n\n return { scannedSets, removed };\n }\n\n #sweepScopes(inflightDataKeys: string[]): Array<{ pattern: string; inflightDataKeys: string[] }> {\n const keys = this.keys;\n if (keys.tenantShard && keys.concurrencyKeyPattern) {\n return this.groups.flatMap((group) =>\n inflightDataKeys.map((inflightDataKey, shardId) => ({\n pattern: keys.concurrencyKeyPattern!(group.name, shardId),\n inflightDataKeys: [inflightDataKey],\n }))\n );\n }\n return this.groups.map((group) => ({\n pattern: keys.concurrencyKey(group.name, \"*\"),\n inflightDataKeys,\n }));\n }\n\n /**\n * Get current concurrency for a specific group.\n */\n async getCurrentConcurrency(groupName: string, groupId: string): Promise<number> {\n const key = this.keys.concurrencyKey(groupName, groupId);\n return await this.redis.scard(key);\n }\n\n /**\n * Get available capacity for a queue across all concurrency groups.\n * Returns the minimum available capacity across all groups.\n */\n async getAvailableCapacity(queue: QueueDescriptor): Promise<number> {\n if (this.groups.length === 0) {\n return 0;\n }\n\n // Build group data for parallel fetching\n const groupData = this.groups.map((group) => ({\n group,\n groupId: group.extractGroupId(queue),\n }));\n\n // Fetch all current counts and limits in parallel\n const [currents, limits] = await Promise.all([\n Promise.all(\n groupData.map(({ group, groupId }) =>\n this.redis.scard(this.keys.concurrencyKey(group.name, groupId))\n )\n ),\n Promise.all(\n groupData.map(({ group, groupId }) =>\n group.getLimit(groupId).then((limit) => limit || group.defaultLimit)\n )\n ),\n ]);\n\n // Calculate minimum available capacity across all groups\n let minCapacity = Infinity;\n for (let i = 0; i < groupData.length; i++) {\n const available = Math.max(0, limits[i]! - currents[i]!);\n minCapacity = Math.min(minCapacity, available);\n }\n\n return minCapacity === Infinity ? 0 : minCapacity;\n }\n\n /**\n * Get concurrency limit for a specific group.\n */\n async getConcurrencyLimit(groupName: string, groupId: string): Promise<number> {\n const group = this.groupsByName.get(groupName);\n if (!group) {\n throw new Error(`Unknown concurrency group: ${groupName}`);\n }\n return (await group.getLimit(groupId)) || group.defaultLimit;\n }\n\n /**\n * Check if a group is at capacity.\n */\n async isAtCapacity(groupName: string, groupId: string): Promise<boolean> {\n const [current, limit] = await Promise.all([\n this.getCurrentConcurrency(groupName, groupId),\n this.getConcurrencyLimit(groupName, groupId),\n ]);\n return current >= limit;\n }\n\n /**\n * Get full state for a group.\n */\n async getState(groupName: string, groupId: string): Promise<ConcurrencyState> {\n const [current, limit] = await Promise.all([\n this.getCurrentConcurrency(groupName, groupId),\n this.getConcurrencyLimit(groupName, groupId),\n ]);\n return {\n groupName,\n groupId,\n current,\n limit,\n };\n }\n\n /**\n * Get all active message IDs for a group.\n */\n async getActiveMessages(groupName: string, groupId: string): Promise<string[]> {\n const key = this.keys.concurrencyKey(groupName, groupId);\n return await this.redis.smembers(key);\n }\n\n /**\n * Force-clear concurrency for a group (use with caution).\n * Useful for cleanup after crashes.\n */\n async clearGroup(groupName: string, groupId: string): Promise<void> {\n const key = this.keys.concurrencyKey(groupName, groupId);\n await this.redis.del(key);\n }\n\n /**\n * Remove a specific message from concurrency tracking.\n * Useful for cleanup.\n */\n async removeMessage(messageId: string, queue: QueueDescriptor): Promise<void> {\n await this.release(queue, messageId);\n }\n\n /**\n * Get configured group names.\n */\n getGroupNames(): string[] {\n return this.groups.map((g) => g.name);\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n #registerCommands(): void {\n // Atomic multi-group reservation\n // KEYS: concurrency set keys for each group (keyPrefix is applied by ioredis)\n // ARGV[1]: messageId\n // ARGV[2..n]: limits for each group (in same order as KEYS)\n this.redis.defineCommand(\"reserveConcurrency\", {\n lua: `\nlocal numGroups = #KEYS\nlocal messageId = ARGV[1]\n\n-- Check all groups first. A message that is already a member of a group's set passes\n-- that group's check: re-admitting it does not increase concurrency (SADD is a no-op),\n-- and counting its own leftover slot against it would let a message whose earlier\n-- release failed block its own retry forever.\nfor i = 1, numGroups do\n local key = KEYS[i]\n local limit = tonumber(ARGV[1 + i]) -- Limits start at ARGV[2]\n\n if redis.call('SISMEMBER', key, messageId) == 0 then\n local current = redis.call('SCARD', key)\n\n if current >= limit then\n return 0 -- At capacity\n end\n end\nend\n\n-- All groups have capacity, add message to all\nfor i = 1, numGroups do\n local key = KEYS[i]\n redis.call('SADD', key, messageId)\nend\n\nreturn 1\n `,\n });\n\n // Atomic orphan sweep for one concurrency set\n // KEYS[1]: concurrency set key\n // KEYS[2..n]: in-flight data hash keys for every shard\n // ARGV: candidate messageIds (a snapshot of the set's members)\n this.redis.defineCommand(\"removeOrphanedConcurrencySlots\", {\n lua: `\nlocal concurrencyKey = KEYS[1]\nlocal removedIds = {}\n\nfor i = 1, #ARGV do\n local messageId = ARGV[i]\n local inflight = false\n\n for j = 2, #KEYS do\n if redis.call('HEXISTS', KEYS[j], messageId) == 1 then\n inflight = true\n break\n end\n end\n\n if not inflight then\n if redis.call('SREM', concurrencyKey, messageId) == 1 then\n table.insert(removedIds, messageId)\n end\n end\nend\n\nreturn removedIds\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n reserveConcurrency(\n numKeys: number,\n keys: string[],\n messageId: string,\n ...limits: string[]\n ): Promise<number>;\n\n removeOrphanedConcurrencySlots(\n numKeys: number,\n keys: string[],\n ...messageIds: string[]\n ): Promise<string[]>;\n }\n}\n","import type { RedisClient } from \"@internal/redis\";\nimport { createFairQueueRedisClient, type FairQueueRedisOptions } from \"./connection.js\";\nimport { jumpHash } from \"@trigger.dev/core/v3/serverOnly\";\nimport type { FairQueueKeyProducer, QueueWithScore } from \"./types.js\";\n\nexport interface MasterQueueOptions {\n redis: FairQueueRedisOptions;\n keys: FairQueueKeyProducer;\n shardCount: number;\n}\n\n/**\n * Master queue manages the top-level queue of queues.\n *\n * Features:\n * - Sharding for horizontal scaling\n * - Consistent hashing for queue-to-shard assignment\n * - Queues scored by oldest message timestamp\n */\nexport class MasterQueue {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private shardCount: number;\n\n constructor(private options: MasterQueueOptions) {\n this.redis = createFairQueueRedisClient(options.redis);\n this.keys = options.keys;\n this.shardCount = Math.max(1, options.shardCount);\n\n this.#registerCommands();\n }\n\n // ============================================================================\n // Public Methods\n // ============================================================================\n\n /**\n * Get the shard ID for a queue.\n * Uses consistent hashing based on queue ID.\n */\n getShardForQueue(queueId: string): number {\n return this.#hashToShard(queueId);\n }\n\n /**\n * Add a queue to its master queue shard.\n * Updates the score to the oldest message timestamp.\n *\n * @param queueId - The queue identifier\n * @param oldestMessageTimestamp - Timestamp of the oldest message in the queue\n */\n async addQueue(queueId: string, oldestMessageTimestamp: number): Promise<void> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n // Just use plain ZADD - it will add if not exists, or update if exists\n // The score represents the oldest message timestamp\n // We rely on the enqueue Lua scripts to set the correct score\n await this.redis.zadd(masterKey, oldestMessageTimestamp, queueId);\n }\n\n /**\n * Update a queue's score in the master queue.\n * This is typically called after dequeuing to update to the new oldest message.\n *\n * @param queueId - The queue identifier\n * @param newOldestTimestamp - New timestamp of the oldest message\n */\n async updateQueueScore(queueId: string, newOldestTimestamp: number): Promise<void> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n await this.redis.zadd(masterKey, newOldestTimestamp, queueId);\n }\n\n /**\n * Remove a queue from its master queue shard.\n * Called when a queue becomes empty.\n *\n * @param queueId - The queue identifier\n */\n async removeQueue(queueId: string): Promise<void> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n await this.redis.zrem(masterKey, queueId);\n }\n\n /**\n * Get queues from a shard, ordered by oldest message (lowest score first).\n *\n * @param shardId - The shard to query\n * @param limit - Maximum number of queues to return (default: 1000)\n * @param maxScore - Maximum score (timestamp) to include (default: now)\n */\n async getQueuesFromShard(\n shardId: number,\n limit: number = 1000,\n maxScore?: number\n ): Promise<QueueWithScore[]> {\n const masterKey = this.keys.masterQueueKey(shardId);\n const score = maxScore ?? Date.now();\n\n // Get queues with scores up to maxScore\n const results = await this.redis.zrangebyscore(\n masterKey,\n \"-inf\",\n score,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n limit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId: this.keys.extractTenantId(queueId),\n });\n }\n }\n\n return queues;\n }\n\n /**\n * Get the number of queues in a shard.\n */\n async getShardQueueCount(shardId: number): Promise<number> {\n const masterKey = this.keys.masterQueueKey(shardId);\n return await this.redis.zcard(masterKey);\n }\n\n /**\n * Get total queue count across all shards.\n */\n async getTotalQueueCount(): Promise<number> {\n const counts = await Promise.all(\n Array.from({ length: this.shardCount }, (_, i) => this.getShardQueueCount(i))\n );\n return counts.reduce((sum, count) => sum + count, 0);\n }\n\n /**\n * Atomically add a queue to master queue only if queue has messages.\n * Uses Lua script for atomicity.\n *\n * @param queueId - The queue identifier\n * @param queueKey - The actual queue sorted set key\n * @returns Whether the queue was added to the master queue\n */\n async addQueueIfNotEmpty(queueId: string, queueKey: string): Promise<boolean> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n const result = await this.redis.addQueueIfNotEmpty(masterKey, queueKey, queueId);\n return result === 1;\n }\n\n /**\n * Atomically remove a queue from master queue only if queue is empty.\n * Uses Lua script for atomicity.\n *\n * @param queueId - The queue identifier\n * @param queueKey - The actual queue sorted set key\n * @returns Whether the queue was removed from the master queue\n */\n async removeQueueIfEmpty(queueId: string, queueKey: string): Promise<boolean> {\n const shardId = this.getShardForQueue(queueId);\n const masterKey = this.keys.masterQueueKey(shardId);\n\n const result = await this.redis.removeQueueIfEmpty(masterKey, queueKey, queueId);\n return result === 1;\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n /**\n * Map queue ID to shard using Jump Consistent Hash.\n * Provides better distribution than djb2 and minimal reshuffling when shard count changes.\n */\n #hashToShard(queueId: string): number {\n const keys = this.options.keys;\n if (keys.tenantShard) {\n return keys.tenantShard(keys.extractTenantId(queueId));\n }\n return jumpHash(queueId, this.shardCount);\n }\n\n #registerCommands(): void {\n // Atomically add queue to master if it has messages\n this.redis.defineCommand(\"addQueueIfNotEmpty\", {\n numberOfKeys: 2,\n lua: `\nlocal masterKey = KEYS[1]\nlocal queueKey = KEYS[2]\nlocal queueId = ARGV[1]\n\n-- Check if queue has any messages\nlocal count = redis.call('ZCARD', queueKey)\nif count == 0 then\n return 0\nend\n\n-- Get the oldest message timestamp (lowest score)\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest == 0 then\n return 0\nend\n\nlocal score = oldest[2]\n\n-- Add to master queue with the oldest message score\nredis.call('ZADD', masterKey, score, queueId)\nreturn 1\n `,\n });\n\n // Atomically remove queue from master if it's empty\n this.redis.defineCommand(\"removeQueueIfEmpty\", {\n numberOfKeys: 2,\n lua: `\nlocal masterKey = KEYS[1]\nlocal queueKey = KEYS[2]\nlocal queueId = ARGV[1]\n\n-- Check if queue is empty\nlocal count = redis.call('ZCARD', queueKey)\nif count > 0 then\n return 0\nend\n\n-- Remove from master queue\nredis.call('ZREM', masterKey, queueId)\nreturn 1\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n addQueueIfNotEmpty(masterKey: string, queueKey: string, queueId: string): Promise<number>;\n\n removeQueueIfEmpty(masterKey: string, queueKey: string, queueId: string): Promise<number>;\n }\n}\n","import type {\n Attributes,\n Counter,\n Histogram,\n Meter,\n ObservableGauge,\n Span,\n SpanKind,\n SpanOptions,\n Tracer,\n Context,\n} from \"@internal/tracing\";\nimport { context, trace, SpanStatusCode, ROOT_CONTEXT } from \"@internal/tracing\";\n\n/**\n * Semantic attributes for fair queue messaging operations.\n */\nexport const FairQueueAttributes = {\n QUEUE_ID: \"fairqueue.queue_id\",\n TENANT_ID: \"fairqueue.tenant_id\",\n MESSAGE_ID: \"fairqueue.message_id\",\n SHARD_ID: \"fairqueue.shard_id\",\n WORKER_QUEUE: \"fairqueue.worker_queue\",\n CONSUMER_ID: \"fairqueue.consumer_id\",\n ATTEMPT: \"fairqueue.attempt\",\n CONCURRENCY_GROUP: \"fairqueue.concurrency_group\",\n MESSAGE_COUNT: \"fairqueue.message_count\",\n RESULT: \"fairqueue.result\",\n} as const;\n\n/**\n * Standard messaging semantic attributes.\n */\nexport const MessagingAttributes = {\n SYSTEM: \"messaging.system\",\n OPERATION: \"messaging.operation\",\n MESSAGE_ID: \"messaging.message_id\",\n DESTINATION_NAME: \"messaging.destination.name\",\n} as const;\n\n/**\n * FairQueue metrics collection.\n */\nexport interface FairQueueMetrics {\n // Counters\n messagesEnqueued: Counter;\n messagesCompleted: Counter;\n messagesFailed: Counter;\n messagesRetried: Counter;\n messagesToDLQ: Counter;\n\n // Histograms\n processingTime: Histogram;\n queueTime: Histogram;\n\n // Observable gauges (registered with callbacks)\n queueLength: ObservableGauge;\n masterQueueLength: ObservableGauge;\n dispatchLength: ObservableGauge;\n inflightCount: ObservableGauge;\n dlqLength: ObservableGauge;\n oldestMessageAge: ObservableGauge;\n}\n\n/**\n * Options for creating FairQueue telemetry.\n */\nexport interface TelemetryOptions {\n tracer?: Tracer;\n meter?: Meter;\n /** Custom name for metrics prefix */\n name?: string;\n}\n\n/**\n * Telemetry helper for FairQueue.\n *\n * Provides:\n * - Span creation with proper attributes\n * - Metric recording\n * - Context propagation helpers\n */\nexport class FairQueueTelemetry {\n private tracer?: Tracer;\n private meter?: Meter;\n private metrics?: FairQueueMetrics;\n private name: string;\n\n constructor(options: TelemetryOptions) {\n this.tracer = options.tracer;\n this.meter = options.meter;\n this.name = options.name ?? \"fairqueue\";\n\n if (this.meter) {\n this.#initializeMetrics();\n }\n }\n\n // ============================================================================\n // Tracing\n // ============================================================================\n\n /**\n * Create a traced span for an operation.\n * Returns the result of the function, or throws any error after recording it.\n */\n async trace<T>(\n name: string,\n fn: (span: Span) => Promise<T>,\n options?: {\n kind?: SpanKind;\n attributes?: Attributes;\n }\n ): Promise<T> {\n if (!this.tracer) {\n // No tracer, just execute the function with a no-op span\n return fn(noopSpan);\n }\n\n const spanOptions: SpanOptions = {\n kind: options?.kind,\n attributes: {\n [MessagingAttributes.SYSTEM]: this.name,\n ...options?.attributes,\n },\n };\n\n return this.tracer.startActiveSpan(`${this.name}.${name}`, spanOptions, async (span) => {\n try {\n const result = await fn(span);\n return result;\n } catch (error) {\n if (error instanceof Error) {\n span.recordException(error);\n } else {\n span.recordException(new Error(String(error)));\n }\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n /**\n * Synchronous version of trace.\n */\n traceSync<T>(\n name: string,\n fn: (span: Span) => T,\n options?: {\n kind?: SpanKind;\n attributes?: Attributes;\n }\n ): T {\n if (!this.tracer) {\n return fn(noopSpan);\n }\n\n const spanOptions: SpanOptions = {\n kind: options?.kind,\n attributes: {\n [MessagingAttributes.SYSTEM]: this.name,\n ...options?.attributes,\n },\n };\n\n return this.tracer.startActiveSpan(`${this.name}.${name}`, spanOptions, (span) => {\n try {\n return fn(span);\n } catch (error) {\n if (error instanceof Error) {\n span.recordException(error);\n } else {\n span.recordException(new Error(String(error)));\n }\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n // ============================================================================\n // Metrics\n // ============================================================================\n\n /**\n * Record a message enqueued.\n */\n recordEnqueue(attributes?: Attributes): void {\n this.metrics?.messagesEnqueued.add(1, attributes);\n }\n\n /**\n * Record a batch of messages enqueued.\n */\n recordEnqueueBatch(count: number, attributes?: Attributes): void {\n this.metrics?.messagesEnqueued.add(count, attributes);\n }\n\n /**\n * Record a message completed successfully.\n */\n recordComplete(attributes?: Attributes): void {\n this.metrics?.messagesCompleted.add(1, attributes);\n }\n\n /**\n * Record a message processing failure.\n */\n recordFailure(attributes?: Attributes): void {\n this.metrics?.messagesFailed.add(1, attributes);\n }\n\n /**\n * Record a message retry.\n */\n recordRetry(attributes?: Attributes): void {\n this.metrics?.messagesRetried.add(1, attributes);\n }\n\n /**\n * Record a message sent to DLQ.\n */\n recordDLQ(attributes?: Attributes): void {\n this.metrics?.messagesToDLQ.add(1, attributes);\n }\n\n /**\n * Record message processing time.\n *\n * @param durationMs - Processing duration in milliseconds\n */\n recordProcessingTime(durationMs: number, attributes?: Attributes): void {\n this.metrics?.processingTime.record(durationMs, attributes);\n }\n\n /**\n * Record time a message spent waiting in queue.\n *\n * @param durationMs - Queue wait time in milliseconds\n */\n recordQueueTime(durationMs: number, attributes?: Attributes): void {\n this.metrics?.queueTime.record(durationMs, attributes);\n }\n\n /**\n * Register observable gauge callbacks.\n * Call this after FairQueue is initialized to register the gauge callbacks.\n */\n registerGaugeCallbacks(callbacks: {\n getQueueLength?: (queueId: string) => Promise<number>;\n getMasterQueueLength?: (shardId: number) => Promise<number>;\n getDispatchLength?: (shardId: number) => Promise<number>;\n getInflightCount?: (shardId: number) => Promise<number>;\n getDLQLength?: (tenantId: string) => Promise<number>;\n getOldestMessageAge?: (shardId: number) => Promise<number>;\n shardCount?: number;\n observedQueues?: string[];\n observedTenants?: string[];\n }): void {\n if (!this.metrics) return;\n\n // Queue length gauge\n if (callbacks.getQueueLength && callbacks.observedQueues) {\n const getQueueLength = callbacks.getQueueLength;\n const queues = callbacks.observedQueues;\n\n this.metrics.queueLength.addCallback(async (observableResult) => {\n for (const queueId of queues) {\n const length = await getQueueLength(queueId);\n observableResult.observe(length, {\n [FairQueueAttributes.QUEUE_ID]: queueId,\n });\n }\n });\n }\n\n // Legacy master queue length gauge (draining, should trend to 0)\n if (callbacks.getMasterQueueLength && callbacks.shardCount) {\n const getMasterQueueLength = callbacks.getMasterQueueLength;\n const shardCount = callbacks.shardCount;\n\n this.metrics.masterQueueLength.addCallback(async (observableResult) => {\n for (let shardId = 0; shardId < shardCount; shardId++) {\n const length = await getMasterQueueLength(shardId);\n observableResult.observe(length, {\n [FairQueueAttributes.SHARD_ID]: shardId.toString(),\n });\n }\n });\n }\n\n // Dispatch index length gauge (new two-level dispatch, tenant count per shard)\n if (callbacks.getDispatchLength && callbacks.shardCount) {\n const getDispatchLength = callbacks.getDispatchLength;\n const shardCount = callbacks.shardCount;\n\n this.metrics.dispatchLength.addCallback(async (observableResult) => {\n for (let shardId = 0; shardId < shardCount; shardId++) {\n const length = await getDispatchLength(shardId);\n observableResult.observe(length, {\n [FairQueueAttributes.SHARD_ID]: shardId.toString(),\n });\n }\n });\n }\n\n // Inflight count gauge\n if (callbacks.getInflightCount && callbacks.shardCount) {\n const getInflightCount = callbacks.getInflightCount;\n const shardCount = callbacks.shardCount;\n\n this.metrics.inflightCount.addCallback(async (observableResult) => {\n for (let shardId = 0; shardId < shardCount; shardId++) {\n const count = await getInflightCount(shardId);\n observableResult.observe(count, {\n [FairQueueAttributes.SHARD_ID]: shardId.toString(),\n });\n }\n });\n }\n\n if (callbacks.getOldestMessageAge && callbacks.shardCount) {\n const getOldestMessageAge = callbacks.getOldestMessageAge;\n const shardCount = callbacks.shardCount;\n\n this.metrics.oldestMessageAge.addCallback(async (observableResult) => {\n for (let shardId = 0; shardId < shardCount; shardId++) {\n const age = await getOldestMessageAge(shardId);\n observableResult.observe(age, {\n [FairQueueAttributes.SHARD_ID]: shardId.toString(),\n });\n }\n });\n }\n\n // DLQ length gauge\n if (callbacks.getDLQLength && callbacks.observedTenants) {\n const getDLQLength = callbacks.getDLQLength;\n const tenants = callbacks.observedTenants;\n\n this.metrics.dlqLength.addCallback(async (observableResult) => {\n for (const tenantId of tenants) {\n const length = await getDLQLength(tenantId);\n observableResult.observe(length, {\n [FairQueueAttributes.TENANT_ID]: tenantId,\n });\n }\n });\n }\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n /**\n * Create standard attributes for a message operation (for spans/traces).\n * Use this for span attributes where high cardinality is acceptable.\n */\n messageAttributes(params: {\n queueId?: string;\n tenantId?: string;\n messageId?: string;\n attempt?: number;\n workerQueue?: string;\n consumerId?: string;\n }): Attributes {\n const attrs: Attributes = {};\n\n if (params.queueId) attrs[FairQueueAttributes.QUEUE_ID] = params.queueId;\n if (params.tenantId) attrs[FairQueueAttributes.TENANT_ID] = params.tenantId;\n if (params.messageId) attrs[FairQueueAttributes.MESSAGE_ID] = params.messageId;\n if (params.attempt !== undefined) attrs[FairQueueAttributes.ATTEMPT] = params.attempt;\n if (params.workerQueue) attrs[FairQueueAttributes.WORKER_QUEUE] = params.workerQueue;\n if (params.consumerId) attrs[FairQueueAttributes.CONSUMER_ID] = params.consumerId;\n\n return attrs;\n }\n\n /**\n * Check if telemetry is enabled.\n */\n get isEnabled(): boolean {\n return !!this.tracer || !!this.meter;\n }\n\n /**\n * Check if tracing is enabled.\n */\n get hasTracer(): boolean {\n return !!this.tracer;\n }\n\n /**\n * Check if metrics are enabled.\n */\n get hasMetrics(): boolean {\n return !!this.meter;\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n #initializeMetrics(): void {\n if (!this.meter) return;\n\n this.metrics = {\n // Counters\n messagesEnqueued: this.meter.createCounter(`${this.name}.messages.enqueued`, {\n description: \"Number of messages enqueued\",\n unit: \"messages\",\n }),\n messagesCompleted: this.meter.createCounter(`${this.name}.messages.completed`, {\n description: \"Number of messages completed successfully\",\n unit: \"messages\",\n }),\n messagesFailed: this.meter.createCounter(`${this.name}.messages.failed`, {\n description: \"Number of messages that failed processing\",\n unit: \"messages\",\n }),\n messagesRetried: this.meter.createCounter(`${this.name}.messages.retried`, {\n description: \"Number of message retries\",\n unit: \"messages\",\n }),\n messagesToDLQ: this.meter.createCounter(`${this.name}.messages.dlq`, {\n description: \"Number of messages sent to dead letter queue\",\n unit: \"messages\",\n }),\n\n // Histograms\n processingTime: this.meter.createHistogram(`${this.name}.message.processing_time`, {\n description: \"Message processing time\",\n unit: \"ms\",\n }),\n queueTime: this.meter.createHistogram(`${this.name}.message.queue_time`, {\n description: \"Time message spent waiting in queue\",\n unit: \"ms\",\n }),\n\n // Observable gauges\n queueLength: this.meter.createObservableGauge(`${this.name}.queue.length`, {\n description: \"Number of messages in a queue\",\n unit: \"messages\",\n }),\n masterQueueLength: this.meter.createObservableGauge(`${this.name}.master_queue.length`, {\n description: \"Number of queues in legacy master queue shard (draining)\",\n unit: \"queues\",\n }),\n dispatchLength: this.meter.createObservableGauge(`${this.name}.dispatch.length`, {\n description: \"Number of tenants in dispatch index shard\",\n unit: \"tenants\",\n }),\n inflightCount: this.meter.createObservableGauge(`${this.name}.inflight.count`, {\n description: \"Number of messages currently being processed\",\n unit: \"messages\",\n }),\n dlqLength: this.meter.createObservableGauge(`${this.name}.dlq.length`, {\n description: \"Number of messages in dead letter queue\",\n unit: \"messages\",\n }),\n oldestMessageAge: this.meter.createObservableGauge(`${this.name}.oldest_message_age`, {\n description:\n \"Age of the oldest due message not yet completed in a shard, including claimed messages until their queue next completes or empties\",\n unit: \"ms\",\n }),\n };\n }\n}\n\n// ============================================================================\n// Batched Span Manager\n// ============================================================================\n\n/**\n * State for tracking a consumer loop's batched span.\n */\nexport interface ConsumerLoopState {\n /** Countdown of iterations before starting a new span */\n perTraceCountdown: number;\n /** When the current trace started */\n traceStartedAt: Date;\n /** The current batched span */\n currentSpan?: Span;\n /** The context for the current batched span */\n currentSpanContext?: Context;\n /** Number of iterations in the current span */\n iterationsCount: number;\n /** Total iterations across all spans */\n totalIterationsCount: number;\n /** Running duration in milliseconds for the current span */\n runningDurationInMs: number;\n /** Stats counters for the current span */\n stats: Record<string, number>;\n /** Flag to force span end on next iteration */\n endSpanInNextIteration: boolean;\n}\n\n/**\n * Configuration for the BatchedSpanManager.\n */\nexport interface BatchedSpanManagerOptions {\n /** The tracer to use for creating spans */\n tracer?: Tracer;\n /** Name prefix for spans */\n name: string;\n /** Maximum iterations before rotating the span */\n maxIterations: number;\n /** Maximum seconds before rotating the span */\n timeoutSeconds: number;\n /** Optional callback to get dynamic attributes when starting a new batched span */\n getDynamicAttributes?: () => Attributes;\n}\n\n/**\n * Manages batched spans for consumer loops.\n *\n * This allows multiple iterations to be grouped into a single parent span,\n * reducing the volume of spans while maintaining observability.\n */\nexport class BatchedSpanManager {\n private tracer?: Tracer;\n private name: string;\n private maxIterations: number;\n private timeoutSeconds: number;\n private loopStates = new Map<string, ConsumerLoopState>();\n private getDynamicAttributes?: () => Attributes;\n\n constructor(options: BatchedSpanManagerOptions) {\n this.tracer = options.tracer;\n this.name = options.name;\n this.maxIterations = options.maxIterations;\n this.timeoutSeconds = options.timeoutSeconds;\n this.getDynamicAttributes = options.getDynamicAttributes;\n }\n\n /**\n * Initialize state for a consumer loop.\n */\n initializeLoop(loopId: string): void {\n this.loopStates.set(loopId, {\n perTraceCountdown: this.maxIterations,\n traceStartedAt: new Date(),\n iterationsCount: 0,\n totalIterationsCount: 0,\n runningDurationInMs: 0,\n stats: {},\n endSpanInNextIteration: false,\n });\n }\n\n /**\n * Get the state for a consumer loop.\n */\n getState(loopId: string): ConsumerLoopState | undefined {\n return this.loopStates.get(loopId);\n }\n\n /**\n * Increment a stat counter for a loop.\n */\n incrementStat(loopId: string, statName: string, value: number = 1): void {\n const state = this.loopStates.get(loopId);\n if (state) {\n state.stats[statName] = (state.stats[statName] ?? 0) + value;\n }\n }\n\n /**\n * Mark that the span should end on the next iteration.\n */\n markForRotation(loopId: string): void {\n const state = this.loopStates.get(loopId);\n if (state) {\n state.endSpanInNextIteration = true;\n }\n }\n\n /**\n * Check if the span should be rotated (ended and a new one started).\n */\n shouldRotate(loopId: string): boolean {\n const state = this.loopStates.get(loopId);\n if (!state) return true;\n\n return (\n state.perTraceCountdown <= 0 ||\n Date.now() - state.traceStartedAt.getTime() > this.timeoutSeconds * 1000 ||\n state.currentSpanContext === undefined ||\n state.endSpanInNextIteration\n );\n }\n\n /**\n * End the current span for a loop and record stats.\n */\n endCurrentSpan(loopId: string): void {\n const state = this.loopStates.get(loopId);\n if (!state?.currentSpan) return;\n\n // Record stats as span attributes\n for (const [statName, count] of Object.entries(state.stats)) {\n state.currentSpan.setAttribute(`stats.${statName}`, count);\n }\n\n state.currentSpan.end();\n state.currentSpan = undefined;\n state.currentSpanContext = undefined;\n }\n\n /**\n * Start a new batched span for a loop.\n */\n startNewSpan(loopId: string, attributes?: Attributes): void {\n if (!this.tracer) return;\n\n const state = this.loopStates.get(loopId);\n if (!state) return;\n\n // End any existing span first\n this.endCurrentSpan(loopId);\n\n // Calculate metrics from previous span period\n const traceDurationInMs = state.traceStartedAt\n ? Date.now() - state.traceStartedAt.getTime()\n : undefined;\n const iterationsPerSecond =\n traceDurationInMs && traceDurationInMs > 0\n ? state.iterationsCount / (traceDurationInMs / 1000)\n : undefined;\n\n // Get dynamic attributes if callback is provided\n const dynamicAttributes = this.getDynamicAttributes?.() ?? {};\n\n // Start new span\n state.currentSpan = this.tracer.startSpan(\n `${this.name}.consumerLoop`,\n {\n kind: 1, // SpanKind.CONSUMER\n attributes: {\n loop_id: loopId,\n max_iterations: this.maxIterations,\n timeout_seconds: this.timeoutSeconds,\n previous_iterations: state.iterationsCount,\n previous_duration_ms: traceDurationInMs,\n previous_iterations_per_second: iterationsPerSecond,\n total_iterations: state.totalIterationsCount,\n ...dynamicAttributes,\n ...attributes,\n },\n },\n ROOT_CONTEXT\n );\n\n // Set up context for child spans\n state.currentSpanContext = trace.setSpan(ROOT_CONTEXT, state.currentSpan);\n\n // Reset counters\n state.perTraceCountdown = this.maxIterations;\n state.traceStartedAt = new Date();\n state.iterationsCount = 0;\n state.runningDurationInMs = 0;\n state.stats = {};\n state.endSpanInNextIteration = false;\n }\n\n /**\n * Execute a function within the batched span context.\n * Automatically handles span rotation and iteration tracking.\n */\n async withBatchedSpan<T>(\n loopId: string,\n fn: (span: Span) => Promise<T>,\n options?: {\n iterationSpanName?: string;\n attributes?: Attributes;\n }\n ): Promise<T> {\n let state = this.loopStates.get(loopId);\n\n // Initialize state if not present\n if (!state) {\n this.initializeLoop(loopId);\n state = this.loopStates.get(loopId)!;\n }\n\n // Check if we need to rotate the span\n if (this.shouldRotate(loopId)) {\n this.startNewSpan(loopId);\n }\n\n const startTime = performance.now();\n\n try {\n // If no tracer, just execute the function\n if (!this.tracer || !state.currentSpanContext) {\n return await fn(noopSpan);\n }\n\n // Execute within the batched span context\n return await context.with(state.currentSpanContext, async () => {\n // Create an iteration span within the batched span\n const iterationSpanName = options?.iterationSpanName ?? \"iteration\";\n\n return await this.tracer!.startActiveSpan(\n `${this.name}.${iterationSpanName}`,\n {\n attributes: {\n loop_id: loopId,\n iteration: state.iterationsCount,\n ...options?.attributes,\n },\n },\n async (iterationSpan) => {\n try {\n return await fn(iterationSpan);\n } catch (error) {\n if (error instanceof Error) {\n iterationSpan.recordException(error);\n state.currentSpan?.recordException(error);\n }\n iterationSpan.setStatus({ code: SpanStatusCode.ERROR });\n state.endSpanInNextIteration = true;\n throw error;\n } finally {\n iterationSpan.end();\n }\n }\n );\n });\n } finally {\n // Update iteration tracking\n const duration = performance.now() - startTime;\n state.runningDurationInMs += duration;\n state.iterationsCount++;\n state.totalIterationsCount++;\n state.perTraceCountdown--;\n }\n }\n\n /**\n * Clean up state for a loop when it's stopped.\n */\n cleanup(loopId: string): void {\n this.endCurrentSpan(loopId);\n this.loopStates.delete(loopId);\n }\n\n /**\n * Clean up all loop states.\n */\n cleanupAll(): void {\n for (const loopId of this.loopStates.keys()) {\n this.cleanup(loopId);\n }\n }\n}\n\n/**\n * No-op span implementation for when telemetry is disabled.\n */\nconst noopSpan: Span = {\n spanContext: () => ({\n traceId: \"\",\n spanId: \"\",\n traceFlags: 0,\n }),\n setAttribute: () => noopSpan,\n setAttributes: () => noopSpan,\n addEvent: () => noopSpan,\n addLink: () => noopSpan,\n addLinks: () => noopSpan,\n setStatus: () => noopSpan,\n updateName: () => noopSpan,\n end: () => {},\n isRecording: () => false,\n recordException: () => {},\n};\n\n/**\n * No-op telemetry instance for when telemetry is disabled.\n */\nexport const noopTelemetry = new FairQueueTelemetry({});\n","import type { RedisClient } from \"@internal/redis\";\nimport { createFairQueueRedisClient, type FairQueueRedisOptions } from \"./connection.js\";\nimport { jumpHash } from \"@trigger.dev/core/v3/serverOnly\";\nimport type { FairQueueKeyProducer, QueueWithScore } from \"./types.js\";\n\nexport interface TenantDispatchOptions {\n redis: FairQueueRedisOptions;\n keys: FairQueueKeyProducer;\n shardCount: number;\n}\n\nexport interface TenantWithScore {\n tenantId: string;\n score: number;\n}\n\n/**\n * TenantDispatch manages the two-level tenant dispatch index.\n *\n * Level 1 - Dispatch Index (per shard):\n * Key: {prefix}:dispatch:{shardId}\n * ZSET of tenantIds scored by oldest message timestamp across their queues.\n * Only tenants with queues containing messages appear here.\n *\n * Level 2 - Per-Tenant Queue Index:\n * Key: {prefix}:tenantq:{tenantId}\n * ZSET of queueIds scored by oldest message timestamp in that queue.\n *\n * This replaces the flat master queue for new enqueues, isolating each tenant's\n * queue backlog so the scheduler iterates tenants (not queues) at Level 1.\n */\nexport class TenantDispatch {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private shardCount: number;\n\n constructor(private options: TenantDispatchOptions) {\n this.redis = createFairQueueRedisClient(options.redis);\n this.keys = options.keys;\n this.shardCount = Math.max(1, options.shardCount);\n }\n\n /**\n * Get the dispatch shard ID for a tenant.\n * Uses jump consistent hash on the tenant ID so each tenant\n * always maps to exactly one dispatch shard.\n */\n getShardForTenant(tenantId: string): number {\n if (this.options.keys.tenantShard) {\n return this.options.keys.tenantShard(tenantId);\n }\n return jumpHash(tenantId, this.shardCount);\n }\n\n /**\n * Get eligible tenants from a dispatch shard (Level 1).\n * Returns tenants ordered by oldest message (lowest score first).\n */\n async getTenantsFromShard(\n shardId: number,\n limit: number = 1000,\n maxScore?: number\n ): Promise<TenantWithScore[]> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n const score = maxScore ?? Date.now();\n\n const results = await this.redis.zrangebyscore(\n dispatchKey,\n \"-inf\",\n score,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n limit\n );\n\n const tenants: TenantWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const tenantId = results[i];\n const scoreStr = results[i + 1];\n if (tenantId && scoreStr) {\n tenants.push({\n tenantId,\n score: parseFloat(scoreStr),\n });\n }\n }\n\n return tenants;\n }\n\n /**\n * Get queues for a specific tenant (Level 2).\n * Returns queues ordered by oldest message (lowest score first).\n */\n async getQueuesForTenant(\n tenantId: string,\n limit: number = 1000,\n maxScore?: number\n ): Promise<QueueWithScore[]> {\n const tenantQueueKey = this.keys.tenantQueueIndexKey(tenantId);\n const score = maxScore ?? Date.now();\n\n const results = await this.redis.zrangebyscore(\n tenantQueueKey,\n \"-inf\",\n score,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n limit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId,\n });\n }\n }\n\n return queues;\n }\n\n /**\n * Get the number of tenants in a dispatch shard.\n */\n async getShardTenantCount(shardId: number): Promise<number> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n return await this.redis.zcard(dispatchKey);\n }\n\n /**\n * Get total tenant count across all dispatch shards.\n * Note: tenants may appear in multiple shards, so this may overcount.\n */\n async getTotalTenantCount(): Promise<number> {\n const counts = await Promise.all(\n Array.from({ length: this.shardCount }, (_, i) => this.getShardTenantCount(i))\n );\n return counts.reduce((sum, count) => sum + count, 0);\n }\n\n /**\n * Get the number of queues for a tenant.\n */\n async getTenantQueueCount(tenantId: string): Promise<number> {\n const tenantQueueKey = this.keys.tenantQueueIndexKey(tenantId);\n return await this.redis.zcard(tenantQueueKey);\n }\n\n /**\n * Remove a tenant from a specific dispatch shard.\n */\n async removeTenantFromShard(shardId: number, tenantId: string): Promise<void> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n await this.redis.zrem(dispatchKey, tenantId);\n }\n\n /**\n * Add a tenant to a dispatch shard with the given score.\n */\n async addTenantToShard(shardId: number, tenantId: string, score: number): Promise<void> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n await this.redis.zadd(dispatchKey, score, tenantId);\n }\n\n /**\n * Remove a queue from a tenant's queue index.\n */\n async removeQueueFromTenant(tenantId: string, queueId: string): Promise<void> {\n const tenantQueueKey = this.keys.tenantQueueIndexKey(tenantId);\n await this.redis.zrem(tenantQueueKey, queueId);\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n}\n","import type { RedisClient } from \"@internal/redis\";\nimport { createFairQueueRedisClient, type FairQueueRedisOptions } from \"./connection.js\";\nimport { jumpHash } from \"@trigger.dev/core/v3/serverOnly\";\nimport type {\n ClaimResult,\n FairQueueKeyProducer,\n InFlightMessage,\n ReclaimedMessageInfo,\n StoredMessage,\n} from \"./types.js\";\n\nexport interface VisibilityManagerOptions {\n redis: FairQueueRedisOptions;\n keys: FairQueueKeyProducer;\n shardCount: number;\n defaultTimeoutMs: number;\n logger?: {\n debug: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n };\n}\n\n/**\n * VisibilityManager handles message visibility timeouts for safe message processing.\n *\n * Features:\n * - Claim messages with visibility timeout\n * - Heartbeat to extend timeout\n * - Automatic reclaim of timed-out messages\n * - Per-shard in-flight tracking\n *\n * Data structures:\n * - In-flight sorted set: score = deadline timestamp, member = \"{messageId}:{queueId}\"\n * - In-flight data hash: field = messageId, value = JSON message data\n */\nexport class VisibilityManager {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private shardCount: number;\n private defaultTimeoutMs: number;\n private logger: NonNullable<VisibilityManagerOptions[\"logger\"]>;\n\n constructor(private options: VisibilityManagerOptions) {\n this.redis = createFairQueueRedisClient(options.redis);\n this.keys = options.keys;\n this.shardCount = options.shardCount;\n this.defaultTimeoutMs = options.defaultTimeoutMs;\n this.logger = options.logger ?? {\n debug: () => {},\n error: () => {},\n };\n\n this.#registerCommands();\n }\n\n // ============================================================================\n // Public Methods\n // ============================================================================\n\n /**\n * Claim a message for processing.\n * Moves the message from its queue to the in-flight set with a visibility timeout.\n *\n * @param queueId - The queue to claim from\n * @param queueKey - The Redis key for the queue sorted set\n * @param queueItemsKey - The Redis key for the queue items hash\n * @param consumerId - ID of the consumer claiming the message\n * @param timeoutMs - Visibility timeout in milliseconds\n * @returns Claim result with the message if successful\n */\n async claim<TPayload = unknown>(\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n consumerId: string,\n timeoutMs?: number\n ): Promise<ClaimResult<TPayload>> {\n const timeout = timeoutMs ?? this.defaultTimeoutMs;\n const deadline = Date.now() + timeout;\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Use Lua script to atomically:\n // 1. Pop oldest message from queue\n // 2. Add to in-flight set with deadline\n // 3. Store message data\n const result = await this.redis.claimMessage(\n queueKey,\n queueItemsKey,\n inflightKey,\n inflightDataKey,\n queueId,\n consumerId,\n deadline.toString()\n );\n\n if (!result) {\n return { claimed: false };\n }\n\n const [messageId, payloadJson] = result;\n\n try {\n const payload = JSON.parse(payloadJson) as TPayload;\n const message: InFlightMessage<TPayload> = {\n messageId,\n queueId,\n payload,\n deadline,\n consumerId,\n };\n\n this.logger.debug(\"Message claimed\", {\n messageId,\n queueId,\n consumerId,\n deadline,\n });\n\n return { claimed: true, message };\n } catch (error) {\n // JSON parse error - message data is corrupted\n this.logger.error(\"Failed to parse claimed message\", {\n messageId,\n queueId,\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Remove the corrupted message from in-flight\n await this.#removeFromInflight(shardId, messageId, queueId);\n\n return { claimed: false };\n }\n }\n\n /**\n * Claim multiple messages for processing (batch claim).\n * Moves up to maxCount messages from the queue to the in-flight set.\n *\n * @param queueId - The queue to claim from\n * @param queueKey - The Redis key for the queue sorted set\n * @param queueItemsKey - The Redis key for the queue items hash\n * @param consumerId - ID of the consumer claiming the messages\n * @param maxCount - Maximum number of messages to claim\n * @param timeoutMs - Visibility timeout in milliseconds\n * @returns Array of claimed messages\n */\n async claimBatch<TPayload = unknown>(\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n consumerId: string,\n maxCount: number,\n timeoutMs?: number\n ): Promise<Array<InFlightMessage<TPayload>>> {\n const timeout = timeoutMs ?? this.defaultTimeoutMs;\n const deadline = Date.now() + timeout;\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Use Lua script to atomically claim up to maxCount messages\n const result = await this.redis.claimMessageBatch(\n queueKey,\n queueItemsKey,\n inflightKey,\n inflightDataKey,\n queueId,\n deadline.toString(),\n maxCount.toString()\n );\n\n if (!result || result.length === 0) {\n return [];\n }\n\n const messages: Array<InFlightMessage<TPayload>> = [];\n\n // Results come in pairs: [messageId1, payload1, messageId2, payload2, ...]\n for (let i = 0; i < result.length; i += 2) {\n const messageId = result[i];\n const payloadJson = result[i + 1];\n\n // Skip if either value is missing\n if (!messageId || !payloadJson) {\n continue;\n }\n\n try {\n const payload = JSON.parse(payloadJson) as TPayload;\n messages.push({\n messageId,\n queueId,\n payload,\n deadline,\n consumerId,\n });\n } catch (error) {\n // JSON parse error - skip this message\n this.logger.error(\"Failed to parse claimed message in batch\", {\n messageId,\n queueId,\n error: error instanceof Error ? error.message : String(error),\n });\n // Remove the corrupted message from in-flight\n await this.#removeFromInflight(shardId, messageId, queueId);\n }\n }\n\n if (messages.length > 0) {\n this.logger.debug(\"Batch claimed messages\", {\n queueId,\n consumerId,\n count: messages.length,\n deadline,\n });\n }\n\n return messages;\n }\n\n /**\n * Extend the visibility timeout for a message (heartbeat).\n *\n * @param messageId - The message ID\n * @param queueId - The queue ID\n * @param extendMs - Additional milliseconds to add to the deadline\n * @returns true if the heartbeat was successful\n */\n async heartbeat(messageId: string, queueId: string, extendMs: number): Promise<boolean> {\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const member = this.#makeMember(messageId, queueId);\n const newDeadline = Date.now() + extendMs;\n\n // Use Lua script to atomically check existence and update score\n // ZADD XX returns 0 even on successful updates, so we use a custom command\n const result = await this.redis.heartbeatMessage(inflightKey, member, newDeadline.toString());\n\n const success = result === 1;\n\n if (success) {\n this.logger.debug(\"Heartbeat successful\", {\n messageId,\n queueId,\n newDeadline,\n });\n }\n\n return success;\n }\n\n /**\n * Mark a message as successfully processed.\n * Removes the message from in-flight tracking.\n *\n * @param messageId - The message ID\n * @param queueId - The queue ID\n */\n async complete(messageId: string, queueId: string): Promise<void> {\n const shardId = this.#getShardForQueue(queueId);\n await this.#removeFromInflight(shardId, messageId, queueId);\n\n this.logger.debug(\"Message completed\", {\n messageId,\n queueId,\n });\n }\n\n /**\n * Release a message back to its queue.\n * Used when processing fails or consumer wants to retry later.\n *\n * @param messageId - The message ID\n * @param queueId - The queue ID\n * @param queueKey - The Redis key for the queue\n * @param queueItemsKey - The Redis key for the queue items hash\n * @param tenantQueueIndexKey - The Redis key for the tenant queue index (Level 2)\n * @param dispatchKey - The Redis key for the dispatch index (Level 1)\n * @param tenantId - The tenant ID\n * @param score - Optional score for the message (defaults to now)\n */\n async release<_TPayload = unknown>(\n messageId: string,\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n tenantId: string,\n score?: number,\n updatedData?: string\n ): Promise<void> {\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const member = this.#makeMember(messageId, queueId);\n const messageScore = score ?? Date.now();\n\n // Use Lua script to atomically:\n // 1. Get message data from in-flight (or use updatedData if provided)\n // 2. Remove from in-flight\n // 3. Add back to queue\n // 4. Update dispatch indexes to ensure queue is picked up\n await this.redis.releaseMessage(\n inflightKey,\n inflightDataKey,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n member,\n messageId,\n messageScore.toString(),\n queueId,\n updatedData ?? \"\",\n tenantId\n );\n\n this.logger.debug(\"Message released\", {\n messageId,\n queueId,\n score: messageScore,\n });\n }\n\n /**\n * Release multiple messages back to their queue in a single operation.\n * Used when processing fails or consumer wants to retry later.\n * All messages must belong to the same queue.\n *\n * @param messages - Array of messages to release (must all have same queueId)\n * @param queueId - The queue ID\n * @param queueKey - The Redis key for the queue\n * @param queueItemsKey - The Redis key for the queue items hash\n * @param tenantQueueIndexKey - The Redis key for the tenant queue index (Level 2)\n * @param dispatchKey - The Redis key for the dispatch index (Level 1)\n * @param tenantId - The tenant ID\n * @param score - Optional score for the messages (defaults to now)\n */\n async releaseBatch(\n messages: Array<{ messageId: string }>,\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n tenantId: string,\n score?: number\n ): Promise<void> {\n if (messages.length === 0) {\n return;\n }\n\n const shardId = this.#getShardForQueue(queueId);\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const messageScore = score ?? Date.now();\n\n // Build arrays of members and messageIds for the Lua script\n const messageIds = messages.map((m) => m.messageId);\n const members = messages.map((m) => this.#makeMember(m.messageId, queueId));\n\n await this.redis.releaseMessageBatch(\n inflightKey,\n inflightDataKey,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n messageScore.toString(),\n queueId,\n tenantId,\n ...members,\n ...messageIds\n );\n\n this.logger.debug(\"Batch messages released\", {\n queueId,\n count: messages.length,\n score: messageScore,\n });\n }\n\n /**\n * Reclaim timed-out messages from a shard.\n * Returns messages to their original queues.\n *\n * @param shardId - The shard to check\n * @param getQueueKeys - Function to get queue keys for a queue ID\n * @param onBeforeRequeue - Hook invoked with the batch before any message is requeued,\n * used to free concurrency slots. A throw aborts the whole batch, leaving the\n * messages in-flight for the next reclaim tick.\n * @returns Array of reclaimed message info\n */\n async reclaimTimedOut(\n shardId: number,\n getQueueKeys: (queueId: string) => {\n queueKey: string;\n queueItemsKey: string;\n tenantQueueIndexKey: string;\n dispatchKey: string;\n tenantId: string;\n },\n onBeforeRequeue?: (messages: ReclaimedMessageInfo[]) => Promise<void>\n ): Promise<ReclaimedMessageInfo[]> {\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const now = Date.now();\n\n // Get all messages past their deadline\n const timedOut = await this.redis.zrangebyscore(\n inflightKey,\n \"-inf\",\n now,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n 100 // Process in batches\n );\n\n const candidates: Array<{\n member: string;\n deadlineScore: string;\n info: ReclaimedMessageInfo;\n storedMessage: StoredMessage | null;\n }> = [];\n\n for (let i = 0; i < timedOut.length; i += 2) {\n const member = timedOut[i];\n const deadlineScore = timedOut[i + 1];\n if (!member || !deadlineScore) {\n continue;\n }\n const { messageId, queueId } = this.#parseMember(member);\n\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n let storedMessage: StoredMessage | null = null;\n if (dataJson) {\n try {\n storedMessage = JSON.parse(dataJson);\n } catch {\n // Ignore parse error, proceed with reclaim\n }\n }\n\n if (!storedMessage) {\n this.logger.error(\"Missing or corrupted message data during reclaim, using fallback\", {\n messageId,\n queueId,\n });\n }\n\n candidates.push({\n member,\n deadlineScore,\n storedMessage,\n info: {\n messageId,\n queueId,\n tenantId: storedMessage?.tenantId ?? this.keys.extractTenantId(queueId),\n metadata: storedMessage?.metadata ?? {},\n },\n });\n }\n\n if (candidates.length === 0) {\n return [];\n }\n\n if (onBeforeRequeue) {\n await onBeforeRequeue(candidates.map((candidate) => candidate.info));\n }\n\n const reclaimedMessages: ReclaimedMessageInfo[] = [];\n\n for (const { member, deadlineScore, storedMessage, info } of candidates) {\n const { messageId, queueId } = info;\n\n const { queueKey, queueItemsKey, tenantQueueIndexKey, dispatchKey, tenantId } =\n getQueueKeys(queueId);\n\n try {\n // Re-add to queue with original timestamp to preserve priority\n // Fall back to now if we can't get the original timestamp\n const score = storedMessage?.timestamp ?? now;\n await this.redis.releaseMessage(\n inflightKey,\n inflightDataKey,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n member,\n messageId,\n score.toString(),\n queueId,\n \"\",\n tenantId\n );\n\n reclaimedMessages.push(info);\n\n this.logger.debug(\"Reclaimed timed-out message\", {\n messageId,\n queueId,\n deadline: deadlineScore,\n });\n } catch (error) {\n this.logger.error(\"Failed to reclaim message\", {\n messageId,\n queueId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return reclaimedMessages;\n }\n\n /**\n * Get all in-flight messages for a shard.\n */\n async getInflightMessages(shardId: number): Promise<\n Array<{\n messageId: string;\n queueId: string;\n deadline: number;\n }>\n > {\n const inflightKey = this.keys.inflightKey(shardId);\n const results = await this.redis.zrange(inflightKey, 0, -1, \"WITHSCORES\");\n\n const messages: Array<{ messageId: string; queueId: string; deadline: number }> = [];\n\n for (let i = 0; i < results.length; i += 2) {\n const member = results[i];\n const deadlineStr = results[i + 1];\n if (!member || !deadlineStr) {\n continue;\n }\n const deadline = parseFloat(deadlineStr);\n const { messageId, queueId } = this.#parseMember(member);\n\n messages.push({ messageId, queueId, deadline });\n }\n\n return messages;\n }\n\n /**\n * Get count of in-flight messages for a shard.\n */\n async getInflightCount(shardId: number): Promise<number> {\n const inflightKey = this.keys.inflightKey(shardId);\n return await this.redis.zcard(inflightKey);\n }\n\n /**\n * Get total in-flight count across all shards.\n */\n async getTotalInflightCount(): Promise<number> {\n const counts = await Promise.all(\n Array.from({ length: this.shardCount }, (_, i) => this.getInflightCount(i))\n );\n return counts.reduce((sum, count) => sum + count, 0);\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n /**\n * Map queue ID to shard using Jump Consistent Hash.\n * Must use same algorithm as MasterQueue for consistency.\n */\n #getShardForQueue(queueId: string): number {\n if (this.keys.tenantShard) {\n return this.keys.tenantShard(this.keys.extractTenantId(queueId));\n }\n return jumpHash(queueId, this.shardCount);\n }\n\n #makeMember(messageId: string, queueId: string): string {\n return `${messageId}:${queueId}`;\n }\n\n #parseMember(member: string): { messageId: string; queueId: string } {\n const colonIndex = member.indexOf(\":\");\n if (colonIndex === -1) {\n return { messageId: member, queueId: \"\" };\n }\n return {\n messageId: member.substring(0, colonIndex),\n queueId: member.substring(colonIndex + 1),\n };\n }\n\n async #removeFromInflight(shardId: number, messageId: string, queueId: string): Promise<void> {\n const inflightKey = this.keys.inflightKey(shardId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const member = this.#makeMember(messageId, queueId);\n\n const pipeline = this.redis.pipeline();\n pipeline.zrem(inflightKey, member);\n pipeline.hdel(inflightDataKey, messageId);\n await pipeline.exec();\n }\n\n #registerCommands(): void {\n // Atomic claim: pop from queue, add to in-flight\n this.redis.defineCommand(\"claimMessage\", {\n numberOfKeys: 4,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal inflightKey = KEYS[3]\nlocal inflightDataKey = KEYS[4]\n\nlocal queueId = ARGV[1]\nlocal consumerId = ARGV[2]\nlocal deadline = tonumber(ARGV[3])\n\n-- Get oldest message from queue\nlocal items = redis.call('ZRANGE', queueKey, 0, 0)\nif #items == 0 then\n return nil\nend\n\nlocal messageId = items[1]\n\n-- Get message data\nlocal payload = redis.call('HGET', queueItemsKey, messageId)\nif not payload then\n -- Message data missing, remove from queue and return nil\n redis.call('ZREM', queueKey, messageId)\n return nil\nend\n\n-- Remove from queue\nredis.call('ZREM', queueKey, messageId)\nredis.call('HDEL', queueItemsKey, messageId)\n\n-- Add to in-flight set with deadline\nlocal member = messageId .. ':' .. queueId\nredis.call('ZADD', inflightKey, deadline, member)\n\n-- Store message data for potential release\nredis.call('HSET', inflightDataKey, messageId, payload)\n\nreturn {messageId, payload}\n `,\n });\n\n // Atomic batch claim: pop up to N messages from queue, add to in-flight\n this.redis.defineCommand(\"claimMessageBatch\", {\n numberOfKeys: 4,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal inflightKey = KEYS[3]\nlocal inflightDataKey = KEYS[4]\n\nlocal queueId = ARGV[1]\nlocal deadline = tonumber(ARGV[2])\nlocal maxCount = tonumber(ARGV[3])\n\n-- Get up to maxCount oldest messages from queue\nlocal items = redis.call('ZRANGE', queueKey, 0, maxCount - 1)\nif #items == 0 then\n return {}\nend\n\nlocal results = {}\n\nfor i, messageId in ipairs(items) do\n -- Get message data\n local payload = redis.call('HGET', queueItemsKey, messageId)\n \n if payload then\n -- Remove from queue\n redis.call('ZREM', queueKey, messageId)\n redis.call('HDEL', queueItemsKey, messageId)\n \n -- Add to in-flight set with deadline\n local member = messageId .. ':' .. queueId\n redis.call('ZADD', inflightKey, deadline, member)\n \n -- Store message data for potential release\n redis.call('HSET', inflightDataKey, messageId, payload)\n \n -- Add to results\n table.insert(results, messageId)\n table.insert(results, payload)\n else\n -- Message data missing, remove from queue\n redis.call('ZREM', queueKey, messageId)\n end\nend\n\nreturn results\n `,\n });\n\n // Atomic release: remove from in-flight, add back to queue, update dispatch indexes\n this.redis.defineCommand(\"releaseMessage\", {\n numberOfKeys: 6,\n lua: `\nlocal inflightKey = KEYS[1]\nlocal inflightDataKey = KEYS[2]\nlocal queueKey = KEYS[3]\nlocal queueItemsKey = KEYS[4]\nlocal tenantQueueIndexKey = KEYS[5]\nlocal dispatchKey = KEYS[6]\n\nlocal member = ARGV[1]\nlocal messageId = ARGV[2]\nlocal score = tonumber(ARGV[3])\nlocal queueId = ARGV[4]\nlocal updatedData = ARGV[5]\nlocal tenantId = ARGV[6]\n\n-- Get message data from in-flight\nlocal payload = redis.call('HGET', inflightDataKey, messageId)\nif not payload then\n -- Message not in in-flight or already released. Drop the dangling in-flight\n -- entry so it stops consuming a slot in every future reclaim scan.\n redis.call('ZREM', inflightKey, member)\n return 0\nend\n\n-- Use updatedData if provided (e.g. incremented attempt count for retries),\n-- otherwise use the original in-flight data\nif updatedData and updatedData ~= \"\" then\n payload = updatedData\nend\n\n-- Add back to queue before dropping the in-flight record. Lua does not roll back on\n-- error, so removing first would lose the message outright if the queue write failed.\nredis.call('ZADD', queueKey, score, messageId)\nredis.call('HSET', queueItemsKey, messageId, payload)\n\n-- Remove from in-flight\nredis.call('ZREM', inflightKey, member)\nredis.call('HDEL', inflightDataKey, messageId)\n\n-- Update tenant queue index (Level 2) with queue's oldest message\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\nend\n\n-- Update dispatch index (Level 1) with tenant's oldest across all queues\nlocal tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\nif #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\nend\n\nreturn 1\n `,\n });\n\n // Atomic batch release: release multiple messages back to queue\n this.redis.defineCommand(\"releaseMessageBatch\", {\n numberOfKeys: 6,\n lua: `\nlocal inflightKey = KEYS[1]\nlocal inflightDataKey = KEYS[2]\nlocal queueKey = KEYS[3]\nlocal queueItemsKey = KEYS[4]\nlocal tenantQueueIndexKey = KEYS[5]\nlocal dispatchKey = KEYS[6]\n\nlocal score = tonumber(ARGV[1])\nlocal queueId = ARGV[2]\nlocal tenantId = ARGV[3]\n\n-- Remaining args are: members..., messageIds...\n-- Calculate how many messages we have\nlocal numMessages = (table.getn(ARGV) - 3) / 2\nlocal membersStart = 4\nlocal messageIdsStart = membersStart + numMessages\n\nlocal releasedCount = 0\n\nfor i = 0, numMessages - 1 do\n local member = ARGV[membersStart + i]\n local messageId = ARGV[messageIdsStart + i]\n\n -- Get message data from in-flight\n local payload = redis.call('HGET', inflightDataKey, messageId)\n if payload then\n -- Add back to queue before dropping the in-flight record, so a failed queue write\n -- cannot lose the message: Lua does not roll back already-applied commands.\n redis.call('ZADD', queueKey, score, messageId)\n redis.call('HSET', queueItemsKey, messageId, payload)\n\n -- Remove from in-flight\n redis.call('ZREM', inflightKey, member)\n redis.call('HDEL', inflightDataKey, messageId)\n\n releasedCount = releasedCount + 1\n else\n -- Dangling in-flight entry with no payload: drop it so it stops consuming\n -- a slot in every future reclaim scan.\n redis.call('ZREM', inflightKey, member)\n end\nend\n\n-- Update dispatch indexes (only once at the end)\nif releasedCount > 0 then\n -- Update tenant queue index (Level 2)\n local oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\n if #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\n end\n -- Update dispatch index (Level 1)\n local tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\n if #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\n end\nend\n\nreturn releasedCount\n `,\n });\n\n // Atomic heartbeat: check if member exists and update score\n // ZADD XX returns 0 even on successful updates (it counts new additions only)\n // So we need to check existence first with ZSCORE\n this.redis.defineCommand(\"heartbeatMessage\", {\n numberOfKeys: 1,\n lua: `\nlocal inflightKey = KEYS[1]\nlocal member = ARGV[1]\nlocal newDeadline = tonumber(ARGV[2])\n\n-- Check if member exists in the in-flight set\nlocal score = redis.call('ZSCORE', inflightKey, member)\nif not score then\n return 0\nend\n\n-- Update the deadline\nredis.call('ZADD', inflightKey, 'XX', newDeadline, member)\nreturn 1\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n claimMessage(\n queueKey: string,\n queueItemsKey: string,\n inflightKey: string,\n inflightDataKey: string,\n queueId: string,\n consumerId: string,\n deadline: string\n ): Promise<[string, string] | null>;\n\n claimMessageBatch(\n queueKey: string,\n queueItemsKey: string,\n inflightKey: string,\n inflightDataKey: string,\n queueId: string,\n deadline: string,\n maxCount: string\n ): Promise<string[]>;\n\n releaseMessage(\n inflightKey: string,\n inflightDataKey: string,\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n member: string,\n messageId: string,\n score: string,\n queueId: string,\n updatedData: string,\n tenantId: string\n ): Promise<number>;\n\n releaseMessageBatch(\n inflightKey: string,\n inflightDataKey: string,\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n score: string,\n queueId: string,\n tenantId: string,\n ...membersAndMessageIds: string[]\n ): Promise<number>;\n\n heartbeatMessage(inflightKey: string, member: string, newDeadline: string): Promise<number>;\n }\n}\n","import type { RedisClient } from \"@internal/redis\";\nimport { createFairQueueRedisClient, type FairQueueRedisOptions } from \"./connection.js\";\nimport type { FairQueueKeyProducer } from \"./types.js\";\n\nexport interface WorkerQueueManagerOptions {\n redis: FairQueueRedisOptions;\n keys: FairQueueKeyProducer;\n logger?: {\n debug: (message: string, context?: Record<string, unknown>) => void;\n error: (message: string, context?: Record<string, unknown>) => void;\n };\n}\n\n/**\n * WorkerQueueManager handles the intermediate worker queue layer.\n *\n * This provides:\n * - Low-latency message delivery via blocking pop (BLPOP)\n * - Routing of messages to specific workers/consumers\n * - Efficient waiting without polling\n *\n * Flow:\n * 1. Master queue consumer claims message from message queue\n * 2. Message key is pushed to worker queue\n * 3. Worker queue consumer does blocking pop to receive message\n */\nexport class WorkerQueueManager {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private logger: NonNullable<WorkerQueueManagerOptions[\"logger\"]>;\n\n constructor(private options: WorkerQueueManagerOptions) {\n this.redis = createFairQueueRedisClient(options.redis);\n this.keys = options.keys;\n this.logger = options.logger ?? {\n debug: () => {},\n error: () => {},\n };\n this.#registerCommands();\n }\n\n // ============================================================================\n // Public Methods\n // ============================================================================\n\n /**\n * Push a message key to a worker queue.\n * Called after claiming a message from the message queue.\n *\n * @param workerQueueId - The worker queue identifier\n * @param messageKey - The message key to push (typically \"messageId:queueId\")\n */\n async push(workerQueueId: string, messageKey: string): Promise<void> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n await this.redis.rpush(workerQueueKey, messageKey);\n\n this.logger.debug(\"Pushed to worker queue\", {\n workerQueueId,\n workerQueueKey,\n messageKey,\n });\n }\n\n /**\n * Push multiple message keys to a worker queue.\n *\n * @param workerQueueId - The worker queue identifier\n * @param messageKeys - The message keys to push\n */\n async pushBatch(workerQueueId: string, messageKeys: string[]): Promise<void> {\n if (messageKeys.length === 0) {\n return;\n }\n\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n await this.redis.rpush(workerQueueKey, ...messageKeys);\n\n this.logger.debug(\"Pushed batch to worker queue\", {\n workerQueueId,\n workerQueueKey,\n count: messageKeys.length,\n });\n }\n\n /**\n * Blocking pop from a worker queue.\n * Waits until a message is available or timeout expires.\n *\n * @param workerQueueId - The worker queue identifier\n * @param timeoutSeconds - Maximum time to wait (0 = wait forever)\n * @param signal - Optional abort signal to cancel waiting\n * @returns The message key, or null if timeout\n */\n async blockingPop(\n workerQueueId: string,\n timeoutSeconds: number,\n signal?: AbortSignal\n ): Promise<string | null> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n\n if (signal?.aborted) {\n return null;\n }\n\n // Fast path: under load the queue is rarely empty, so pop on the shared connection\n // and only pay for a dedicated blocking connection when there is nothing to take\n const readyMessageKey = await this.redis.lpop(workerQueueKey);\n if (readyMessageKey) {\n return readyMessageKey;\n }\n\n // Create a separate client for blocking operation\n // This is required because BLPOP blocks the connection\n const blockingClient = this.redis.duplicate();\n\n // Define cleanup outside try so it's accessible in finally\n // This prevents listener accumulation on the AbortSignal\n const cleanup = signal\n ? () => {\n blockingClient.disconnect();\n }\n : null;\n\n try {\n // Set up abort handler\n if (signal && cleanup) {\n signal.addEventListener(\"abort\", cleanup, { once: true });\n\n if (signal.aborted) {\n return null;\n }\n }\n\n const result = await blockingClient.blpop(workerQueueKey, timeoutSeconds);\n\n if (!result) {\n return null;\n }\n\n // BLPOP returns [key, value]\n const [, messageKey] = result;\n\n this.logger.debug(\"Blocking pop received message\", {\n workerQueueId,\n workerQueueKey,\n messageKey,\n });\n\n return messageKey;\n } catch (error) {\n // Handle abort/disconnect\n if (signal?.aborted) {\n return null;\n }\n\n this.logger.error(\"Blocking pop error\", {\n workerQueueId,\n error: error instanceof Error ? error.message : String(error),\n });\n\n throw error;\n } finally {\n // Always remove the listener to prevent accumulation on the AbortSignal\n // (once: true only removes if abort fires, not on normal completion)\n if (cleanup && signal) {\n signal.removeEventListener(\"abort\", cleanup);\n }\n if (blockingClient.status !== \"end\") {\n await blockingClient.quit().catch(() => {\n // Ignore quit errors (may already be disconnected)\n });\n }\n }\n }\n\n /**\n * Non-blocking pop from a worker queue.\n *\n * @param workerQueueId - The worker queue identifier\n * @returns The message key and queue length, or null if empty\n */\n async pop(workerQueueId: string): Promise<{ messageKey: string; queueLength: number } | null> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n\n const result = await this.redis.popWithLength(workerQueueKey);\n\n if (!result) {\n return null;\n }\n\n const [messageKey, queueLength] = result;\n\n this.logger.debug(\"Non-blocking pop received message\", {\n workerQueueId,\n workerQueueKey,\n messageKey,\n queueLength,\n });\n\n return { messageKey, queueLength: Number(queueLength) };\n }\n\n /**\n * Get the current length of a worker queue.\n */\n async getLength(workerQueueId: string): Promise<number> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n return await this.redis.llen(workerQueueKey);\n }\n\n /**\n * Peek at all messages in a worker queue without removing them.\n * Useful for debugging and tests.\n */\n async peek(workerQueueId: string): Promise<string[]> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n return await this.redis.lrange(workerQueueKey, 0, -1);\n }\n\n /**\n * Remove a specific message from the worker queue.\n * Used when a message needs to be removed without processing.\n *\n * @param workerQueueId - The worker queue identifier\n * @param messageKey - The message key to remove\n * @returns Number of removed items\n */\n async remove(workerQueueId: string, messageKey: string): Promise<number> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n return await this.redis.lrem(workerQueueKey, 0, messageKey);\n }\n\n /**\n * Clear all messages from a worker queue.\n */\n async clear(workerQueueId: string): Promise<void> {\n const workerQueueKey = this.keys.workerQueueKey(workerQueueId);\n await this.redis.del(workerQueueKey);\n }\n\n /**\n * Close the Redis connection.\n */\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private - Register Commands\n // ============================================================================\n\n /**\n * Initialize custom Redis commands.\n */\n #registerCommands(): void {\n // Non-blocking pop with queue length\n this.redis.defineCommand(\"popWithLength\", {\n numberOfKeys: 1,\n lua: `\nlocal workerQueueKey = KEYS[1]\n\n-- Pop the first message\nlocal messageKey = redis.call('LPOP', workerQueueKey)\nif not messageKey then\n return nil\nend\n\n-- Get remaining queue length\nlocal queueLength = redis.call('LLEN', workerQueueKey)\n\nreturn {messageKey, queueLength}\n `,\n });\n }\n\n /**\n * Register custom commands on an external Redis client.\n * Use this when initializing FairQueue with worker queues.\n */\n registerCommands(redis: RedisClient): void {\n redis.defineCommand(\"popWithLength\", {\n numberOfKeys: 1,\n lua: `\nlocal workerQueueKey = KEYS[1]\n\n-- Pop the first message\nlocal messageKey = redis.call('LPOP', workerQueueKey)\nif not messageKey then\n return nil\nend\n\n-- Get remaining queue length\nlocal queueLength = redis.call('LLEN', workerQueueKey)\n\nreturn {messageKey, queueLength}\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n popWithLength(workerQueueKey: string): Promise<[string, string] | null>;\n }\n}\n","import { jumpHash } from \"@trigger.dev/core/v3/serverOnly\";\nimport type { FairQueueKeyProducer } from \"./types.js\";\n\n/**\n * Default key producer for the fair queue system.\n * Uses a configurable prefix and standard key structure.\n *\n * Key structure:\n * - Master queue: {prefix}:master:{shardId} (legacy, drain-only)\n * - Dispatch index: {prefix}:dispatch:{shardId} (Level 1: tenantIds)\n * - Tenant queue index: {prefix}:tenantq:{tenantId} (Level 2: queueIds)\n * - Queue: {prefix}:queue:{queueId}\n * - Queue items: {prefix}:queue:{queueId}:items\n * - Concurrency: {prefix}:concurrency:{groupName}:{groupId}\n * - In-flight: {prefix}:inflight:{shardId}\n * - In-flight data: {prefix}:inflight:{shardId}:data\n * - Worker queue: {prefix}:worker:{consumerId}\n */\nexport class DefaultFairQueueKeyProducer implements FairQueueKeyProducer {\n private readonly prefix: string;\n private readonly separator: string;\n\n constructor(options: { prefix?: string; separator?: string } = {}) {\n this.prefix = options.prefix ?? \"fq\";\n this.separator = options.separator ?? \":\";\n }\n\n // ============================================================================\n // Master Queue Keys\n // ============================================================================\n\n masterQueueKey(shardId: number): string {\n return this.#buildKey(\"master\", shardId.toString());\n }\n\n // ============================================================================\n // Queue Keys\n // ============================================================================\n\n queueKey(queueId: string): string {\n return this.#buildKey(\"queue\", queueId);\n }\n\n queueItemsKey(queueId: string): string {\n return this.#buildKey(\"queue\", queueId, \"items\");\n }\n\n // ============================================================================\n // Concurrency Keys\n // ============================================================================\n\n concurrencyKey(groupName: string, groupId: string): string {\n return this.#buildKey(\"concurrency\", groupName, groupId);\n }\n\n // ============================================================================\n // In-Flight Keys\n // ============================================================================\n\n inflightKey(shardId: number): string {\n return this.#buildKey(\"inflight\", shardId.toString());\n }\n\n inflightDataKey(shardId: number): string {\n return this.#buildKey(\"inflight\", shardId.toString(), \"data\");\n }\n\n // ============================================================================\n // Worker Queue Keys\n // ============================================================================\n\n workerQueueKey(consumerId: string): string {\n return this.#buildKey(\"worker\", consumerId);\n }\n\n // ============================================================================\n // Tenant Dispatch Keys (Two-Level Index)\n // ============================================================================\n\n dispatchKey(shardId: number): string {\n return this.#buildKey(\"dispatch\", shardId.toString());\n }\n\n tenantQueueIndexKey(tenantId: string): string {\n return this.#buildKey(\"tenantq\", tenantId);\n }\n\n // ============================================================================\n // Dead Letter Queue Keys\n // ============================================================================\n\n deadLetterQueueKey(tenantId: string): string {\n return this.#buildKey(\"dlq\", tenantId);\n }\n\n deadLetterQueueDataKey(tenantId: string): string {\n return this.#buildKey(\"dlq\", tenantId, \"data\");\n }\n\n // ============================================================================\n // Extraction Methods\n // ============================================================================\n\n /**\n * Extract tenant ID from a queue ID.\n * Default implementation assumes queue IDs are formatted as: tenant:{tenantId}:...\n * Override this method for custom queue ID formats.\n */\n extractTenantId(queueId: string): string {\n const parts = queueId.split(this.separator);\n // Expect format: tenant:{tenantId}:...\n if (parts.length >= 2 && parts[0] === \"tenant\" && parts[1]) {\n return parts[1];\n }\n // Fallback: return the first segment\n return parts[0] ?? \"\";\n }\n\n /**\n * Extract a group ID from a queue ID.\n * Default implementation looks for pattern: {groupName}:{groupId}:...\n * Override this method for custom queue ID formats.\n */\n extractGroupId(groupName: string, queueId: string): string {\n const parts = queueId.split(this.separator);\n\n // Look for the group name in the queue ID parts\n for (let i = 0; i < parts.length - 1; i++) {\n if (parts[i] === groupName) {\n const nextPart = parts[i + 1];\n if (nextPart) {\n return nextPart;\n }\n }\n }\n\n // Fallback: return an empty string\n return \"\";\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n #buildKey(...parts: string[]): string {\n return [this.prefix, ...parts].join(this.separator);\n }\n}\n\n/**\n * Key producer with custom extraction logic via callbacks.\n * Useful when queue IDs don't follow a standard pattern.\n */\nexport class CallbackFairQueueKeyProducer extends DefaultFairQueueKeyProducer {\n private readonly tenantExtractor: (queueId: string) => string;\n private readonly groupExtractor: (groupName: string, queueId: string) => string;\n\n constructor(options: {\n prefix?: string;\n separator?: string;\n extractTenantId: (queueId: string) => string;\n extractGroupId: (groupName: string, queueId: string) => string;\n }) {\n super({ prefix: options.prefix, separator: options.separator });\n this.tenantExtractor = options.extractTenantId;\n this.groupExtractor = options.extractGroupId;\n }\n\n override extractTenantId(queueId: string): string {\n return this.tenantExtractor(queueId);\n }\n\n override extractGroupId(groupName: string, queueId: string): string {\n return this.groupExtractor(groupName, queueId);\n }\n}\n\n/**\n * Key producer for running a fair queue on a Redis cluster. Each tenant belongs to one shard,\n * `jumpHash(tenantId, shardCount)`, and every key of a shard carries the hash tag\n * `{prefix:shard}`, so a shard's queues, items, payloads, tenant indexes, dispatch index,\n * in-flight set and concurrency sets share a slot and every script stays single-slot.\n *\n * Concurrency groups must be keyed by tenant id. The shard count can't change without moving keys.\n *\n * Key structure (S = the tenant's shard):\n * - Dispatch index: {prefix:S}:dispatch\n * - Tenant queue index: {prefix:S}:tenantq:{tenantId}\n * - Queue: {prefix:S}:queue:{queueId}, items {prefix:S}:queue:{queueId}:items\n * - Payload: {prefix:S}:payload:{queueId}:{messageId}\n * - Payload bytes per tenant: {prefix:S}:payloadbytes:{tenantId}\n * - Concurrency: {prefix:S}:concurrency:{groupName}:{tenantId}\n * - In-flight: {prefix:S}:inflight, data {prefix:S}:inflight:data\n * - Dead letter queue: {prefix:S}:dlq:{tenantId}, data {prefix:S}:dlq:{tenantId}:data\n * - Legacy master queue: {prefix:S}:master\n * - Worker queue: {prefix}:worker:{consumerId} (its own slot)\n * - DRR deficits: {prefix}:drr:deficit (its own slot)\n */\nexport class TenantShardedFairQueueKeyProducer implements FairQueueKeyProducer {\n readonly shardCount: number;\n private readonly prefix: string;\n private readonly tenantExtractor: (queueId: string) => string;\n private readonly groupExtractor: (groupName: string, queueId: string) => string;\n\n constructor(options: {\n prefix: string;\n shardCount: number;\n extractTenantId: (queueId: string) => string;\n extractGroupId: (groupName: string, queueId: string) => string;\n }) {\n if (!Number.isInteger(options.shardCount) || options.shardCount < 1) {\n throw new Error(`shardCount must be a positive integer, got ${options.shardCount}`);\n }\n this.prefix = options.prefix;\n this.shardCount = options.shardCount;\n this.tenantExtractor = options.extractTenantId;\n this.groupExtractor = options.extractGroupId;\n }\n\n tenantShard(tenantId: string): number {\n return jumpHash(tenantId, this.shardCount);\n }\n\n masterQueueKey(shardId: number): string {\n return `${this.#tag(shardId)}:master`;\n }\n\n queueKey(queueId: string): string {\n return `${this.#queueTag(queueId)}:queue:${queueId}`;\n }\n\n queueItemsKey(queueId: string): string {\n return `${this.#queueTag(queueId)}:queue:${queueId}:items`;\n }\n\n payloadKey(queueId: string, messageId: string): string {\n return `${this.#queueTag(queueId)}:payload:${queueId}:${messageId}`;\n }\n\n tenantPayloadBytesKey(tenantId: string): string {\n return `${this.#tag(this.tenantShard(tenantId))}:payloadbytes:${tenantId}`;\n }\n\n concurrencyKey(groupName: string, groupId: string): string {\n return `${this.#tag(this.tenantShard(groupId))}:concurrency:${groupName}:${groupId}`;\n }\n\n concurrencyKeyPattern(groupName: string, shardId: number): string {\n return `${this.#tag(shardId)}:concurrency:${groupName}:*`;\n }\n\n inflightKey(shardId: number): string {\n return `${this.#tag(shardId)}:inflight`;\n }\n\n inflightDataKey(shardId: number): string {\n return `${this.#tag(shardId)}:inflight:data`;\n }\n\n workerQueueKey(consumerId: string): string {\n return `${this.prefix}:worker:${consumerId}`;\n }\n\n deadLetterQueueKey(tenantId: string): string {\n return `${this.#tag(this.tenantShard(tenantId))}:dlq:${tenantId}`;\n }\n\n deadLetterQueueDataKey(tenantId: string): string {\n return `${this.#tag(this.tenantShard(tenantId))}:dlq:${tenantId}:data`;\n }\n\n dispatchKey(shardId: number): string {\n return `${this.#tag(shardId)}:dispatch`;\n }\n\n tenantQueueIndexKey(tenantId: string): string {\n return `${this.#tag(this.tenantShard(tenantId))}:tenantq:${tenantId}`;\n }\n\n drrDeficitKey(): string {\n return `${this.prefix}:drr:deficit`;\n }\n\n extractTenantId(queueId: string): string {\n return this.tenantExtractor(queueId);\n }\n\n extractGroupId(groupName: string, queueId: string): string {\n return this.groupExtractor(groupName, queueId);\n }\n\n #queueTag(queueId: string): string {\n return this.#tag(this.tenantShard(this.tenantExtractor(queueId)));\n }\n\n #tag(shardId: number): string {\n return `{${this.prefix}:${shardId}}`;\n }\n}\n","import { calculateNextRetryDelay } from \"@trigger.dev/core/v3\";\nimport type { RetryOptions } from \"@trigger.dev/core/v3/schemas\";\n\n/**\n * RetryStrategy interface for pluggable retry logic.\n */\nexport interface RetryStrategy {\n /**\n * Calculate the next retry delay in milliseconds.\n * Return null to indicate the message should be sent to DLQ.\n *\n * @param attempt - Current attempt number (1-indexed)\n * @param error - Optional error from the failed attempt\n * @returns Delay in milliseconds, or null to send to DLQ\n */\n getNextDelay(attempt: number, error?: Error): number | null;\n\n /**\n * Maximum number of attempts before moving to DLQ.\n */\n maxAttempts: number;\n}\n\n/**\n * Exponential backoff retry strategy.\n *\n * Uses the same algorithm as @trigger.dev/core's calculateNextRetryDelay.\n */\nexport class ExponentialBackoffRetry implements RetryStrategy {\n readonly maxAttempts: number;\n private options: RetryOptions;\n\n constructor(options?: Partial<RetryOptions>) {\n this.options = {\n maxAttempts: options?.maxAttempts ?? 12,\n factor: options?.factor ?? 2,\n minTimeoutInMs: options?.minTimeoutInMs ?? 1_000,\n maxTimeoutInMs: options?.maxTimeoutInMs ?? 3_600_000, // 1 hour\n randomize: options?.randomize ?? true,\n };\n this.maxAttempts = this.options.maxAttempts ?? 12;\n }\n\n getNextDelay(attempt: number, _error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null; // Send to DLQ\n }\n\n const delay = calculateNextRetryDelay(this.options, attempt);\n return delay ?? null;\n }\n}\n\n/**\n * Fixed delay retry strategy.\n *\n * Always waits the same amount of time between retries.\n */\nexport class FixedDelayRetry implements RetryStrategy {\n readonly maxAttempts: number;\n private delayMs: number;\n\n constructor(options: { maxAttempts: number; delayMs: number }) {\n this.maxAttempts = options.maxAttempts;\n this.delayMs = options.delayMs;\n }\n\n getNextDelay(attempt: number, _error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null; // Send to DLQ\n }\n return this.delayMs;\n }\n}\n\n/**\n * Linear backoff retry strategy.\n *\n * Delay increases linearly with each attempt.\n */\nexport class LinearBackoffRetry implements RetryStrategy {\n readonly maxAttempts: number;\n private baseDelayMs: number;\n private maxDelayMs: number;\n\n constructor(options: { maxAttempts: number; baseDelayMs: number; maxDelayMs?: number }) {\n this.maxAttempts = options.maxAttempts;\n this.baseDelayMs = options.baseDelayMs;\n this.maxDelayMs = options.maxDelayMs ?? options.baseDelayMs * options.maxAttempts;\n }\n\n getNextDelay(attempt: number, _error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null; // Send to DLQ\n }\n const delay = this.baseDelayMs * attempt;\n return Math.min(delay, this.maxDelayMs);\n }\n}\n\n/**\n * No retry strategy.\n *\n * Messages go directly to DLQ on first failure.\n */\nexport class NoRetry implements RetryStrategy {\n readonly maxAttempts = 1;\n\n getNextDelay(_attempt: number, _error?: Error): number | null {\n return null; // Always send to DLQ\n }\n}\n\n/**\n * Immediate retry strategy.\n *\n * Retries immediately without any delay.\n */\nexport class ImmediateRetry implements RetryStrategy {\n readonly maxAttempts: number;\n\n constructor(maxAttempts: number) {\n this.maxAttempts = maxAttempts;\n }\n\n getNextDelay(attempt: number, _error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null; // Send to DLQ\n }\n return 0; // Immediate retry\n }\n}\n\n/**\n * Custom retry strategy that uses a user-provided function.\n */\nexport class CustomRetry implements RetryStrategy {\n readonly maxAttempts: number;\n private calculateDelay: (attempt: number, error?: Error) => number | null;\n\n constructor(options: {\n maxAttempts: number;\n calculateDelay: (attempt: number, error?: Error) => number | null;\n }) {\n this.maxAttempts = options.maxAttempts;\n this.calculateDelay = options.calculateDelay;\n }\n\n getNextDelay(attempt: number, error?: Error): number | null {\n if (attempt >= this.maxAttempts) {\n return null;\n }\n return this.calculateDelay(attempt, error);\n }\n}\n\n/**\n * Default retry options matching @trigger.dev/core defaults.\n */\nexport const defaultRetryOptions: RetryOptions = {\n maxAttempts: 12,\n factor: 2,\n minTimeoutInMs: 1_000,\n maxTimeoutInMs: 3_600_000,\n randomize: true,\n};\n\n/**\n * Create an exponential backoff retry strategy with default options.\n */\nexport function createDefaultRetryStrategy(): RetryStrategy {\n return new ExponentialBackoffRetry(defaultRetryOptions);\n}\n","import type { FairScheduler, SchedulerContext, TenantQueues } from \"./types.js\";\n\n/**\n * Re-export scheduler types for convenience.\n */\nexport type { FairScheduler, SchedulerContext, TenantQueues };\n\n/**\n * Base class for scheduler implementations.\n * Provides common utilities and default implementations.\n */\nexport abstract class BaseScheduler implements FairScheduler {\n /**\n * Select queues for processing from a master queue shard.\n * Must be implemented by subclasses.\n */\n abstract selectQueues(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<TenantQueues[]>;\n\n /**\n * Called after processing a message to update scheduler state.\n * Default implementation does nothing.\n */\n async recordProcessed(_tenantId: string, _queueId: string): Promise<void> {\n // Default: no state tracking\n }\n\n /**\n * Called after processing multiple messages to update scheduler state.\n * Batch variant for efficiency - reduces Redis calls when processing multiple messages.\n * Default implementation does nothing.\n */\n async recordProcessedBatch(_tenantId: string, _queueId: string, _count: number): Promise<void> {\n // Default: no state tracking\n }\n\n /**\n * Initialize the scheduler.\n * Default implementation does nothing.\n */\n async initialize(): Promise<void> {\n // Default: no initialization needed\n }\n\n /**\n * Cleanup scheduler resources.\n * Default implementation does nothing.\n */\n async close(): Promise<void> {\n // Default: no cleanup needed\n }\n\n /**\n * Helper to group queues by tenant.\n */\n protected groupQueuesByTenant(\n queues: Array<{ queueId: string; tenantId: string }>\n ): Map<string, string[]> {\n const grouped = new Map<string, string[]>();\n\n for (const { queueId, tenantId } of queues) {\n const existing = grouped.get(tenantId) ?? [];\n existing.push(queueId);\n grouped.set(tenantId, existing);\n }\n\n return grouped;\n }\n\n /**\n * Helper to convert grouped queues to TenantQueues array.\n */\n protected toTenantQueuesArray(grouped: Map<string, string[]>): TenantQueues[] {\n return Array.from(grouped.entries()).map(([tenantId, queues]) => ({\n tenantId,\n queues,\n }));\n }\n\n /**\n * Helper to filter out tenants at capacity.\n */\n protected async filterAtCapacity(\n tenants: TenantQueues[],\n context: SchedulerContext,\n groupName: string = \"tenant\"\n ): Promise<TenantQueues[]> {\n const filtered: TenantQueues[] = [];\n\n for (const tenant of tenants) {\n const isAtCapacity = await context.isAtCapacity(groupName, tenant.tenantId);\n if (!isAtCapacity) {\n filtered.push(tenant);\n }\n }\n\n return filtered;\n }\n}\n\n/**\n * Simple noop scheduler that returns empty results.\n * Useful for testing or disabling scheduling.\n */\nexport class NoopScheduler extends BaseScheduler {\n async selectQueues(\n _masterQueueShard: string,\n _consumerId: string,\n _context: SchedulerContext\n ): Promise<TenantQueues[]> {\n return [];\n }\n}\n","import type { RedisClient } from \"@internal/redis\";\nimport { createFairQueueRedisClient } from \"../connection.js\";\nimport { BaseScheduler } from \"../scheduler.js\";\nimport type {\n DRRSchedulerConfig,\n DispatchSchedulerContext,\n FairQueueKeyProducer,\n SchedulerContext,\n TenantQueues,\n QueueWithScore,\n} from \"../types.js\";\n\n/**\n * Deficit Round Robin (DRR) Scheduler.\n *\n * DRR ensures fair processing across tenants by:\n * - Allocating a \"quantum\" of credits to each tenant per round\n * - Accumulating unused credits as \"deficit\"\n * - Processing from tenants with available deficit\n * - Capping deficit to prevent starvation\n *\n * Key improvements over basic implementations:\n * - Atomic deficit operations using Lua scripts\n * - Efficient iteration through tenants\n * - Automatic deficit cleanup for inactive tenants\n */\nexport class DRRScheduler extends BaseScheduler {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private quantum: number;\n private maxDeficit: number;\n private masterQueueLimit: number;\n private logger: NonNullable<DRRSchedulerConfig[\"logger\"]>;\n\n constructor(private config: DRRSchedulerConfig) {\n super();\n this.redis = createFairQueueRedisClient(config.redis);\n this.keys = config.keys;\n this.quantum = config.quantum;\n this.maxDeficit = config.maxDeficit;\n this.masterQueueLimit = config.masterQueueLimit ?? 1000;\n this.logger = config.logger ?? {\n debug: () => {},\n error: () => {},\n };\n\n this.#registerCommands();\n }\n\n // ============================================================================\n // FairScheduler Implementation\n // ============================================================================\n\n /**\n * Select queues for processing using DRR algorithm.\n *\n * Algorithm:\n * 1. Get all queues from the master shard\n * 2. Group by tenant\n * 3. Filter out tenants at concurrency capacity\n * 4. Add quantum to each tenant's deficit (atomically)\n * 5. Select queues from tenants with deficit >= 1\n * 6. Order tenants by deficit (highest first for fairness)\n */\n async selectQueues(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<TenantQueues[]> {\n // Get all queues from the master shard\n const queues = await this.#getQueuesFromShard(masterQueueShard);\n\n if (queues.length === 0) {\n return [];\n }\n\n // Group queues by tenant\n const queuesByTenant = this.groupQueuesByTenant(\n queues.map((q) => ({ queueId: q.queueId, tenantId: q.tenantId }))\n );\n\n // Get unique tenant IDs\n const tenantIds = Array.from(queuesByTenant.keys());\n\n // Add quantum to all active tenants atomically\n const deficits = await this.#addQuantumToTenants(tenantIds);\n\n // Build tenant data with deficits\n const tenantData: Array<{\n tenantId: string;\n deficit: number;\n queues: string[];\n isAtCapacity: boolean;\n }> = await Promise.all(\n tenantIds.map(async (tenantId, index) => {\n const isAtCapacity = await context.isAtCapacity(\"tenant\", tenantId);\n return {\n tenantId,\n deficit: deficits[index] ?? 0,\n queues: queuesByTenant.get(tenantId) ?? [],\n isAtCapacity,\n };\n })\n );\n\n // Filter out tenants at capacity or with no deficit\n const eligibleTenants = tenantData.filter((t) => !t.isAtCapacity && t.deficit >= 1);\n\n // Log tenants blocked by capacity\n const blockedTenants = tenantData.filter((t) => t.isAtCapacity);\n if (blockedTenants.length > 0) {\n this.logger.debug(\"DRR: tenants blocked by concurrency\", {\n blockedCount: blockedTenants.length,\n blockedTenants: blockedTenants.map((t) => t.tenantId),\n });\n }\n\n // Sort by deficit (highest first for fairness)\n eligibleTenants.sort((a, b) => b.deficit - a.deficit);\n\n this.logger.debug(\"DRR: queue selection complete\", {\n totalQueues: queues.length,\n totalTenants: tenantIds.length,\n eligibleTenants: eligibleTenants.length,\n topTenantDeficit: eligibleTenants[0]?.deficit,\n });\n\n // Convert to TenantQueues format\n return eligibleTenants.map((t) => ({\n tenantId: t.tenantId,\n queues: t.queues,\n }));\n }\n\n /**\n * Select queues using the two-level tenant dispatch index.\n *\n * Algorithm:\n * 1. ZRANGEBYSCORE on dispatch index (gets only tenants with queues - much smaller)\n * 2. Add quantum to each tenant's deficit (atomically)\n * 3. Check capacity as safety net (dispatch should only have tenants with capacity)\n * 4. Select tenants with deficit >= 1, sorted by deficit (highest first)\n * 5. For each tenant, fetch their queues from Level 2 index\n */\n async selectQueuesFromDispatch(\n dispatchShardKey: string,\n consumerId: string,\n context: DispatchSchedulerContext\n ): Promise<TenantQueues[]> {\n // Level 1: Get tenants from dispatch index\n const tenants = await this.#getTenantsFromDispatch(dispatchShardKey);\n\n if (tenants.length === 0) {\n return [];\n }\n\n const tenantIds = tenants.map((t) => t.tenantId);\n\n // Add quantum to all active tenants atomically (1 Lua call)\n const deficits = await this.#addQuantumToTenants(tenantIds);\n\n // Build candidates sorted by deficit (highest first)\n const candidates = tenantIds\n .map((tenantId, index) => ({ tenantId, deficit: deficits[index] ?? 0 }))\n .filter((t) => t.deficit >= 1);\n\n candidates.sort((a, b) => b.deficit - a.deficit);\n\n // Pick the first tenant with available capacity and fetch their queues.\n // This keeps the scheduler cheap: O(1) in the common case where the\n // highest-deficit tenant has capacity. The consumer loop iterates fast\n // (1ms yield between rounds) so we cycle through tenants quickly.\n for (const { tenantId, deficit } of candidates) {\n const isAtCapacity = await context.isAtCapacity(\"tenant\", tenantId);\n if (isAtCapacity) continue;\n\n // Limit queues fetched to what the tenant can actually process this round.\n // deficit = max messages this tenant should process, so no point fetching\n // more queues than that (each queue yields at least 1 message).\n const queueLimit = Math.ceil(deficit);\n const queues = await context.getQueuesForTenant(tenantId, queueLimit);\n if (queues.length > 0) {\n this.logger.debug(\"DRR dispatch: selected tenant\", {\n dispatchTenants: tenants.length,\n candidates: candidates.length,\n selectedTenant: tenantId,\n deficit,\n queueLimit,\n queuesReturned: queues.length,\n });\n\n return [{ tenantId, queues: queues.map((q) => q.queueId) }];\n }\n }\n\n return [];\n }\n\n /**\n * Record that a message was processed from a tenant.\n * Decrements the tenant's deficit.\n */\n override async recordProcessed(tenantId: string, _queueId: string): Promise<void> {\n await this.#decrementDeficit(tenantId);\n }\n\n /**\n * Record that multiple messages were processed from a tenant.\n * Decrements the tenant's deficit by count atomically.\n */\n override async recordProcessedBatch(\n tenantId: string,\n _queueId: string,\n count: number\n ): Promise<void> {\n await this.#decrementDeficitBatch(tenantId, count);\n }\n\n override async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Public Methods for Deficit Management\n // ============================================================================\n\n /**\n * Get the current deficit for a tenant.\n */\n async getDeficit(tenantId: string): Promise<number> {\n const key = this.#deficitKey();\n const value = await this.redis.hget(key, tenantId);\n return value ? parseFloat(value) : 0;\n }\n\n /**\n * Reset deficit for a tenant.\n * Used when a tenant has no more active queues.\n */\n async resetDeficit(tenantId: string): Promise<void> {\n const key = this.#deficitKey();\n await this.redis.hdel(key, tenantId);\n }\n\n /**\n * Get all tenant deficits.\n */\n async getAllDeficits(): Promise<Map<string, number>> {\n const key = this.#deficitKey();\n const data = await this.redis.hgetall(key);\n const result = new Map<string, number>();\n for (const [tenantId, value] of Object.entries(data)) {\n result.set(tenantId, parseFloat(value));\n }\n return result;\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n #deficitKey(): string {\n if (this.keys.drrDeficitKey) {\n return this.keys.drrDeficitKey();\n }\n // Use a fixed key for DRR deficit tracking\n return `${this.keys.masterQueueKey(0).split(\":\")[0]}:drr:deficit`;\n }\n\n async #getTenantsFromDispatch(\n dispatchKey: string\n ): Promise<Array<{ tenantId: string; score: number }>> {\n const now = Date.now();\n const results = await this.redis.zrangebyscore(\n dispatchKey,\n \"-inf\",\n now,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n this.masterQueueLimit\n );\n\n const tenants: Array<{ tenantId: string; score: number }> = [];\n for (let i = 0; i < results.length; i += 2) {\n const tenantId = results[i];\n const scoreStr = results[i + 1];\n if (tenantId && scoreStr) {\n tenants.push({\n tenantId,\n score: parseFloat(scoreStr),\n });\n }\n }\n\n return tenants;\n }\n\n async #getQueuesFromShard(shardKey: string): Promise<QueueWithScore[]> {\n const now = Date.now();\n const results = await this.redis.zrangebyscore(\n shardKey,\n \"-inf\",\n now,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n this.masterQueueLimit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId: this.keys.extractTenantId(queueId),\n });\n }\n }\n\n return queues;\n }\n\n /**\n * Add quantum to multiple tenants atomically.\n * Returns the new deficit values.\n */\n async #addQuantumToTenants(tenantIds: string[]): Promise<number[]> {\n if (tenantIds.length === 0) {\n return [];\n }\n\n const key = this.#deficitKey();\n\n // Use Lua script for atomic quantum addition with capping\n const results = await this.redis.drrAddQuantum(\n key,\n this.quantum.toString(),\n this.maxDeficit.toString(),\n ...tenantIds\n );\n\n return results.map((r) => parseFloat(r));\n }\n\n /**\n * Decrement deficit for a tenant atomically.\n */\n async #decrementDeficit(tenantId: string): Promise<number> {\n const key = this.#deficitKey();\n\n // Use Lua script to decrement and ensure non-negative\n const result = await this.redis.drrDecrementDeficit(key, tenantId);\n return parseFloat(result);\n }\n\n /**\n * Decrement deficit for a tenant by a count atomically.\n */\n async #decrementDeficitBatch(tenantId: string, count: number): Promise<number> {\n const key = this.#deficitKey();\n\n // Use Lua script to decrement by count and ensure non-negative\n const result = await this.redis.drrDecrementDeficitBatch(key, tenantId, count.toString());\n return parseFloat(result);\n }\n\n #registerCommands(): void {\n // Atomic quantum addition with capping for multiple tenants\n this.redis.defineCommand(\"drrAddQuantum\", {\n numberOfKeys: 1,\n lua: `\nlocal deficitKey = KEYS[1]\nlocal quantum = tonumber(ARGV[1])\nlocal maxDeficit = tonumber(ARGV[2])\nlocal results = {}\n\nfor i = 3, #ARGV do\n local tenantId = ARGV[i]\n \n -- Add quantum to deficit\n local newDeficit = redis.call('HINCRBYFLOAT', deficitKey, tenantId, quantum)\n newDeficit = tonumber(newDeficit)\n \n -- Cap at maxDeficit\n if newDeficit > maxDeficit then\n redis.call('HSET', deficitKey, tenantId, maxDeficit)\n newDeficit = maxDeficit\n end\n \n table.insert(results, tostring(newDeficit))\nend\n\nreturn results\n `,\n });\n\n // Atomic deficit decrement with floor at 0\n this.redis.defineCommand(\"drrDecrementDeficit\", {\n numberOfKeys: 1,\n lua: `\nlocal deficitKey = KEYS[1]\nlocal tenantId = ARGV[1]\n\nlocal newDeficit = redis.call('HINCRBYFLOAT', deficitKey, tenantId, -1)\nnewDeficit = tonumber(newDeficit)\n\n-- Floor at 0\nif newDeficit < 0 then\n redis.call('HSET', deficitKey, tenantId, 0)\n newDeficit = 0\nend\n\nreturn tostring(newDeficit)\n `,\n });\n\n // Atomic deficit decrement by count with floor at 0\n this.redis.defineCommand(\"drrDecrementDeficitBatch\", {\n numberOfKeys: 1,\n lua: `\nlocal deficitKey = KEYS[1]\nlocal tenantId = ARGV[1]\nlocal count = tonumber(ARGV[2])\n\nlocal newDeficit = redis.call('HINCRBYFLOAT', deficitKey, tenantId, -count)\nnewDeficit = tonumber(newDeficit)\n\n-- Floor at 0\nif newDeficit < 0 then\n redis.call('HSET', deficitKey, tenantId, 0)\n newDeficit = 0\nend\n\nreturn tostring(newDeficit)\n `,\n });\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n drrAddQuantum(\n deficitKey: string,\n quantum: string,\n maxDeficit: string,\n ...tenantIds: string[]\n ): Promise<string[]>;\n\n drrDecrementDeficit(deficitKey: string, tenantId: string): Promise<string>;\n\n drrDecrementDeficitBatch(deficitKey: string, tenantId: string, count: string): Promise<string>;\n }\n}\n","import type { RedisClient } from \"@internal/redis\";\nimport { createFairQueueRedisClient } from \"../connection.js\";\nimport seedrandom from \"seedrandom\";\nimport { BaseScheduler } from \"../scheduler.js\";\nimport type {\n FairQueueKeyProducer,\n SchedulerContext,\n TenantQueues,\n QueueWithScore,\n WeightedSchedulerBiases,\n WeightedSchedulerConfig,\n} from \"../types.js\";\n\ninterface TenantConcurrency {\n current: number;\n limit: number;\n}\n\ninterface TenantSnapshot {\n tenantId: string;\n concurrency: TenantConcurrency;\n queues: Array<{ queueId: string; age: number }>;\n}\n\ninterface QueueSnapshot {\n id: string;\n tenants: Map<string, TenantSnapshot>;\n queues: Array<{ queueId: string; tenantId: string; age: number }>;\n}\n\nconst defaultBiases: WeightedSchedulerBiases = {\n concurrencyLimitBias: 0,\n availableCapacityBias: 0,\n queueAgeRandomization: 0,\n};\n\n/**\n * Weighted Shuffle Scheduler.\n *\n * Uses weighted random selection to balance between:\n * - Concurrency limit (higher limits get more weight)\n * - Available capacity (tenants with more capacity get more weight)\n * - Queue age (older queues get priority, with configurable randomization)\n *\n * Features:\n * - Snapshot caching to reduce Redis calls\n * - Configurable biases for fine-tuning\n * - Maximum tenant count to limit iteration\n */\nexport class WeightedScheduler extends BaseScheduler {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private rng: seedrandom.PRNG;\n private biases: WeightedSchedulerBiases;\n private defaultTenantLimit: number;\n private masterQueueLimit: number;\n private reuseSnapshotCount: number;\n private maximumTenantCount: number;\n\n // Snapshot cache\n private snapshotCache: Map<string, { snapshot: QueueSnapshot; reuseCount: number }> = new Map();\n\n constructor(private config: WeightedSchedulerConfig) {\n super();\n this.redis = createFairQueueRedisClient(config.redis);\n this.keys = config.keys;\n this.rng = seedrandom(config.seed);\n this.biases = config.biases ?? defaultBiases;\n this.defaultTenantLimit = config.defaultTenantConcurrencyLimit ?? 100;\n this.masterQueueLimit = config.masterQueueLimit ?? 100;\n this.reuseSnapshotCount = config.reuseSnapshotCount ?? 0;\n this.maximumTenantCount = config.maximumTenantCount ?? 0;\n }\n\n // ============================================================================\n // FairScheduler Implementation\n // ============================================================================\n\n async selectQueues(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<TenantQueues[]> {\n const snapshot = await this.#getOrCreateSnapshot(masterQueueShard, consumerId, context);\n\n if (snapshot.queues.length === 0) {\n return [];\n }\n\n // Shuffle tenants based on weights\n const shuffledTenants = this.#shuffleTenantsByWeight(snapshot);\n\n // Order queues within each tenant\n return shuffledTenants.map((tenantId) => ({\n tenantId,\n queues: this.#orderQueuesForTenant(snapshot, tenantId),\n }));\n }\n\n override async close(): Promise<void> {\n this.snapshotCache.clear();\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n async #getOrCreateSnapshot(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<QueueSnapshot> {\n const cacheKey = `${masterQueueShard}:${consumerId}`;\n\n // Check cache\n if (this.reuseSnapshotCount > 0) {\n const cached = this.snapshotCache.get(cacheKey);\n if (cached && cached.reuseCount < this.reuseSnapshotCount) {\n this.snapshotCache.set(cacheKey, {\n snapshot: cached.snapshot,\n reuseCount: cached.reuseCount + 1,\n });\n return cached.snapshot;\n }\n }\n\n // Create new snapshot\n const snapshot = await this.#createSnapshot(masterQueueShard, context);\n\n // Cache if enabled\n if (this.reuseSnapshotCount > 0) {\n this.snapshotCache.set(cacheKey, { snapshot, reuseCount: 0 });\n }\n\n return snapshot;\n }\n\n async #createSnapshot(\n masterQueueShard: string,\n context: SchedulerContext\n ): Promise<QueueSnapshot> {\n const now = Date.now();\n\n // Get queues from master shard\n let rawQueues = await this.#getQueuesFromShard(masterQueueShard, now);\n\n if (rawQueues.length === 0) {\n return { id: crypto.randomUUID(), tenants: new Map(), queues: [] };\n }\n\n // Apply maximum tenant count if configured\n if (this.maximumTenantCount > 0) {\n rawQueues = this.#selectTopTenantQueues(rawQueues);\n }\n\n // Build tenant data\n const tenantIds = new Set<string>();\n const queuesByTenant = new Map<string, Array<{ queueId: string; age: number }>>();\n\n for (const queue of rawQueues) {\n tenantIds.add(queue.tenantId);\n const tenantQueues = queuesByTenant.get(queue.tenantId) ?? [];\n tenantQueues.push({\n queueId: queue.queueId,\n age: now - queue.score,\n });\n queuesByTenant.set(queue.tenantId, tenantQueues);\n }\n\n // Get concurrency for each tenant\n const tenants = new Map<string, TenantSnapshot>();\n for (const tenantId of tenantIds) {\n const [current, limit] = await Promise.all([\n context.getCurrentConcurrency(\"tenant\", tenantId),\n context.getConcurrencyLimit(\"tenant\", tenantId),\n ]);\n\n // Skip tenants at capacity\n if (current >= limit) {\n continue;\n }\n\n tenants.set(tenantId, {\n tenantId,\n concurrency: { current, limit },\n queues: queuesByTenant.get(tenantId) ?? [],\n });\n }\n\n // Build final queue list (only from non-capacity tenants)\n const queues = rawQueues\n .filter((q) => tenants.has(q.tenantId))\n .map((q) => ({\n queueId: q.queueId,\n tenantId: q.tenantId,\n age: now - q.score,\n }));\n\n return {\n id: crypto.randomUUID(),\n tenants,\n queues,\n };\n }\n\n async #getQueuesFromShard(shardKey: string, maxScore: number): Promise<QueueWithScore[]> {\n const results = await this.redis.zrangebyscore(\n shardKey,\n \"-inf\",\n maxScore,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n this.masterQueueLimit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId: this.keys.extractTenantId(queueId),\n });\n }\n }\n\n return queues;\n }\n\n #selectTopTenantQueues(queues: QueueWithScore[]): QueueWithScore[] {\n // Group by tenant and calculate average age\n const queuesByTenant = new Map<string, QueueWithScore[]>();\n for (const queue of queues) {\n const tenantQueues = queuesByTenant.get(queue.tenantId) ?? [];\n tenantQueues.push(queue);\n queuesByTenant.set(queue.tenantId, tenantQueues);\n }\n\n // Calculate average age per tenant\n const tenantAges = Array.from(queuesByTenant.entries()).map(([tenantId, tQueues]) => {\n const avgAge = tQueues.reduce((sum, q) => sum + q.score, 0) / tQueues.length;\n return { tenantId, avgAge };\n });\n\n // Weighted shuffle to select top N tenants\n const maxAge = Math.max(...tenantAges.map((t) => t.avgAge));\n // Guard against division by zero: if maxAge is 0, assign equal weights\n const weightedTenants =\n maxAge === 0\n ? tenantAges.map((t) => ({\n tenantId: t.tenantId,\n weight: 1 / tenantAges.length,\n }))\n : tenantAges.map((t) => ({\n tenantId: t.tenantId,\n weight: t.avgAge / maxAge,\n }));\n\n const selectedTenants = new Set<string>();\n let remaining = [...weightedTenants];\n let totalWeight = remaining.reduce((sum, t) => sum + t.weight, 0);\n\n while (selectedTenants.size < this.maximumTenantCount && remaining.length > 0) {\n let random = this.rng() * totalWeight;\n let index = 0;\n\n while (random > 0 && index < remaining.length) {\n const item = remaining[index];\n if (item) {\n random -= item.weight;\n }\n index++;\n }\n index = Math.max(0, index - 1);\n\n const selected = remaining[index];\n if (selected) {\n selectedTenants.add(selected.tenantId);\n totalWeight -= selected.weight;\n remaining.splice(index, 1);\n }\n }\n\n // Return queues only from selected tenants\n return queues.filter((q) => selectedTenants.has(q.tenantId));\n }\n\n #shuffleTenantsByWeight(snapshot: QueueSnapshot): string[] {\n const tenantIds = Array.from(snapshot.tenants.keys());\n\n if (tenantIds.length === 0) {\n return [];\n }\n\n const { concurrencyLimitBias, availableCapacityBias } = this.biases;\n\n // If no biases, do simple shuffle\n if (concurrencyLimitBias === 0 && availableCapacityBias === 0) {\n return this.#shuffle(tenantIds);\n }\n\n // Calculate weights\n const maxLimit = Math.max(\n ...tenantIds.map((id) => snapshot.tenants.get(id)!.concurrency.limit)\n );\n\n const weightedTenants = tenantIds.map((tenantId) => {\n const tenant = snapshot.tenants.get(tenantId)!;\n let weight = 1;\n\n // Concurrency limit bias\n if (concurrencyLimitBias > 0) {\n // Guard against division by zero: if maxLimit is 0, treat normalizedLimit as 0\n const normalizedLimit = maxLimit > 0 ? tenant.concurrency.limit / maxLimit : 0;\n weight *= 1 + Math.pow(normalizedLimit * concurrencyLimitBias, 2);\n }\n\n // Available capacity bias\n if (availableCapacityBias > 0) {\n // Guard against division by zero: if limit is 0, treat as fully used (no bonus)\n const usedPercentage =\n tenant.concurrency.limit > 0 ? tenant.concurrency.current / tenant.concurrency.limit : 1;\n const availableBonus = 1 - usedPercentage;\n weight *= 1 + Math.pow(availableBonus * availableCapacityBias, 2);\n }\n\n return { tenantId, weight };\n });\n\n return this.#weightedShuffle(weightedTenants);\n }\n\n #orderQueuesForTenant(snapshot: QueueSnapshot, tenantId: string): string[] {\n const tenant = snapshot.tenants.get(tenantId);\n if (!tenant || tenant.queues.length === 0) {\n return [];\n }\n\n const queues = [...tenant.queues];\n const { queueAgeRandomization } = this.biases;\n\n // Strict age-based ordering\n if (queueAgeRandomization === 0) {\n return queues.sort((a, b) => b.age - a.age).map((q) => q.queueId);\n }\n\n // Weighted random based on age\n const maxAge = Math.max(...queues.map((q) => q.age));\n // Guard against division by zero: if maxAge is 0, all queues have equal weight\n const ageDenom = maxAge === 0 ? 1 : maxAge;\n const weightedQueues = queues.map((q) => ({\n queue: q,\n weight: 1 + (q.age / ageDenom) * queueAgeRandomization,\n }));\n\n const result: string[] = [];\n let remaining = [...weightedQueues];\n let totalWeight = remaining.reduce((sum, q) => sum + q.weight, 0);\n\n while (remaining.length > 0) {\n let random = this.rng() * totalWeight;\n let index = 0;\n\n while (random > 0 && index < remaining.length) {\n const item = remaining[index];\n if (item) {\n random -= item.weight;\n }\n index++;\n }\n index = Math.max(0, index - 1);\n\n const selected = remaining[index];\n if (selected) {\n result.push(selected.queue.queueId);\n totalWeight -= selected.weight;\n remaining.splice(index, 1);\n }\n }\n\n return result;\n }\n\n #shuffle<T>(array: T[]): T[] {\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(this.rng() * (i + 1));\n const temp = result[i];\n const swapValue = result[j];\n if (temp !== undefined && swapValue !== undefined) {\n result[i] = swapValue;\n result[j] = temp;\n }\n }\n return result;\n }\n\n #weightedShuffle(items: Array<{ tenantId: string; weight: number }>): string[] {\n const result: string[] = [];\n let remaining = [...items];\n let totalWeight = remaining.reduce((sum, item) => sum + item.weight, 0);\n\n while (remaining.length > 0) {\n let random = this.rng() * totalWeight;\n let index = 0;\n\n while (random > 0 && index < remaining.length) {\n const item = remaining[index];\n if (item) {\n random -= item.weight;\n }\n index++;\n }\n index = Math.max(0, index - 1);\n\n const selected = remaining[index];\n if (selected) {\n result.push(selected.tenantId);\n totalWeight -= selected.weight;\n remaining.splice(index, 1);\n }\n }\n\n return result;\n }\n}\n","import type { RedisClient } from \"@internal/redis\";\nimport { createFairQueueRedisClient, type FairQueueRedisOptions } from \"../connection.js\";\nimport { BaseScheduler } from \"../scheduler.js\";\nimport type {\n FairQueueKeyProducer,\n SchedulerContext,\n TenantQueues,\n QueueWithScore,\n} from \"../types.js\";\n\ninterface RoundRobinSchedulerConfig {\n redis: FairQueueRedisOptions;\n keys: FairQueueKeyProducer;\n /** Maximum queues to fetch from master queue per iteration */\n masterQueueLimit?: number;\n}\n\n/**\n * Round Robin Scheduler.\n *\n * Simple scheduler that processes tenants in strict rotation order.\n * Maintains a \"last served\" pointer in Redis to track position.\n *\n * Features:\n * - Predictable ordering (good for debugging)\n * - Fair rotation through all tenants\n * - No weighting or bias\n */\nexport class RoundRobinScheduler extends BaseScheduler {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private masterQueueLimit: number;\n\n constructor(private config: RoundRobinSchedulerConfig) {\n super();\n this.redis = createFairQueueRedisClient(config.redis);\n this.keys = config.keys;\n this.masterQueueLimit = config.masterQueueLimit ?? 1000;\n }\n\n // ============================================================================\n // FairScheduler Implementation\n // ============================================================================\n\n async selectQueues(\n masterQueueShard: string,\n consumerId: string,\n context: SchedulerContext\n ): Promise<TenantQueues[]> {\n const now = Date.now();\n\n // Get all queues from master shard\n const queues = await this.#getQueuesFromShard(masterQueueShard, now);\n\n if (queues.length === 0) {\n return [];\n }\n\n // Group queues by tenant\n const queuesByTenant = new Map<string, string[]>();\n const tenantOrder: string[] = [];\n\n for (const queue of queues) {\n if (!queuesByTenant.has(queue.tenantId)) {\n queuesByTenant.set(queue.tenantId, []);\n tenantOrder.push(queue.tenantId);\n }\n queuesByTenant.get(queue.tenantId)!.push(queue.queueId);\n }\n\n // Get last served index\n const lastServedIndex = await this.#getLastServedIndex(masterQueueShard);\n\n // Rotate tenant order based on last served\n const rotatedTenants = this.#rotateArray(tenantOrder, lastServedIndex);\n\n // Filter out tenants at capacity\n const eligibleTenants: TenantQueues[] = [];\n\n for (const tenantId of rotatedTenants) {\n const isAtCapacity = await context.isAtCapacity(\"tenant\", tenantId);\n if (!isAtCapacity) {\n const tenantQueues = queuesByTenant.get(tenantId) ?? [];\n // Sort queues by age (oldest first based on original scores)\n eligibleTenants.push({\n tenantId,\n queues: tenantQueues,\n });\n }\n }\n\n // Update last served index to the first eligible tenant\n const firstEligible = eligibleTenants[0];\n if (firstEligible) {\n const firstTenantIndex = tenantOrder.indexOf(firstEligible.tenantId);\n await this.#setLastServedIndex(masterQueueShard, firstTenantIndex + 1);\n }\n\n return eligibleTenants;\n }\n\n override async close(): Promise<void> {\n await this.redis.quit();\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n async #getQueuesFromShard(shardKey: string, maxScore: number): Promise<QueueWithScore[]> {\n const results = await this.redis.zrangebyscore(\n shardKey,\n \"-inf\",\n maxScore,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n this.masterQueueLimit\n );\n\n const queues: QueueWithScore[] = [];\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const scoreStr = results[i + 1];\n if (queueId && scoreStr) {\n queues.push({\n queueId,\n score: parseFloat(scoreStr),\n tenantId: this.keys.extractTenantId(queueId),\n });\n }\n }\n\n return queues;\n }\n\n #lastServedKey(shardKey: string): string {\n return `${shardKey}:rr:lastServed`;\n }\n\n async #getLastServedIndex(shardKey: string): Promise<number> {\n const key = this.#lastServedKey(shardKey);\n const value = await this.redis.get(key);\n return value ? parseInt(value, 10) : 0;\n }\n\n async #setLastServedIndex(shardKey: string, index: number): Promise<void> {\n const key = this.#lastServedKey(shardKey);\n await this.redis.set(key, index.toString());\n }\n\n #rotateArray<T>(array: T[], startIndex: number): T[] {\n if (array.length === 0) return [];\n const normalizedIndex = startIndex % array.length;\n return [...array.slice(normalizedIndex), ...array.slice(0, normalizedIndex)];\n }\n}\n","import type { RedisClient } from \"@internal/redis\";\nimport { SpanKind, type Span } from \"@internal/tracing\";\nimport { Logger } from \"@trigger.dev/core/logger\";\nimport type { AnyZodSchema, inferZodSchemaOutput } from \"@trigger.dev/core/v3\";\nimport { nanoid } from \"nanoid\";\nimport { setInterval, setTimeout as delay } from \"node:timers/promises\";\nimport { type z } from \"zod/v4\";\nimport { isAbortError } from \"../utils.js\";\nimport { ConcurrencyManager } from \"./concurrency.js\";\nimport { createFairQueueRedisClient, isClusterConnection } from \"./connection.js\";\nimport { MasterQueue } from \"./masterQueue.js\";\nimport { type RetryStrategy } from \"./retry.js\";\nimport {\n BatchedSpanManager,\n FairQueueAttributes,\n FairQueueTelemetry,\n MessagingAttributes,\n} from \"./telemetry.js\";\nimport { TenantDispatch } from \"./tenantDispatch.js\";\nimport type {\n DeadLetterMessage,\n DispatchSchedulerContext,\n EnqueueBatchOptions,\n EnqueueOptions,\n FairQueueKeyProducer,\n FairQueueOptions,\n FairScheduler,\n QueueCooloffState,\n QueueDescriptor,\n ReclaimedMessageInfo,\n SchedulerContext,\n StoredMessage,\n TenantQueues,\n} from \"./types.js\";\nimport { VisibilityManager } from \"./visibility.js\";\nimport { WorkerQueueManager } from \"./workerQueue.js\";\n\n// Re-export all types and components\nexport * from \"./concurrency.js\";\nexport * from \"./connection.js\";\nexport * from \"./keyProducer.js\";\nexport * from \"./masterQueue.js\";\nexport * from \"./retry.js\";\nexport * from \"./scheduler.js\";\nexport * from \"./schedulers/index.js\";\nexport * from \"./telemetry.js\";\nexport * from \"./tenantDispatch.js\";\nexport * from \"./types.js\";\nexport * from \"./visibility.js\";\nexport * from \"./workerQueue.js\";\n\n/** An enqueue that would take a tenant past `tenantPayloadBytesLimit`. */\nexport class TenantQueueFullError extends Error {\n constructor(\n readonly tenantId: string,\n readonly limitBytes: number\n ) {\n super(`Tenant ${tenantId} is at its limit of ${limitBytes} queued payload bytes`);\n this.name = \"TenantQueueFullError\";\n }\n}\n\n/**\n * FairQueue is the main orchestrator for fair queue message routing.\n *\n * FairQueue handles:\n * - Master queue with sharding (using jump consistent hash)\n * - Fair scheduling via pluggable schedulers\n * - Multi-level concurrency limiting\n * - Visibility timeouts with heartbeats\n * - Routing messages to worker queues\n * - Retry strategies with dead letter queue\n * - OpenTelemetry tracing and metrics\n *\n * External consumers are responsible for:\n * - Running their own worker queue consumer loops\n * - Calling complete/release/fail APIs after processing\n *\n * @typeParam TPayloadSchema - Zod schema for message payload validation\n */\nexport class FairQueue<TPayloadSchema extends AnyZodSchema = z.ZodUnknown> {\n private redis: RedisClient;\n private keys: FairQueueKeyProducer;\n private scheduler: FairScheduler;\n private masterQueue: MasterQueue;\n private concurrencyManager?: ConcurrencyManager;\n private visibilityManager: VisibilityManager;\n private workerQueueManager: WorkerQueueManager;\n private telemetry: FairQueueTelemetry;\n private logger: Logger;\n\n // Configuration\n private payloadSchema?: TPayloadSchema;\n private validateOnEnqueue: boolean;\n private retryStrategy?: RetryStrategy;\n private deadLetterQueueEnabled: boolean;\n private shardCount: number;\n private consumerCount: number;\n private consumerIntervalMs: number;\n private visibilityTimeoutMs: number;\n private heartbeatIntervalMs: number;\n private reclaimIntervalMs: number;\n private reconcileIntervalMs: number;\n private workerQueueResolver: (\n message: StoredMessage<inferZodSchemaOutput<TPayloadSchema>>\n ) => string;\n private batchClaimSize: number;\n private separatePayloads: boolean;\n\n // Cooloff state\n private cooloffEnabled: boolean;\n private cooloffThreshold: number;\n private cooloffPeriodMs: number;\n private maxCooloffStatesSize: number;\n private queueCooloffStates = new Map<string, QueueCooloffState>();\n\n // Worker queue backpressure\n private workerQueueMaxDepth: number;\n private workerQueueDepthCheckId?: string;\n\n // Consumer tracing\n private consumerTraceMaxIterations: number;\n private consumerTraceTimeoutSeconds: number;\n private batchedSpanManager: BatchedSpanManager;\n\n // Runtime state\n private isRunning = false;\n private abortController: AbortController;\n private masterQueueConsumerLoops: Promise<void>[] = [];\n private reclaimLoop?: Promise<void>;\n private reconcileLoop?: Promise<void>;\n\n // Queue descriptor cache for message processing\n private queueDescriptorCache = new Map<string, QueueDescriptor>();\n\n // Two-level tenant dispatch\n private tenantDispatch: TenantDispatch;\n\n constructor(private options: FairQueueOptions<TPayloadSchema>) {\n FairQueue.#validateLayout(options);\n this.redis = createFairQueueRedisClient(options.redis);\n this.keys = options.keys;\n this.separatePayloads = options.separatePayloads ?? false;\n this.scheduler = options.scheduler;\n this.logger = options.logger ?? new Logger(\"FairQueue\", \"info\");\n this.abortController = new AbortController();\n\n // Payload validation\n this.payloadSchema = options.payloadSchema;\n this.validateOnEnqueue = options.validateOnEnqueue ?? false;\n\n // Retry and DLQ\n this.retryStrategy = options.retry?.strategy;\n this.deadLetterQueueEnabled = options.retry?.deadLetterQueue ?? true;\n\n // Configuration\n this.shardCount = options.keys.shardCount ?? options.shardCount ?? 1;\n this.consumerCount = options.consumerCount ?? 1;\n this.consumerIntervalMs = options.consumerIntervalMs ?? 100;\n this.visibilityTimeoutMs = options.visibilityTimeoutMs ?? 30_000;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? this.visibilityTimeoutMs / 3;\n this.reclaimIntervalMs = options.reclaimIntervalMs ?? 5_000;\n this.reconcileIntervalMs = options.reconcileIntervalMs ?? 60_000;\n\n // Worker queue resolver (required)\n this.workerQueueResolver = options.workerQueue.resolveWorkerQueue;\n\n // Batch claiming\n this.batchClaimSize = options.batchClaimSize ?? 10;\n\n // Cooloff\n this.cooloffEnabled = options.cooloff?.enabled ?? true;\n this.cooloffThreshold = options.cooloff?.threshold ?? 10;\n this.cooloffPeriodMs = options.cooloff?.periodMs ?? 10_000;\n this.maxCooloffStatesSize = options.cooloff?.maxStatesSize ?? 1000;\n\n // Worker queue backpressure\n this.workerQueueMaxDepth = options.workerQueueMaxDepth ?? 0;\n this.workerQueueDepthCheckId = options.workerQueueDepthCheckId;\n\n // Consumer tracing\n this.consumerTraceMaxIterations = options.consumerTraceMaxIterations ?? 500;\n this.consumerTraceTimeoutSeconds = options.consumerTraceTimeoutSeconds ?? 60;\n\n // Initialize telemetry\n this.telemetry = new FairQueueTelemetry({\n tracer: options.tracer,\n meter: options.meter,\n name: options.name ?? \"fairqueue\",\n });\n\n // Initialize batched span manager for consumer tracing\n this.batchedSpanManager = new BatchedSpanManager({\n tracer: options.tracer,\n name: options.name ?? \"fairqueue\",\n maxIterations: this.consumerTraceMaxIterations,\n timeoutSeconds: this.consumerTraceTimeoutSeconds,\n getDynamicAttributes: () => ({\n \"cache.descriptor_size\": this.queueDescriptorCache.size,\n \"cache.cooloff_states_size\": this.queueCooloffStates.size,\n }),\n });\n\n // Initialize components\n this.masterQueue = new MasterQueue({\n redis: options.redis,\n keys: options.keys,\n shardCount: this.shardCount,\n });\n\n this.tenantDispatch = new TenantDispatch({\n redis: options.redis,\n keys: options.keys,\n shardCount: this.shardCount,\n });\n\n if (options.concurrencyGroups && options.concurrencyGroups.length > 0) {\n this.concurrencyManager = new ConcurrencyManager({\n redis: options.redis,\n keys: options.keys,\n groups: options.concurrencyGroups,\n logger: {\n debug: (msg, ctx) => this.logger.debug(msg, ctx),\n error: (msg, ctx) => this.logger.error(msg, ctx),\n },\n });\n }\n\n this.visibilityManager = new VisibilityManager({\n redis: options.redis,\n keys: options.keys,\n shardCount: this.shardCount,\n defaultTimeoutMs: this.visibilityTimeoutMs,\n logger: {\n debug: (msg, ctx) => this.logger.debug(msg, ctx),\n error: (msg, ctx) => this.logger.error(msg, ctx),\n },\n });\n\n // Worker queue manager for pushing messages to worker queues\n this.workerQueueManager = new WorkerQueueManager({\n redis: options.redis,\n keys: options.keys,\n logger: {\n debug: (msg, ctx) => this.logger.debug(msg, ctx),\n error: (msg, ctx) => this.logger.error(msg, ctx),\n },\n });\n\n this.#registerCommands();\n\n // Auto-start consumers if not disabled\n if (options.startConsumers !== false) {\n this.start();\n }\n }\n\n // ============================================================================\n // Public API - Telemetry\n // ============================================================================\n\n /**\n * Register observable gauge callbacks for telemetry.\n * Call this after FairQueue is created to enable gauge metrics.\n *\n * @param options.observedTenants - List of tenant IDs to observe for DLQ metrics\n */\n registerTelemetryGauges(options?: { observedTenants?: string[] }): void {\n this.telemetry.registerGaugeCallbacks({\n getMasterQueueLength: async (shardId: number) => {\n return await this.masterQueue.getShardQueueCount(shardId);\n },\n getDispatchLength: async (shardId: number) => {\n return await this.tenantDispatch.getShardTenantCount(shardId);\n },\n getInflightCount: async (shardId: number) => {\n return await this.visibilityManager.getInflightCount(shardId);\n },\n getDLQLength: async (tenantId: string) => {\n return await this.getDeadLetterQueueLength(tenantId);\n },\n getOldestMessageAge: async (shardId: number) => {\n return await this.getOldestMessageAge(shardId);\n },\n shardCount: this.shardCount,\n observedTenants: options?.observedTenants,\n });\n }\n\n // ============================================================================\n // Public API - Enqueueing\n // ============================================================================\n\n /**\n * Enqueue a single message to a queue.\n */\n async enqueue(options: EnqueueOptions<inferZodSchemaOutput<TPayloadSchema>>): Promise<string> {\n return this.telemetry.trace(\n \"enqueue\",\n async (span) => {\n const messageId = options.messageId ?? nanoid();\n const timestamp = options.timestamp ?? Date.now();\n const queueKey = this.keys.queueKey(options.queueId);\n const queueItemsKey = this.keys.queueItemsKey(options.queueId);\n const dispatchShardId = this.tenantDispatch.getShardForTenant(options.tenantId);\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(options.tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n\n // Validate payload if schema provided and validation enabled\n if (this.validateOnEnqueue && this.payloadSchema) {\n const result = this.payloadSchema.safeParse(options.payload);\n if (!result.success) {\n throw new Error(`Payload validation failed: ${result.error.message}`);\n }\n }\n\n // Store queue descriptor for later use\n const descriptor: QueueDescriptor = {\n id: options.queueId,\n tenantId: options.tenantId,\n metadata: options.metadata ?? {},\n };\n this.queueDescriptorCache.set(options.queueId, descriptor);\n\n // Build stored message\n const storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>> = {\n id: messageId,\n queueId: options.queueId,\n tenantId: options.tenantId,\n payload: options.payload,\n timestamp,\n attempt: 1,\n workerQueue: this.workerQueueResolver\n ? this.workerQueueResolver({\n id: messageId,\n queueId: options.queueId,\n tenantId: options.tenantId,\n payload: options.payload,\n timestamp,\n attempt: 1,\n metadata: options.metadata,\n })\n : undefined,\n metadata: options.metadata,\n };\n\n if (this.separatePayloads) {\n const { payload, ...envelope } = storedMessage;\n const limit = options.ignorePayloadBytesLimit\n ? 0\n : ((await this.options.tenantPayloadBytesLimit?.(options.tenantId)) ?? 0);\n const result = await this.redis.enqueueMessageSeparatePayload(\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n this.keys.payloadKey!(options.queueId, messageId),\n this.keys.inflightKey(this.masterQueue.getShardForQueue(options.queueId)),\n this.keys.tenantPayloadBytesKey!(options.tenantId),\n options.queueId,\n messageId,\n timestamp.toString(),\n JSON.stringify(envelope),\n options.tenantId,\n JSON.stringify(payload),\n `${messageId}:${options.queueId}`,\n String(limit)\n );\n if (result === -1) {\n throw new TenantQueueFullError(options.tenantId, limit);\n }\n span.setAttribute(\"enqueued\", result === 1);\n } else {\n // Use atomic Lua script to enqueue and update tenant dispatch indexes\n await this.redis.enqueueMessageAtomicV2(\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n options.queueId,\n messageId,\n timestamp.toString(),\n JSON.stringify(storedMessage),\n options.tenantId\n );\n }\n\n span.setAttributes({\n [FairQueueAttributes.QUEUE_ID]: options.queueId,\n [FairQueueAttributes.TENANT_ID]: options.tenantId,\n [FairQueueAttributes.MESSAGE_ID]: messageId,\n [FairQueueAttributes.SHARD_ID]: dispatchShardId.toString(),\n });\n\n this.telemetry.recordEnqueue();\n\n this.logger.debug(\"Message enqueued\", {\n queueId: options.queueId,\n messageId,\n timestamp,\n });\n\n return messageId;\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n [MessagingAttributes.OPERATION]: \"publish\",\n },\n }\n );\n }\n\n /**\n * Enqueue multiple messages to a queue.\n */\n async enqueueBatch(\n options: EnqueueBatchOptions<inferZodSchemaOutput<TPayloadSchema>>\n ): Promise<string[]> {\n return this.telemetry.trace(\n \"enqueueBatch\",\n async (span) => {\n if (this.separatePayloads) {\n throw new Error(\"enqueueBatch isn't supported with separatePayloads\");\n }\n const queueKey = this.keys.queueKey(options.queueId);\n const queueItemsKey = this.keys.queueItemsKey(options.queueId);\n const dispatchShardId = this.tenantDispatch.getShardForTenant(options.tenantId);\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(options.tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n const now = Date.now();\n\n // Store queue descriptor\n const descriptor: QueueDescriptor = {\n id: options.queueId,\n tenantId: options.tenantId,\n metadata: options.metadata ?? {},\n };\n this.queueDescriptorCache.set(options.queueId, descriptor);\n\n const messageIds: string[] = [];\n const args: string[] = [];\n\n for (const message of options.messages) {\n const messageId = message.messageId ?? nanoid();\n const timestamp = message.timestamp ?? now;\n\n // Validate if enabled\n if (this.validateOnEnqueue && this.payloadSchema) {\n const result = this.payloadSchema.safeParse(message.payload);\n if (!result.success) {\n throw new Error(\n `Payload validation failed for message ${messageId}: ${result.error.message}`\n );\n }\n }\n\n const storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>> = {\n id: messageId,\n queueId: options.queueId,\n tenantId: options.tenantId,\n payload: message.payload,\n timestamp,\n attempt: 1,\n workerQueue: this.workerQueueResolver\n ? this.workerQueueResolver({\n id: messageId,\n queueId: options.queueId,\n tenantId: options.tenantId,\n payload: message.payload,\n timestamp,\n attempt: 1,\n metadata: options.metadata,\n })\n : undefined,\n metadata: options.metadata,\n };\n\n messageIds.push(messageId);\n args.push(messageId, timestamp.toString(), JSON.stringify(storedMessage));\n }\n\n // Use atomic Lua script for batch enqueue with tenant dispatch indexes\n await this.redis.enqueueBatchAtomicV2(\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n options.queueId,\n options.tenantId,\n ...args\n );\n\n span.setAttributes({\n [FairQueueAttributes.QUEUE_ID]: options.queueId,\n [FairQueueAttributes.TENANT_ID]: options.tenantId,\n [FairQueueAttributes.MESSAGE_COUNT]: messageIds.length,\n [FairQueueAttributes.SHARD_ID]: dispatchShardId.toString(),\n });\n\n this.telemetry.recordEnqueueBatch(messageIds.length);\n\n this.logger.debug(\"Batch enqueued\", {\n queueId: options.queueId,\n messageCount: messageIds.length,\n });\n\n return messageIds;\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n [MessagingAttributes.OPERATION]: \"publish\",\n },\n }\n );\n }\n\n // ============================================================================\n // Public API - Dead Letter Queue\n // ============================================================================\n\n /**\n * Get messages from the dead letter queue for a tenant.\n */\n async getDeadLetterMessages(\n tenantId: string,\n limit: number = 100\n ): Promise<DeadLetterMessage<inferZodSchemaOutput<TPayloadSchema>>[]> {\n if (!this.deadLetterQueueEnabled) {\n return [];\n }\n\n const dlqKey = this.keys.deadLetterQueueKey(tenantId);\n const dlqDataKey = this.keys.deadLetterQueueDataKey(tenantId);\n\n // Get message IDs with scores (deadLetteredAt timestamps)\n const results = await this.redis.zrange(dlqKey, 0, limit - 1, \"WITHSCORES\");\n\n const messages: DeadLetterMessage<inferZodSchemaOutput<TPayloadSchema>>[] = [];\n\n for (let i = 0; i < results.length; i += 2) {\n const messageId = results[i];\n const deadLetteredAtStr = results[i + 1];\n if (!messageId || !deadLetteredAtStr) continue;\n\n const dataJson = await this.redis.hget(dlqDataKey, messageId);\n if (!dataJson) continue;\n\n try {\n const data = JSON.parse(dataJson) as DeadLetterMessage<\n inferZodSchemaOutput<TPayloadSchema>\n >;\n data.deadLetteredAt = parseFloat(deadLetteredAtStr);\n messages.push(data);\n } catch {\n this.logger.error(\"Failed to parse DLQ message\", { messageId, tenantId });\n }\n }\n\n return messages;\n }\n\n /**\n * Redrive a message from DLQ back to its original queue.\n */\n async redriveMessage(tenantId: string, messageId: string): Promise<boolean> {\n if (!this.deadLetterQueueEnabled) {\n return false;\n }\n\n return this.telemetry.trace(\n \"redriveMessage\",\n async (span) => {\n const dlqKey = this.keys.deadLetterQueueKey(tenantId);\n const dlqDataKey = this.keys.deadLetterQueueDataKey(tenantId);\n\n // Get the message data\n const dataJson = await this.redis.hget(dlqDataKey, messageId);\n if (!dataJson) {\n return false;\n }\n\n const dlqMessage = JSON.parse(dataJson) as DeadLetterMessage<\n inferZodSchemaOutput<TPayloadSchema>\n >;\n\n // Re-enqueue with reset attempt count\n await this.enqueue({\n queueId: dlqMessage.queueId,\n tenantId: dlqMessage.tenantId,\n payload: dlqMessage.payload,\n messageId: dlqMessage.id,\n timestamp: Date.now(),\n });\n\n // Remove from DLQ\n const pipeline = this.redis.pipeline();\n pipeline.zrem(dlqKey, messageId);\n pipeline.hdel(dlqDataKey, messageId);\n await pipeline.exec();\n\n span.setAttributes({\n [FairQueueAttributes.TENANT_ID]: tenantId,\n [FairQueueAttributes.MESSAGE_ID]: messageId,\n });\n\n this.logger.info(\"Redrived message from DLQ\", { tenantId, messageId });\n\n return true;\n },\n {\n kind: SpanKind.PRODUCER,\n attributes: {\n [MessagingAttributes.OPERATION]: \"redrive\",\n },\n }\n );\n }\n\n /**\n * Redrive all messages from DLQ back to their original queues.\n */\n async redriveAll(tenantId: string): Promise<number> {\n const messages = await this.getDeadLetterMessages(tenantId, 1000);\n let count = 0;\n\n for (const message of messages) {\n const success = await this.redriveMessage(tenantId, message.id);\n if (success) count++;\n }\n\n return count;\n }\n\n /**\n * Purge all messages from a tenant's DLQ.\n */\n async purgeDeadLetterQueue(tenantId: string): Promise<number> {\n if (!this.deadLetterQueueEnabled) {\n return 0;\n }\n\n const dlqKey = this.keys.deadLetterQueueKey(tenantId);\n const dlqDataKey = this.keys.deadLetterQueueDataKey(tenantId);\n\n const count = await this.redis.zcard(dlqKey);\n\n const pipeline = this.redis.pipeline();\n pipeline.del(dlqKey);\n pipeline.del(dlqDataKey);\n await pipeline.exec();\n\n this.logger.info(\"Purged DLQ\", { tenantId, count });\n\n return count;\n }\n\n /**\n * Get the number of messages in a tenant's DLQ.\n */\n async getDeadLetterQueueLength(tenantId: string): Promise<number> {\n if (!this.deadLetterQueueEnabled) {\n return 0;\n }\n\n const dlqKey = this.keys.deadLetterQueueKey(tenantId);\n return await this.redis.zcard(dlqKey);\n }\n\n /**\n * Get the size of the in-memory queue descriptor cache.\n * This cache stores metadata for queues that have been enqueued.\n * The cache is cleaned up when queues are fully processed.\n */\n getQueueDescriptorCacheSize(): number {\n return this.queueDescriptorCache.size;\n }\n\n /**\n * Get the size of the in-memory cooloff states cache.\n * This cache tracks queues that are in cooloff due to repeated failures.\n * The cache is cleaned up when queues are fully processed or cooloff expires.\n */\n getQueueCooloffStatesSize(): number {\n return this.queueCooloffStates.size;\n }\n\n /**\n * Get all in-memory cache sizes for monitoring.\n * Useful for adding as span attributes.\n */\n getCacheSizes(): { descriptorCacheSize: number; cooloffStatesSize: number } {\n return {\n descriptorCacheSize: this.queueDescriptorCache.size,\n cooloffStatesSize: this.queueCooloffStates.size,\n };\n }\n\n // ============================================================================\n // Public API - Lifecycle\n // ============================================================================\n\n /**\n * Start the master queue consumer loops and reclaim loop.\n * FairQueue claims messages and pushes them to worker queues.\n * External consumers are responsible for consuming from worker queues.\n */\n start(): void {\n if (this.isRunning) {\n return;\n }\n\n this.isRunning = true;\n this.abortController = new AbortController();\n\n // Start master queue consumers (one per shard)\n // These claim messages from queues and push to worker queues\n for (let shardId = 0; shardId < this.shardCount; shardId++) {\n const loop = this.#runMasterQueueConsumerLoop(shardId);\n this.masterQueueConsumerLoops.push(loop);\n }\n\n // Start reclaim loop for handling timed-out messages\n this.reclaimLoop = this.#runReclaimLoop();\n\n if (this.concurrencyManager && this.reconcileIntervalMs > 0) {\n this.reconcileLoop = this.#runReconcileLoop();\n }\n\n this.logger.info(\"FairQueue started\", {\n consumerCount: this.consumerCount,\n shardCount: this.shardCount,\n consumerIntervalMs: this.consumerIntervalMs,\n });\n }\n\n /**\n * Stop the consumer loops gracefully.\n */\n async stop(): Promise<void> {\n if (!this.isRunning) {\n return;\n }\n\n this.isRunning = false;\n this.abortController.abort();\n\n await Promise.allSettled([\n ...this.masterQueueConsumerLoops,\n this.reclaimLoop,\n this.reconcileLoop,\n ]);\n\n this.masterQueueConsumerLoops = [];\n this.reclaimLoop = undefined;\n this.reconcileLoop = undefined;\n\n this.logger.info(\"FairQueue stopped\");\n }\n\n /**\n * Close all resources.\n */\n async close(): Promise<void> {\n await this.stop();\n\n // Clean up any remaining batched spans\n this.batchedSpanManager.cleanupAll();\n\n await Promise.all([\n this.masterQueue.close(),\n this.tenantDispatch.close(),\n this.concurrencyManager?.close(),\n this.visibilityManager.close(),\n this.workerQueueManager.close(),\n this.scheduler.close?.(),\n this.redis.quit(),\n ]);\n }\n\n // ============================================================================\n // Public API - Inspection\n // ============================================================================\n\n /**\n * Get the number of messages in a queue.\n */\n async getQueueLength(queueId: string): Promise<number> {\n const queueKey = this.keys.queueKey(queueId);\n return await this.redis.zcard(queueKey);\n }\n\n /**\n * Get total tenant count across dispatch shards plus any legacy queues still draining.\n */\n async getTotalQueueCount(): Promise<number> {\n const [dispatchCount, legacyCount] = await Promise.all([\n this.tenantDispatch.getTotalTenantCount(),\n this.masterQueue.getTotalQueueCount(),\n ]);\n return dispatchCount + legacyCount;\n }\n\n /**\n * Get the age in ms of the oldest due message not yet completed in a shard, or 0 if none.\n * Claims don't refresh the index scores, so claimed messages count until their queue next completes or empties.\n */\n async getOldestMessageAge(shardId: number): Promise<number> {\n const now = Date.now();\n const [[oldestTenant], [oldestLegacyQueue]] = await Promise.all([\n this.tenantDispatch.getTenantsFromShard(shardId, 1, now),\n this.masterQueue.getQueuesFromShard(shardId, 1, now),\n ]);\n const oldestScore = Math.min(\n oldestTenant?.score ?? Infinity,\n oldestLegacyQueue?.score ?? Infinity\n );\n if (!Number.isFinite(oldestScore)) return 0;\n return Math.max(0, now - oldestScore);\n }\n\n /**\n * Get total in-flight message count.\n */\n async getTotalInflightCount(): Promise<number> {\n return await this.visibilityManager.getTotalInflightCount();\n }\n\n /**\n * Get the shard ID for a queue.\n */\n getShardForQueue(queueId: string): number {\n return this.masterQueue.getShardForQueue(queueId);\n }\n\n // ============================================================================\n // Private - Master Queue Consumer Loop (Two-Stage)\n // ============================================================================\n\n async #runMasterQueueConsumerLoop(shardId: number): Promise<void> {\n const loopId = `master-shard-${shardId}`;\n\n // Initialize batched span tracking for this loop\n this.batchedSpanManager.initializeLoop(loopId);\n\n try {\n while (this.isRunning) {\n // Check abort signal\n if (this.abortController.signal.aborted) {\n break;\n }\n\n let hadWork = false;\n try {\n hadWork = await this.batchedSpanManager.withBatchedSpan(\n loopId,\n async (span) => {\n span.setAttribute(\"shard_id\", shardId);\n return await this.#processShardIteration(loopId, shardId, span);\n },\n {\n iterationSpanName: \"processMasterQueueShard\",\n attributes: { shard_id: shardId },\n }\n );\n } catch (error) {\n this.logger.error(\"Master queue consumer error\", {\n loopId,\n shardId,\n error: error instanceof Error ? error.message : String(error),\n });\n this.batchedSpanManager.markForRotation(loopId);\n }\n\n // Wait between iterations to prevent CPU spin\n // Short delay when there's work (yield to event loop), longer delay when idle\n const waitMs = hadWork ? 1 : this.consumerIntervalMs;\n await new Promise<void>((resolve, reject) => {\n const abortHandler = () => {\n clearTimeout(timeout);\n reject(new Error(\"AbortError\"));\n };\n const timeout = setTimeout(() => {\n // Must remove listener when timeout fires, otherwise listeners accumulate\n // (the { once: true } option only removes on abort, not on timeout)\n this.abortController.signal.removeEventListener(\"abort\", abortHandler);\n resolve();\n }, waitMs);\n this.abortController.signal.addEventListener(\"abort\", abortHandler, { once: true });\n });\n }\n } catch (error) {\n if (isAbortError(error)) {\n this.logger.debug(\"Master queue consumer aborted\", { loopId });\n this.batchedSpanManager.cleanup(loopId);\n return;\n }\n throw error;\n } finally {\n this.batchedSpanManager.cleanup(loopId);\n }\n }\n\n /**\n * Process a shard iteration. Runs both the new tenant dispatch path\n * and the legacy master queue drain path.\n */\n async #processShardIteration(\n loopId: string,\n shardId: number,\n parentSpan?: Span\n ): Promise<boolean> {\n let hadWork = false;\n\n // Main path: new two-level tenant dispatch (gets full DRR scheduling)\n hadWork = await this.#processDispatchShard(loopId, shardId, parentSpan);\n\n // Drain path: legacy master queue (simple scheduling, no DRR)\n // Check ZCARD first (O(1)) to skip the drain path when empty\n const legacyCount = await this.masterQueue.getShardQueueCount(shardId);\n if (legacyCount > 0) {\n const drainHadWork = await this.#drainLegacyMasterQueueShard(loopId, shardId, parentSpan);\n hadWork = hadWork || drainHadWork;\n }\n\n return hadWork;\n }\n\n /**\n * Main path: process queues using the two-level tenant dispatch index.\n * Level 1: dispatch index → tenantIds. Level 2: per-tenant → queueIds.\n */\n async #processDispatchShard(\n loopId: string,\n shardId: number,\n parentSpan?: Span\n ): Promise<boolean> {\n const dispatchKey = this.keys.dispatchKey(shardId);\n\n // Get dispatch index size for observability\n const dispatchSize = await this.tenantDispatch.getShardTenantCount(shardId);\n parentSpan?.setAttribute(\"dispatch_size\", dispatchSize);\n this.batchedSpanManager.incrementStat(loopId, \"dispatch_size_sum\", dispatchSize);\n\n // Create dispatch-aware scheduler context\n const schedulerContext: DispatchSchedulerContext = {\n ...this.#createSchedulerContext(),\n getQueuesForTenant: async (tenantId: string, limit?: number) => {\n return this.tenantDispatch.getQueuesForTenant(tenantId, limit);\n },\n };\n\n // Get queues to process from scheduler\n let tenantQueues: TenantQueues[];\n\n if (this.scheduler.selectQueuesFromDispatch) {\n // Use dispatch-aware scheduler method (DRR with two-level lookup)\n tenantQueues = await this.telemetry.trace(\n \"selectQueuesFromDispatch\",\n async (span) => {\n span.setAttribute(FairQueueAttributes.SHARD_ID, shardId.toString());\n span.setAttribute(FairQueueAttributes.CONSUMER_ID, loopId);\n span.setAttribute(\"dispatch_size\", dispatchSize);\n const result = await this.scheduler.selectQueuesFromDispatch!(\n dispatchKey,\n loopId,\n schedulerContext\n );\n span.setAttribute(\"tenant_count\", result.length);\n span.setAttribute(\n \"queue_count\",\n result.reduce((acc, t) => acc + t.queues.length, 0)\n );\n return result;\n },\n { kind: SpanKind.INTERNAL }\n );\n } else {\n // Fallback: read dispatch index, build flat queue list, use legacy selectQueues\n tenantQueues = await this.#fallbackDispatchToLegacyScheduler(\n loopId,\n shardId,\n schedulerContext,\n parentSpan\n );\n }\n\n if (tenantQueues.length === 0) {\n this.batchedSpanManager.incrementStat(loopId, \"empty_iterations\");\n return false;\n }\n\n return this.#processSelectedQueues(loopId, shardId, tenantQueues);\n }\n\n /**\n * Drain path: process remaining messages from the legacy master queue shard.\n * Uses simple ZRANGEBYSCORE without DRR - just flushing pre-deploy messages.\n */\n async #drainLegacyMasterQueueShard(\n loopId: string,\n shardId: number,\n parentSpan?: Span\n ): Promise<boolean> {\n const masterQueueKey = this.keys.masterQueueKey(shardId);\n const now = Date.now();\n\n // Simple fetch from old master queue - no DRR needed for drain\n const results = await this.redis.zrangebyscore(\n masterQueueKey,\n \"-inf\",\n now,\n \"WITHSCORES\",\n \"LIMIT\",\n 0,\n 100\n );\n\n if (results.length === 0) {\n return false;\n }\n\n // Parse results into QueueWithScore, group by tenant\n const byTenant = new Map<string, string[]>();\n for (let i = 0; i < results.length; i += 2) {\n const queueId = results[i];\n const _score = results[i + 1];\n if (queueId && _score) {\n const tenantId = this.keys.extractTenantId(queueId);\n const existing = byTenant.get(tenantId) ?? [];\n existing.push(queueId);\n byTenant.set(tenantId, existing);\n }\n }\n\n // Build TenantQueues, filter at-capacity tenants\n const tenantQueues: TenantQueues[] = [];\n for (const [tenantId, queueIds] of byTenant) {\n if (this.concurrencyManager) {\n const atCapacity = await this.concurrencyManager.isAtCapacity(\"tenant\", tenantId);\n if (atCapacity) continue;\n }\n tenantQueues.push({ tenantId, queues: queueIds });\n }\n\n if (tenantQueues.length === 0) {\n return false;\n }\n\n parentSpan?.setAttribute(\"drain_tenants\", tenantQueues.length);\n this.batchedSpanManager.incrementStat(loopId, \"drain_tenants\", tenantQueues.length);\n\n return this.#processSelectedQueues(loopId, shardId, tenantQueues);\n }\n\n /**\n * Fallback for schedulers that don't implement selectQueuesFromDispatch.\n * Reads dispatch index, fetches per-tenant queues, groups by tenant,\n * and filters at-capacity tenants. No DRR deficit tracking in this path.\n */\n async #fallbackDispatchToLegacyScheduler(\n loopId: string,\n shardId: number,\n context: DispatchSchedulerContext,\n parentSpan?: Span\n ): Promise<TenantQueues[]> {\n // Get tenants from dispatch\n const tenants = await this.tenantDispatch.getTenantsFromShard(shardId);\n if (tenants.length === 0) return [];\n\n // For each tenant, get their queues and build grouped result\n const tenantQueues: TenantQueues[] = [];\n for (const { tenantId } of tenants) {\n if (this.concurrencyManager) {\n const atCapacity = await this.concurrencyManager.isAtCapacity(\"tenant\", tenantId);\n if (atCapacity) continue;\n }\n const queues = await this.tenantDispatch.getQueuesForTenant(tenantId);\n if (queues.length > 0) {\n tenantQueues.push({ tenantId, queues: queues.map((q) => q.queueId) });\n }\n }\n\n return tenantQueues;\n }\n\n /**\n * Shared claim loop: process selected queues from either dispatch or drain path.\n * Claims messages and pushes to worker queues.\n */\n async #processSelectedQueues(\n loopId: string,\n shardId: number,\n tenantQueues: TenantQueues[]\n ): Promise<boolean> {\n // Track stats\n this.batchedSpanManager.incrementStat(loopId, \"tenants_selected\", tenantQueues.length);\n this.batchedSpanManager.incrementStat(\n loopId,\n \"queues_selected\",\n tenantQueues.reduce((acc, t) => acc + t.queues.length, 0)\n );\n\n let messagesProcessed = 0;\n\n for (const { tenantId, queues } of tenantQueues) {\n for (const queueId of queues) {\n // Check cooloff\n if (this.cooloffEnabled && this.#isInCooloff(queueId)) {\n this.batchedSpanManager.incrementStat(loopId, \"cooloff_skipped\");\n continue;\n }\n\n // Check tenant capacity before attempting to process\n if (this.concurrencyManager) {\n const isAtCapacity = await this.concurrencyManager.isAtCapacity(\"tenant\", tenantId);\n if (isAtCapacity) {\n this.batchedSpanManager.incrementStat(loopId, \"tenant_capacity_skipped\");\n break;\n }\n }\n\n const processedFromQueue = await this.telemetry.trace(\n \"claimAndPushToWorkerQueue\",\n async (span) => {\n span.setAttribute(FairQueueAttributes.QUEUE_ID, queueId);\n span.setAttribute(FairQueueAttributes.TENANT_ID, tenantId);\n span.setAttribute(FairQueueAttributes.SHARD_ID, shardId.toString());\n const count = await this.#claimAndPushToWorkerQueue(loopId, queueId, tenantId, shardId);\n span.setAttribute(\"messages_claimed\", count);\n return count;\n },\n { kind: SpanKind.INTERNAL }\n );\n\n if (processedFromQueue > 0) {\n messagesProcessed += processedFromQueue;\n this.batchedSpanManager.incrementStat(loopId, \"messages_claimed\", processedFromQueue);\n\n if (this.scheduler.recordProcessedBatch) {\n await this.telemetry.trace(\n \"recordProcessedBatch\",\n async (span) => {\n span.setAttribute(FairQueueAttributes.QUEUE_ID, queueId);\n span.setAttribute(FairQueueAttributes.TENANT_ID, tenantId);\n span.setAttribute(\"count\", processedFromQueue);\n await this.scheduler.recordProcessedBatch!(tenantId, queueId, processedFromQueue);\n },\n { kind: SpanKind.INTERNAL }\n );\n } else if (this.scheduler.recordProcessed) {\n for (let i = 0; i < processedFromQueue; i++) {\n await this.telemetry.trace(\n \"recordProcessed\",\n async (span) => {\n span.setAttribute(FairQueueAttributes.QUEUE_ID, queueId);\n span.setAttribute(FairQueueAttributes.TENANT_ID, tenantId);\n await this.scheduler.recordProcessed!(tenantId, queueId);\n },\n { kind: SpanKind.INTERNAL }\n );\n }\n }\n } else {\n this.batchedSpanManager.incrementStat(loopId, \"claim_skipped\");\n }\n }\n }\n\n return messagesProcessed > 0;\n }\n\n async #claimAndPushToWorkerQueue(\n loopId: string,\n queueId: string,\n tenantId: string,\n _consumerShardId: number\n ): Promise<number> {\n // Dispatch shard is tenant-based (tenantId hash), not queue-based.\n // In-flight/master queue shard is queue-based.\n const dispatchShardId = this.tenantDispatch.getShardForTenant(tenantId);\n const queueKey = this.keys.queueKey(queueId);\n const queueItemsKey = this.keys.queueItemsKey(queueId);\n const descriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId,\n metadata: {},\n };\n\n // Determine how many messages we can claim based on concurrency\n let maxClaimCount = this.batchClaimSize;\n if (this.concurrencyManager) {\n const availableCapacity = await this.concurrencyManager.getAvailableCapacity(descriptor);\n if (availableCapacity === 0) {\n // Queue at max concurrency - don't increment cooloff here.\n // The outer loop already handles this case (concurrency blocked)\n // and explicitly avoids cooloff for it. Cooloff here causes\n // spurious 5s stalls when capacity races between the tenant\n // pre-check and this per-queue check.\n return 0;\n }\n maxClaimCount = Math.min(maxClaimCount, availableCapacity);\n }\n\n // Check worker queue depth to prevent unbounded growth.\n // Messages in the worker queue are already in-flight with a visibility timeout.\n // If the queue is too deep, consumers can't keep up, and messages risk timing out.\n if (this.workerQueueMaxDepth > 0 && this.workerQueueDepthCheckId) {\n const depth = await this.workerQueueManager.getLength(this.workerQueueDepthCheckId);\n if (depth >= this.workerQueueMaxDepth) {\n return 0;\n }\n // Cap claim size to remaining capacity so we don't overshoot the depth limit\n const remainingCapacity = this.workerQueueMaxDepth - depth;\n maxClaimCount = Math.min(maxClaimCount, remainingCapacity);\n }\n\n // Claim batch of messages with visibility timeout\n const claimedMessages = await this.visibilityManager.claimBatch<\n StoredMessage<inferZodSchemaOutput<TPayloadSchema>>\n >(queueId, queueKey, queueItemsKey, loopId, maxClaimCount, this.visibilityTimeoutMs);\n\n if (claimedMessages.length === 0) {\n // Queue is empty, update both old and new indexes and clean up caches\n await this.#updateAllIndexesAfterDequeue(queueId, tenantId);\n this.queueDescriptorCache.delete(queueId);\n this.queueCooloffStates.delete(queueId);\n return 0;\n }\n\n let processedCount = 0;\n\n // Reserve concurrency and push each message to worker queue\n for (let i = 0; i < claimedMessages.length; i++) {\n const message = claimedMessages[i]!;\n\n // Reserve concurrency slot\n if (this.concurrencyManager) {\n const reserved = await this.concurrencyManager.reserve(descriptor, message.messageId);\n if (!reserved) {\n // Release ALL remaining messages (from index i onward) back to queue\n // This prevents messages from being stranded in the in-flight set\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n await this.visibilityManager.releaseBatch(\n claimedMessages.slice(i),\n queueId,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n tenantId\n );\n // Stop processing more messages from this queue since we're at capacity\n break;\n }\n }\n\n // Resolve which worker queue this message should go to\n const workerQueueId = this.workerQueueResolver(message.payload);\n\n // Push to worker queue with format \"messageId:queueId\"\n const messageKey = `${message.messageId}:${queueId}`;\n await this.workerQueueManager.push(workerQueueId, messageKey);\n processedCount++;\n }\n\n if (processedCount > 0) {\n this.#resetCooloff(queueId);\n }\n\n return processedCount;\n }\n\n // ============================================================================\n // Public API - Message Lifecycle (for external consumers)\n // ============================================================================\n\n /**\n * Get message data from in-flight storage.\n * External consumers use this to retrieve the stored message after popping from worker queue.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n * @returns The stored message or null if not found\n */\n async getMessageData(\n messageId: string,\n queueId: string\n ): Promise<StoredMessage<inferZodSchemaOutput<TPayloadSchema>> | null> {\n const shardId = this.masterQueue.getShardForQueue(queueId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n const [dataJson, payloadJson] = await Promise.all([\n this.redis.hget(inflightDataKey, messageId),\n this.separatePayloads\n ? this.redis.get(this.keys.payloadKey!(queueId, messageId))\n : Promise.resolve(null),\n ]);\n\n if (!dataJson) {\n return null;\n }\n\n try {\n const message = JSON.parse(dataJson) as StoredMessage<inferZodSchemaOutput<TPayloadSchema>>;\n if (!this.separatePayloads) {\n return message;\n }\n if (payloadJson === null) {\n this.logger.error(\"In-flight message has no payload\", { messageId, queueId });\n return null;\n }\n return { ...message, payload: JSON.parse(payloadJson) };\n } catch {\n this.logger.error(\"Failed to parse message data\", { messageId, queueId });\n return null;\n }\n }\n\n /**\n * Extend the visibility timeout for a message.\n * External consumers should call this periodically during long-running processing.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n * @returns true if heartbeat was successful\n */\n async heartbeatMessage(messageId: string, queueId: string): Promise<boolean> {\n return this.visibilityManager.heartbeat(messageId, queueId, this.heartbeatIntervalMs);\n }\n\n /**\n * Mark a message as successfully processed.\n * This removes the message from in-flight and releases concurrency.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n */\n async completeMessage(messageId: string, queueId: string): Promise<void> {\n const shardId = this.masterQueue.getShardForQueue(queueId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Get stored message for concurrency release\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n let storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>> | null = null;\n if (dataJson) {\n try {\n storedMessage = JSON.parse(dataJson);\n } catch {\n // Ignore parse error, proceed with completion\n }\n }\n\n const descriptor: QueueDescriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: storedMessage?.tenantId ?? this.keys.extractTenantId(queueId),\n metadata: storedMessage?.metadata ?? {},\n };\n\n await this.#releaseConcurrencySafely(descriptor, messageId, \"completeMessage\");\n\n await this.#completeInVisibility(messageId, queueId, descriptor.tenantId);\n\n // Update both old and new indexes, clean up caches if queue is empty\n const { queueEmpty } = await this.#updateAllIndexesAfterDequeue(queueId, descriptor.tenantId);\n if (queueEmpty) {\n this.queueDescriptorCache.delete(queueId);\n this.queueCooloffStates.delete(queueId);\n }\n\n this.telemetry.recordComplete();\n\n this.logger.debug(\"Message completed\", {\n messageId,\n queueId,\n });\n }\n\n /**\n * Release a message back to the queue for processing by another consumer.\n * The message is placed at the back of the queue.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n */\n async releaseMessage(messageId: string, queueId: string): Promise<void> {\n const shardId = this.masterQueue.getShardForQueue(queueId);\n const queueKey = this.keys.queueKey(queueId);\n const queueItemsKey = this.keys.queueItemsKey(queueId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Get stored message for concurrency release\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n let storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>> | null = null;\n if (dataJson) {\n try {\n storedMessage = JSON.parse(dataJson);\n } catch {\n // Ignore parse error\n }\n }\n\n const descriptor: QueueDescriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: storedMessage?.tenantId ?? this.keys.extractTenantId(queueId),\n metadata: storedMessage?.metadata ?? {},\n };\n\n // Release concurrency\n await this.#releaseConcurrencySafely(descriptor, messageId, \"releaseMessage\");\n\n // Release back to queue (visibility manager updates dispatch indexes atomically)\n // Dispatch shard is tenant-based, not queue-based\n const dispatchShardId = this.tenantDispatch.getShardForTenant(descriptor.tenantId);\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(descriptor.tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n await this.visibilityManager.release(\n messageId,\n queueId,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n descriptor.tenantId,\n Date.now() // Put at back of queue\n );\n\n this.logger.debug(\"Message released\", {\n messageId,\n queueId,\n });\n }\n\n /**\n * Release a message's concurrency slots without letting a failure escape. Release is\n * best-effort cleanup: the primary state transition (complete, retry, DLQ, requeue)\n * must proceed even when the slot cannot be freed, because aborting the transition\n * re-delivers or strands the message, while a leaked slot is recoverable — reserve()\n * re-admits a message that already holds its own slot, and the reconcile loop removes\n * members that are no longer in flight.\n */\n async #releaseConcurrencySafely(\n descriptor: QueueDescriptor,\n messageId: string,\n context: string\n ): Promise<void> {\n if (!this.concurrencyManager) {\n return;\n }\n\n try {\n await this.concurrencyManager.release(descriptor, messageId);\n } catch (error) {\n this.logger.error(\"Failed to release concurrency slot, leaving it for the reconciler\", {\n context,\n messageId,\n queueId: descriptor.id,\n tenantId: descriptor.tenantId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n /**\n * Release a concurrency slot for a message we can no longer describe, deriving the\n * group from the queue id alone. Used on paths that bail out before the stored\n * message is available, where the slot would otherwise be held with nothing left\n * to reclaim it.\n */\n async #releaseOrphanedConcurrency(messageId: string, queueId: string): Promise<void> {\n if (!this.concurrencyManager) {\n return;\n }\n\n const descriptor: QueueDescriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: this.keys.extractTenantId(queueId),\n metadata: {},\n };\n\n await this.#releaseConcurrencySafely(descriptor, messageId, \"failMessage:missing-record\");\n }\n\n /**\n * Mark a message as failed. This will trigger retry logic if configured,\n * or move the message to the dead letter queue.\n *\n * @param messageId - The ID of the message\n * @param queueId - The queue ID the message belongs to\n * @param error - Optional error that caused the failure\n */\n async failMessage(messageId: string, queueId: string, error?: Error): Promise<void> {\n const shardId = this.masterQueue.getShardForQueue(queueId);\n const queueKey = this.keys.queueKey(queueId);\n const queueItemsKey = this.keys.queueItemsKey(queueId);\n const inflightDataKey = this.keys.inflightDataKey(shardId);\n\n // Get stored message\n const dataJson = await this.redis.hget(inflightDataKey, messageId);\n if (!dataJson) {\n this.logger.error(\"Cannot fail message: not found in in-flight data\", { messageId, queueId });\n await this.#releaseOrphanedConcurrency(messageId, queueId);\n return;\n }\n\n let storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>>;\n try {\n storedMessage = JSON.parse(dataJson);\n } catch {\n this.logger.error(\"Cannot fail message: failed to parse stored message\", {\n messageId,\n queueId,\n });\n await this.#releaseOrphanedConcurrency(messageId, queueId);\n return;\n }\n\n const descriptor = this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: storedMessage.tenantId,\n metadata: storedMessage.metadata ?? {},\n };\n\n const dispatchShardId = this.tenantDispatch.getShardForTenant(descriptor.tenantId);\n await this.#handleMessageFailure(\n storedMessage,\n queueId,\n queueKey,\n queueItemsKey,\n dispatchShardId,\n descriptor,\n error\n );\n }\n\n // ============================================================================\n // Private - Message Processing Helpers\n // ============================================================================\n\n async #handleMessageFailure(\n storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>>,\n queueId: string,\n queueKey: string,\n queueItemsKey: string,\n dispatchShardId: number,\n descriptor: QueueDescriptor,\n error?: Error\n ): Promise<void> {\n this.telemetry.recordFailure();\n\n // Check retry strategy\n if (this.retryStrategy) {\n const nextDelay = this.retryStrategy.getNextDelay(storedMessage.attempt, error);\n\n if (nextDelay !== null) {\n // Retry with incremented attempt\n const updatedMessage = {\n ...storedMessage,\n attempt: storedMessage.attempt + 1,\n };\n\n await this.#releaseConcurrencySafely(descriptor, storedMessage.id, \"retry\");\n\n // Release with delay, passing the updated message data so the Lua script\n // atomically writes the incremented attempt count when re-queuing.\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(descriptor.tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n await this.visibilityManager.release(\n storedMessage.id,\n queueId,\n queueKey,\n queueItemsKey,\n tenantQueueIndexKey,\n dispatchKey,\n descriptor.tenantId,\n Date.now() + nextDelay,\n JSON.stringify(updatedMessage)\n );\n\n this.telemetry.recordRetry();\n\n this.logger.debug(\"Message scheduled for retry\", {\n messageId: storedMessage.id,\n queueId,\n attempt: storedMessage.attempt + 1,\n delayMs: nextDelay,\n });\n\n return;\n }\n }\n\n // Release concurrency\n await this.#releaseConcurrencySafely(descriptor, storedMessage.id, \"deadLetter\");\n\n // Move to DLQ\n await this.#moveToDeadLetterQueue(storedMessage, error?.message);\n }\n\n async #moveToDeadLetterQueue(\n storedMessage: StoredMessage<inferZodSchemaOutput<TPayloadSchema>>,\n errorMessage?: string\n ): Promise<void> {\n if (!this.deadLetterQueueEnabled) {\n await this.#completeInVisibility(\n storedMessage.id,\n storedMessage.queueId,\n storedMessage.tenantId\n );\n return;\n }\n\n if (this.separatePayloads) {\n const payloadJson = await this.redis.get(\n this.keys.payloadKey!(storedMessage.queueId, storedMessage.id)\n );\n storedMessage = {\n ...storedMessage,\n payload: payloadJson === null ? undefined : JSON.parse(payloadJson),\n };\n }\n\n const dlqKey = this.keys.deadLetterQueueKey(storedMessage.tenantId);\n const dlqDataKey = this.keys.deadLetterQueueDataKey(storedMessage.tenantId);\n const _shardId = this.masterQueue.getShardForQueue(storedMessage.queueId);\n\n const dlqMessage: DeadLetterMessage<inferZodSchemaOutput<TPayloadSchema>> = {\n id: storedMessage.id,\n queueId: storedMessage.queueId,\n tenantId: storedMessage.tenantId,\n payload: storedMessage.payload,\n deadLetteredAt: Date.now(),\n attempts: storedMessage.attempt,\n lastError: errorMessage,\n originalTimestamp: storedMessage.timestamp,\n };\n\n await this.#completeInVisibility(\n storedMessage.id,\n storedMessage.queueId,\n storedMessage.tenantId\n );\n\n // Add to DLQ\n const pipeline = this.redis.pipeline();\n pipeline.zadd(dlqKey, dlqMessage.deadLetteredAt, storedMessage.id);\n pipeline.hset(dlqDataKey, storedMessage.id, JSON.stringify(dlqMessage));\n await pipeline.exec();\n\n this.telemetry.recordDLQ();\n\n this.logger.info(\"Message moved to DLQ\", {\n messageId: storedMessage.id,\n queueId: storedMessage.queueId,\n tenantId: storedMessage.tenantId,\n attempts: storedMessage.attempt,\n error: errorMessage,\n });\n }\n\n // ============================================================================\n // Private - Reclaim Loop\n // ============================================================================\n\n async #runReclaimLoop(): Promise<void> {\n try {\n for await (const _ of setInterval(this.reclaimIntervalMs, null, {\n signal: this.abortController.signal,\n })) {\n try {\n await this.#reclaimTimedOutMessages();\n } catch (error) {\n this.logger.error(\"Reclaim loop error\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n } catch (error) {\n if (isAbortError(error)) {\n this.logger.debug(\"Reclaim loop aborted\");\n return;\n }\n throw error;\n }\n }\n\n /**\n * Free every timed-out message's concurrency slot in one pipeline before the batch is\n * requeued. A failed release never blocks the requeue: holding the message in-flight\n * would stall it behind a persistent release failure, while the leaked slot self-heals\n * when the message is re-admitted (reserve is idempotent for a message that already\n * holds its own slot) or via the reconcile loop.\n */\n async #releaseReclaimedConcurrency(messages: ReclaimedMessageInfo[]): Promise<void> {\n if (!this.concurrencyManager || messages.length === 0) {\n return;\n }\n\n const descriptorFor = (message: ReclaimedMessageInfo): QueueDescriptor => ({\n id: message.queueId,\n tenantId: message.tenantId,\n metadata: message.metadata ?? {},\n });\n\n try {\n await this.concurrencyManager.releaseBatch(\n messages.map((message) => ({ queue: descriptorFor(message), messageId: message.messageId }))\n );\n return;\n } catch (error) {\n this.logger.error(\"Batch concurrency release failed, retrying message by message\", {\n count: messages.length,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n for (const message of messages) {\n await this.#releaseConcurrencySafely(descriptorFor(message), message.messageId, \"reclaim\");\n }\n }\n\n async #reclaimTimedOutMessages(): Promise<void> {\n let totalReclaimed = 0;\n\n for (let shardId = 0; shardId < this.shardCount; shardId++) {\n try {\n const reclaimedMessages = await this.visibilityManager.reclaimTimedOut(\n shardId,\n (queueId) => {\n const tenantId = this.keys.extractTenantId(queueId);\n const dispatchShardId = this.tenantDispatch.getShardForTenant(tenantId);\n return {\n queueKey: this.keys.queueKey(queueId),\n queueItemsKey: this.keys.queueItemsKey(queueId),\n tenantQueueIndexKey: this.keys.tenantQueueIndexKey(tenantId),\n dispatchKey: this.keys.dispatchKey(dispatchShardId),\n tenantId,\n };\n },\n this.#releaseReclaimedConcurrency.bind(this)\n );\n\n totalReclaimed += reclaimedMessages.length;\n } catch (error) {\n this.logger.error(\"Failed to reclaim shard, leaving messages in-flight for the next tick\", {\n shardId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (totalReclaimed > 0) {\n this.logger.info(\"Reclaimed timed-out messages\", { count: totalReclaimed });\n }\n }\n\n /**\n * The initial delay is jittered so instances sharing a Redis do not all sweep at once.\n */\n async #runReconcileLoop(): Promise<void> {\n try {\n await delay(Math.random() * this.reconcileIntervalMs, null, {\n signal: this.abortController.signal,\n });\n\n for await (const _ of setInterval(this.reconcileIntervalMs, null, {\n signal: this.abortController.signal,\n })) {\n try {\n await this.#reconcileConcurrency();\n } catch (error) {\n this.logger.error(\"Concurrency reconcile loop error\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n } catch (error) {\n if (isAbortError(error)) {\n this.logger.debug(\"Concurrency reconcile loop aborted\");\n return;\n }\n throw error;\n }\n }\n\n /**\n * Heal orphaned concurrency slots: remove any concurrency set member whose message is\n * not registered in-flight on any shard. This is the recovery path for slots leaked by\n * failed releases, which otherwise count against a tenant's limit forever and can\n * wedge every queue the tenant owns.\n */\n async #reconcileConcurrency(): Promise<void> {\n if (!this.concurrencyManager) {\n return;\n }\n\n const inflightDataKeys = Array.from({ length: this.shardCount }, (_, shardId) =>\n this.keys.inflightDataKey(shardId)\n );\n\n const { scannedSets, removed } =\n await this.concurrencyManager.sweepOrphanedSlots(inflightDataKeys);\n\n if (removed.length > 0) {\n this.logger.info(\"Reconciled orphaned concurrency slots\", {\n count: removed.length,\n scannedSets,\n messageIds: removed.slice(0, 50),\n });\n }\n }\n\n // ============================================================================\n // Private - Cooloff State\n // ============================================================================\n\n #isInCooloff(queueId: string): boolean {\n const state = this.queueCooloffStates.get(queueId);\n if (!state) return false;\n\n if (state.tag === \"cooloff\") {\n if (Date.now() >= state.expiresAt) {\n this.queueCooloffStates.delete(queueId);\n return false;\n }\n return true;\n }\n\n return false;\n }\n\n #resetCooloff(queueId: string): void {\n this.queueCooloffStates.delete(queueId);\n }\n\n // ============================================================================\n // Private - Helpers\n // ============================================================================\n\n /**\n * Update both old master queue and new dispatch indexes after a dequeue/complete.\n * Both calls are idempotent - ZREM on a non-existent member is a no-op.\n * This handles the transition period where queues may exist in either or both indexes.\n */\n async #updateAllIndexesAfterDequeue(\n queueId: string,\n tenantId: string\n ): Promise<{ queueEmpty: boolean }> {\n const queueShardId = this.masterQueue.getShardForQueue(queueId);\n const dispatchShardId = this.tenantDispatch.getShardForTenant(tenantId);\n const queueKey = this.keys.queueKey(queueId);\n const masterQueueKey = this.keys.masterQueueKey(queueShardId);\n const tenantQueueIndexKey = this.keys.tenantQueueIndexKey(tenantId);\n const dispatchKey = this.keys.dispatchKey(dispatchShardId);\n\n // Update legacy master queue (drain path, no-op if queue not there)\n const removedFromMaster = await this.redis.updateMasterQueueIfEmpty(\n masterQueueKey,\n queueKey,\n queueId\n );\n\n // Update new dispatch indexes\n const removedFromDispatch = await this.redis.updateDispatchIndexes(\n queueKey,\n tenantQueueIndexKey,\n dispatchKey,\n queueId,\n tenantId\n );\n\n return { queueEmpty: removedFromMaster === 1 || removedFromDispatch === 1 };\n }\n\n /**\n * Remove a settled message from in-flight. With separate payloads this also deletes the payload\n * and takes its bytes off the tenant's count, in one script, so the count never drifts.\n */\n async #completeInVisibility(messageId: string, queueId: string, tenantId: string): Promise<void> {\n if (!this.separatePayloads) {\n await this.visibilityManager.complete(messageId, queueId);\n return;\n }\n const shardId = this.masterQueue.getShardForQueue(queueId);\n await this.redis.completeSeparatePayload(\n this.keys.inflightKey(shardId),\n this.keys.inflightDataKey(shardId),\n this.keys.payloadKey!(queueId, messageId),\n this.keys.tenantPayloadBytesKey!(tenantId),\n `${messageId}:${queueId}`,\n messageId\n );\n }\n\n /** A tenant's queued and in-flight payload bytes, with `separatePayloads`. */\n async getTenantPayloadBytes(tenantId: string): Promise<number> {\n if (!this.separatePayloads) return 0;\n return Number((await this.redis.get(this.keys.tenantPayloadBytesKey!(tenantId))) ?? 0);\n }\n\n /**\n * A cluster needs every script's keys in one slot, which only a tenant-sharded key producer\n * gives, and the concurrency reservation touches every group's set at once, so it allows one\n * group, keyed by tenant.\n */\n static #validateLayout(\n options: Pick<\n FairQueueOptions,\n \"keys\" | \"separatePayloads\" | \"shardCount\" | \"redis\" | \"concurrencyGroups\"\n >\n ): void {\n const keys = options.keys;\n if (options.separatePayloads && (!keys.payloadKey || !keys.tenantPayloadBytesKey)) {\n throw new Error(\n \"separatePayloads needs a key producer with payloadKey and tenantPayloadBytesKey\"\n );\n }\n if (keys.tenantShard) {\n if (!keys.shardCount) {\n throw new Error(\"A key producer with tenantShard must set shardCount\");\n }\n if (options.shardCount !== undefined && options.shardCount !== keys.shardCount) {\n throw new Error(\n `shardCount ${options.shardCount} doesn't match the key producer's ${keys.shardCount}`\n );\n }\n }\n if (isClusterConnection(options.redis)) {\n if (!keys.tenantShard) {\n throw new Error(\"A cluster connection needs a tenant-sharded key producer\");\n }\n if ((options.concurrencyGroups?.length ?? 0) > 1) {\n throw new Error(\"A cluster connection supports at most one concurrency group\");\n }\n }\n }\n\n #createSchedulerContext(): SchedulerContext {\n return {\n getCurrentConcurrency: async (groupName, groupId) => {\n if (!this.concurrencyManager) return 0;\n return this.concurrencyManager.getCurrentConcurrency(groupName, groupId);\n },\n getConcurrencyLimit: async (groupName, groupId) => {\n if (!this.concurrencyManager) return Infinity;\n return this.concurrencyManager.getConcurrencyLimit(groupName, groupId);\n },\n isAtCapacity: async (groupName, groupId) => {\n if (!this.concurrencyManager) return false;\n return this.concurrencyManager.isAtCapacity(groupName, groupId);\n },\n getQueueDescriptor: (queueId) => {\n return (\n this.queueDescriptorCache.get(queueId) ?? {\n id: queueId,\n tenantId: this.keys.extractTenantId(queueId),\n metadata: {},\n }\n );\n },\n };\n }\n\n // ============================================================================\n // Private - Redis Commands\n // ============================================================================\n\n #registerCommands(): void {\n // ---- Legacy Lua scripts (kept for drain of old master queue) ----\n\n // Atomic single message enqueue with master queue update (legacy, used for drain only)\n this.redis.defineCommand(\"enqueueMessageAtomic\", {\n numberOfKeys: 3,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal masterQueueKey = KEYS[3]\n\nlocal queueId = ARGV[1]\nlocal messageId = ARGV[2]\nlocal timestamp = tonumber(ARGV[3])\nlocal payload = ARGV[4]\n\nredis.call('ZADD', queueKey, timestamp, messageId)\nredis.call('HSET', queueItemsKey, messageId, payload)\n\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', masterQueueKey, oldest[2], queueId)\nend\n\nreturn 1\n `,\n });\n\n // Atomic batch message enqueue with master queue update (legacy, used for drain only)\n this.redis.defineCommand(\"enqueueBatchAtomic\", {\n numberOfKeys: 3,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal masterQueueKey = KEYS[3]\n\nlocal queueId = ARGV[1]\n\nfor i = 2, #ARGV, 3 do\n local messageId = ARGV[i]\n local timestamp = tonumber(ARGV[i + 1])\n local payload = ARGV[i + 2]\n redis.call('ZADD', queueKey, timestamp, messageId)\n redis.call('HSET', queueItemsKey, messageId, payload)\nend\n\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', masterQueueKey, oldest[2], queueId)\nend\n\nreturn (#ARGV - 1) / 3\n `,\n });\n\n // Remove queue from legacy master queue if empty (drain-only, never re-adds)\n this.redis.defineCommand(\"updateMasterQueueIfEmpty\", {\n numberOfKeys: 2,\n lua: `\nlocal masterQueueKey = KEYS[1]\nlocal queueKey = KEYS[2]\nlocal queueId = ARGV[1]\n\nlocal count = redis.call('ZCARD', queueKey)\nif count == 0 then\n redis.call('ZREM', masterQueueKey, queueId)\n return 1\nend\n\n-- Queue still has messages but don't re-add to legacy master queue.\n-- New enqueues go through the V2 dispatch path, so we only drain here.\n-- Just remove it so it doesn't linger.\nredis.call('ZREM', masterQueueKey, queueId)\nreturn 0\n `,\n });\n\n // ---- New V2 Lua scripts (two-level tenant dispatch) ----\n\n // Atomic single message enqueue with tenant dispatch index update\n this.redis.defineCommand(\"enqueueMessageAtomicV2\", {\n numberOfKeys: 4,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal tenantQueueIndexKey = KEYS[3]\nlocal dispatchKey = KEYS[4]\n\nlocal queueId = ARGV[1]\nlocal messageId = ARGV[2]\nlocal timestamp = tonumber(ARGV[3])\nlocal payload = ARGV[4]\nlocal tenantId = ARGV[5]\n\n-- Add to per-queue storage (same as before)\nredis.call('ZADD', queueKey, timestamp, messageId)\nredis.call('HSET', queueItemsKey, messageId, payload)\n\n-- Update tenant queue index (Level 2) with queue's oldest message\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\nend\n\n-- Update dispatch index (Level 1) with tenant's oldest across all queues\nlocal tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\nif #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\nend\n\nreturn 1\n `,\n });\n\n // Atomic batch message enqueue with tenant dispatch index update\n this.redis.defineCommand(\"enqueueBatchAtomicV2\", {\n numberOfKeys: 4,\n lua: `\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal tenantQueueIndexKey = KEYS[3]\nlocal dispatchKey = KEYS[4]\n\nlocal queueId = ARGV[1]\nlocal tenantId = ARGV[2]\n\n-- Args after queueId and tenantId are triples: [messageId, timestamp, payload, ...]\nfor i = 3, #ARGV, 3 do\n local messageId = ARGV[i]\n local timestamp = tonumber(ARGV[i + 1])\n local payload = ARGV[i + 2]\n redis.call('ZADD', queueKey, timestamp, messageId)\n redis.call('HSET', queueItemsKey, messageId, payload)\nend\n\n-- Update tenant queue index (Level 2)\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\nend\n\n-- Update dispatch index (Level 1)\nlocal tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\nif #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\nend\n\nreturn (#ARGV - 2) / 3\n `,\n });\n\n this.redis.defineCommand(\"enqueueMessageSeparatePayload\", {\n numberOfKeys: 7,\n lua: `#!lua\nlocal queueKey = KEYS[1]\nlocal queueItemsKey = KEYS[2]\nlocal tenantQueueIndexKey = KEYS[3]\nlocal dispatchKey = KEYS[4]\nlocal payloadKey = KEYS[5]\nlocal inflightKey = KEYS[6]\nlocal bytesKey = KEYS[7]\n\nlocal queueId = ARGV[1]\nlocal messageId = ARGV[2]\nlocal timestamp = tonumber(ARGV[3])\nlocal envelope = ARGV[4]\nlocal tenantId = ARGV[5]\nlocal payload = ARGV[6]\nlocal inflightMember = ARGV[7]\nlocal limit = tonumber(ARGV[8])\n\nif redis.call('HEXISTS', queueItemsKey, messageId) == 1 then\n return 0\nend\nif redis.call('ZSCORE', inflightKey, inflightMember) then\n return 0\nend\n\nlocal size = string.len(payload)\nif limit > 0 and tonumber(redis.call('GET', bytesKey) or '0') + size > limit then\n return -1\nend\n\nredis.call('SET', payloadKey, payload)\nredis.call('INCRBY', bytesKey, size)\nredis.call('ZADD', queueKey, timestamp, messageId)\nredis.call('HSET', queueItemsKey, messageId, envelope)\n\nlocal oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\nif #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\nend\n\nlocal tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\nif #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\nend\n\nreturn 1\n `,\n });\n\n this.redis.defineCommand(\"completeSeparatePayload\", {\n numberOfKeys: 4,\n lua: `\nlocal inflightKey = KEYS[1]\nlocal inflightDataKey = KEYS[2]\nlocal payloadKey = KEYS[3]\nlocal bytesKey = KEYS[4]\n\nredis.call('ZREM', inflightKey, ARGV[1])\nredis.call('HDEL', inflightDataKey, ARGV[2])\n\nlocal size = redis.call('STRLEN', payloadKey)\nif size > 0 then\n redis.call('DEL', payloadKey)\n if redis.call('DECRBY', bytesKey, size) <= 0 then\n redis.call('DEL', bytesKey)\n end\nend\nreturn size\n `,\n });\n\n // Update tenant dispatch indexes after dequeue/complete\n // Handles both queue-empty (remove from indexes) and queue-has-messages (update scores)\n this.redis.defineCommand(\"updateDispatchIndexes\", {\n numberOfKeys: 3,\n lua: `\nlocal queueKey = KEYS[1]\nlocal tenantQueueIndexKey = KEYS[2]\nlocal dispatchKey = KEYS[3]\nlocal queueId = ARGV[1]\nlocal tenantId = ARGV[2]\n\nlocal count = redis.call('ZCARD', queueKey)\nif count == 0 then\n -- Queue is empty: remove from tenant queue index\n redis.call('ZREM', tenantQueueIndexKey, queueId)\n\n -- Check if tenant has any queues left\n local tenantQueueCount = redis.call('ZCARD', tenantQueueIndexKey)\n if tenantQueueCount == 0 then\n -- No more queues: remove tenant from dispatch\n redis.call('ZREM', dispatchKey, tenantId)\n else\n -- Update dispatch score to tenant's new oldest\n local tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\n if #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\n end\n end\n return 1\nelse\n -- Queue still has messages: update scores\n local oldest = redis.call('ZRANGE', queueKey, 0, 0, 'WITHSCORES')\n if #oldest >= 2 then\n redis.call('ZADD', tenantQueueIndexKey, oldest[2], queueId)\n end\n local tenantOldest = redis.call('ZRANGE', tenantQueueIndexKey, 0, 0, 'WITHSCORES')\n if #tenantOldest >= 2 then\n redis.call('ZADD', dispatchKey, tenantOldest[2], tenantId)\n end\n return 0\nend\n `,\n });\n\n // Register worker queue commands if enabled\n if (this.workerQueueManager) {\n this.workerQueueManager.registerCommands(this.redis);\n }\n }\n}\n\n// Extend Redis interface for custom commands\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n // Legacy commands (kept for drain of old master queue)\n enqueueMessageAtomic(\n queueKey: string,\n queueItemsKey: string,\n masterQueueKey: string,\n queueId: string,\n messageId: string,\n timestamp: string,\n payload: string\n ): Promise<number>;\n\n enqueueBatchAtomic(\n queueKey: string,\n queueItemsKey: string,\n masterQueueKey: string,\n queueId: string,\n ...args: string[]\n ): Promise<number>;\n\n updateMasterQueueIfEmpty(\n masterQueueKey: string,\n queueKey: string,\n queueId: string\n ): Promise<number>;\n\n // V2 commands (two-level tenant dispatch)\n enqueueMessageAtomicV2(\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n queueId: string,\n messageId: string,\n timestamp: string,\n payload: string,\n tenantId: string\n ): Promise<number>;\n\n enqueueBatchAtomicV2(\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n queueId: string,\n tenantId: string,\n ...args: string[]\n ): Promise<number>;\n\n updateDispatchIndexes(\n queueKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n queueId: string,\n tenantId: string\n ): Promise<number>;\n\n enqueueMessageSeparatePayload(\n queueKey: string,\n queueItemsKey: string,\n tenantQueueIndexKey: string,\n dispatchKey: string,\n payloadKey: string,\n inflightKey: string,\n bytesKey: string,\n queueId: string,\n messageId: string,\n timestamp: string,\n envelope: string,\n tenantId: string,\n payload: string,\n inflightMember: string,\n limit: string\n ): Promise<number>;\n\n completeSeparatePayload(\n inflightKey: string,\n inflightDataKey: string,\n payloadKey: string,\n bytesKey: string,\n inflightMember: string,\n messageId: string\n ): Promise<number>;\n }\n}\n","import { z } from \"zod/v4\";\n\nexport const BufferEntryStatus = z.enum([\"QUEUED\", \"DRAINING\", \"FAILED\"]);\nexport type BufferEntryStatus = z.infer<typeof BufferEntryStatus>;\n\nexport const BufferEntryError = z.object({\n code: z.string(),\n message: z.string(),\n});\nexport type BufferEntryError = z.infer<typeof BufferEntryError>;\n\nconst stringToInt = z.string().transform((v, ctx) => {\n const n = Number(v);\n if (!Number.isInteger(n) || n < 0) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: \"expected non-negative integer string\" });\n return z.NEVER;\n }\n return n;\n});\n\nconst stringToDate = z.string().transform((v, ctx) => {\n const d = new Date(v);\n if (Number.isNaN(d.getTime())) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: \"expected ISO date string\" });\n return z.NEVER;\n }\n return d;\n});\n\nconst stringToBool = z\n .union([z.literal(\"true\"), z.literal(\"false\")])\n .transform((v) => v === \"true\");\n\nconst stringToError = z.string().transform((v, ctx) => {\n try {\n return BufferEntryError.parse(JSON.parse(v));\n } catch {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"expected JSON-encoded BufferEntryError\",\n });\n return z.NEVER;\n }\n});\n\nexport const BufferEntrySchema = z.object({\n runId: z.string().min(1),\n envId: z.string().min(1),\n orgId: z.string().min(1),\n payload: z.string(),\n status: BufferEntryStatus,\n attempts: stringToInt,\n createdAt: stringToDate,\n // Microsecond epoch of accept time, kept as a hash field for dwell\n // metrics. Not a queue sort key (the queue is a FIFO LIST). Defaulted\n // so an entry written by an accept Lua predating this field — or one\n // surviving across the deploy that introduced it — still parses instead\n // of being silently dropped on pop.\n createdAtMicros: stringToInt.default(0),\n // Drainer-ack flag: `true` once the drainer has materialised this run\n // into PG. The hash persists for a short grace TTL after ack so direct\n // reads (retrieve, trace, etc.) still resolve while PG replica lag\n // settles. Absent on pre-ack entries.\n materialised: stringToBool.default(false),\n // Denormalised pointer to the Redis idempotency lookup key (set when\n // the run was accepted with an idempotency key, empty otherwise). The\n // ack Lua reads this to DEL the lookup atomically with marking the\n // entry materialised.\n idempotencyLookupKey: z.string().optional().default(\"\"),\n // Optimistic-lock counter for the snapshot's `metadata` field.\n // Incremented atomically by the CAS metadata Lua. Matches the\n // semantic of `TaskRun.metadataVersion` on the PG side (which the\n // UpdateMetadataService uses for the same retry-on-conflict pattern).\n metadataVersion: stringToInt.default(0),\n lastError: stringToError.optional(),\n});\n\nexport type BufferEntry = z.infer<typeof BufferEntrySchema>;\n\nexport function serialiseSnapshot(snapshot: unknown): string {\n return JSON.stringify(snapshot);\n}\n\nexport function deserialiseSnapshot<T = unknown>(serialised: string): T {\n return JSON.parse(serialised) as T;\n}\n","import {\n createRedisClient,\n type Callback,\n type Redis,\n type RedisOptions,\n type Result,\n} from \"@internal/redis\";\nimport { Logger } from \"@trigger.dev/core/logger\";\nimport type { BufferEntry } from \"./schemas.js\";\nimport { BufferEntrySchema } from \"./schemas.js\";\n\nexport type MollifierBufferOptions = {\n redisOptions: RedisOptions;\n logger?: Logger;\n // Grace TTL applied to the entry hash on drainer ack. The entry survives\n // this long after materialisation so direct reads (retrieve, trace, etc.)\n // have a safety net while PG replica lag settles. Defaults to 30s.\n ackGraceTtlSeconds?: number;\n // ioredis per-request retry limit on the buffer's Redis client. Defaults to 20.\n maxRetriesPerRequest?: number;\n // Reconnect backoff envelope (see `mollifierReconnectDelayMs`). Defaults\n // to 50ms per attempt capped at 1000ms.\n reconnectStepMs?: number;\n reconnectMaxMs?: number;\n};\n\n// Default grace TTL applied to the entry hash on drainer ack.\nconst DEFAULT_ACK_GRACE_TTL_SECONDS = 30;\n// Default ioredis reconnect backoff envelope for the buffer client.\nconst DEFAULT_RECONNECT_STEP_MS = 50;\nconst DEFAULT_RECONNECT_MAX_MS = 1000;\n// Default ioredis per-request retry limit.\nconst DEFAULT_MAX_RETRIES_PER_REQUEST = 20;\n\n// Observability-only sorted set of entries currently in DRAINING state\n// (popped by the drainer, not yet acked/failed/requeued). Score is the\n// pop wall-clock in milliseconds — `ZRANGEBYSCORE 0 <now-Xms>` gives\n// the entries stuck mid-drain for longer than X. NOT load-bearing for\n// correctness: the per-entry hash already carries `status` and the\n// stale-sweep would catch stranded entries via the queue LISTs. This\n// set is a fast top-level index for ops (gauge cardinality, post-crash\n// forensics after an ECS OOM) — see `mollifierDrainerWorker` for the\n// gauge wiring.\nexport const DRAINING_SET_KEY = \"mollifier:draining\";\n\n// ioredis reconnect backoff for the mollifier buffer client. The base\n// grows linearly with the attempt count and is capped at 1s (the same\n// envelope as the previous fixed `Math.min(times * 50, 1000)` schedule).\n// We then apply equal jitter — a uniform pick in `[base/2, base]` — so a\n// fleet of webapp instances reconnecting after the same Redis blip don't\n// retry in lockstep and stampede Redis on recovery (thundering herd).\n// Because the jittered value never exceeds the original cap, this is never\n// slower than before — just decorrelated. Mirrors the jittered-backoff\n// approach the mutate-fallback wait loop adopted for the same reason.\nexport function mollifierReconnectDelayMs(\n times: number,\n random: () => number = Math.random,\n stepMs: number = DEFAULT_RECONNECT_STEP_MS,\n maxMs: number = DEFAULT_RECONNECT_MAX_MS\n): number {\n const base = Math.min(times * stepMs, maxMs);\n const half = Math.floor(base / 2);\n return half + Math.round(random() * (base - half));\n}\n\nexport type SnapshotPatch =\n // `maxTags`, when set, caps the deduped tag count atomically inside the\n // Lua: if appending would push the snapshot over the limit the patch is\n // rejected (\"limit_exceeded\") and nothing is written, mirroring the\n // PG-path MAX_TAGS_PER_RUN check so a buffered run can't accumulate more\n // tags than the trigger validator would have allowed at creation.\n | { type: \"append_tags\"; tags: string[]; maxTags?: number }\n | { type: \"set_metadata\"; metadata: string; metadataType: string }\n | { type: \"set_delay\"; delayUntil: string }\n | { type: \"mark_cancelled\"; cancelledAt: string; cancelReason?: string };\n\nexport type MutateSnapshotResult = \"applied_to_snapshot\" | \"not_found\" | \"busy\" | \"limit_exceeded\";\n\nexport type CasSetMetadataResult =\n | { kind: \"applied\"; newVersion: number }\n | { kind: \"version_conflict\"; currentVersion: number }\n | { kind: \"not_found\" }\n | { kind: \"busy\" };\n\nexport type AcceptResult =\n | { kind: \"accepted\" }\n | { kind: \"duplicate_run_id\" }\n | { kind: \"duplicate_idempotency\"; existingRunId: string };\n\nexport type IdempotencyLookupInput = {\n envId: string;\n taskIdentifier: string;\n idempotencyKey: string;\n};\n\n// Reversible encoding for Redis-key segments. The composite-key builders\n// concatenate `envId`, `taskIdentifier`, and `idempotencyKey` with `:`\n// separators; if any segment contains a literal `:` (envId is internal\n// and `:`-free, but taskIdentifier and idempotencyKey are\n// customer-supplied) different tuples would map to the same Redis key\n// and dedupe the wrong run. base64url has no `:` in its alphabet and is\n// bijective on the input string, so the encoded keys are\n// collision-free.\nfunction encodeKeyPart(value: string): string {\n return Buffer.from(value, \"utf8\").toString(\"base64url\");\n}\n\n// Exported so tests can compute the same Redis key the buffer writes\n// without hard-coding the encoding (which is a buffer-internal detail).\nexport function idempotencyLookupKeyFor(input: IdempotencyLookupInput): string {\n return `mollifier:idempotency:${encodeKeyPart(input.envId)}:${encodeKeyPart(input.taskIdentifier)}:${encodeKeyPart(input.idempotencyKey)}`;\n}\n\n// Pre-gate claim key namespace, distinct from `mollifier:idempotency` so the\n// existing buffer-side dedup stays isolated. The claim is the\n// authoritative cross-store \"this idempotency key is in flight or\n// resolved\" pointer used by the trigger hot path. Values:\n// \"pending:<token>\" → claimed by a trigger pipeline; `<token>` is the\n// caller-supplied ownership token. Release and\n// publish compare-and-act on this token so a\n// late release from a previous claimant whose TTL\n// expired cannot erase a new owner's claim.\n// <runId> → the winning trigger's resolved runId.\nconst PENDING_PREFIX = \"pending:\";\n\n// Exported (like `idempotencyLookupKeyFor`) so tests can target the same\n// claim key the buffer writes without hard-coding the encoding.\nexport function makeIdempotencyClaimKey(input: IdempotencyLookupInput): string {\n return `mollifier:claim:${encodeKeyPart(input.envId)}:${encodeKeyPart(input.taskIdentifier)}:${encodeKeyPart(input.idempotencyKey)}`;\n}\n\nexport type IdempotencyClaimResult =\n | { kind: \"claimed\" }\n | { kind: \"pending\" }\n | { kind: \"resolved\"; runId: string };\n\nexport class MollifierBuffer {\n private readonly redis: Redis;\n private readonly logger: Logger;\n private readonly ackGraceTtlSeconds: number;\n\n constructor(options: MollifierBufferOptions) {\n this.logger = options.logger ?? new Logger(\"MollifierBuffer\", \"debug\");\n this.ackGraceTtlSeconds = options.ackGraceTtlSeconds ?? DEFAULT_ACK_GRACE_TTL_SECONDS;\n const reconnectStepMs = options.reconnectStepMs ?? DEFAULT_RECONNECT_STEP_MS;\n const reconnectMaxMs = options.reconnectMaxMs ?? DEFAULT_RECONNECT_MAX_MS;\n\n this.redis = createRedisClient(\n {\n ...options.redisOptions,\n retryStrategy(times) {\n return mollifierReconnectDelayMs(times, Math.random, reconnectStepMs, reconnectMaxMs);\n },\n maxRetriesPerRequest: options.maxRetriesPerRequest ?? DEFAULT_MAX_RETRIES_PER_REQUEST,\n },\n {\n onError: (error) => {\n this.logger.error(\"MollifierBuffer redis client error:\", { error });\n },\n }\n );\n this.#registerCommands();\n }\n\n // Three outcomes:\n // - { kind: \"accepted\" } — entry was newly written.\n // - { kind: \"duplicate_run_id\" } — runId was already buffered (idempotent\n // no-op, same semantic as the previous boolean-false return).\n // - { kind: \"duplicate_idempotency\", existingRunId } — the (env, task,\n // idempotencyKey) tuple was already bound to another buffered run.\n // The Lua's atomic SETNX is the race-winner; the second caller gets\n // the winner's runId so it can return that as the trigger response.\n async accept(input: {\n runId: string;\n envId: string;\n orgId: string;\n payload: string;\n // Optional idempotency-key triple. When all three are present we\n // SETNX a Redis lookup at `mollifier:idempotency:{env}:{task}:{key}`\n // pointing at the runId so trigger-time dedup during the buffered\n // window resolves the same way PG's unique constraint resolves it\n // post-materialisation.\n idempotencyKey?: string;\n taskIdentifier?: string;\n }): Promise<AcceptResult> {\n const entryKey = `mollifier:entries:${input.runId}`;\n const queueKey = `mollifier:queue:${input.envId}`;\n const orgsKey = \"mollifier:orgs\";\n const nowMs = Date.now();\n const createdAt = new Date(nowMs).toISOString();\n // Microsecond epoch, stored as a hash field for dwell-time metrics\n // (stale sweep, drainer dwell span). FIFO ordering comes from the\n // LIST itself (LPUSH head / RPOP tail), not from this value — it is\n // no longer a queue sort key.\n const createdAtMicros = nowMs * 1000;\n const idempotencyLookupKey =\n input.idempotencyKey && input.taskIdentifier\n ? idempotencyLookupKeyFor({\n envId: input.envId,\n taskIdentifier: input.taskIdentifier,\n idempotencyKey: input.idempotencyKey,\n })\n : \"\";\n const result = await this.redis.acceptMollifierEntry(\n entryKey,\n queueKey,\n orgsKey,\n input.runId,\n input.envId,\n input.orgId,\n input.payload,\n createdAt,\n String(createdAtMicros),\n \"mollifier:org-envs:\",\n idempotencyLookupKey,\n \"mollifier:entries:\"\n );\n // Lua returns 1 (accepted), 0 (duplicate runId), or a string runId\n // (duplicate idempotency — value is the existing winner's runId).\n if (typeof result === \"string\" && result.length > 0) {\n return { kind: \"duplicate_idempotency\", existingRunId: result };\n }\n if (result === 1) return { kind: \"accepted\" };\n return { kind: \"duplicate_run_id\" };\n }\n\n async pop(envId: string): Promise<BufferEntry | null> {\n const queueKey = `mollifier:queue:${envId}`;\n const orgsKey = \"mollifier:orgs\";\n const entryPrefix = \"mollifier:entries:\";\n const encoded = (await this.redis.popAndMarkDraining(\n queueKey,\n orgsKey,\n DRAINING_SET_KEY,\n entryPrefix,\n envId,\n \"mollifier:org-envs:\"\n )) as string | null;\n if (!encoded) return null;\n\n let raw: unknown;\n try {\n raw = JSON.parse(encoded);\n } catch {\n this.logger.error(\"MollifierBuffer.pop: failed to parse script result\", { envId });\n return null;\n }\n\n const parsed = BufferEntrySchema.safeParse(raw);\n if (!parsed.success) {\n this.logger.error(\"MollifierBuffer.pop: invalid entry shape\", {\n envId,\n errors: parsed.error.flatten(),\n });\n return null;\n }\n return parsed.data;\n }\n\n async getEntry(runId: string): Promise<BufferEntry | null> {\n const raw = await this.redis.hgetall(`mollifier:entries:${runId}`);\n if (!raw || Object.keys(raw).length === 0) return null;\n\n const parsed = BufferEntrySchema.safeParse(raw);\n if (!parsed.success) {\n this.logger.error(\"MollifierBuffer.getEntry: invalid entry shape\", {\n runId,\n errors: parsed.error.flatten(),\n });\n return null;\n }\n return parsed.data;\n }\n\n // Drainer walks these two methods to schedule pops with org-level\n // fairness: one env per org per tick. The Lua scripts maintain both\n // sets atomically with the per-env queues, so an org/env appears here\n // exactly when at least one of its envs has a queued entry.\n async listOrgs(): Promise<string[]> {\n return this.redis.smembers(\"mollifier:orgs\");\n }\n\n async listEnvsForOrg(orgId: string): Promise<string[]> {\n return this.redis.smembers(`mollifier:org-envs:${orgId}`);\n }\n\n // Read-only enumeration of currently-queued entries for a single env.\n // Used by the stale-sweep to compute per-entry dwell time, so order is\n // immaterial — LRANGE returns them newest-first (LPUSH head) but the\n // caller scans the whole window. Non-destructive: the drainer still\n // RPOPs these entries in FIFO order.\n //\n // The entry HGETALLs are issued in a single pipelined batch (one\n // network round-trip instead of N) — at the stale-sweep's default\n // maxCount=1000 the serial implementation cost ~1000 RTTs per env,\n // which dominated sweep wall-time at any meaningful backlog.\n //\n // A missing entry (empty hash) is skipped: the drainer's RPOP+DEL of\n // the entry hash can race our LRANGE→HGETALL window, so a runId on\n // the queue with no backing hash is an expected concurrency outcome,\n // not an error.\n async listEntriesForEnv(envId: string, maxCount: number): Promise<BufferEntry[]> {\n if (maxCount <= 0) return [];\n const runIds = await this.redis.lrange(`mollifier:queue:${envId}`, 0, maxCount - 1);\n if (runIds.length === 0) return [];\n\n const pipeline = this.redis.pipeline();\n for (const runId of runIds) {\n pipeline.hgetall(`mollifier:entries:${runId}`);\n }\n const results = await pipeline.exec();\n if (!results) return [];\n\n const entries: BufferEntry[] = [];\n for (let i = 0; i < results.length; i++) {\n const [err, raw] = results[i] as [Error | null, Record<string, string> | null];\n if (err) {\n this.logger.error(\"MollifierBuffer.listEntriesForEnv: hgetall failed\", {\n runId: runIds[i],\n err: err.message,\n });\n continue;\n }\n if (!raw || Object.keys(raw).length === 0) continue;\n const parsed = BufferEntrySchema.safeParse(raw);\n if (!parsed.success) {\n this.logger.error(\"MollifierBuffer.listEntriesForEnv: invalid entry shape\", {\n runId: runIds[i],\n errors: parsed.error.flatten(),\n });\n continue;\n }\n entries.push(parsed.data);\n }\n return entries;\n }\n\n // Atomic snapshot mutation. Used by customer-mutation API endpoints\n // (tags, metadata-put, reschedule, cancel) when the run is still in\n // the buffer. Three outcomes:\n // - \"applied_to_snapshot\": entry was QUEUED + not materialised; the\n // drainer will read the patched payload on its next pop.\n // - \"not_found\": no entry hash exists for this runId — including a\n // FAILED entry, whose hash the drainer-terminal `fail` path DELs.\n // - \"busy\": entry is DRAINING or materialised. The API\n // wait-and-bounces through PG.\n // - \"limit_exceeded\": an `append_tags` patch carrying `maxTags` would\n // push the deduped tag count over the cap; nothing is written.\n async mutateSnapshot(runId: string, patch: SnapshotPatch): Promise<MutateSnapshotResult> {\n const result = (await this.redis.mutateMollifierSnapshot(\n `mollifier:entries:${runId}`,\n JSON.stringify(patch)\n )) as string;\n if (\n result === \"applied_to_snapshot\" ||\n result === \"not_found\" ||\n result === \"busy\" ||\n result === \"limit_exceeded\"\n ) {\n return result;\n }\n throw new Error(`MollifierBuffer.mutateSnapshot: unexpected Lua return value: ${result}`);\n }\n\n // Optimistic compare-and-swap on the snapshot's metadata. Caller reads\n // the current metadataVersion via getEntry, applies operations in JS via\n // `applyMetadataOperations`, then calls this with the new metadata + the\n // expected version. Lua refuses if the version has moved (caller retries\n // up to N times). Mirrors the PG-side `UpdateMetadataService` retry\n // loop so concurrent increment/append operations don't lose deltas.\n async casSetMetadata(input: {\n runId: string;\n expectedVersion: number;\n newMetadata: string;\n newMetadataType: string;\n }): Promise<CasSetMetadataResult> {\n const entryKey = `mollifier:entries:${input.runId}`;\n const raw = (await this.redis.casSetMollifierMetadata(\n entryKey,\n String(input.expectedVersion),\n input.newMetadata,\n input.newMetadataType\n )) as string;\n if (raw === \"not_found\") return { kind: \"not_found\" };\n if (raw === \"busy\") return { kind: \"busy\" };\n if (raw.startsWith(\"conflict:\")) {\n return { kind: \"version_conflict\", currentVersion: Number(raw.slice(\"conflict:\".length)) };\n }\n if (raw.startsWith(\"applied:\")) {\n return { kind: \"applied\", newVersion: Number(raw.slice(\"applied:\".length)) };\n }\n throw new Error(`MollifierBuffer.casSetMetadata: unexpected Lua return: ${raw}`);\n }\n\n // Atomic pre-gate claim on a (env, task, idempotencyKey) tuple. One\n // call across both PG and buffer paths serialises through this claim;\n // closes the race the buffer-side SETNX leaves open during the\n // gate-transition burst window.\n //\n // The caller supplies an opaque `token` (UUID) on claim. The same token\n // MUST be passed to `publishClaim` / `releaseClaim`, which compare-and-\n // act so a late release from a previous claimant whose TTL expired\n // cannot erase a new owner's claim.\n //\n // - \"claimed\": we now own the claim, the caller proceeds with the\n // trigger pipeline and must `publishClaim` on success or\n // `releaseClaim` on failure.\n // - \"pending\": another trigger owns the claim and hasn't published\n // yet; the caller should poll.\n // - \"resolved\": the claim already holds a runId; the caller can\n // return that runId as a cached hit.\n async claimIdempotency(\n input: IdempotencyLookupInput & { token: string; ttlSeconds: number }\n ): Promise<IdempotencyClaimResult> {\n const claimKey = makeIdempotencyClaimKey(input);\n const raw = (await this.redis.claimMollifierIdempotency(\n claimKey,\n `${PENDING_PREFIX}${input.token}`,\n PENDING_PREFIX,\n String(input.ttlSeconds)\n )) as string;\n if (raw === \"claimed\") return { kind: \"claimed\" };\n if (raw === \"pending\") return { kind: \"pending\" };\n if (raw.startsWith(\"resolved:\")) {\n return { kind: \"resolved\", runId: raw.slice(\"resolved:\".length) };\n }\n throw new Error(`MollifierBuffer.claimIdempotency: unexpected return: ${raw}`);\n }\n\n // Publish the winning runId to the claim so subsequent claimants /\n // waiters see \"resolved\". TTL bounded by the customer's\n // `idempotencyKeyExpiresAt` minus now; caller computes.\n //\n // Compare-and-set on the caller's token: if the current value isn't\n // our pending marker (TTL expired and another claimant moved in, or\n // someone else already published), the publish is a no-op. The caller\n // can treat any such case as \"we lost the claim\" and re-read.\n // Returns true if we published; false if the claim slot was no longer\n // ours.\n async publishClaim(\n input: IdempotencyLookupInput & { token: string; runId: string; ttlSeconds: number }\n ): Promise<boolean> {\n const claimKey = makeIdempotencyClaimKey(input);\n const result = (await this.redis.publishMollifierClaim(\n claimKey,\n `${PENDING_PREFIX}${input.token}`,\n input.runId,\n String(input.ttlSeconds)\n )) as number;\n return result === 1;\n }\n\n // Release the claim on pipeline error so waiters can re-claim and\n // retry. Idempotent.\n //\n // Compare-and-delete on the caller's token: only deletes if the\n // current value is exactly our pending marker. A late release from a\n // claimant whose TTL expired is a no-op, so a new owner's claim is\n // never wiped by a slow predecessor.\n async releaseClaim(input: IdempotencyLookupInput & { token: string }): Promise<void> {\n const claimKey = makeIdempotencyClaimKey(input);\n await this.redis.releaseMollifierClaim(claimKey, `${PENDING_PREFIX}${input.token}`);\n }\n\n // Reopen a RESOLVED claim slot whose winner was cleared, so the claim-loser\n // reacquire path can re-serialise a cross-DB recreate through a fresh claim.\n // Compare-and-delete on the observed `expectedRunId` (never an unconditional\n // DEL) so a concurrent reacquirer that already re-published a NEW winner is\n // never wiped. Reuses the lookup self-heal's compare-and-delete Lua. Returns\n // true if the stale slot was cleared.\n async resetResolvedClaim(\n input: IdempotencyLookupInput & { expectedRunId: string }\n ): Promise<boolean> {\n const claimKey = makeIdempotencyClaimKey(input);\n const deleted = (await this.redis.delMollifierKeyIfEquals(\n claimKey,\n input.expectedRunId\n )) as number;\n return deleted === 1;\n }\n\n // Read the current claim value, used by the wait/poll loop on losers\n // to detect \"pending\" → \"resolved\" transitions and timeouts.\n async readClaim(input: IdempotencyLookupInput): Promise<IdempotencyClaimResult | null> {\n const claimKey = makeIdempotencyClaimKey(input);\n const value = await this.redis.get(claimKey);\n if (value === null) return null;\n if (value.startsWith(PENDING_PREFIX)) return { kind: \"pending\" };\n return { kind: \"resolved\", runId: value };\n }\n\n // Resolve a buffered run by (env, task, idempotencyKey) tuple. Used by\n // `IdempotencyKeyConcern.handleTriggerRequest` after the PG check\n // misses — same key may belong to a buffered run waiting to drain. The\n // lookup self-heals: if the lookup points at an entry hash that's gone,\n // we clear the lookup and report a miss. The clear is a compare-and-\n // delete (only if the key still holds the stale runId we observed) so a\n // fresh accept that rebinds the key between our GET and DEL isn't wiped.\n async lookupIdempotency(input: IdempotencyLookupInput): Promise<string | null> {\n const lookupKey = idempotencyLookupKeyFor(input);\n const runId = await this.redis.get(lookupKey);\n if (!runId) return null;\n const entry = await this.getEntry(runId);\n if (!entry) {\n await this.redis.delMollifierKeyIfEquals(lookupKey, runId);\n return null;\n }\n return runId;\n }\n\n // Clear the idempotency binding from a buffered run. Used by\n // `ResetIdempotencyKeyService` alongside the existing PG-side\n // `updateMany`. Returns the runId that was cleared, or null if no\n // buffered run held this key.\n async resetIdempotency(input: IdempotencyLookupInput): Promise<{ clearedRunId: string | null }> {\n const lookupKey = idempotencyLookupKeyFor(input);\n const claimKey = makeIdempotencyClaimKey(input);\n const clearedRunId = (await this.redis.resetMollifierIdempotency(\n lookupKey,\n \"mollifier:entries:\",\n claimKey\n )) as string;\n return { clearedRunId: clearedRunId.length > 0 ? clearedRunId : null };\n }\n\n // Marks the entry as materialised (PG row written) and resets its TTL to\n // the grace window. Entry hash persists past ack as a read-fallback\n // safety net for the brief PG replica-lag window between drainer-side\n // write and reader-side visibility. Also clears the associated\n // idempotency lookup if one was set on accept.\n async ack(runId: string): Promise<void> {\n await this.redis.ackMollifierEntry(\n `mollifier:entries:${runId}`,\n DRAINING_SET_KEY,\n String(this.ackGraceTtlSeconds),\n runId\n );\n }\n\n async requeue(runId: string): Promise<void> {\n await this.redis.requeueMollifierEntry(\n `mollifier:entries:${runId}`,\n \"mollifier:orgs\",\n DRAINING_SET_KEY,\n \"mollifier:queue:\",\n runId,\n \"mollifier:org-envs:\"\n );\n }\n\n // Returns true if a live entry was torn down; false if the entry no\n // longer existed (a concurrent ack or manual cleanup removed it between\n // pop and fail — there is no accept-time TTL). Note FAILED is not an\n // observable state: the Lua marks the hash FAILED then DELs it in the\n // same atomic script, so a subsequent getEntry returns null. Caller can\n // use the boolean to skip downstream FAILED handling for ghost entries.\n async fail(runId: string, error: { code: string; message: string }): Promise<boolean> {\n const result = await this.redis.failMollifierEntry(\n `mollifier:entries:${runId}`,\n DRAINING_SET_KEY,\n JSON.stringify(error),\n runId\n );\n return result === 1;\n }\n\n // Observability-only: number of entries currently in DRAINING state\n // (popped, not yet acked/failed/requeued). The gauge in the webapp\n // drainer worker polls this on a short interval and emits it as\n // `mollifier.draining.current` for ops dashboards and post-crash\n // forensics. Cheap (single ZCARD).\n async getDrainingCount(): Promise<number> {\n return this.redis.zcard(DRAINING_SET_KEY);\n }\n\n // Observability-only: list runIds that have been DRAINING longer than\n // `olderThanMs` (i.e. popped before `now - olderThanMs`). Bounded by\n // `limit` to keep the result set tractable when something has gone\n // very wrong. ZRANGEBYSCORE is O(log N + K). Score is the pop wall-clock\n // in milliseconds as written by the popAndMarkDraining Lua.\n async listStaleDraining(olderThanMs: number, limit: number): Promise<string[]> {\n const maxScore = Date.now() - Math.max(0, olderThanMs);\n return this.redis.zrangebyscore(\n DRAINING_SET_KEY,\n \"-inf\",\n String(maxScore),\n \"LIMIT\",\n 0,\n Math.max(0, limit)\n );\n }\n\n // Returns Redis-side TTL on the entry hash. Returns -1 for entries\n // with no TTL — the steady state under the current design, where\n // entries persist until drainer ack/fail. The ack grace TTL (30s\n // post-materialise) is the only context where this returns a\n // positive value; tests around the grace TTL still rely on it.\n async getEntryTtlSeconds(runId: string): Promise<number> {\n return this.redis.ttl(`mollifier:entries:${runId}`);\n }\n\n async evaluateTrip(\n envId: string,\n options: { windowMs: number; threshold: number; holdMs: number }\n ): Promise<{ tripped: boolean; count: number }> {\n const rateKey = `mollifier:rate:${envId}`;\n const trippedKey = `mollifier:tripped:${envId}`;\n const result = (await this.redis.mollifierEvaluateTrip(\n rateKey,\n trippedKey,\n String(options.windowMs),\n String(options.threshold),\n String(options.holdMs)\n )) as [number, number];\n\n return { count: result[0], tripped: result[1] === 1 };\n }\n\n async close(): Promise<void> {\n await this.redis.quit();\n }\n\n #registerCommands() {\n this.redis.defineCommand(\"acceptMollifierEntry\", {\n numberOfKeys: 3,\n lua: `\n local entryKey = KEYS[1]\n local queueKey = KEYS[2]\n local orgsKey = KEYS[3]\n local runId = ARGV[1]\n local envId = ARGV[2]\n local orgId = ARGV[3]\n local payload = ARGV[4]\n local createdAt = ARGV[5]\n local createdAtMicros = ARGV[6]\n local orgEnvsPrefix = ARGV[7]\n local idempotencyLookupKey = ARGV[8] or ''\n local entryPrefix = ARGV[9]\n\n -- Idempotent: refuse if an entry for this runId already exists in any\n -- state. Caller-side dedup is also enforced via API idempotency keys,\n -- but the buffer must not double-enqueue if a caller retries.\n if redis.call('EXISTS', entryKey) == 1 then\n return 0\n end\n\n -- Idempotency-key dedup. If the caller passed a lookup key\n -- and it's already bound to another buffered run, return the\n -- winner's runId so the loser's API response can echo it as a\n -- cached hit. Otherwise SET the lookup (no TTL — lifecycle is\n -- paired with the entry hash; drainer ack/fail clear it\n -- explicitly).\n if idempotencyLookupKey ~= '' then\n local existing = redis.call('GET', idempotencyLookupKey)\n if existing then\n -- Self-heal: only honour the binding if its entry hash still\n -- exists. If the entry was evicted (maxmemory) but the lookup\n -- survived, the binding is stale — fall through and rebind to\n -- this run rather than returning a dead runId that would block\n -- the key indefinitely. Mirrors lookupIdempotency's self-heal.\n if redis.call('EXISTS', entryPrefix .. existing) == 1 then\n return existing\n end\n end\n redis.call('SET', idempotencyLookupKey, runId)\n end\n\n redis.call('HSET', entryKey,\n 'runId', runId,\n 'envId', envId,\n 'orgId', orgId,\n 'payload', payload,\n 'status', 'QUEUED',\n 'attempts', '0',\n 'createdAt', createdAt,\n 'createdAtMicros', createdAtMicros,\n 'idempotencyLookupKey', idempotencyLookupKey,\n 'metadataVersion', '0')\n -- No EXPIRE on the entry hash. Buffer entries persist until the\n -- drainer ACKs (post-materialise grace) or FAILs them — the\n -- drainer is the only recovery mechanism, so silent TTL-based\n -- eviction would lose runs with no customer-visible signal.\n -- Memory pressure from an offline drainer is the alertable\n -- failure mode instead; see _ops/mollifier-ops.md.\n -- LIST queue: LPUSH at the head, drainer RPOPs from the tail, so\n -- insertion order == drain order (FIFO). createdAtMicros is kept\n -- as a hash field for dwell metrics only — it is no longer a sort\n -- key now that the buffer has no list/pagination surface.\n redis.call('LPUSH', queueKey, runId)\n -- Org-level membership: maintained atomically with the per-env\n -- queue so the drainer can walk orgs → envs-for-org and\n -- schedule one env per org per tick. SADDs are idempotent if the\n -- org/env are already tracked.\n redis.call('SADD', orgsKey, orgId)\n redis.call('SADD', orgEnvsPrefix .. orgId, envId)\n return 1\n `,\n });\n\n this.redis.defineCommand(\"requeueMollifierEntry\", {\n numberOfKeys: 3,\n lua: `\n local entryKey = KEYS[1]\n local orgsKey = KEYS[2]\n local drainingSetKey = KEYS[3]\n local queuePrefix = ARGV[1]\n local runId = ARGV[2]\n local orgEnvsPrefix = ARGV[3]\n\n local envId = redis.call('HGET', entryKey, 'envId')\n local orgId = redis.call('HGET', entryKey, 'orgId')\n if not envId then\n return 0\n end\n\n local currentAttempts = redis.call('HGET', entryKey, 'attempts')\n local nextAttempts = tonumber(currentAttempts or '0') + 1\n\n redis.call('HSET', entryKey, 'status', 'QUEUED', 'attempts', tostring(nextAttempts))\n -- Requeue RPUSHes to the tail (the RPOP end) so a transiently\n -- failed entry pops next rather than going to the back of the\n -- line behind a fresh backlog. createdAt is immutable across\n -- retries; the drainer's maxAttempts caps the\n -- retry loop so a poisoned entry doesn't head-of-line forever.\n redis.call('RPUSH', queuePrefix .. envId, runId)\n -- Re-track the org/env: pop may have SREM'd them when the queue\n -- last emptied. SADDs are idempotent if the values are still\n -- present.\n if orgId then\n redis.call('SADD', orgsKey, orgId)\n redis.call('SADD', orgEnvsPrefix .. orgId, envId)\n end\n -- Observability-only: leaving DRAINING state, so drop the\n -- entry from the draining-tracker set. ZREM on absent member\n -- is a no-op.\n redis.call('ZREM', drainingSetKey, runId)\n return 1\n `,\n });\n\n this.redis.defineCommand(\"popAndMarkDraining\", {\n numberOfKeys: 3,\n lua: `\n local queueKey = KEYS[1]\n local orgsKey = KEYS[2]\n local drainingSetKey = KEYS[3]\n local entryPrefix = ARGV[1]\n local envId = ARGV[2]\n local orgEnvsPrefix = ARGV[3]\n\n -- Wall-clock millis used as the ZADD score on the draining-tracker\n -- set. Computed once per script invocation so all observers see\n -- the same pop instant. redis.call('TIME') is deterministic per\n -- script execution (Lua sees it as a single read), satisfying the\n -- write-determinism contract on replicas/AOF replay.\n local timeArr = redis.call('TIME')\n local nowMs = tonumber(timeArr[1]) * 1000 + math.floor(tonumber(timeArr[2]) / 1000)\n\n -- Helper: prune org-level membership when an env's queue empties.\n -- Called only from the success branch where we know orgId from the\n -- popped entry. The no-runId branch below can't reach this because\n -- it has no entry to read orgId from — accept any stale org-envs\n -- entries that result (bounded by env count, recovered next accept).\n local function pruneOrgMembership(orgId)\n if not orgId then return end\n local orgEnvsKey = orgEnvsPrefix .. orgId\n redis.call('SREM', orgEnvsKey, envId)\n if redis.call('SCARD', orgEnvsKey) == 0 then\n redis.call('SREM', orgsKey, orgId)\n end\n end\n\n -- Loop to skip orphan queue references — runIds whose entry hash is\n -- gone (e.g. Redis maxmemory eviction, since QUEUED entries carry\n -- no TTL of their own). HSET on a missing key would CREATE a\n -- partial hash without a TTL, leaking memory. The loop is bounded\n -- by queue length; entire Lua script remains atomic.\n while true do\n -- RPOP returns the tail member (oldest, FIFO), or false when empty.\n local runId = redis.call('RPOP', queueKey)\n if not runId then\n -- Queue is empty AND we have no entry to read orgId from, so\n -- skip org-level cleanup. Stale org-envs entries are bounded\n -- by env count and recovered on the next accept.\n return nil\n end\n\n local entryKey = entryPrefix .. runId\n if redis.call('EXISTS', entryKey) == 1 then\n redis.call('HSET', entryKey, 'status', 'DRAINING')\n -- Observability-only: track the runId in the draining set\n -- with the pop wall-clock as score. Acked/failed/requeued\n -- in the corresponding Lua scripts. The set is NOT\n -- load-bearing for correctness — the per-entry hash carries\n -- status — so a missed ZREM on a partial Lua execution is\n -- recoverable via the stale-sweep + entry hash, not a\n -- correctness bug.\n redis.call('ZADD', drainingSetKey, nowMs, runId)\n local raw = redis.call('HGETALL', entryKey)\n local result = {}\n for i = 1, #raw, 2 do\n result[raw[i]] = raw[i + 1]\n end\n -- Prune org-level membership if this pop drained the queue.\n -- Atomic with the RPOP above — a concurrent accept AFTER\n -- this script will SADD both back along with its LPUSH.\n if redis.call('LLEN', queueKey) == 0 then\n pruneOrgMembership(result['orgId'])\n end\n return cjson.encode(result)\n end\n -- Orphan queue reference: entry hash gone (evicted) while runId\n -- was queued. Discard the reference and loop to the next.\n end\n `,\n });\n\n this.redis.defineCommand(\"casSetMollifierMetadata\", {\n numberOfKeys: 1,\n lua: `\n local entryKey = KEYS[1]\n local expectedVersion = tonumber(ARGV[1])\n local newMetadata = ARGV[2]\n local newMetadataType = ARGV[3]\n\n if redis.call('EXISTS', entryKey) == 0 then\n return 'not_found'\n end\n\n local status = redis.call('HGET', entryKey, 'status')\n local materialised = redis.call('HGET', entryKey, 'materialised')\n if status ~= 'QUEUED' or materialised == 'true' then\n return 'busy'\n end\n\n local currentVersionStr = redis.call('HGET', entryKey, 'metadataVersion') or '0'\n local currentVersion = tonumber(currentVersionStr) or 0\n if currentVersion ~= expectedVersion then\n return 'conflict:' .. tostring(currentVersion)\n end\n\n -- Write the new metadata onto the snapshot's payload JSON. We\n -- keep the rest of the payload intact — only metadata/metadataType\n -- change. metadataVersion is denormalised on the hash for cheap\n -- CAS reads; it's intentionally NOT stored inside the payload\n -- itself (PG-side metadataVersion is a column, not a JSON field).\n local payloadJson = redis.call('HGET', entryKey, 'payload')\n local ok, payload = pcall(cjson.decode, payloadJson)\n if not ok then return 'busy' end\n payload.metadata = newMetadata\n payload.metadataType = newMetadataType\n\n local newVersion = currentVersion + 1\n redis.call('HSET', entryKey,\n 'payload', cjson.encode(payload),\n 'metadataVersion', tostring(newVersion))\n return 'applied:' .. tostring(newVersion)\n `,\n });\n\n this.redis.defineCommand(\"claimMollifierIdempotency\", {\n numberOfKeys: 1,\n lua: `\n local claimKey = KEYS[1]\n local pendingMarker = ARGV[1] -- \"pending:<caller-token>\"\n local pendingPrefix = ARGV[2] -- \"pending:\"\n local ttl = tonumber(ARGV[3])\n\n -- SETNX-with-TTL: atomic; only one caller can win.\n local won = redis.call('SET', claimKey, pendingMarker, 'NX', 'EX', ttl)\n if won then\n return 'claimed'\n end\n\n local existing = redis.call('GET', claimKey)\n if not existing then\n -- The slot expired in the race window between the SET NX\n -- failing and this GET. It's free now — claim it so we don't\n -- string.sub a nil and error out.\n redis.call('SET', claimKey, pendingMarker, 'EX', ttl)\n return 'claimed'\n end\n -- Any \"pending:*\" value is a live claim — the caller-supplied\n -- token differentiates ownership but is opaque to losers.\n if string.sub(existing, 1, string.len(pendingPrefix)) == pendingPrefix then\n return 'pending'\n end\n return 'resolved:' .. existing\n `,\n });\n\n // Publish a winning runId to a claim slot we own. Compare-and-set on\n // the caller's pending marker: if the slot is no longer ours (TTL\n // expired and another claimant moved in, or already resolved by\n // someone else), we no-op. Returns 1 on publish, 0 on no-op.\n this.redis.defineCommand(\"publishMollifierClaim\", {\n numberOfKeys: 1,\n lua: `\n local claimKey = KEYS[1]\n local ownerMarker = ARGV[1] -- \"pending:<our-token>\"\n local runId = ARGV[2]\n local ttl = tonumber(ARGV[3])\n\n local existing = redis.call('GET', claimKey)\n if existing == ownerMarker then\n redis.call('SET', claimKey, runId, 'EX', ttl)\n return 1\n end\n return 0\n `,\n });\n\n // Release a claim slot we own. Compare-and-delete on the caller's\n // pending marker: a late release from a previous claimant whose TTL\n // expired is a no-op, so a new owner's claim is never wiped.\n this.redis.defineCommand(\"releaseMollifierClaim\", {\n numberOfKeys: 1,\n lua: `\n local claimKey = KEYS[1]\n local ownerMarker = ARGV[1] -- \"pending:<our-token>\"\n\n local existing = redis.call('GET', claimKey)\n if existing == ownerMarker then\n redis.call('DEL', claimKey)\n return 1\n end\n return 0\n `,\n });\n\n this.redis.defineCommand(\"resetMollifierIdempotency\", {\n numberOfKeys: 1,\n lua: `\n local lookupKey = KEYS[1]\n local entryPrefix = ARGV[1]\n local claimKey = ARGV[2]\n\n -- Reset reopens the key across BOTH the buffer lookup and the\n -- cross-store pre-gate claim pointer. Without clearing the claim,\n -- a resolved/pending claim would keep deduping new triggers for\n -- the rest of its TTL even though the binding was reset. DEL is\n -- unconditional — the claim is gone regardless of whether a\n -- buffered run currently holds the lookup.\n redis.call('DEL', claimKey)\n\n local runId = redis.call('GET', lookupKey)\n if not runId then\n return ''\n end\n\n local entryKey = entryPrefix .. runId\n if redis.call('EXISTS', entryKey) == 0 then\n -- Stale lookup. Lazy cleanup.\n redis.call('DEL', lookupKey)\n return ''\n end\n\n -- Clear the idempotency fields on the snapshot payload so the\n -- drainer's eventual engine.trigger call inserts a PG row\n -- without the key set.\n local payloadJson = redis.call('HGET', entryKey, 'payload')\n if payloadJson then\n local ok, payload = pcall(cjson.decode, payloadJson)\n if ok then\n payload.idempotencyKey = cjson.null\n payload.idempotencyKeyExpiresAt = cjson.null\n redis.call('HSET', entryKey, 'payload', cjson.encode(payload))\n end\n end\n -- Clear the denormalised lookup pointer on the hash so a later\n -- ack doesn't try to DEL a key that's already gone.\n redis.call('HSET', entryKey, 'idempotencyLookupKey', '')\n redis.call('DEL', lookupKey)\n return runId\n `,\n });\n\n this.redis.defineCommand(\"mutateMollifierSnapshot\", {\n numberOfKeys: 1,\n lua: `\n local entryKey = KEYS[1]\n local patchJson = ARGV[1]\n\n if redis.call('EXISTS', entryKey) == 0 then\n return 'not_found'\n end\n\n local status = redis.call('HGET', entryKey, 'status')\n local materialised = redis.call('HGET', entryKey, 'materialised')\n if status ~= 'QUEUED' or materialised == 'true' then\n return 'busy'\n end\n\n local payloadJson = redis.call('HGET', entryKey, 'payload')\n local ok, payload = pcall(cjson.decode, payloadJson)\n if not ok then return 'busy' end\n\n local patch = cjson.decode(patchJson)\n\n if patch.type == 'append_tags' then\n -- cjson decode of an absent or empty-array field gives nil or\n -- an empty table; we rebuild as a dense array. Existing tags\n -- are preserved; new tags are appended only if not present.\n local existing = payload.tags or {}\n local seen = {}\n local merged = {}\n for _, t in ipairs(existing) do\n if not seen[t] then\n seen[t] = true\n table.insert(merged, t)\n end\n end\n for _, t in ipairs(patch.tags or {}) do\n if not seen[t] then\n seen[t] = true\n table.insert(merged, t)\n end\n end\n -- Cap the deduped count when the caller supplies a limit, so a\n -- buffered run can't exceed MAX_TAGS_PER_RUN via the tags API.\n -- Reject the whole patch (write nothing) rather than truncating.\n if patch.maxTags ~= nil and #merged > patch.maxTags then\n return 'limit_exceeded'\n end\n payload.tags = merged\n elseif patch.type == 'set_metadata' then\n payload.metadata = patch.metadata\n payload.metadataType = patch.metadataType\n -- Bump the denormalised metadataVersion so an in-flight\n -- casSetMetadata (optimistic CAS keyed on this counter) sees\n -- the concurrent write as a version conflict and retries,\n -- instead of clobbering it under a now-stale expectedVersion.\n local currentVersion = tonumber(redis.call('HGET', entryKey, 'metadataVersion') or '0') or 0\n redis.call('HSET', entryKey, 'metadataVersion', tostring(currentVersion + 1))\n elseif patch.type == 'set_delay' then\n payload.delayUntil = patch.delayUntil\n elseif patch.type == 'mark_cancelled' then\n payload.cancelledAt = patch.cancelledAt\n payload.cancelReason = patch.cancelReason\n else\n return 'busy'\n end\n\n redis.call('HSET', entryKey, 'payload', cjson.encode(payload))\n return 'applied_to_snapshot'\n `,\n });\n\n this.redis.defineCommand(\"ackMollifierEntry\", {\n numberOfKeys: 2,\n lua: `\n local entryKey = KEYS[1]\n local drainingSetKey = KEYS[2]\n local graceTtlSeconds = tonumber(ARGV[1])\n local runId = ARGV[2]\n\n -- Always ZREM from the draining-tracker — even if the entry hash\n -- has been concurrently torn down, the runId might still be in\n -- the set (e.g. fail() ran first and cleared the hash but a\n -- delayed ack races in). Idempotent: ZREM on absent is a no-op.\n redis.call('ZREM', drainingSetKey, runId)\n\n -- Guard: never create a partial entry. If the hash is gone between\n -- pop and ack (concurrent fail or eviction — QUEUED entries carry\n -- no TTL), the run is gone, nothing to mark materialised.\n if redis.call('EXISTS', entryKey) == 0 then\n return 0\n end\n\n -- If the entry was accepted with an idempotency key, the lookup\n -- string was stored on the hash at accept time. Clear it now —\n -- PG becomes canonical for the key post-materialisation.\n local lookupKey = redis.call('HGET', entryKey, 'idempotencyLookupKey')\n if lookupKey and lookupKey ~= '' then\n redis.call('DEL', lookupKey)\n end\n\n redis.call('HSET', entryKey, 'materialised', 'true')\n redis.call('EXPIRE', entryKey, graceTtlSeconds)\n return 1\n `,\n });\n\n this.redis.defineCommand(\"failMollifierEntry\", {\n numberOfKeys: 2,\n lua: `\n local entryKey = KEYS[1]\n local drainingSetKey = KEYS[2]\n local errorPayload = ARGV[1]\n local runId = ARGV[2]\n\n -- Always ZREM from the draining-tracker (idempotent on absent).\n -- Mirrors ack: the runId may be in the set even if the entry hash\n -- has been raced away.\n redis.call('ZREM', drainingSetKey, runId)\n\n -- Guard: nothing to mark FAILED if the hash is gone (concurrent\n -- ack/manual cleanup). Returning 0 lets the caller distinguish\n -- \"marked failed\" from \"no-op\".\n if redis.call('EXISTS', entryKey) == 0 then\n return 0\n end\n\n redis.call('HSET', entryKey, 'status', 'FAILED', 'lastError', errorPayload)\n\n -- Terminal-failure contract: the drainer's onTerminalFailure\n -- callback (see MollifierDrainer.processEntry) has been\n -- invoked before this fail() and has either written a\n -- SYSTEM_FAILURE PG row (for both non-retryable AND\n -- max-attempts-exhausted retryable errors) or chosen to fall\n -- through (genuinely bad snapshot the engine can't materialise\n -- a row from). Either way the buffer entry is no longer\n -- load-bearing here. Clear the idempotency lookup -- PG's\n -- unique constraint is the canonical dedup mechanism\n -- post-materialise -- and drop the entry hash so failed runs\n -- don't accrete forever now that there's no accept-time TTL.\n local lookupKey = redis.call('HGET', entryKey, 'idempotencyLookupKey')\n if lookupKey and lookupKey ~= '' then\n redis.call('DEL', lookupKey)\n end\n redis.call('DEL', entryKey)\n return 1\n `,\n });\n\n // Compare-and-delete: DEL the key only if it still holds the expected\n // value. Used by lookupIdempotency's stale-lookup self-heal so a\n // concurrent accept that rebinds the key between the reader's GET and\n // this DEL isn't clobbered.\n this.redis.defineCommand(\"delMollifierKeyIfEquals\", {\n numberOfKeys: 1,\n lua: `\n if redis.call('GET', KEYS[1]) == ARGV[1] then\n return redis.call('DEL', KEYS[1])\n end\n return 0\n `,\n });\n\n this.redis.defineCommand(\"mollifierEvaluateTrip\", {\n numberOfKeys: 2,\n lua: `\n local rateKey = KEYS[1]\n local trippedKey = KEYS[2]\n local windowMs = tonumber(ARGV[1])\n local threshold = tonumber(ARGV[2])\n local holdMs = tonumber(ARGV[3])\n\n local count = redis.call('INCR', rateKey)\n if count == 1 then\n redis.call('PEXPIRE', rateKey, windowMs)\n end\n\n if count > threshold then\n redis.call('PSETEX', trippedKey, holdMs, '1')\n end\n\n local tripped = redis.call('EXISTS', trippedKey)\n return {count, tripped}\n `,\n });\n }\n}\n\ndeclare module \"@internal/redis\" {\n interface RedisCommander<Context> {\n acceptMollifierEntry(\n entryKey: string,\n queueKey: string,\n orgsKey: string,\n runId: string,\n envId: string,\n orgId: string,\n payload: string,\n createdAt: string,\n createdAtMicros: string,\n orgEnvsPrefix: string,\n idempotencyLookupKey: string,\n entryPrefix: string,\n callback?: Callback<number | string>\n ): Result<number | string, Context>;\n popAndMarkDraining(\n queueKey: string,\n orgsKey: string,\n drainingSetKey: string,\n entryPrefix: string,\n envId: string,\n orgEnvsPrefix: string,\n callback?: Callback<string | null>\n ): Result<string | null, Context>;\n requeueMollifierEntry(\n entryKey: string,\n orgsKey: string,\n drainingSetKey: string,\n queuePrefix: string,\n runId: string,\n orgEnvsPrefix: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n mutateMollifierSnapshot(\n entryKey: string,\n patchJson: string,\n callback?: Callback<string>\n ): Result<string, Context>;\n casSetMollifierMetadata(\n entryKey: string,\n expectedVersion: string,\n newMetadata: string,\n newMetadataType: string,\n callback?: Callback<string>\n ): Result<string, Context>;\n resetMollifierIdempotency(\n lookupKey: string,\n entryPrefix: string,\n claimKey: string,\n callback?: Callback<string>\n ): Result<string, Context>;\n claimMollifierIdempotency(\n claimKey: string,\n pendingMarker: string,\n pendingPrefix: string,\n ttlSeconds: string,\n callback?: Callback<string>\n ): Result<string, Context>;\n publishMollifierClaim(\n claimKey: string,\n ownerMarker: string,\n runId: string,\n ttlSeconds: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n releaseMollifierClaim(\n claimKey: string,\n ownerMarker: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n ackMollifierEntry(\n entryKey: string,\n drainingSetKey: string,\n graceTtlSeconds: string,\n runId: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n failMollifierEntry(\n entryKey: string,\n drainingSetKey: string,\n errorPayload: string,\n runId: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n delMollifierKeyIfEquals(\n key: string,\n expected: string,\n callback?: Callback<number>\n ): Result<number, Context>;\n mollifierEvaluateTrip(\n rateKey: string,\n trippedKey: string,\n windowMs: string,\n threshold: string,\n holdMs: string,\n callback?: Callback<[number, number]>\n ): Result<[number, number], Context>;\n }\n}\n","import { Logger } from \"@trigger.dev/core/logger\";\nimport type { MollifierBuffer } from \"./buffer.js\";\nimport type { BufferEntry } from \"./schemas.js\";\nimport { deserialiseSnapshot } from \"./schemas.js\";\n\nexport type MollifierDrainerHandler<TPayload> = (input: {\n runId: string;\n envId: string;\n orgId: string;\n payload: TPayload;\n attempts: number;\n createdAt: Date;\n}) => Promise<void>;\n\n// Invoked once per entry before `buffer.fail()` on any terminal path —\n// non-retryable error OR retryable error after maxAttempts. Lets the caller\n// land a SYSTEM_FAILURE PG row so the customer sees the run instead of it\n// silently disappearing alongside the buffer entry. Throwing a retryable\n// error from the callback causes the drainer to requeue rather than fail\n// (so the PG write itself gets another chance once PG recovers); throwing\n// anything else falls through to `buffer.fail()` to avoid an infinite loop\n// on a genuinely bad payload.\nexport type MollifierDrainerTerminalFailureCause = \"non-retryable\" | \"max-attempts-exhausted\";\nexport type MollifierDrainerTerminalFailureHandler<TPayload> = (input: {\n runId: string;\n envId: string;\n orgId: string;\n payload: TPayload;\n attempts: number;\n createdAt: Date;\n error: { code: string; message: string };\n cause: MollifierDrainerTerminalFailureCause;\n}) => Promise<void>;\n\nexport type MollifierDrainerOptions<TPayload> = {\n buffer: MollifierBuffer;\n handler: MollifierDrainerHandler<TPayload>;\n onTerminalFailure?: MollifierDrainerTerminalFailureHandler<TPayload>;\n concurrency: number;\n maxAttempts: number;\n isRetryable: (err: unknown) => boolean;\n pollIntervalMs?: number;\n // Cap on how many ORGS `runOnce` processes per tick. The drainer rotates\n // through orgs at the top level and picks one env per org per tick, so\n // the actual per-tick pop count is at most `maxOrgsPerTick`. Tune for\n // \"typical orgs with pending entries\" rather than total system org\n // count. Defaults to 500.\n //\n // The buffer maintains `mollifier:orgs` and `mollifier:org-envs:${orgId}`\n // atomically with per-env queues, so the drainer can walk orgs → envs\n // directly. An org with N envs gets the same per-tick scheduling slot\n // as an org with 1 env — tenant-level drainage throughput is determined\n // by org count, not env count.\n maxOrgsPerTick?: number;\n // Per-env per-tick pop cap. Default 1 preserves the original\n // one-pop-per-env-per-tick behaviour. Setting it higher lets a single\n // env drain at handler-parallelism speed: each tick the drainer pops\n // up to `drainBatchSize` entries from the env's queue, then dispatches\n // them all through the shared `concurrency`-bounded pLimit. For a\n // single-env burst this turns N sequential ticks into one tick of N\n // parallel handler calls, capped by `concurrency`. Org/env fairness\n // still holds — each org still contributes exactly one env per tick.\n //\n // Memory: per-tick in-flight entries ≤ `maxOrgsPerTick × drainBatchSize`.\n // Operators sizing this should ensure their PG pool / engine handler\n // can sustain `concurrency` parallel writes; popping more than the\n // handler can process per tick just queues entries in JS waiting on\n // pLimit.\n drainBatchSize?: number;\n // Cap on the exponential backoff applied after consecutive `runOnce`\n // errors. Defaults to 5000ms. The backoff base is `max(pollIntervalMs,\n // backoffFloorMs)` and doubles per consecutive error up to this cap.\n maxBackoffMs?: number;\n // Floor for the exponential-backoff base, so a tiny `pollIntervalMs`\n // doesn't collapse the backoff to near-zero on a sustained outage.\n // Defaults to 100ms.\n backoffFloorMs?: number;\n logger?: Logger;\n};\n\nexport type DrainResult = {\n drained: number;\n failed: number;\n};\n\nexport class MollifierDrainer<TPayload = unknown> {\n private readonly buffer: MollifierBuffer;\n private readonly handler: MollifierDrainerHandler<TPayload>;\n private readonly onTerminalFailure?: MollifierDrainerTerminalFailureHandler<TPayload>;\n private readonly maxAttempts: number;\n private readonly isRetryable: (err: unknown) => boolean;\n private readonly pollIntervalMs: number;\n private readonly maxOrgsPerTick: number;\n private readonly drainBatchSize: number;\n private readonly concurrency: number;\n private readonly maxBackoffMs: number;\n private readonly backoffFloorMs: number;\n private readonly logger: Logger;\n // Rotation state. `orgCursor` advances through the active-orgs list.\n // Each org has its own internal cursor in `perOrgEnvCursors` for\n // cycling through that org's envs. Both reset on `start()`.\n private orgCursor = 0;\n private perOrgEnvCursors = new Map<string, number>();\n private isRunning = false;\n private stopping = false;\n private loopPromise: Promise<void> | null = null;\n\n constructor(options: MollifierDrainerOptions<TPayload>) {\n this.buffer = options.buffer;\n this.handler = options.handler;\n this.onTerminalFailure = options.onTerminalFailure;\n this.maxAttempts = options.maxAttempts;\n this.isRetryable = options.isRetryable;\n this.pollIntervalMs = options.pollIntervalMs ?? 100;\n this.maxOrgsPerTick = options.maxOrgsPerTick ?? 500;\n this.drainBatchSize = Math.max(1, options.drainBatchSize ?? 1);\n this.concurrency = Math.max(1, options.concurrency);\n this.maxBackoffMs = options.maxBackoffMs ?? 5_000;\n this.backoffFloorMs = Math.max(1, options.backoffFloorMs ?? 100);\n this.logger = options.logger ?? new Logger(\"MollifierDrainer\", \"debug\");\n }\n\n async runOnce(): Promise<DrainResult> {\n const orgs = await this.buffer.listOrgs();\n if (orgs.length === 0) return { drained: 0, failed: 0 };\n\n const orgSlice = this.takeOrgSlice(orgs);\n\n // Fan the per-org SMEMBERS out in a single pipelined round-trip. Serial\n // awaits would otherwise add `orgSlice.length × RTT` of dead time before\n // pops start — at the default `maxOrgsPerTick=500` and a ~1ms ElastiCache\n // RTT that's a ~500ms per-tick floor. ioredis auto-pipelines concurrent\n // commands into one batch, so the burst is cheap; SMEMBERS on a small set\n // is O(N) per org and trivial at this scale. `Promise.all` preserves\n // order, so the org→envs pairing below stays deterministic.\n const envsByOrg = await Promise.all(orgSlice.map((orgId) => this.buffer.listEnvsForOrg(orgId)));\n const targets: string[] = [];\n for (let i = 0; i < orgSlice.length; i++) {\n const orgId = orgSlice[i]!;\n const envsForOrg = envsByOrg[i]!;\n if (envsForOrg.length === 0) continue;\n const envId = this.pickEnvForOrg(orgId, envsForOrg);\n targets.push(envId);\n }\n\n if (targets.length === 0) return { drained: 0, failed: 0 };\n\n // Worker-pool draining. We spawn up to `concurrency` workers; each\n // worker repeatedly:\n // 1. Picks the next env with budget remaining (round-robin),\n // atomically claiming one slot of that env's per-tick budget.\n // 2. Pops one entry and processes it.\n // 3. Repeats until pickNextEnv returns null.\n //\n // This pattern gives us both invariants the prior two designs traded\n // off:\n // - Single-env bursts use the full `concurrency` budget. All\n // workers can pull from one env, processing `concurrency` entries\n // in parallel.\n // - The number of entries in \"popped-but-not-acked\" (DRAINING)\n // state at any moment is bounded by the worker count, i.e.\n // `concurrency` — same blast radius as the pre-batch\n // one-pop-per-env model. A process crash mid-tick strands at\n // most `concurrency` entries for stale-sweep to recover, not\n // `maxOrgsPerTick × drainBatchSize`.\n //\n // Fairness: pickNextEnv advances a cursor by 1 each successful pick,\n // so workers round-robin across envs at the entry level. Combined\n // with the per-env budget cap, an env contributes at most\n // `drainBatchSize` entries per tick regardless of how many workers\n // are free — a heavy env can't starve siblings within a tick.\n const remaining = new Map<string, number>();\n const skip = new Set<string>(); // envs with empty queue or pop failure this tick\n for (const envId of targets) remaining.set(envId, this.drainBatchSize);\n\n let cursor = 0;\n const pickNextEnv = (): string | null => {\n for (let i = 0; i < targets.length; i++) {\n const idx = (cursor + i) % targets.length;\n const envId = targets[idx]!;\n if (skip.has(envId)) continue;\n const r = remaining.get(envId) ?? 0;\n if (r > 0) {\n remaining.set(envId, r - 1);\n cursor = (idx + 1) % targets.length;\n return envId;\n }\n }\n return null;\n };\n\n let drained = 0;\n let failed = 0;\n\n const worker = async (): Promise<void> => {\n while (true) {\n const envId = pickNextEnv();\n if (envId === null) return;\n let entry: BufferEntry | null;\n try {\n entry = await this.buffer.pop(envId);\n } catch (err) {\n // A pop failure on one env aborts that env's batch for this\n // tick (don't keep hammering a broken Redis) and counts as\n // exactly one failure — same as the pre-batch path on a pop\n // blowup. Other envs continue.\n //\n // `pickNextEnv` decrements `remaining` before the pop settles,\n // so multiple workers can race into the same env and all hit\n // a throwing pop before the first catch lands. Guarding the\n // failure increment on `!skip.has(envId)` keeps the per-env\n // failure count at exactly one even under that race —\n // matching the documented contract.\n this.logger.error(\"MollifierDrainer.pop failed\", { envId, err });\n if (!skip.has(envId)) {\n skip.add(envId);\n failed += 1;\n }\n continue;\n }\n if (!entry) {\n // Queue exhausted between scheduling and this pop. Mark the\n // env skipped so siblings aren't held up by repeated empty pops.\n skip.add(envId);\n continue;\n }\n try {\n const outcome = await this.processEntry(entry);\n if (outcome === \"drained\") drained += 1;\n else failed += 1;\n } catch (err) {\n this.logger.error(\"MollifierDrainer.processEntry failed\", {\n envId,\n runId: entry.runId,\n err,\n });\n failed += 1;\n }\n }\n };\n\n const totalBudget = targets.length * this.drainBatchSize;\n const workerCount = Math.min(this.concurrency, totalBudget);\n await Promise.all(Array.from({ length: workerCount }, () => worker()));\n\n return { drained, failed };\n }\n\n start(): void {\n if (this.isRunning) return;\n this.isRunning = true;\n this.stopping = false;\n // Reset rotation state on each (re)start. A stop+start cycle means\n // operator intent to \"begin clean\" — between-restart cursor drift\n // would otherwise carry implicit state across what should look like\n // a fresh boot.\n this.orgCursor = 0;\n this.perOrgEnvCursors = new Map();\n this.loopPromise = this.loop();\n }\n\n // Signal the loop to exit (`stopping = true`) and wait for it. With no\n // timeout, wait indefinitely for the in-flight `runOnce` and its handlers\n // to settle — same semantic as FairQueue / BatchQueue's `stop()`. With a\n // timeout, race the loop promise against a deadline so a hung handler\n // can't wedge the process past its termination grace period.\n async stop(options: { timeoutMs?: number } = {}): Promise<void> {\n if (!this.isRunning || !this.loopPromise) return;\n this.stopping = true;\n if (options.timeoutMs == null) {\n await this.loopPromise;\n return;\n }\n // Hold the timer handle so we can clearTimeout() it after the race.\n // Without this, when the loop wins the race, the discarded timer is\n // still ref'd and pins the Node event loop for up to `timeoutMs`,\n // delaying process shutdown by exactly the slack we were trying to\n // bound. try/finally clears the handle in every exit path (loop-won,\n // timeout-won, or exception).\n const timeoutSentinel = Symbol(\"mollifier.stop.timeout\");\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<typeof timeoutSentinel>((resolve) => {\n timeoutHandle = setTimeout(() => resolve(timeoutSentinel), options.timeoutMs);\n });\n try {\n const winner = await Promise.race([\n this.loopPromise.then(() => \"done\" as const),\n timeoutPromise,\n ]);\n if (winner === timeoutSentinel) {\n this.logger.warn(\n \"MollifierDrainer.stop: deadline exceeded; returning while loop iteration is in flight\",\n { timeoutMs: options.timeoutMs }\n );\n }\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n\n // Transient Redis errors (e.g. a connection blip in `listOrgs` /\n // `listEnvsForOrg` / `pop`) must not kill the polling loop permanently.\n // We log each `runOnce` failure, back off so we don't spin tight on a\n // sustained outage, and resume. The loop only exits when `stop()` flips\n // `stopping`.\n private async loop(): Promise<void> {\n try {\n let consecutiveErrors = 0;\n while (!this.stopping) {\n try {\n const result = await this.runOnce();\n consecutiveErrors = 0;\n if (result.drained === 0 && result.failed === 0) {\n await this.delay(this.pollIntervalMs);\n }\n } catch (err) {\n consecutiveErrors += 1;\n this.logger.error(\"MollifierDrainer.runOnce failed; backing off\", {\n err,\n consecutiveErrors,\n });\n await this.delay(this.backoffMs(consecutiveErrors));\n }\n }\n } finally {\n this.isRunning = false;\n }\n }\n\n // Exponential backoff capped at 5s. Keeps the loop responsive after a\n // brief blip while preventing a tight retry loop during a long Redis\n // outage. 1 → 200ms, 2 → 400ms, 3 → 800ms, 4 → 1.6s, 5 → 3.2s, 6+ → 5s.\n private backoffMs(consecutiveErrors: number): number {\n const base = Math.max(this.pollIntervalMs, this.backoffFloorMs);\n const capped = Math.min(base * 2 ** (consecutiveErrors - 1), this.maxBackoffMs);\n return capped;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // Take up to `maxOrgsPerTick` orgs starting at the current cursor, with\n // wrap-around. Cursor advances by 1 each tick so every org reaches\n // every slot position (0..sliceSize-1) over a full cycle — no\n // head-of-line bias within the slice. Orgs are sorted before slicing\n // so rotation is deterministic regardless of Redis SET iteration order.\n private takeOrgSlice(orgs: string[]): string[] {\n const sorted = [...orgs].sort();\n const n = sorted.length;\n const sliceSize = Math.min(this.maxOrgsPerTick, n);\n const start = this.orgCursor % n;\n this.orgCursor = (this.orgCursor + 1) % Math.max(n, 1);\n const end = start + sliceSize;\n if (end <= n) return sorted.slice(start, end);\n return [...sorted.slice(start), ...sorted.slice(0, end - n)];\n }\n\n // Pick one env from the org's active-envs list, rotating per org via\n // the per-org cursor. Each org's cursor advances by 1 each visit, so\n // an org with N envs cycles through them across N visits.\n private pickEnvForOrg(orgId: string, envsForOrg: string[]): string {\n const sorted = [...envsForOrg].sort();\n const cursor = this.perOrgEnvCursors.get(orgId) ?? 0;\n const idx = cursor % sorted.length;\n this.perOrgEnvCursors.set(orgId, (cursor + 1) % sorted.length);\n return sorted[idx]!;\n }\n\n private async processEntry(entry: BufferEntry): Promise<\"drained\" | \"failed\"> {\n try {\n const payload = deserialiseSnapshot<TPayload>(entry.payload);\n await this.handler({\n runId: entry.runId,\n envId: entry.envId,\n orgId: entry.orgId,\n payload,\n attempts: entry.attempts,\n createdAt: entry.createdAt,\n });\n await this.buffer.ack(entry.runId);\n return \"drained\";\n } catch (err) {\n const nextAttempts = entry.attempts + 1;\n if (this.isRetryable(err) && nextAttempts < this.maxAttempts) {\n await this.buffer.requeue(entry.runId);\n this.logger.warn(\"MollifierDrainer: retryable error, requeued\", {\n runId: entry.runId,\n attempts: nextAttempts,\n });\n return \"failed\";\n }\n const cause: MollifierDrainerTerminalFailureCause = this.isRetryable(err)\n ? \"max-attempts-exhausted\"\n : \"non-retryable\";\n const code = err instanceof Error ? err.name : \"Unknown\";\n const message = err instanceof Error ? err.message : String(err);\n // Run the terminal-failure callback BEFORE buffer.fail() so a\n // SYSTEM_FAILURE PG row can land while the entry is still around to\n // read from (and so we don't lose the run if the callback's own\n // write itself needs a retry). If the callback throws a retryable\n // error, requeue the entry instead of fail()ing — PG is still\n // unreachable, give it another tick. Any other callback failure\n // falls through to buffer.fail() so a genuinely bad snapshot\n // doesn't loop forever.\n if (this.onTerminalFailure) {\n try {\n await this.onTerminalFailure({\n runId: entry.runId,\n envId: entry.envId,\n orgId: entry.orgId,\n payload: deserialiseSnapshot<TPayload>(entry.payload),\n attempts: nextAttempts,\n createdAt: entry.createdAt,\n error: { code, message },\n cause,\n });\n } catch (writeErr) {\n if (this.isRetryable(writeErr)) {\n await this.buffer.requeue(entry.runId);\n this.logger.warn(\"MollifierDrainer: terminal-failure callback retryable; requeued\", {\n runId: entry.runId,\n attempts: nextAttempts,\n writeErr,\n });\n return \"failed\";\n }\n this.logger.error(\"MollifierDrainer: terminal-failure callback failed\", {\n runId: entry.runId,\n writeErr,\n });\n }\n }\n await this.buffer.fail(entry.runId, { code, message });\n this.logger.error(\"MollifierDrainer: terminal failure\", {\n runId: entry.runId,\n code,\n message,\n cause,\n });\n return \"failed\";\n }\n }\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,55,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,87,88],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}