0

I'm trying to work out how to close my promise based connections after publishing messages.

I've tried to extrapolate away shared code for my sender and my receiver, so I have a connection file like this:

connector.js

const amqp = require('amqplib');
class Connector {
  constructor(RabbitMQUrl) {
    this.rabbitMQUrl = RabbitMQUrl;
  }

  connect() {
    return amqp.connect(this.rabbitMQUrl)
      .then((connection) => {
        this.connection = connection;
        process.once('SIGINT', () => {
          this.connection.close();
        });
        return this.connection.createChannel();
      })
      .catch( (err) => {
        console.error('Errrored here');
        console.error(err);
      });
  }
}

module.exports = new Connector(
  `amqp://${process.env.AMQP_HOST}:5672`
);

Then my publisher/sender looks like this:

publisher.js

const connector = require('./connector');

class Publisher {
  constructor(exchange, exchangeType) {
    this.exchange = exchange;
    this.exchangeType = exchangeType;
    this.durabilityOptions = {
      durable: true,
      autoDelete: false,
    };
  }

  publish(msg) {
    connector.connect()
      .then( (channel) => {
        let ok = channel.assertExchange(
          this.exchange,
          this.exchangeType,
          this.durabilityOptions
        );
        return ok
          .then( () => {
            channel.publish(this.exchange, '', Buffer.from(msg));
            return channel.close();
          })
          .catch( (err) => {
            console.error(err);
          });
      });
  }
}

module.exports = new Publisher(
  process.env.AMQP_EXCHANGE,
  process.env.AMQP_TOPIC
);

But as said, I can't quite work out how to close my connection after calling publish().

Jarede
  • 3,310
  • 4
  • 44
  • 68

1 Answers1

1

You could add a close() function to connector:

  close() {
      if (this.connection) {
          console.log('Connector: Closing connection..');
          this.connection.close();
      }
  }

Publisher:

class Publisher {
  constructor(exchange, exchangeType) {
    this.exchange = exchange;
    this.exchangeType = exchangeType;
    this.durabilityOptions = {
      durable: true,
      autoDelete: false,
    };
  }

  connect() {
      return connector.connect().then( (channel) => {
         console.log('Connecting..');
         return channel.assertExchange(
          this.exchange,
          this.exchangeType,
          this.durabilityOptions
        ).then (() => {  
            this.channel = channel;
            return Promise.resolve();
        }).catch( (err) => {
            console.error(err);
        });;
      });
  }

  disconnect() {
      return this.channel.close().then( () => { return connector.close();});
  }

  publish(msg) {
      this.channel.publish(this.exchange, '', Buffer.from(msg));      
  };

}

Test.js

'use strict'

const connector = require('./connector');
const publisher = require('./publisher');


publisher.connect().then(() => { 
    publisher.publish('message');
    publisher.publish('message2');
    publisher.disconnect();
});
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
  • 2
    hmmm doing it this way is throwing up errors for me, like: `Unhandled rejection IllegalOperationError: Connection closing` – Jarede Jan 08 '18 at 16:49
  • Yes, if you call publish() twice in succession, you'll get the error since the response is a promise and the channel is being closed when you make the call. You'd have to do something like publish('message').then(() => { publish('message2');}); – Terry Lennox Jan 08 '18 at 17:28
  • 1
    I'd actually make the suggestion that you would open the connection and channel in the publisher and only close when you're done rather than after each publish() call. – Terry Lennox Jan 08 '18 at 17:34
  • Ahhh yeah i was trying to DRY up my code for the publisher and the sender since there's so much shared code. – Jarede Jan 08 '18 at 17:40