Bull: Unhandled promise rejections still occur

Created on 28 Nov 2018  路  10Comments  路  Source: OptimalBits/bull

Description

The problem with unhandled promise rejections do still occur (see #1012).

Minimal, Working Test code to reproduce the issue.

Reproduced the issue in a separate repo: https://github.com/joakimbeng/bull-connection-problem

The code is essentially this:

'use strict';
const Queue = require('bull');

const queue = new Queue('my-queue');

queue.on('waiting', jobId => console.log('Job waiting', jobId));
queue.on('error', error => console.error('Queue Error', error));

queue.process(job => {
  console.log('processing job', job.id);
});

queue.add({some: 'data'});

process.on('unhandledRejection', error => {
  console.error('Unhandled Rejection', error);
  process.exit(1);
});

Bull version

v3.5.2

Additional information

The two function calls that are causing this is the this.setWorkerName() and utils.isRedisReady in commands/index.js. (utils.isRedisReady is the function that's actually causing the issue in this.setWorkerName as well).

Also, the problem only occurs after the queue.process function have been called, which the #1012 did not cover.

enhancement

All 10 comments

I have a workaround for now (also in the linked repo above) but I don't think that's good enough or the right way to do it to make a PR for it

This works for me.

//process queue 
bullQueue.isReady(()=>{
  bullQueue.process( (job='', jobDone) =>{
    console.log('Started Queues.');
    jobDone();
    // await processJobs(job, data);
  });
})

@macpatel I cannot find isReady in the docs in https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md, do you know why?

@macpatel I cannot find isReady in the docs in https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md, do you know why?

Don't remember how i ended up with this.
Check this ->
https://github.com/OptimalBits/bull/issues/567
https://github.com/OptimalBits/bull/search?q=isReady&unscoped_q=isReady

Same here, calling Bull.process with a broken connection to Redis triggers an unhandled promise rejection.

Bull.isReady does the trick to catch the rejection though :

(async main() {
  const queue = new Bull('worker', { redis: '//localhost:22' });  // Impossible connection

  try {
    await queue.isReady() // rejects correctly (connect ECONNREFUSED 127.0.0.1:22)
    await queue.process(doSomething) // doesn't reject + unhandled promise rejection
  } catch (err) {
    // ...
  }
})()

I think this edge case is not a very rare one. Bull.process should reject.

I'd be happy to help if someone can point me in the right direction.

To add to this, if you have an async event that throws an exception the promise is not caught.

const Bull = require('bull');
const queue = new Bull('worker', 'localhost');
queue.on('error', () => console.log('there was an error'));
queue.on('completed', async () => {
  throw new Error('test');
});
await queue.add({ foo: 'bar' });
await queue.process(() => console.log('completed'));

Gives me UnhandledPromiseRejectionWarning: Error: test

@simontong That's a problem in your code. You have to handle any errors thrown by an event handler in application code. The event source (Bull in this case) can't be responsible for handling the error you throw in the handler.

I am seeing unhandled promise rejections when I try to add a job to a queue with a bad connection (point being, this issue doesn't just manifest with a call to .process). There doesn't appear to be anywhere I can reliably trap and handle the error. I'm seeing the unhandled rejection error even when I have an error handler on the queue (queue.on('error', ...)). The error handler traps an error, but that error also bubbles up as an unhandled promise rejection.

Same problem here about not being able to easily catch the connection errors. The only way seems to be:

try {
  await queue.isReady()
} catch (err) {
  // ...
}

Buts as @zebulonj says this isn't always convenient.

I have the same issue, bull queues should provide a callback(or event) like

queue.onError(() => handle err)
queue.onReady(() => start processing)
Was this page helpful?
0 / 5 - 0 ratings