Lidando com tarefas assíncronas em Node.js

BullMQ

Alan Ferreira dos Santos

Trajetória

 

+10 anos atuando com tecnologia

Especialista em Desenvolvimento de Software na TOTVS - CX

Amante dos Eventos de Tecnologia

Docente Ensino Superior + Bootcamps

alanfsantos

woodyalan

O que é o BullMQ?

O BullMQ

Biblioteca de filas de mensagens,  rápida e robusta

Redis é a sua base

Criado para o Node.js

Queues

 

São as filas, onde adicionamos os trabalhos a serem processados

const emailQueue = new Queue('Emails');
const imageQueue = new Queue('Images');
const syncDataQueue = new Queue('Sync Data');

Jobs

 

São os trabalhos produzidos para serem adicionados na fila

await queue.add('email', {
  to: 'user@example.com',
  subject: 'BullMQ Message' 
})
const job = await queue.add(...);

console.log(job.name) // 'email'
console.log(job.data) // { input: '...', output: '...' }
console.log(job.id) // 8ed91589-f509-444d-b131-074d6473f3b8

Dados do Job

Remoção

const job = await queue.add('email', {
  to: 'user@example.com',
  subject: 'BullMQ Message' 
})

await job.remove();

Pause

await queue.pause();

await queue.resume();

FIFO/LIFO

await queue.add('email', {
  to: 'user@example.com',
  subject: 'BullMQ Message' 
}, { lifo: true })

Retardar Execução

const job = await queue.add('email', {
  to: 'user@example.com',
  subject: 'BullMQ Message' 
}, { delay: 5000 })

await job.changeDelay(new Date('03-07-2035 10:30'));

Priorização

 

 

const job = await queue.add('email', {
  to: 'user@example.com',
  subject: 'BullMQ Message - Last' 
}, { priority: 10 })

await queue.add('email', {
  to: 'user@example.com',
  subject: 'BullMQ Message  - First' 
}, { priority: 1 })

await job.changePriority({
  lifo: true,
});

const jobs = await queue.getPrioritized();

Tentativas

await queue.add('email', {
  to: 'user@example.com',
  subject: 'BullMQ Message' 
}, { attempts: 3 })

Ciclo de Vida



waiting

delayed

active

completed

failed

delayedRetry

paused

Workers

 

São instâncias que executam algum trabalho adicionado a fila com a missão de concluí-lo.

const worker = new Worker('Emails', async (job: Job) => {
  // Do something with job
  return 'some value';
});

Simultaneidade

const worker = new Worker(
  'Emails',
  async (job: Job) => {
    // Do something with job
    return 'some value';
  },
  { concurrency: 10 },
);

Progresso

const worker = new Worker(
  'Emails',
  async (job: Job) => {
    job.progress(0);
    
    // first step
    job.progress(50);
    
    // last step
    job.progress(100);
    // Do something with job
    return 'some value';
  }
);

Tratamento de Erros

const worker = new Worker(
  'Emails',
  async (job: Job) => {
    try {
      // job logic

      // Do something with job
      return 'some value';
    } catch(err) {
      // Reject Promise on error
      throw err
    }
  }
);

Monitoramento

 

Possui um pacote NPM que permite visualizar filas, trabalhos, falhas e novas tentativas, além de permitir pausar e retomar filas

@bull-board/ui

Eventos

 

 

waiting

active

stalled

completed

failed

paused

removed

resumed

progress

Eventos

job.on('completed', () => {
  // Job completed
})

job.on('failed', (err) => {
  // Job failed with error
})

Práticas recomendadas

 

  • Lidar com os erros de forma adequada para que os trabalhos sejam repetidos;
  • Monitore e alerte quando trabalhos falharem;
  • Utilize variáveis de ambiente para gerenciar limites de simultaneidade, podendo equilibrar o desempenho e a carga;
  • Faça testes de estresse antes de utilizar em produção.

Obrigado!