
Processamento em Segundo Plano com Hangfire: Evite Travamentos em Suas APIs
Introdução — Quando construímos aplicações web e APIs, o tempo de resposta é crucial para a experiência do usuário. Operações como o envio de milhares de e-mails, o processamento de imagens pesadas ou a geração de relatórios complexos podem bloquear a sua API e gerar timeouts. A solução? Processamento em segundo plano (Background Jobs) com o Hangfire.
1. O Que é o Hangfire?
O Hangfire é uma biblioteca incrivelmente robusta (e open-source na sua versão Community) para .NET que permite criar tarefas em segundo plano de forma fácil e sem depender do Windows Services ou do Agendador de Tarefas do Windows.
Tudo acontece dentro do contexto da sua própria aplicação ASP.NET Core:
- Fire-and-forget: Tarefas que você quer executar apenas uma vez, em background, logo após sua criação.
- Delayed: Tarefas agendadas para execução em um tempo específico no futuro.
- Recurring: Tarefas que rodam repetidamente baseadas em uma expressão CRON (como jobs diários).
- Continuations: Tarefas que só executam após a finalização de uma tarefa pai.
2. O Problema das Chamadas Síncronas
Imagine um fluxo básico de um e-commerce: o usuário finaliza a compra, e a aplicação precisa processar o pagamento, baixar o estoque, emitir nota fiscal e enviar e-mail.
[HttpPost("finalizar")]
public async Task<IActionResult> FinalizarCompra(CheckoutRequest req)
{
var pedido = await _pedidoService.Criar(req);
await _pagamentoService.Processar(pedido);
// O problema está aqui! 🚨
await _emailService.EnviarConfirmacao(pedido);
await _notaFiscalService.Gerar(pedido);
return Ok("Pedido finalizado com sucesso");
}
Neste cenário síncrono, se o serviço da Nota Fiscal (Sefaz) estiver lento, o usuário fica olhando para um loading sem fim. É um forte candidato a timeout.
3. Resolvendo com Hangfire
Com o Hangfire, transferimos o trabalho pesado para o background, liberando a thread (e o usuário) quase imediatamente:
[HttpPost("finalizar")]
public async Task<IActionResult> FinalizarCompra(CheckoutRequest req)
{
var pedido = await _pedidoService.Criar(req);
await _pagamentoService.Processar(pedido);
// Jogando pra execução em segundo plano! 🚀
BackgroundJob.Enqueue(() => _emailService.EnviarConfirmacao(pedido.Id));
BackgroundJob.Enqueue(() => _notaFiscalService.Gerar(pedido.Id));
return Ok("Pedido recebido e em processamento");
}
A mágica acontece com o BackgroundJob.Enqueue. O Hangfire serializa essa chamada de método (com os argumentos), joga num Storage persistente (como SQL Server, Redis, ou PostgreSQL) e deixa que um Worker a processe assim que puder.
4. Dashboard e Execução na Prática
Uma das maiores vantagens do Hangfire é que ele já possui um Dashboard integrado. Com uma ou duas linhas no Program.cs, você ganha uma interface visual completa para monitorar seus jobs em tempo real.
O dashboard permite acompanhar o progresso, as falhas e os retrys automáticos de suas tarefas em background.
Como ele garante a resiliência?
Se o seu servidor reiniciar no exato momento em que uma tarefa estava gerando um relatório, não entre em pânico! Diferente das construções nativas de .NET como BackgroundService puramente em memória, o Hangfire persiste o estado de cada job.
Quando a aplicação subir novamente, o Hangfire encontrará o job que foi interrompido e fará a tentativa automática (retry). Por padrão, ele tenta até 10 vezes com atrasos exponenciais crescentes até marcar o job como Failed.
5. Configuração Básica no ASP.NET Core
Adicionar o Hangfire ao seu projeto requer poucos passos. Vamos usar o banco de dados SQL Server como armazenamento:
// Program.cs
builder.Services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(builder.Configuration.GetConnectionString("DefaultConnection")));
// Adiciona o Worker que consumirá a fila
builder.Services.AddHangfireServer();
var app = builder.Build();
// Configura o dashboard na rota /hangfire
app.UseHangfireDashboard();
Com essas linhas, assim que a aplicação subir, o Hangfire criará automaticamente todas as tabelas necessárias no seu SQL Server e você já poderá acessar o painel pela URL padrão: https://localhost:porta/hangfire.
6. Jobs Recorrentes (CRON)
Outra função de extrema utilidade é o agendamento de relatórios semanais, limpeza de cache, ou disparos de cobrança noturnos.
No Hangfire, isto é feito atravéz do RecurringJob:
// Vai rodar todos os dias à meia noite (00:00)
RecurringJob.AddOrUpdate("Limpeza-Logs-Semanal",
() => _logService.LimparLogsAntigos(),
Cron.Daily);
Você especifica um ID único ("Limpeza-Logs-Semanal"), o que deve ser executado, e a periodicidade. As expressões Cron do Hangfire garantem alta flexibilidade (seja "a cada 15 minutos" ou "na última sexta-feira do mês corrente").
7. Conclusão
Sistemas robustos não deixam o usuário final pagando pelas demoras de infraestrutura ou de terceiros. A assincronia e os processos em Background Jobs proporcionam uma UX imbatível.
Seja disparando e-mails, sincronizando estoques, ou processando vídeo, o Hangfire brilha intensamente no ecossistema .NET, fornecendo persistência confiável, retry pattern automático e um belíssimo dashboard (nosso fiel amigo quando precisamos dar manutenção!).