Introdução: por que precisamos de filas de tarefas em JavaScript?
\nNo desenvolvimento web moderno, as aplicações frequentemente enfrentam tarefas que não podem ser executadas instantaneamente dentro de uma única requisição HTTP. Envio de e-mails, processamento de imagens, geração de relatórios em PDF ou sincronização com APIs externas — tudo isso consome tempo e pode "travar" o servidor se for executado de forma síncrona.
\nAs Filas de Tarefas (Task Queues) resolvem esse problema. Elas permitem adiar a execução de operações que consomem muitos recursos e processá-las de forma assíncrona em segundo plano. Neste artigo, vamos explorar como criar e gerenciar filas de tarefas no ambiente Node.js, utilizando bibliotecas populares.
\n\n1. Fundamentos do trabalho com filas em Node.js
\nUma fila de tarefas é uma estrutura de dados que opera pelo princípio FIFO (First In, First Out). As tarefas são adicionadas ao final da fila e processadas a partir do início. No contexto do Node.js, isso significa que seu servidor pode responder rapidamente ao usuário ("Tarefa recebida para processamento"), enquanto a tarefa em si será executada posteriormente.
\nPara trabalhar com filas em Node.js, são utilizadas bibliotecas especializadas que dependem de armazenamentos externos (geralmente Redis). Vamos analisar as duas mais populares:
\n- \n
- Bull — uma biblioteca moderna, rápida e estável baseada em Redis. \n
- Kue — uma biblioteca mais antiga, mas ainda popular, com uma interface web integrada. \n
Vamos nos concentrar no Bull, pois ele é o padrão de facto para novos projetos.
\n\n1.1 Instalação e configuração do Bull
\nPara começar, instale as dependências necessárias:
\nnpm install bull ioredis\nAgora, vamos criar uma fila simples:
\nconst Queue = require('bull');\nconst myQueue = new Queue('emailQueue', {\n redis: {\n host: '127.0.0.1',\n port: 6379\n }\n});\n\n// Adiciona uma tarefa à fila\nmyQueue.add({\n to: 'user@example.com',\n subject: 'E-mail de boas-vindas',\n body: 'Bem-vindo ao nosso site!'\n});\n\nconsole.log('Tarefa adicionada à fila');\nNeste exemplo, criamos uma fila chamada emailQueue e adicionamos uma tarefa a ela — o envio de um e-mail. A tarefa ainda não foi executada; ela está apenas aguardando seu processador.
2. Processamento de tarefas da fila
\nPara que as tarefas comecem a ser executadas, precisamos de um processador (consumer). Ele "escutará" a fila e retirará as tarefas para execução.
\nCrie um arquivo worker.js:
const Queue = require('bull');\nconst emailQueue = new Queue('emailQueue', {\n redis: { host: '127.0.0.1', port: 6379 }\n});\n\n// Função processadora\nemailQueue.process(async (job) => {\n const { to, subject, body } = job.data;\n console.log(`Enviando e-mail para ${to}...`);\n \n // Simula o envio do e-mail (em um projeto real, usaria nodemailer)\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n console.log(`E-mail "${subject}" enviado para ${to}`);\n return { status: 'sent', email: to };\n});\n\nconsole.log('Processador iniciado e aguardando tarefas...');\nExecute este script e, em seguida, adicione uma tarefa do primeiro exemplo. Você verá a tarefa sendo processada.
\n\n2.1 Tratamento de erros e novas tentativas
\nEm projetos reais, as tarefas podem falhar (por exemplo, se o servidor SMTP estiver indisponível). O Bull oferece um mecanismo interno de novas tentativas:
\nemailQueue.add(\n { to: 'user@example.com', subject: 'E-mail importante' },\n { \n attempts: 5, // Número de tentativas\n backoff: { type: 'exponential', delay: 2000 } // Atraso exponencial\n }\n);\n\n// No processador, é possível tratar a falha\nemailQueue.on('failed', (job, err) => {\n console.error(`Tarefa ${job.id} falhou: ${err.message}`);\n});\n\n3. Recursos avançados de filas
\nO Bull oferece diversas funções úteis para gerenciamento de tarefas.
\n\n