Você acabou de criar uma rota na sua aplicação ou um script que extrai dados pesados de um banco SQL, gera um relatório incrível e envia por e-mail.
O problema? A query demora 45 segundos para rodar. Se o usuário clicar no botão "Gerar Relatório", ele vai ficar olhando para uma tela travada (ou pior, receber um erro de Timeout) enquanto o servidor sofre para processar tudo de forma síncrona.
A regra de ouro do desenvolvimento backend e engenharia de dados é: nunca bloqueie a thread principal com tarefas lentas.
É aqui que entram as Filas de Processamento (Background Queues) com Python e Redis. Vamos desmistificar isso agora.
A Arquitetura: A Sala de Espera e o Atendente
Antes de codar, precisamos entender a lógica. Imagine um restaurante de fast-food:
- O Produtor (Sua Aplicação/API): É o caixa do restaurante. Ele apenas anota o pedido, cobra e te dá uma senha. É instantâneo.
- O Broker (Redis): É o painel de pedidos na cozinha. Ele guarda a fila de tudo que precisa ser feito de forma segura e ordenada.
- O Worker (Processador): É o cozinheiro. Ele olha para o painel (Redis), pega o primeiro pedido da fila, prepara (processa o dado pesado) e finaliza.
Enquanto o Worker está fritando a batata (rodando sua query SQL pesada), o Produtor (Sua API) continua livre para atender novos clientes.
Passo 1: Preparando o Terreno 🛠️
Para fazer essa mágica no Python, a dobradinha mais famosa é usar o Celery, mas ele pode ser complexo demais para começar. Hoje, vamos usar o RQ (Redis Queue) — uma biblioteca Python ridiculamente simples e elegante para filas.
Se você estiver no macOS, suba o seu Redis usando o OrbStack (ou Docker, se preferir) como vimos no artigo anterior:
docker run --name redis-local -p 6379:6379 -d redis
Agora, vamos usar o nosso gerenciador super rápido uv para instalar as dependências:
uv pip install redis rq
Passo 2: Criando a Tarefa Pesada (A Cozinha) 🍳
Crie um arquivo chamado tarefas.py. É aqui que vai morar a função que demora muito para rodar.
Atenção: Para o RQ funcionar bem, as funções que vão para a fila devem estar em um arquivo separado do script que envia a tarefa.
# tarefas.py
import time
def processar_relatorio_vendas(cliente_id, data_inicio, data_fim):
"""
Simula um processamento pesado de dados, como uma query complexa
de Business Intelligence agregando milhões de linhas.
"""
print(f"[WORKER] Iniciando extração de dados para o cliente {cliente_id}...")
# Simulando o tempo da query SQL ou processamento Pandas
time.sleep(5)
print(f"[WORKER] Processamento finalizado! Relatório de {data_inicio} a {data_fim} gerado.")
# Aqui você poderia salvar o arquivo num S3 ou enviar um email
return "Relatório salvo com sucesso."
Passo 3: O Produtor (O Caixa do Restaurante) 📝
Agora, vamos criar o script que envia essa tarefa para a fila. Crie o arquivo app.py.
# app.py
from redis import Redis
from rq import Queue
from tarefas import processar_relatorio_vendas
# 1. Conecta ao Redis
conexao_redis = Redis(host='localhost', port=6379)
# 2. Inicia a Fila (chamaremos a fila de 'default')
fila = Queue('default', connection=conexao_redis)
print("Recebendo requisição do usuário...")
# 3. Envia a tarefa para o Redis (NÃO bloqueia o código aqui)
# Em vez de chamar a função direto, usamos fila.enqueue()
trabalho = fila.enqueue(
processar_relatorio_vendas, # A função
cliente_id=1042, # Os argumentos da função...
data_inicio='2026-01-01',
data_fim='2026-01-31'
)
# 4. Resposta imediata!
print(f"Pedido anotado! O ID da tarefa no background é: {trabalho.id}")
print("A API já está livre para receber novos usuários!")
Se você rodar o app.py no terminal (python app.py), vai ver que ele executa em menos de 1 segundo e finaliza. Mas cadê o "Processamento finalizado"?
O pedido foi anotado no Redis, mas não há nenhum cozinheiro na cozinha!
Passo 4: Ligando o Worker (O Cozinheiro) 👨🍳
Precisamos de um processo separado rodando em background, escutando o Redis e executando as tarefas. O rq nos dá um comando de terminal perfeito para isso.
Abra uma nova aba no seu terminal (garanta que está no mesmo diretório e com seu ambiente virtual ativado) e digite:
rq worker default
Nota: default é o nome da fila que criamos.
Imediatamente, você verá o terminal ganhar vida! O worker vai se conectar ao Redis, achar a tarefa que deixamos "na geladeira" e começar a rodar o nosso script pesado:
10:15:32 Worker rq:worker:abc1234: started, version 1.15.0
10:15:32 *** Listening on default...
10:15:32 default: tarefas.processar_relatorio_vendas(cliente_id=1042, data_inicio='2026-01-01', data_fim='2026-01-31') (4f8a9...)
[WORKER] Iniciando extração de dados para o cliente 1042...
[WORKER] Processamento finalizado! Relatório de 2026-01-01 a 2026-01-31 gerado.
10:15:37 default: Job OK (4f8a9...)
10:15:37 Result is kept for 500 seconds
Por que essa arquitetura muda o jogo?
-
Escalabilidade: Se você tiver 1.000 relatórios para gerar, você pode simplesmente abrir 5 abas no terminal e rodar 5 vezes o comando
rq worker. Agora você tem 5 cozinheiros dividindo a mesma fila do Redis simultaneamente! -
Resiliência: Se o seu Worker quebrar ou o computador reiniciar no meio do processamento, a tarefa não se perde. O Redis sabe que ela falhou e você pode configurar o RQ para tentar de novo (
retry). - Desacoplamento: O seu código que atende o usuário (a API web) fica totalmente separado do código que processa os dados pesados.
Conclusão
Implementar processamento assíncrono parece um bicho de sete cabeças no começo, mas usando ferramentas modernas e simples como Python, RQ e Redis (gerenciado facilmente via OrbStack), você cria aplicações de nível empresarial em poucos minutos.
Seja para enviar e-mails em lote, processar pagamentos ou rodar integrações complexas de banco de dados, delegar o "trabalho sujo" para uma fila em background é o segredo para uma aplicação rápida e responsiva.
Gostou do tutorial? Já usou RQ ou prefere o Celery no seu dia a dia? Deixe aí nos comentários!
Top comments (0)