0

I follow the recommendation here and also this thread and I use the following code in order to gracefully shutdown BullMQ workers in my development environment on Ubuntu:

  const handleTermination = async () => {
    log.info(`Gracefully shutting down worker for queue '${name}'.`);
    await worker.close();
  };
  process.on('SIGTERM', handleTermination).on('SIGINT', handleTermination);

However the above code prevents the app from ending. The result in the console is the following for 3 consecutive Ctrl+C:

^C[2023-04-23T16:15:46.423] [INFO] development - Gracefully shutting down worker for queue 'X'.
[2023-04-23T16:15:46.423] [INFO] development - Gracefully shutting down worker for queue 'Y'.
^C[2023-04-23T16:15:47.075] [INFO] development - Gracefully shutting down worker for queue 'X'.
[2023-04-23T16:15:47.075] [INFO] development - Gracefully shutting down worker for queue 'Y'.
^C[2023-04-23T16:15:47.793] [INFO] development - Gracefully shutting down worker for queue 'X'.
[2023-04-23T16:15:47.793] [INFO] development - Gracefully shutting down worker for queue 'Y'.

Obviously the process is still there forever and can only be finished with kill -9. Note that there is no pending job.

What I am missing here?

Of course the problem is gone when I use process.exit() but I understand that this is not the recommended handling.

user9839468
  • 31
  • 1
  • 5
  • Do you also close all queues? – rveerd Jul 17 '23 at 08:30
  • @rveerd what do you mean exactly? Do you mean cleaning them from any existing jobs? In most of the cases there are no jobs in the queues anyhow. – user9839468 Jul 18 '23 at 09:41
  • 1
    When you create a queue object with `new Queue()` BullMQ creates a connection to the Redis database. If you do not perform `queue.close()`, this connection remains active and Node.js will not exit. – rveerd Jul 18 '23 at 11:16
  • @reveerd you are right. This is the correct answer. Strangely I had not found any reference on this in their documentation. Thank you. – user9839468 Jul 20 '23 at 06:27
  • I will post an answer with some more details. – rveerd Jul 20 '23 at 06:32

1 Answers1

1

A Node.js process will exit when there is no more work to be done. See this answer for details.

BullMQ creates a connection to the Redis database when you create Worker objects. But it also creates a connection when you create Queue objects. To gracefully exit Node.js you have to close all connections. You have to call close() both on the workers and the queues.

Another option is to create the Redis connection yourself and pass it to the Queue constructor. The queue object uses the passed connection and does not create its own connection. In this case, you only have to close the Redis connection.

import { Queue } from 'bullmq';
import { Redis } from 'ioredis';

const connection = new Redis();
const queue = new Queue('foo', { connection });

// create more queues with the same connection...

// post jobs to queues...

connection.quit();

Note that the same does not work for worker objects. A worker object creates additional connections to the Redis database. See the documentation for details.

You can easily see all active connections to the Redis database using redis-cli:

$ redis-cli CLIENT LIST
rveerd
  • 3,620
  • 1
  • 14
  • 30