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.
- Visão Geral
- Arquitetura
- Tecnologias
- Estrutura de Pastas
- Pré-requisitos
- Instalação
- Como Executar
- Endpoints da API
- Fluxo Completo
- Detalhamento dos Módulos
- Testando com Postman
- Possíveis Melhorias
O projeto simula um cenário real de backend onde:
- Um usuário faz login e recebe um token JWT.
- Com o token, ele cria uma tarefa (ex: "analise este texto").
- A tarefa é salva no Redis e enviada para uma fila BullMQ.
- Um Worker em processo separado consome a fila, processa a tarefa (chamando um serviço de IA mockado) e atualiza seu status.
- O usuário pode consultar o status da tarefa a qualquer momento.
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.
┌──────────────────────────────────────────────────────────────┐
│ 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 │
└────────────────────────┘
| 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 |
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)
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
- Via Docker:
⚠️ O Redis é obrigatório. O BullMQ e o armazenamento de tarefas dependem dele.
# Clone o repositório
git clone <url-do-repositorio>
cd api-auth-bullmq
# Instale as dependências
npm installO projeto precisa de dois processos rodando simultaneamente: o servidor da API e o worker da fila.
# Se estiver usando Docker:
docker run -d --name redis -p 6379:6379 redisnpm run devSaída esperada:
🚀 Server running on http://localhost:3000
npm run workerO worker ficará ouvindo a fila
task-processinge processando tarefas em background.
| 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 |
GET /ping
Resposta:
{ "message": "Pong!" }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" }🔒 Todas as rotas de tarefas exigem autenticação via header
Authorization: Bearer <token>.
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"
}
}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 | 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 |
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)
Arquivos: routes/auth.routes.ts → controllers/auth.controller.ts → services/auth.service.ts
- Gera um token JWT com
jsonwebtokenusando 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
401se o token estiver ausente ou inválido.
Arquivos: routes/task.routes.ts → controllers/task.controller.ts → services/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).
Arquivos: queue/redis.ts, queue/task.queue.ts, queue/worker.ts
- Usa
ioredispara conectar emlocalhost:6379. maxRetriesPerRequest: null— necessário para BullMQ funcionar corretamente.
- Cria uma fila BullMQ chamada
"task-processing"conectada ao Redis. - Jobs são adicionados com
taskQueue.add("process-task", { taskId, text, userId }).
- Escuta a fila
"task-processing". - Para cada job:
- Atualiza status da tarefa para
"processing". - Chama o
ai.service.tscom o texto da tarefa. - Atualiza status para
"completed"e salva o resultado.
- Atualiza status da tarefa para
- Se o job falhar, atualiza status para
"failed". - Roda como processo separado via
npm run worker.
- 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.
- 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.tscom armazenamento em memória (Map), mas o fluxo principal usa otask.store.tscom Redis.
tasks.ts: DefineTaskStatus("queued" | "processing" | "completed" | "failed") e a interfaceTask.express.d.ts: Estende o tipoRequestdo Express para incluirreq.usercom{ id: string }.
POST http://localhost:3000/auth/login
Content-Type: application/json
{
"email": "eduardo@email.com",
"password": "123456"
}
✅ Copie o token da resposta.
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.
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.
GET http://localhost:3000/ping
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