New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Missing 'added' Events for Multiple Queues #1281
Comments
hi @Trystan-C, I'm not really sure why you need to create a new worker, queue and queueEvent each time you add a new job in your test case, commonly you may need only one queueEvent, I changed your test case a little bit and the test case passed: describe.only("'Added' Event Emission Inconsistency Demo", function() {
this.timeout(120_000);
describe("adding a bunch of jobs to the queue", () => {
let jobsAddedToTheQueue = 0;
let addedEventsReceived = 0;
let completedEventsReceived = 0;
before(async () => {
console.log("Adding one job to a bunch of queues...");
const configs: TestConfig[] = [];
const name = uuid();
const config = setup(name);
config.events.on("added", () => addedEventsReceived++);
config.events.on("completed", () => completedEventsReceived++);
configs.push(config);
await Promise.all([
config.queue.waitUntilReady(),
config.worker.waitUntilReady(),
config.events.waitUntilReady(),
]);
for (let i = 0; i < 100; i++) {
await config.queue.add(name, {});
jobsAddedToTheQueue++;
}
console.log("Giving the jobs some time to finish...");
await new Promise<void>(resolve => setTimeout(resolve, 15_000));
console.log("Cleaning up...");
await Promise.all([
config.queue.close(),
config.worker.close(),
config.events.close(),
]);
});
it("emits an 'added' event for all new jobs added to the queue", () => {
expect(addedEventsReceived).to.equal(jobsAddedToTheQueue);
});
it("emits a 'completed' event for all jobs added to the queue", () => {
expect(completedEventsReceived).to.equal(jobsAddedToTheQueue);
});
});
function setup(name: string): TestConfig {
return {
queue: new Queue(name, {
defaultJobOptions: {
removeOnComplete: true,
removeOnFail: true,
},
connection: redisConnectionOptions(),
}),
worker: new Worker(
name,
async () => {},
{
concurrency: 1,
lockDuration: 30_000,
connection: redisConnectionOptions(),
},
),
events: new QueueEvents(
name,
{ connection: redisConnectionOptions() },
),
};
}
function redisConnectionOptions(): ConnectionOptions {
return {
host: "localhost",
port: 6379,
maxRetriesPerRequest: null,
enableReadyCheck: false,
};
}
}); (the configs array I think that is not necessary). Also you can use event tests as reference https://github.com/taskforcesh/bullmq/blob/master/tests/test_events.ts |
@roggervalf The example I provided is a diluted version of a much larger test suite which takes advantaged of new queues per test case. Some of the tests cover behavior when closing You're correct that adjusting the example to only use one queue / worker / events resolves the issue, but my question is why does creating many queues cause such a large delay in event emission? Also, if this is a symptom of the implementation of If this is entirely expected due to trade-offs in the |
@Trystan-C there is not a known trade-off about the speed events are delivered to any event observer vs the amount of queues or anything like that. However, we will need a clear and simple test case that demonstrates the issue you are experiencing so that we can investigate it ourselves. |
@manast For sure. Is the example provided in the OP insufficiently clear / simple for reproducing the issue? I know that @roggervalf provided a workaround, which is great, but I believe the example code provided consistently reproduces the issue. |
@Trystan-C the issue here is that the added events are arriving before the QueueEvents has started consuming events, so you only get most of the completed events. The solution for this particular test case is to use the "lastEventId" option in QueueEvents so that it starts consuming events from the start of the event stream, then you will not lose any events, but this may not be what you want to do in production code as it will "replay" old events that have already been consumed. So change your code to this: events: new QueueEvents(name, {
lastEventId: '0-0',
connection: redisConnectionOptions(),
}), |
Thanks, @manast! For the time being, I've added an option used during local testing for applying the |
@manast Wish I found your |
When unit testing against
BullMQ
, I'm creating newQueue
,Worker
, andQueueEvents
objects per test case. Under these circumstances, my tests which depend onadded
event hooks onQueueEvents
often fail for having not received anadded
event despite waiting what seems to be a significant amount of time.The following demo code reproduces the issue:
Demo Code:
Demo Code Output:
Dependencies Used:
node
:16.14.2
bullmq
:^1.86.0
uuid
:^8.3.2
chai
:^4.3.4
mocha
:^9.0.3
redis
:latest
(throughdocker
)Notes:
Oddly enough, I don't observe this issue for other event types, includingcompleted
andfailed
.completed
events take some sort of precedence as compared to theadded
events.Is this behavior expected? Is creating and closing many queues a testing anti-pattern that I should just avoid as much as possible? Is there an SLA for
added
event emission?The text was updated successfully, but these errors were encountered: