channelManager.findOrCreateConsumer = function (topic, options) { let channel = consumersByTopic[topic]; if (channel) return channel; let isServiceChannel = (topic[0] === "_"); channel = consumersByTopic[topic] = new EventEmitter(); channel.raw = channelManager.createRawConsumer(topic, options); channel.setMaxListeners(0); let autoConfirm; if (options && "autoConfirm" in options) { autoConfirm = options.autoConfirm; } else { autoConfirm = adapterConfig && adapterConfig.autoConfirm; } // TODO: is it ok to add custom methods to EventEmitter? channel.onceConsuming = (channel.raw.onceConsuming) ? function (cb) { channel.raw.onceConsuming(cb); return channel; } : noopCb; channel.rejectMessage = (channel.raw.rejectMessage) ? function (message) { channel.raw.rejectMessage(message); } : noop__; channel.confirmProcessedMessage = (channel.raw.confirmProcessedMessage) ? function (message, _safe) { // Only use _safe if you can"t know whether message has already been confirmed/rejected channel.raw.confirmProcessedMessage(message, _safe); } : noop__; function onMessage(message) { if (messageHasExpired(message)) { channel.rejectMessage(message); return; } channelManager.emit(channelManager.CONSUMER_NEW_MESSAGE_EVENT, topic); // TODO: emit custom object rather than instance of EventEmitter channel.emit("message", message, channel); if (autoConfirm) channel.confirmProcessedMessage(message, true); } function onValidationError(err, message) { channel.rejectMessage(message); } // Validate with envelope schema if (!isServiceChannel && config.schema) { channel.raw.on("message", validateWithSchema.onEvent(config.schema, onMessage, onValidationError)); } else { channel.raw.on("message", onMessage); } channel.on("error", function (err, message) { if (autoConfirm && message) { // Reject when a message has generated an error, e.g. not validated channel.rejectMessage(message); } }); channel.raw.on("error", channel.emit.bind(channel, "error")); // TODO: wtf? // channel.raw.on("consuming", channel.emit("consuming")); channelManager.emit(channelManager.CONSUMER_NEW_TOPIC_EVENT, topic); if (isServiceChannel || !config.cleanupConsumers) return channel; channel.on("removeListener", function (eventName) { if (eventName !== "message") return; if (consumerTopicsToCheck.indexOf(topic) > -1 || channel.listeners(eventName).length) return; consumerTopicsToCheck.push(topic); if (consumerTopicsToCheck.length > 1) return; setImmediate(checkConsumers); }); return channel; };