AlariCode / nestjs-rmq

A custom library for NestJS microservice. It allows you to use RabbitMQ or AMQP.
https://purpleschool.ru
MIT License
285 stars 38 forks source link

Catch if Rabbit server is down #1

Closed ebadia closed 5 years ago

ebadia commented 5 years ago

How can I check if the RabbitMQ server is down? In the client, I shutdown RabbitMQ local server to check if I can catch the error but all I receive is:

(node:90094) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:5672
    at Object._errnoException (util.js:992:11)
    at _exceptionWithHostPort (util.js:1014:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1186:14)
(node:90094) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:90094) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:90094) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:5672
    at Object._errnoException (util.js:992:11)
    at _exceptionWithHostPort (util.js:1014:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1186:14)
(node:90094) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)

This happens as a response to

    this.client = new ClientRMQ({
      url: `${process.env.CLOUDAMQP_URL}`,
      queue: 'ampanova_mails',
      queueOptions: { durable: false }
    })
AlariCode commented 5 years ago

@ebadia, thanks for report! I'll look into this issue. I think I'll need to add additional check in package.

ebadia commented 5 years ago

Thanks for making this work so well with nestjs! Just as an idea, I saw that in connect you only return the resolve case, perhaps rejecting the promise could help.

AlariCode commented 5 years ago

@ebadia, I updated package to 0.1.1 with better connection management system.

Now you can catch error on client:

try {
       return this.client.send<string, string>({ cmd: 'test' }, msg);
} catch (err) {
      console.log('Error:' + err);
 }

And server and client will reconnect when RMQ server will be available (if it was down): image

Furthermore, I added support for clustering. You can specify more then one url on client or server:

client = new ClientRMQ({
    urls: [`amqp://login:password@host`],
    queue: 'test',
    queueOptions: { durable: false }
}); 

Please note that now you need to use urls option instead of url and pass string[] instead of string.

ebadia commented 5 years ago

That's great, I'll give it a try. Thanks.

ebadia commented 5 years ago

@AlariCode this solves the error problem when sending the message. And for sure it's great. But the system still returns an error message when I try to do the new ClientRMQ

(node:54282) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:5672

It seems that we have an unhandled promise rejection there too. This does not stops the app and the try/catch you have added helps a lot. But perhaps this "warning" should be considered for the future.

AlariCode commented 5 years ago

@ebadia this is strange. It connects only when first message is sent. This code:

const client = new ClientRMQ({
            urls: [`amqp://${config.default.localhost.amqp.login}:${config.default.localhost.amqp.password}@${config.default.localhost.amqp.host}`],
            queue: 'test',
            queueOptions: { durable: false },
        });

doesn't cause client to connect. And this one does:

this.client.send<string, string>({ cmd: 'test' }, msg);

Could you please show you code with error? This example catches an error perfectly:

@Controller()
export class AppController {
    client = new ClientRMQ({
        urls: [`amqp://${config.default.localhost.amqp.login}:${config.default.localhost.amqp.password}@${config.default.localhost.amqp.host}`],
        queue: 'test',
        queueOptions: { durable: false },
    });

    @Get('a')
    a(): Observable<string> {
        try {
            return this.client.send<string, string>({ cmd: 'test' }, 'test');
        } catch (err) {
            console.log('Got error: ' + err);
        }
    }
}
ebadia commented 5 years ago

@AlariCode Sorry, my fault... I did not upgrade the package to incude the changes... Now the error message has disapeared. Thanks!

AlariCode commented 5 years ago

Thanks for bug report! I’m closing this issue.