如何解决amqplib的Channel#消耗奇怪的签名?

时间:2015-12-31 16:12:36

标签: node.js rabbitmq

我正在编写一个使用amqplib的Channel#consume方法的工作者。我希望这个worker等待作业并在它们出现在队列中时立即处理它们。

我编写了自己的模块以抽象出ampqlib,这里是获取连接,设置队列和使用消息的相关函数:

const getConnection = function(host) {
  return amqp.connect(host);
};

const createChannel = function(conn) {
  connection = conn;
  return conn.createConfirmChannel();
};

const assertQueue = function(channel, queue) {
  return channel.assertQueue(queue);
};

const consume = Promise.method(function(channel, queue, processor) {
  processor = processor || function(msg) { if (msg) Promise.resolve(msg); };
  return channel.consume(queue, processor)
});

const setupQueue = Promise.method(function setupQueue(queue) {
  const amqp_host = 'amqp://' + ((host || process.env.AMQP_HOST) || 'localhost');

  return getConnection(amqp_host)
    .then(conn => createChannel(conn)) // -> returns a `Channel` object
    .tap(channel => assertQueue(channel, queue));
});

consumeJob: Promise.method(function consumeJob(queue) {
  return setupQueue(queue)
    .then(channel => consume(channel, queue))
  });

我的问题是Channel#consume的奇怪签名。来自http://www.squaremobius.net/amqp.node/channel_api.html#channel_consume

#consume(queue, function(msg) {...}, [options, [function(err, ok) {...}]])

回调不是魔术发生的地方,消息的处理实际应该进入第二个参数并且会破坏承诺的流动。

这是我计划使用它的方式:

return queueManager.consumeJob(queue)
  .then(msg => {
     // do some processing
  });

但它不起作用。如果队列中没有消息,则拒绝承诺,然后如果队列中丢弃了消息,则不会发生任何事情。如果有消息,则只处理一条消息,然后工作程序停止,因为它从Channel#consume调用退出“处理器”功能。

我应该怎么做?我想保留queueManager抽象,所以我的代码更容易推理,但我不知道怎么做...任何指针?

2 个答案:

答案 0 :(得分:1)

正如@idbehold所说,Promise只能解决一次。如果要在消息进入时处理消息,除了使用此功能之外别无他法。 Channel#get只检查队列一次然后返回;它不适合你需要工人的场景。

答案 1 :(得分:1)

仅作为选项。您可以将应用程序显示为某些消息(或事件)的流。这个http://highlandjs.org/#examples

有一个库

你的代码看起来应该是这样的(它不是一个完整的样本,但我希望它能说明这个想法):

let messageStream = _((push, next) => {
  consume(queue, (msg) => {
   push(null, msg)
  })
)
// now you can operate with your stream in functional style 
message.map((msg) => msg + 'some value').each((msg) => // do something with msg)

这种方法为您提供了许多用于同步和转换的原语 http://highlandjs.org/#examples