All files index.js

75.61% Statements 31/41
50% Branches 2/4
70.83% Functions 17/24
75.61% Lines 31/41
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 53 54 55 56 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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 1001x   1x 5x 5x   5x     5x               1x 1x 1x 1x                 1x 1x 1x 1x                         1x 1x 1x   1x   1x         1x   1x                             1x   1x 1x 1x     1x 1x 1x     1x     1x                 3x    
const debug = require('debug')('amqp-utils');
 
module.exports = (amqp) => {
  debug(`Connecting to ${process.env.AMQP_URL}`);
  const channelPromise = amqp
    .connect(process.env.AMQP_URL)
    .then(connection => connection.createChannel())
    .catch(err => debug(`Error while connecting to amqp: ${err.message}`));
 
  return {
    subscribe,
    publish,
    request,
    reply,
  };
 
  function subscribe(queue, callback) {
    debug(`Subscribing to ${queue}`);
    return channelPromise
      .then(channel => channel.assertQueue(queue, { durable: true })
      .then(() => channel.consume(queue, (msg) => {
        debug(`Queue ${queue} got a message`);
        callback(JSON.parse(msg.content));
        channel.ack(msg);
      }, { noAck: false })))
      .catch(err => debug(`Error while subscribing to queue ${queue}: ${err.message}`));
  }
 
  function publish(queue, data = '') {
    debug(`Publishing in queue ${queue}`);
    return channelPromise
      .then(channel => channel.assertQueue(queue, { durable: true })
      .then(() => channel.sendToQueue(queue, createBufferFromData(data))))
      .catch(err => debug(`Error while publishing in queue ${queue}: ${err.message}`));
  }
 
  /**
   * Use this method when you have a client that sends a message and needs to wait for the response and can't have
   * other client having the response, ie. a remote procedure call.
   * For more info, check https://www.rabbitmq.com/tutorials/tutorial-six-javascript.html
   * @param  {String}   queue     The name of the queue to which the client must send the message
   * @param  {Any}   [data=''] The data that will be sent to the message queue. Can be any object.
   * @param  {Function} callback  The function that will be executed when the remote procedure call's response comes
   */
  function request({ queue, data = '', callback }) {
    debug(`RPC request to ${queue}`);
    return channelPromise
      .then(channel => channel.assertQueue('', { exclusive: true })
        .then((q) => {
          const correlationId = `${new Date().getUTCMilliseconds()}${Math.random()}`;
 
          channel.consume(q.queue, (msg) => {
            if (msg.properties.correlationId === correlationId) {
              callback(JSON.parse(msg.content));
            }
          }, { noAck: true });
          debug(`RPC will listen to updates in queue ${q.queue}`);
 
          channel.sendToQueue(queue, createBufferFromData(data), {
            correlationId,
            replyTo: q.queue,
          });
        }))
      .catch(err => debug(`Error in RPC request: ${err.message}`));
  }
 
  /**
   * Use this method to enable a RPC to happen, then process some data and return it via callback
   * @param  {String}   queue    The name of the queue that will receive the RPC request
   * @param  {Function} callback A function that will be executed before replying the RPC. If you need to send data,
   * return in the callback.
   */
  function reply(queue, callback) {
    return channelPromise
      .then((channel) => {
        channel.prefetch(1);
        channel.assertQueue(queue, { durable: true });
        return channel;
      })
      .then((channel) => {
        debug(`RPC will respond to queue ${queue}`);
        channel.consume(queue, (msg) => {
          callback()
            .then(createBufferFromData)
            .then((data) => {
              channel.sendToQueue(msg.properties.replyTo, data, {
                correlationId: msg.properties.correlationId,
              });
              channel.ack(msg);
            });
        });
      })
      .catch(err => debug(`Error while running callback/sending data: ${err.message}`));
  }
};
 
function createBufferFromData(data) {
  return Buffer.from(JSON.stringify(data));
}