"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QUEUE_EVENT_SUFFIX = exports.toString = exports.errorToJSON = exports.parseObjectValues = exports.isRedisVersionLowerThan = exports.childSend = exports.asyncSend = exports.DELAY_TIME_1 = exports.DELAY_TIME_5 = exports.clientCommandMessageReg = exports.optsEncodeMap = exports.optsDecodeMap = exports.errorObject = void 0; exports.tryCatch = tryCatch; exports.lengthInUtf8Bytes = lengthInUtf8Bytes; exports.isEmpty = isEmpty; exports.array2obj = array2obj; exports.objectToFlatArray = objectToFlatArray; exports.delay = delay; exports.increaseMaxListeners = increaseMaxListeners; exports.invertObject = invertObject; exports.isRedisInstance = isRedisInstance; exports.isRedisCluster = isRedisCluster; exports.decreaseMaxListeners = decreaseMaxListeners; exports.removeAllQueueData = removeAllQueueData; exports.getParentKey = getParentKey; exports.isNotConnectionError = isNotConnectionError; exports.removeUndefinedFields = removeUndefinedFields; exports.trace = trace; const ioredis_1 = require("ioredis"); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const utils_1 = require("ioredis/built/utils"); const semver = require("semver"); const enums_1 = require("../enums"); exports.errorObject = { value: null }; function tryCatch(fn, ctx, args) { try { return fn.apply(ctx, args); } catch (e) { exports.errorObject.value = e; return exports.errorObject; } } /** * Checks the size of string for ascii/non-ascii characters * @see https://stackoverflow.com/a/23318053/1347170 * @param str - */ function lengthInUtf8Bytes(str) { return Buffer.byteLength(str, 'utf8'); } function isEmpty(obj) { for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { return false; } } return true; } function array2obj(arr) { const obj = {}; for (let i = 0; i < arr.length; i += 2) { obj[arr[i]] = arr[i + 1]; } return obj; } function objectToFlatArray(obj) { const arr = []; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== undefined) { arr[arr.length] = key; arr[arr.length] = obj[key]; } } return arr; } function delay(ms, abortController) { return new Promise(resolve => { // eslint-disable-next-line prefer-const let timeout; const callback = () => { abortController === null || abortController === void 0 ? void 0 : abortController.signal.removeEventListener('abort', callback); clearTimeout(timeout); resolve(); }; timeout = setTimeout(callback, ms); abortController === null || abortController === void 0 ? void 0 : abortController.signal.addEventListener('abort', callback); }); } function increaseMaxListeners(emitter, count) { const maxListeners = emitter.getMaxListeners(); emitter.setMaxListeners(maxListeners + count); } function invertObject(obj) { return Object.entries(obj).reduce((result, [key, value]) => { result[value] = key; return result; }, {}); } exports.optsDecodeMap = { de: 'deduplication', fpof: 'failParentOnFailure', cpof: 'continueParentOnFailure', idof: 'ignoreDependencyOnFailure', kl: 'keepLogs', rdof: 'removeDependencyOnFailure', }; exports.optsEncodeMap = Object.assign(Object.assign({}, invertObject(exports.optsDecodeMap)), { /*/ Legacy for backwards compatibility */ debounce: 'de' }); function isRedisInstance(obj) { if (!obj) { return false; } const redisApi = ['connect', 'disconnect', 'duplicate']; return redisApi.every(name => typeof obj[name] === 'function'); } function isRedisCluster(obj) { return isRedisInstance(obj) && obj.isCluster; } function decreaseMaxListeners(emitter, count) { increaseMaxListeners(emitter, -count); } async function removeAllQueueData(client, queueName, prefix = process.env.BULLMQ_TEST_PREFIX || 'bull') { if (client instanceof ioredis_1.Cluster) { // todo compat with cluster ? // @see https://github.com/luin/ioredis/issues/175 return Promise.resolve(false); } const pattern = `${prefix}:${queueName}:*`; const removing = await new Promise((resolve, reject) => { const stream = client.scanStream({ match: pattern, }); stream.on('data', (keys) => { if (keys.length) { const pipeline = client.pipeline(); keys.forEach(key => { pipeline.del(key); }); pipeline.exec().catch(error => { reject(error); }); } }); stream.on('end', () => resolve()); stream.on('error', error => reject(error)); }); await removing; await client.quit(); } function getParentKey(opts) { if (opts) { return `${opts.queue}:${opts.id}`; } } exports.clientCommandMessageReg = /ERR unknown command ['`]\s*client\s*['`]/; exports.DELAY_TIME_5 = 5000; exports.DELAY_TIME_1 = 100; function isNotConnectionError(error) { const { code, message: errorMessage } = error; return (errorMessage !== utils_1.CONNECTION_CLOSED_ERROR_MSG && !errorMessage.includes('ECONNREFUSED') && code !== 'ECONNREFUSED'); } const asyncSend = (proc, msg) => { return new Promise((resolve, reject) => { if (typeof proc.send === 'function') { proc.send(msg, (err) => { if (err) { reject(err); } else { resolve(); } }); } else if (typeof proc.postMessage === 'function') { resolve(proc.postMessage(msg)); } else { resolve(); } }); }; exports.asyncSend = asyncSend; const childSend = (proc, msg) => (0, exports.asyncSend)(proc, msg); exports.childSend = childSend; const isRedisVersionLowerThan = (currentVersion, minimumVersion) => { const version = semver.valid(semver.coerce(currentVersion)); return semver.lt(version, minimumVersion); }; exports.isRedisVersionLowerThan = isRedisVersionLowerThan; const parseObjectValues = (obj) => { const accumulator = {}; for (const value of Object.entries(obj)) { accumulator[value[0]] = JSON.parse(value[1]); } return accumulator; }; exports.parseObjectValues = parseObjectValues; const getCircularReplacer = (rootReference) => { const references = new WeakSet(); references.add(rootReference); return (_, value) => { if (typeof value === 'object' && value !== null) { if (references.has(value)) { return '[Circular]'; } references.add(value); } return value; }; }; const errorToJSON = (value) => { const error = {}; Object.getOwnPropertyNames(value).forEach(function (propName) { error[propName] = value[propName]; }); return JSON.parse(JSON.stringify(error, getCircularReplacer(value))); }; exports.errorToJSON = errorToJSON; const INFINITY = 1 / 0; const toString = (value) => { if (value == null) { return ''; } // Exit early for strings to avoid a performance hit in some environments. if (typeof value === 'string') { return value; } if (Array.isArray(value)) { // Recursively convert values (susceptible to call stack limits). return `${value.map(other => (other == null ? other : (0, exports.toString)(other)))}`; } if (typeof value == 'symbol' || Object.prototype.toString.call(value) == '[object Symbol]') { return value.toString(); } const result = `${value}`; return result === '0' && 1 / value === -INFINITY ? '-0' : result; }; exports.toString = toString; exports.QUEUE_EVENT_SUFFIX = ':qe'; function removeUndefinedFields(obj) { const newObj = {}; for (const key in obj) { if (obj[key] !== undefined) { newObj[key] = obj[key]; } } return newObj; } /** * Wraps the code with telemetry and provides a span for configuration. * * @param telemetry - telemetry configuration. If undefined, the callback will be executed without telemetry. * @param spanKind - kind of the span: Producer, Consumer, Internal * @param queueName - queue name * @param operation - operation name (such as add, process, etc) * @param destination - destination name (normally the queue name) * @param callback - code to wrap with telemetry * @param srcPropagationMedatada - * @returns */ async function trace(telemetry, spanKind, queueName, operation, destination, callback, srcPropagationMetadata) { if (!telemetry) { return callback(); } else { const { tracer, contextManager } = telemetry; const currentContext = contextManager.active(); let parentContext; if (srcPropagationMetadata) { parentContext = contextManager.fromMetadata(currentContext, srcPropagationMetadata); } const spanName = destination ? `${operation} ${destination}` : operation; const span = tracer.startSpan(spanName, { kind: spanKind, }, parentContext); try { span.setAttributes({ [enums_1.TelemetryAttributes.QueueName]: queueName, [enums_1.TelemetryAttributes.QueueOperation]: operation, }); let messageContext; let dstPropagationMetadata; if (spanKind === enums_1.SpanKind.CONSUMER && parentContext) { messageContext = span.setSpanOnContext(parentContext); } else { messageContext = span.setSpanOnContext(currentContext); } if (callback.length == 2) { dstPropagationMetadata = contextManager.getMetadata(messageContext); } return await contextManager.with(messageContext, () => callback(span, dstPropagationMetadata)); } catch (err) { span.recordException(err); throw err; } finally { span.end(); } } } //# sourceMappingURL=index.js.map