bull vs agenda vs bee-queue vs bree vs kue vs node-resque
Bibliotecas de Gerenciamento de Tarefas em Node.js
bullagendabee-queuebreekuenode-resquePacotes similares:

Bibliotecas de Gerenciamento de Tarefas em Node.js

As bibliotecas de gerenciamento de tarefas em Node.js são projetadas para facilitar a execução de tarefas assíncronas e agendadas, permitindo que os desenvolvedores gerenciem filas de trabalho de forma eficiente. Elas são úteis para tarefas que precisam ser executadas em segundo plano, como envio de e-mails, processamento de dados ou execução de tarefas periódicas. Cada uma dessas bibliotecas possui características únicas que atendem a diferentes necessidades e cenários de uso.

Tendência de downloads npm

3 Anos

Ranking de GitHub Stars

Detalhe de estatísticas

Pacote
Downloads
Stars
Tamanho
Issues
Publicado em
Licença
bull2,245,94716,262309 kB147il y a 2 ansMIT
agenda228,6899,712310 kB19il y a 10 heuresMIT
bee-queue67,7854,039107 kB46il y a un anMIT
bree42,9493,29692 kB30il y a 8 moisMIT
kue31,0799,418-286il y a 9 ansMIT
node-resque26,4421,415720 kB24il y a 3 moisApache-2.0

Comparação de funcionalidades: bull vs agenda vs bee-queue vs bree vs kue vs node-resque

Persistência de Dados

  • bull:

    Bull utiliza Redis para persistir tarefas, oferecendo uma solução robusta para gerenciamento de filas. Isso permite que as tarefas sejam recuperadas após falhas e reinicializações, garantindo maior confiabilidade.

  • agenda:

    O Agenda utiliza MongoDB para persistir tarefas, permitindo que as tarefas sejam agendadas e recuperadas mesmo após reinicializações do servidor. Isso é útil para garantir que as tarefas não sejam perdidas em caso de falhas.

  • bee-queue:

    O Bee-Queue não persiste tarefas em disco, mas utiliza Redis para armazenar informações de fila em memória, o que proporciona alta velocidade e baixa latência, mas pode resultar na perda de tarefas em caso de falhas.

  • bree:

    Bree não requer persistência de dados, pois as tarefas são executadas diretamente no processo Node.js. Isso significa que as tarefas não sobrevivem a reinicializações, mas é extremamente leve e rápido.

  • kue:

    Kue também utiliza Redis para persistir tarefas, permitindo que você monitore e gerencie o status das tarefas através de uma interface de usuário. Isso é útil para aplicações que precisam de visibilidade sobre suas filas de trabalho.

  • node-resque:

    Node-Resque utiliza Redis para persistir tarefas, permitindo que você gerencie filas de trabalho de forma semelhante ao Resque do Ruby. Isso é ideal para aplicações que já utilizam Redis.

Facilidade de Uso

  • bull:

    Bull possui uma API mais rica e complexa, mas oferece muitos recursos avançados. Pode exigir um pouco mais de tempo para aprender, mas é muito poderoso.

  • agenda:

    Agenda é fácil de configurar e usar, com uma API simples que permite agendar tarefas rapidamente. É ideal para desenvolvedores que buscam uma solução sem complicações.

  • bee-queue:

    Bee-Queue é projetado para ser simples e rápido, com uma API intuitiva que facilita a adição de tarefas à fila. É uma excelente escolha para quem precisa de uma solução leve.

  • bree:

    Bree é extremamente fácil de usar, com uma configuração mínima necessária. A sintaxe clara permite que os desenvolvedores agendem tarefas rapidamente.

  • kue:

    Kue oferece uma interface de usuário que facilita o monitoramento e gerenciamento de tarefas, tornando-o mais acessível para desenvolvedores que preferem uma solução visual.

  • node-resque:

    Node-Resque é semelhante ao Resque do Ruby, o que facilita a adoção para desenvolvedores familiarizados com essa biblioteca. A configuração é simples e direta.

Recorrência de Tarefas

  • bull:

    Bull suporta tarefas recorrentes e oferece recursos avançados para gerenciar a repetição de tarefas, tornando-o ideal para aplicações que precisam de controle rigoroso sobre a execução de tarefas.

  • agenda:

    Agenda permite agendar tarefas recorrentes com facilidade, usando uma sintaxe simples para definir a frequência das execuções. Isso é útil para tarefas que precisam ser executadas em intervalos regulares.

  • bee-queue:

    Bee-Queue não possui suporte nativo para tarefas recorrentes, mas você pode implementar essa funcionalidade manualmente, o que pode ser mais trabalhoso.

  • bree:

    Bree é projetado para lidar com tarefas recorrentes de forma robusta, permitindo que você defina facilmente a frequência de execução das tarefas.

  • kue:

    Kue permite agendar tarefas recorrentes, mas a implementação pode ser um pouco mais complexa em comparação com outras bibliotecas.

  • node-resque:

    Node-Resque permite a implementação de tarefas recorrentes, mas não possui suporte nativo, exigindo que os desenvolvedores implementem essa funcionalidade.

Gerenciamento de Falhas

  • bull:

    Bull oferece um gerenciamento de falhas robusto, permitindo que você reprograma tarefas automaticamente em caso de falhas, garantindo maior confiabilidade.

  • agenda:

    Agenda não possui recursos avançados de gerenciamento de falhas, mas permite que você reprograma tarefas manualmente em caso de falhas.

  • bee-queue:

    Bee-Queue é projetado para ser rápido e leve, mas não possui recursos avançados de gerenciamento de falhas, o que pode ser uma limitação em aplicações críticas.

  • bree:

    Bree permite que você gerencie falhas de forma simples, com a capacidade de reprogramar tarefas em caso de erro, mas não possui recursos avançados.

  • kue:

    Kue possui uma interface de usuário que permite monitorar falhas e reprogramar tarefas manualmente, facilitando o gerenciamento de erros.

  • node-resque:

    Node-Resque permite o gerenciamento de falhas, mas não possui uma interface de usuário, exigindo que os desenvolvedores implementem suas próprias soluções.

Desempenho

  • bull:

    Bull oferece um bom desempenho, mas pode ser mais lento que o Bee-Queue devido à sua complexidade e recursos avançados.

  • agenda:

    O desempenho do Agenda é dependente do MongoDB, o que pode resultar em latências mais altas em comparação com soluções baseadas em memória.

  • bee-queue:

    Bee-Queue é extremamente rápido e leve, com baixa latência devido ao uso de Redis em memória, tornando-o ideal para aplicações que exigem alta performance.

  • bree:

    Bree é muito leve e rápido, pois não requer persistência de dados, resultando em um desempenho excelente para tarefas em tempo real.

  • kue:

    Kue pode apresentar latências mais altas em comparação com outras bibliotecas, especialmente em cenários de alta carga, devido à sua dependência de Redis.

  • node-resque:

    Node-Resque oferece um desempenho sólido, mas pode não ser tão rápido quanto soluções mais leves como Bee-Queue.

Como escolher: bull vs agenda vs bee-queue vs bree vs kue vs node-resque

  • bull:

    Escolha o Bull se você precisa de uma biblioteca de gerenciamento de filas avançada com suporte a recursos como repetição de tarefas, priorização e gerenciamento de falhas. Bull é ideal para aplicações que requerem um controle mais rigoroso sobre as filas de trabalho.

  • agenda:

    Escolha o Agenda se você precisa de uma biblioteca leve e fácil de usar para agendar tarefas com suporte a MongoDB. É ideal para aplicações que já utilizam MongoDB e precisam de um sistema de agendamento simples e eficaz.

  • bee-queue:

    Escolha o Bee-Queue se você precisa de uma solução de fila de trabalho rápida e leve, com foco em desempenho e simplicidade. É ideal para aplicações que precisam de uma fila de tarefas em tempo real com baixa latência.

  • bree:

    Escolha o Bree se você precisa de uma biblioteca de agendamento que suporte tarefas recorrentes e seja fácil de configurar. Bree é ideal para aplicações que precisam de um agendador robusto e flexível com suporte a múltiplos tipos de tarefas.

  • kue:

    Escolha o Kue se você precisa de uma interface de usuário para monitorar e gerenciar suas filas de tarefas. É ideal para aplicações que precisam de uma solução visual para acompanhar o status das tarefas e gerenciar falhas.

  • node-resque:

    Escolha o Node-Resque se você precisa de uma biblioteca que imite a funcionalidade do Resque do Ruby, com suporte a Redis. É ideal para aplicações que já utilizam Redis e precisam de uma solução de gerenciamento de tarefas semelhante ao Resque.

README para bull




The fastest, most reliable, Redis-based queue for Node.
Carefully written for rock solid stability and atomicity.


Sponsors · Features · UIs · Install · Quick Guide · Documentation

Check the new Guide!


🚀 Sponsors 🚀

Dragonfly Dragonfly is a new Redis™ drop-in replacement that is fully compatible with BullMQ and brings some important advantages over Redis™ such as massive better performance by utilizing all CPU cores available and faster and more memory efficient data structures. Read more here on how to use it with BullMQ.

📻 News and updates

Bull is currently in maintenance mode, we are only fixing bugs. For new features check BullMQ, a modern rewritten implementation in Typescript. You are still very welcome to use Bull if it suits your needs, which is a safe, battle tested library.

Follow me on Twitter for other important news and updates.

🛠 Tutorials

You can find tutorials and news in this blog: https://blog.taskforce.sh/


Used by

Bull is popular among large and small organizations, like the following ones:

Atlassian Autodesk Mozilla Nest Salesforce


Official FrontEnd

Taskforce.sh, Inc

Supercharge your queues with a professional front end:

  • Get a complete overview of all your queues.
  • Inspect jobs, search, retry, or promote delayed jobs.
  • Metrics and statistics.
  • and many more features.

Sign up at Taskforce.sh


Bull Features

  • Minimal CPU usage due to a polling-free design.
  • Robust design based on Redis.
  • Delayed jobs.
  • Schedule and repeat jobs according to a cron specification.
  • Rate limiter for jobs.
  • Retries.
  • Priority.
  • Concurrency.
  • Pause/resume—globally or locally.
  • Multiple job types per queue.
  • Threaded (sandboxed) processing functions.
  • Automatic recovery from process crashes.

And coming up on the roadmap...

  • Job completion acknowledgement (you can use the message queue pattern in the meantime).
  • Parent-child jobs relationships.

UIs

There are a few third-party UIs that you can use for monitoring:

BullMQ

Bull v3

Bull <= v2


Monitoring & Alerting


Feature Comparison

Since there are a few job queue solutions, here is a table comparing them:

FeatureBullMQ-ProBullMQBullKueBeeAgenda
Backendredisredisredisredisredismongo
Observables✓
Group Rate Limit✓
Group Support✓
Batches Support✓
Parent/Child Dependencies✓✓
Priorities✓✓✓✓✓
Concurrency✓✓✓✓✓✓
Delayed jobs✓✓✓✓✓
Global events✓✓✓✓
Rate Limiter✓✓✓
Pause/Resume✓✓✓✓
Sandboxed worker✓✓✓
Repeatable jobs✓✓✓✓
Atomic ops✓✓✓✓
Persistence✓✓✓✓✓✓
UI✓✓✓✓✓
Optimized forJobs / MessagesJobs / MessagesJobs / MessagesJobsMessagesJobs

Install

npm install bull --save

or

yarn add bull

Requirements: Bull requires a Redis version greater than or equal to 2.8.18.

Typescript Definitions

npm install @types/bull --save-dev
yarn add --dev @types/bull

Definitions are currently maintained in the DefinitelyTyped repo.

Contributing

We welcome all types of contributions, either code fixes, new features or doc improvements. Code formatting is enforced by prettier. For commits please follow conventional commits convention. All code must pass lint rules and test suites before it can be merged into develop.


Quick Guide

Basic Usage

const Queue = require('bull');

const videoQueue = new Queue('video transcoding', 'redis://127.0.0.1:6379');
const audioQueue = new Queue('audio transcoding', { redis: { port: 6379, host: '127.0.0.1', password: 'foobared' } }); // Specify Redis connection using object
const imageQueue = new Queue('image transcoding');
const pdfQueue = new Queue('pdf transcoding');

videoQueue.process(function (job, done) {

  // job.data contains the custom data passed when the job was created
  // job.id contains id of this job.

  // transcode video asynchronously and report progress
  job.progress(42);

  // call done when finished
  done();

  // or give an error if error
  done(new Error('error transcoding'));

  // or pass it a result
  done(null, { framerate: 29.5 /* etc... */ });

  // If the job throws an unhandled exception it is also handled correctly
  throw new Error('some unexpected error');
});

audioQueue.process(function (job, done) {
  // transcode audio asynchronously and report progress
  job.progress(42);

  // call done when finished
  done();

  // or give an error if error
  done(new Error('error transcoding'));

  // or pass it a result
  done(null, { samplerate: 48000 /* etc... */ });

  // If the job throws an unhandled exception it is also handled correctly
  throw new Error('some unexpected error');
});

imageQueue.process(function (job, done) {
  // transcode image asynchronously and report progress
  job.progress(42);

  // call done when finished
  done();

  // or give an error if error
  done(new Error('error transcoding'));

  // or pass it a result
  done(null, { width: 1280, height: 720 /* etc... */ });

  // If the job throws an unhandled exception it is also handled correctly
  throw new Error('some unexpected error');
});

pdfQueue.process(function (job) {
  // Processors can also return promises instead of using the done callback
  return pdfAsyncProcessor();
});

videoQueue.add({ video: 'http://example.com/video1.mov' });
audioQueue.add({ audio: 'http://example.com/audio1.mp3' });
imageQueue.add({ image: 'http://example.com/image1.tiff' });

Using promises

Alternatively, you can return promises instead of using the done callback:

videoQueue.process(function (job) { // don't forget to remove the done callback!
  // Simply return a promise
  return fetchVideo(job.data.url).then(transcodeVideo);

  // Handles promise rejection
  return Promise.reject(new Error('error transcoding'));

  // Passes the value the promise is resolved with to the "completed" event
  return Promise.resolve({ framerate: 29.5 /* etc... */ });

  // If the job throws an unhandled exception it is also handled correctly
  throw new Error('some unexpected error');
  // same as
  return Promise.reject(new Error('some unexpected error'));
});

Separate processes

The process function can also be run in a separate process. This has several advantages:

  • The process is sandboxed so if it crashes it does not affect the worker.
  • You can run blocking code without affecting the queue (jobs will not stall).
  • Much better utilization of multi-core CPUs.
  • Less connections to redis.

In order to use this feature just create a separate file with the processor:

// processor.js
module.exports = function (job) {
  // Do some heavy work

  return Promise.resolve(result);
}

And define the processor like this:

// Single process:
queue.process('/path/to/my/processor.js');

// You can use concurrency as well:
queue.process(5, '/path/to/my/processor.js');

// and named processors:
queue.process('my processor', 5, '/path/to/my/processor.js');

Repeated jobs

A job can be added to a queue and processed repeatedly according to a cron specification:

  paymentsQueue.process(function (job) {
    // Check payments
  });

  // Repeat payment job once every day at 3:15 (am)
  paymentsQueue.add(paymentsData, { repeat: { cron: '15 3 * * *' } });

As a tip, check your expressions here to verify they are correct: cron expression generator

Pause / Resume

A queue can be paused and resumed globally (pass true to pause processing for just this worker):

queue.pause().then(function () {
  // queue is paused now
});

queue.resume().then(function () {
  // queue is resumed now
})

Events

A queue emits some useful events, for example...

.on('completed', function (job, result) {
  // Job completed with output result!
})

For more information on events, including the full list of events that are fired, check out the Events reference

Queues performance

Queues are cheap, so if you need many of them just create new ones with different names:

const userJohn = new Queue('john');
const userLisa = new Queue('lisa');
.
.
.

However every queue instance will require new redis connections, check how to reuse connections or you can also use named processors to achieve a similar result.

Cluster support

NOTE: From version 3.2.0 and above it is recommended to use threaded processors instead.

Queues are robust and can be run in parallel in several threads or processes without any risk of hazards or queue corruption. Check this simple example using cluster to parallelize jobs across processes:

const Queue = require('bull');
const cluster = require('cluster');

const numWorkers = 8;
const queue = new Queue('test concurrent queue');

if (cluster.isMaster) {
  for (let i = 0; i < numWorkers; i++) {
    cluster.fork();
  }

  cluster.on('online', function (worker) {
    // Let's create a few jobs for the queue workers
    for (let i = 0; i < 500; i++) {
      queue.add({ foo: 'bar' });
    };
  });

  cluster.on('exit', function (worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  queue.process(function (job, jobDone) {
    console.log('Job done by worker', cluster.worker.id, job.id);
    jobDone();
  });
}

Documentation

For the full documentation, check out the reference and common patterns:

  • Guide — Your starting point for developing with Bull.
  • Reference — Reference document with all objects and methods available.
  • Patterns — a set of examples for common patterns.
  • License — the Bull license—it's MIT.

If you see anything that could use more docs, please submit a pull request!


Important Notes

The queue aims for an "at least once" working strategy. This means that in some situations, a job could be processed more than once. This mostly happens when a worker fails to keep a lock for a given job during the total duration of the processing.

When a worker is processing a job it will keep the job "locked" so other workers can't process it.

It's important to understand how locking works to prevent your jobs from losing their lock - becoming stalled - and being restarted as a result. Locking is implemented internally by creating a lock for lockDuration on interval lockRenewTime (which is usually half lockDuration). If lockDuration elapses before the lock can be renewed, the job will be considered stalled and is automatically restarted; it will be double processed. This can happen when:

  1. The Node process running your job processor unexpectedly terminates.
  2. Your job processor was too CPU-intensive and stalled the Node event loop, and as a result, Bull couldn't renew the job lock (see #488 for how we might better detect this). You can fix this by breaking your job processor into smaller parts so that no single part can block the Node event loop. Alternatively, you can pass a larger value for the lockDuration setting (with the tradeoff being that it will take longer to recognize a real stalled job).

As such, you should always listen for the stalled event and log this to your error monitoring system, as this means your jobs are likely getting double-processed.

As a safeguard so problematic jobs won't get restarted indefinitely (e.g. if the job processor always crashes its Node process), jobs will be recovered from a stalled state a maximum of maxStalledCount times (default: 1).