Uma API de processamento assíncrono de filas resilientes desenvolvida com NestJS, BullMQ e Redis. Este projeto simula um sistema de envio de e-mails em lote com tratamento avançado de falhas, concorrência e monitoramento visual.
Ideal para demonstrar conceitos de mensageria, arquitetura desacoplada e resiliência em sistemas backend de alta escala para processos seletivos e portfólio técnico.
A API está publicada e disponível publicamente nos links abaixo:
- API Principal (Metadados em JSON): https://queueapi-nestjs.onrender.com/
- Documentação da API (Scalar): https://queueapi-nestjs.onrender.com/docs
- Dashboard de Filas (Bull Board): https://queueapi-nestjs.onrender.com/admin/queues
Note
Aviso sobre Cold Start: Por estar hospedada no plano gratuito da Render, a aplicação entra em suspensão após um período de inatividade. A primeira requisição após isso pode levar em torno de 50 segundos para responder devido à inicialização fria da máquina virtual.
O fluxo de processamento funciona de maneira totalmente assíncrona, desacoplando o recebimento da requisição HTTP do processamento pesado:
graph LR
Client([Cliente HTTP]) -->|POST /jobs/email| API[API NestJS]
API -->|1. Responde 202 Accepted| Client
API -->|2. Adiciona Job| Redis[(Redis Queue)]
Redis -->|3. Consome Job| Worker[EmailProcessor]
Worker -->|Sucesso| LogSuccess[JobsListener logs]
Worker -->|Falha Definitiva - 3x| DLQ[(Fila DLQ: email-failed)]
- Desacoplamento Assíncrono: Rota
POST /jobs/emailretorna202 Acceptedde imediato para o cliente enquanto a tarefa é colocada em segundo plano. - Retentativas e Backoff Exponencial: Tarefas que falham temporariamente são reexecutadas automaticamente até 3 vezes, com intervalos de espera crescentes (espera 1s, depois 2s, depois 4s...) para não sobrecarregar serviços externos.
- Simulação de Falhas Reais: O processador tem uma chance aleatória de 25% de simular uma queda de conexão temporária, facilitando a demonstração do ciclo de vida de retentativas.
- Fila de Falhas Definitivas (DLQ): Se um job esgotar as 3 tentativas de envio, ele é movido automaticamente para a fila
email-failedpara análise futura. - Controle de Concorrência: O processador está configurado para executar até 2 jobs simultaneamente (
concurrency: 2). - Dashboard de Monitoramento (Bull Board): Painel web interativo para gerenciar, visualizar e re-executar tarefas ativas, completadas, agendadas ou com falhas.
- Documentação de API Interativa (Scalar): Interface de documentação moderna em substituição ao Swagger clássico.
- Suíte de Testes Automatizados: Testes unitários focados na lógica do serviço de filas (
JobsService) com mocks do BullMQ.
- NestJS: Framework backend estruturado para aplicações Node.js escaláveis.
- TypeScript: Tipagem forte garantindo segurança e autocomplete.
- BullMQ & Redis: Fila de mensagens baseada em Redis de alta performance.
- Scalar: Interface de documentação OpenAPI/Swagger bonita e interativa.
- Jest: Estrutura padrão para testes unitários e de integração.
- Docker & Docker Compose: Empacotamento completo para rodar a aplicação em qualquer ambiente sem necessidade de instalar dependências locais.
- Desligamento Seguro (Graceful Shutdown): O projeto utiliza
app.enableShutdownHooks()no NestJS. Ao parar o contêiner ou desligar o servidor, a aplicação impede a entrada de novos jobs, espera a execução dos trabalhadores ativos terminarem e encerra com segurança as conexões com o Redis, evitando dados corrompidos. - Isolamento de Infraestrutura (Docker Bridge Network): Os contêineres de banco de dados (
redis) e aplicação (api) comunicam-se de forma isolada dentro de uma rede virtual privada própria do Docker, mitigando a exposição desnecessária de portas do Redis para o ambiente externo. - Fail-Fast com ValidationPipes: A entrada da rota de criação de jobs é validada antes de atingir a lógica de negócio através de DTOs decorados. Se o e-mail não possuir formato correto, o cliente recebe um erro
400 Bad Requestimediatamente, economizando CPU e acessos desnecessários ao banco de dados. - Separação de Preocupações (Events Listener): Todo o fluxo de monitoramento de status da fila é desacoplado do processador usando um
QueueEventsListenerglobal, facilitando a adição posterior de rastreamento de métricas (como APMs/Datadog) sem tocar na regra de negócio.
Ao enviar um lote de requisições, o console exibirá de forma estruturada as falhas temporárias sendo tratadas pelas retentativas, e o envio para a DLQ após a exaustão das tentativas:
[Nest] 14856 - 10/07/2026 19:16:30 LOG [NestApplication] Nest application successfully started
[worker] Processando job: 1
[Queue Events] Job 1 falhou (Tentativa 1/3). Razão: Falha de conexão temporária com o servidor de e-mail.. Tentando novamente...
[worker] Processando job: 1
[Queue Events] Job 1 falhou (Tentativa 2/3). Razão: Falha de conexão temporária com o servidor de e-mail.. Tentando novamente...
[worker] Processando job: 1
[Queue Events] Job 1 falhou (Tentativa 3/3). Razão: Falha de conexão temporária com o servidor de e-mail.. Tentando novamente...
[Queue Events] Job 1 falhou definitivamente. Razão: Falha de conexão temporária com o servidor de e-mail.. Movendo para DLQ (email-failed)...
- Ter o Docker e o Docker Compose instalados (Recomendado).
- Alternativa: Ter o Node.js 22+, PNPM e um servidor Redis rodando localmente.
A forma mais rápida de rodar a API junto com o Redis é usando o compose:
# 1. Clone o repositório e acesse a pasta
git clone <url-do-seu-repositorio>
cd queue-api-nestjs
# 2. Suba os containers
docker compose up --buildIsso iniciará:
- A API NestJS em
http://localhost:3000 - O Redis na porta padrão
6379
Caso prefira rodar a aplicação diretamente no seu ambiente:
# 1. Crie o arquivo .env baseado no exemplo
cp .env.example .env
# 2. Configure as variáveis de ambiente no .env
PORT=3000
REDIS_URL=redis://localhost:6379
# 3. Instale as dependências
pnpm install
# 4. Inicie o servidor em modo de desenvolvimento
pnpm run start:devO projeto conta com suíte de testes unitários para validar a lógica de criação, deleção e leitura de status dos jobs:
# Executa todos os testes
pnpm run testPOST /jobs/email: Envia um e-mail assíncrono para a fila de processamento.- Request Body:
{ "to": "destinatario@email.com", "subject": "Título do e-mail", "body": "Conteúdo do corpo do e-mail...", "priority": 1 }
- Request Body:
GET /jobs/:id: Retorna o status detalhado de um job específico (id, status, data, resultado ou motivo de falha).DELETE /jobs/:id: Cancela e remove um job pendente ou ativo da fila do Redis.