Skip to content

eduardozaniboni/node-async-task-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚀 API de Processamento Assíncrono com BullMQ

API REST construída com Node.js + TypeScript + Express que demonstra autenticação JWT, processamento assíncrono de tarefas com BullMQ (Redis) e integração mockada com serviço de IA.

📋 Índice


🧠 Visão Geral

O projeto simula um cenário real de backend onde:

  1. Um usuário faz login e recebe um token JWT.
  2. Com o token, ele cria uma tarefa (ex: "analise este texto").
  3. A tarefa é salva no Redis e enviada para uma fila BullMQ.
  4. Um Worker em processo separado consome a fila, processa a tarefa (chamando um serviço de IA mockado) e atualiza seu status.
  5. O usuário pode consultar o status da tarefa a qualquer momento.

Contexto

Este projeto foi criado como exercício prático para cobrir os requisitos de uma vaga de desenvolvedor backend Node.js, incluindo: APIs REST, filas e mensageria (BullMQ), autenticação JWT, integração com serviços de IA e processamento assíncrono com workers.


🏗 Arquitetura

┌──────────────────────────────────────────────────────────────┐
│                         CLIENTE                              │
│                  (Postman / Frontend)                        │
└────────────┬───────────────────────────────┬─────────────────┘
             │ POST /auth/login              │ POST /tasks
             │                               │ GET /tasks/:id
             ▼                               ▼
┌──────────────────────────────────────────────────────────────┐
│                    EXPRESS SERVER (porta 3000)               │
│                                                              │
│  ┌─────────────┐    ┌──────────────────┐                     │
│  │ Auth Routes │    │  Task Routes     │                     │
│  │ POST /login │    │  POST /  (auth)  │                     │
│  └──────┬──────┘    │  GET /:id (auth) │                     │
│         │           └────────┬─────────┘                     │
│         ▼                    ▼                               │
│  ┌─────────────┐    ┌──────────────────┐                     │
│  │ Auth Ctrl   │    │  Task Ctrl       │                     │
│  └──────┬──────┘    └────────┬─────────┘                     │
│         │                    │                               │
│         ▼                    ▼                               │
│  ┌─────────────┐    ┌──────────────────┐                     │
│  │ Auth Service│    │  Task Service    │──────┐              │
│  │ (JWT)       │    │  (UUID + Queue)  │      │              │
│  └─────────────┘    └──────────────────┘      │              │
└───────────────────────────────────────────────┼──────────────┘
                                                │
                                                ▼
                               ┌────────────────────────┐
                               │     REDIS (porta 6379) │
                               │  ┌──────────────────┐  │
                               │  │ BullMQ Queue     │  │
                               │  │ "task-processing"│  │
                               │  └──────────────────┘  │
                               │  ┌──────────────────┐  │
                               │  │ Task Store       │  │
                               │  │ (Hash: task:*)   │  │
                               │  └──────────────────┘  │
                               └────────────┬───────────┘
                                            │
                                            ▼
                               ┌────────────────────────┐
                               │  WORKER (processo sep.)│
                               │                        │
                               │  1. Consome job        │
                               │  2. Status → processing│
                               │  3. Chama AI Service   │
                               │  4. Status → completed │
                               └────────────────────────┘

🛠 Tecnologias

Tecnologia Versão Função
Node.js 22+ Runtime JavaScript
TypeScript 5.9 Tipagem estática
Express 5.x Framework HTTP
BullMQ 5.x Gerenciamento de filas
ioredis 5.x Cliente Redis
jsonwebtoken 9.x Autenticação JWT
uuid 13.x Geração de IDs únicos
ts-node-dev 2.x Hot-reload em dev

📁 Estrutura de Pastas

src/
├── app.ts                       # Configuração do Express (cors, json, rotas)
├── server.ts                    # Ponto de entrada — inicia o servidor na porta 3000
│
├── routes/
│   ├── auth.routes.ts           # Rota POST /auth/login
│   └── task.routes.ts           # Rotas POST /tasks e GET /tasks/:id (protegidas)
│
├── controllers/
│   ├── auth.controller.ts       # Lógica de login (recebe email/senha, retorna JWT)
│   └── task.controller.ts       # Lógica de criar e consultar tarefas
│
├── services/
│   ├── auth.service.ts          # Geração e verificação de tokens JWT
│   ├── task.service.ts          # Lógica de negócio: cria tarefa e enfileira no BullMQ
│   └── ai.service.ts            # Serviço de IA mockado (simula processamento)
│
├── middlewares/
│   └── auth.middleware.ts       # Middleware que valida o JWT e injeta req.user
│
├── queue/
│   ├── redis.ts                 # Conexão com Redis (localhost:6379)
│   ├── task.queue.ts            # Instância da fila BullMQ "task-processing"
│   └── worker.ts                # Worker que consome a fila e processa tarefas
│
├── stores/
│   └── task.store.ts            # CRUD de tarefas no Redis (usando Hash)
│
├── repositories/
│   └── task.repository.ts       # Repository in-memory (Map) — alternativo
│
└── types/
    ├── tasks.ts                 # Tipos: Task, TaskStatus
    └── express.d.ts             # Extensão de tipagem do Express (req.user)

✅ Pré-requisitos

Antes de rodar o projeto, você precisa ter instalado:

  • Node.js v18+ (download)
  • Redis rodando em localhost:6379
    • Via Docker: docker run -d --name redis -p 6379:6379 redis
    • Via instalação nativa: docs Redis

⚠️ O Redis é obrigatório. O BullMQ e o armazenamento de tarefas dependem dele.


📦 Instalação

# Clone o repositório
git clone <url-do-repositorio>
cd api-auth-bullmq

# Instale as dependências
npm install

▶️ Como Executar

O projeto precisa de dois processos rodando simultaneamente: o servidor da API e o worker da fila.

1. Suba o Redis

# Se estiver usando Docker:
docker run -d --name redis -p 6379:6379 redis

2. Inicie o Servidor (Terminal 1)

npm run dev

Saída esperada:

🚀 Server running on http://localhost:3000

3. Inicie o Worker (Terminal 2)

npm run worker

O worker ficará ouvindo a fila task-processing e processando tarefas em background.

Scripts disponíveis

Comando Descrição
npm run dev Inicia o servidor em modo desenvolvimento (hot-reload)
npm run worker Inicia o worker BullMQ para processar tarefas
npm run build Compila TypeScript para JavaScript (dist/)
npm start Roda a versão compilada do servidor

📡 Endpoints da API

Saúde / Health Check

GET /ping

Resposta:

{ "message": "Pong!" }

⚡ Autenticação

POST /auth/login

Realiza login e retorna um token JWT.

Request Body:

{
  "email": "usuario@email.com",
  "password": "qualquer-senha"
}

ℹ️ O login é mockado — aceita qualquer email/senha, desde que ambos sejam informados.

Resposta (200):

{
  "user": {
    "id": "user-123",
    "email": "usuario@email.com"
  },
  "token": "eyJhbGciOiJIUzI1NiIs..."
}

Erro (400):

{ "message": "Email e senha são obrigatórios" }

📝 Tarefas

🔒 Todas as rotas de tarefas exigem autenticação via header Authorization: Bearer <token>.

POST /tasks

Cria uma nova tarefa e a envia para a fila de processamento.

Headers:

Authorization: Bearer <token-jwt>

Request Body:

{
  "text": "Texto para ser analisado pela IA"
}

Resposta (201):

{
  "task": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "queued"
  }
}

GET /tasks/:id

Consulta o status e resultado de uma tarefa.

Headers:

Authorization: Bearer <token-jwt>

Resposta (200) — Tarefa em processamento:

{
  "id": "a1b2c3d4-...",
  "userId": "user-123",
  "status": "processing",
  "result": "",
  "createdAt": "2025-01-01T12:00:00.000Z",
  "updatedAt": "2025-01-01T12:00:01.000Z"
}

Resposta (200) — Tarefa concluída:

{
  "id": "a1b2c3d4-...",
  "userId": "user-123",
  "status": "completed",
  "result": "Resumo gerado pela IA: Texto para ser analisado pela I...",
  "createdAt": "2025-01-01T12:00:00.000Z",
  "updatedAt": "2025-01-01T12:00:03.000Z"
}

Erro (404):

{ "message": "Task not found" }

Erro (401) — Sem token ou token inválido:

{ "message": "Token não informado" }
// ou
{ "message": "Token inválido" }

Status possíveis de uma tarefa

Status Descrição
queued Tarefa criada e aguardando na fila
processing Worker pegou a tarefa e está processando
completed Processamento concluído com sucesso
failed Ocorreu um erro durante o processamento

🔄 Fluxo Completo

1. Cliente faz POST /auth/login
   └─► Recebe token JWT

2. Cliente faz POST /tasks com token
   └─► API cria tarefa no Redis (status: queued)
   └─► API enfileira job no BullMQ (fila: task-processing)
   └─► Retorna { id, status: "queued" }

3. Worker consome o job da fila
   └─► Atualiza status para "processing"
   └─► Chama ai.service.ts (mock: aguarda 2s e retorna resumo)
   └─► Atualiza status para "completed" + resultado

4. Cliente faz GET /tasks/:id
   └─► Recebe status atual + resultado (se concluído)

📦 Detalhamento dos Módulos

🔐 Módulo de Autenticação (auth)

Arquivos: routes/auth.routes.tscontrollers/auth.controller.tsservices/auth.service.ts

  • Gera um token JWT com jsonwebtoken usando a chave secreta "super-secret-key".
  • O token expira em 1 hora.
  • O payload do token contém { id, email }.
  • O login é simplificado (mock): aceita qualquer email/senha.
  • Em produção, seria necessário validar credenciais contra um banco de dados e hash de senha (ex: bcrypt).

Middleware: middlewares/auth.middleware.ts

  • Extrai o token do header Authorization: Bearer <token>.
  • Decodifica e valida o token.
  • Injeta req.user = { id } para uso nos controllers.
  • Retorna 401 se o token estiver ausente ou inválido.

📋 Módulo de Tarefas (tasks)

Arquivos: routes/task.routes.tscontrollers/task.controller.tsservices/task.service.ts

  • Criar tarefa: gera UUID, salva no Redis via task.store.ts, e enfileira no BullMQ.
  • Consultar tarefa: busca os dados diretamente do Redis (HGETALL task:<id>).
  • Todas as rotas passam pelo authMiddleware (autenticação obrigatória).

⚙️ Módulo de Filas (queue)

Arquivos: queue/redis.ts, queue/task.queue.ts, queue/worker.ts

Conexão Redis (redis.ts)

  • Usa ioredis para conectar em localhost:6379.
  • maxRetriesPerRequest: null — necessário para BullMQ funcionar corretamente.

Fila (task.queue.ts)

  • Cria uma fila BullMQ chamada "task-processing" conectada ao Redis.
  • Jobs são adicionados com taskQueue.add("process-task", { taskId, text, userId }).

Worker (worker.ts)

  • Escuta a fila "task-processing".
  • Para cada job:
    1. Atualiza status da tarefa para "processing".
    2. Chama o ai.service.ts com o texto da tarefa.
    3. Atualiza status para "completed" e salva o resultado.
  • Se o job falhar, atualiza status para "failed".
  • Roda como processo separado via npm run worker.

🤖 Serviço de IA (ai.service.ts)

  • Simula uma chamada a um serviço de IA (ex: OpenAI).
  • Aguarda 2 segundos (simulando latência) e retorna um resumo do texto.
  • Retorno: "Resumo gerado pela IA: <primeiros 50 caracteres>...".
  • Em produção, este mock seria substituído por uma chamada real à API da OpenAI ou Azure AI.

💾 Armazenamento (stores/task.store.ts)

  • Usa Redis Hashes para armazenar dados das tarefas.
  • Padrão de chave: task:<uuid>.
  • Cada tarefa expira automaticamente em 1 hora (EXPIRE).
  • Campos armazenados: id, userId, status, result, createdAt, updatedAt.

ℹ️ O projeto também contém um repositories/task.repository.ts com armazenamento em memória (Map), mas o fluxo principal usa o task.store.ts com Redis.


🏷 Tipos TypeScript (types/)

  • tasks.ts: Define TaskStatus ("queued" | "processing" | "completed" | "failed") e a interface Task.
  • express.d.ts: Estende o tipo Request do Express para incluir req.user com { id: string }.

🧪 Testando com Postman

Passo 1 — Login

POST http://localhost:3000/auth/login
Content-Type: application/json

{
  "email": "eduardo@email.com",
  "password": "123456"
}

✅ Copie o token da resposta.

Passo 2 — Criar Tarefa

POST http://localhost:3000/tasks
Content-Type: application/json
Authorization: Bearer <cole-o-token-aqui>

{
  "text": "Quero que a IA analise este texto sobre inteligência artificial"
}

✅ Copie o id da tarefa na resposta.

Passo 3 — Consultar Tarefa

GET http://localhost:3000/tasks/<cole-o-id-aqui>
Authorization: Bearer <cole-o-token-aqui>

⏳ Se consultar imediatamente, o status pode ser "queued" ou "processing". Aguarde ~2 segundos e consulte novamente para ver "completed" com o resultado.

Passo 4 — Testar Health Check

GET http://localhost:3000/ping

🚧 Possíveis Melhorias

Este projeto é um MVP para demonstração. Algumas melhorias para produção seriam:

  • Banco de dados real (PostgreSQL com Drizzle) para persistência de tarefas e usuários
  • Hash de senha (bcrypt) para autenticação real
  • Variáveis de ambiente (.env) para segredos e configurações
  • Validação de dados (Zod ou Joi) nos inputs
  • Integração real com OpenAI substituindo o mock do ai.service.ts
  • Docker + docker-compose para subir API + Redis + DB com um comando
  • Testes automatizados com Jest (unitários e de integração)
  • CI/CD com GitHub Actions para rodar testes e deploy
  • Rate limiting e proteção contra abusos
  • Webhook notificando quando uma tarefa for concluída
  • Logs estruturados (Winston ou Pino) para observabilidade
  • Scheduler (cron com BullMQ) para limpar tarefas antigas automaticamente

About

REST API boilerplate with Express, TypeScript, JWT authentication, and BullMQ for async task processing with Redis.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors