ASP.NET Core -  Usando o Hangfire


 Neste artigo vamos apresentar o uso do Hangfire em uma aplicação ASP.NET Core Web Api.

O Hangfire fornece um framework que executa o processamento em segundo plano para aplicativos .NET e .NET Core sem criar um serviço do Windows ou exigir um processo separado, e é usado para agendar o trabalho em um determinado evento e horário.

O Hangfire é aberto e gratuito para uso comercial (assinaturas permitem que você use opções adicionais) e é apoiado por um armazenamento persistente. A arquitetura HangFire é simplesmente um modelo cliente/servidor com persistência usando o Microsoft SQL Server.

O HangFire Server consulta o armazenamento para executar os trabalhos em segundo plano necessários. O componente Servidor funciona usando um conjunto de threads em segundo plano para ouvir o Armazenamento em busca de novos trabalhos e, em seguida, executa a tarefa necessária desserializando tipo, método e argumentos. O componente Cliente cria os trabalhos em segundo plano salvando-os no componente Armazenamento.

O Hangfire é confiável e persistente e cuidará de todas as coisas assim que o trabalho for agendado. Além disso usando o Hangfire Dashboard também podemos gerenciar todas as coisas facilmente.

Neste artigo vamos criar uma projeto ASP .NET Core Web API no ambiente do .NET 6 e configurar o Hangfire para a seguir mostrar os diferentes tipos de jobs existentes no Hangfire.

O Hangfire permite que você enfileira um trabalho em seu código de forma síncrona e executa esse código de forma assíncrona por meio de uma fila de ordem de chegada.

Existem diferentes tipos de jobs ou trabalhos que estão presentes no Hangfire :

Existem também dois os jobs Batch Job e Batch Continuation presentes na versão Hangfire Pro que são usados ​​para executar vários trabalhos em lote como uma única entidade.

Criando o projeto no VS 2022

Crie um novo projeto usando o template ASP.NET Core Web API chamado ApiHangFire e defina as seguintes configurações no projeto:

Ao clicar no botão Create o projeto será criado.

A seguir vamos incluir o pacote Nuget HangFire no projeto :

A seguir vamos configurar o HangFire definindo no arquivo Program o código a seguir:

using Hangfire;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

// Hangfire

builder.Services.AddHangfire(x => x.UseSqlServerStorage(
 
@"Data Source=.;Initial Catalog=HangfireDB;
  Integrated Security=True;Pooling=False"
));

builder.Services.AddHangfireServer();

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if
(app.Environment.IsDevelopment())
{
  app.UseSwagger();
  app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseHangfireDashboard();

app.UseAuthorization();
app.MapControllers();
app.Run();
 

Definimos a string de conexão no serviço AddHangfire onde devemos criar no SQL Server o banco de dados HangfireDB.

Agora vamos criar na pasta Controllers o controlador ProdutosController com o seguinte código:

using Hangfire;
using Microsoft.AspNetCore.Mvc;

namespace ApiHangFire.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ProdutosController : ControllerBase
{
    [HttpGet]
    [Route("login")]
    public String Login()

    {
        //Fire-and-Forget - job executado somente uma vez
        var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Bem-Vindo a loja virtual!"));
        return $"Job ID: {jobId}. Email de boas vindas envidado ao cliente!";
    }

    [HttpGet]
    [Route("produtocheckout")]
    public String CheckoutProduto()

    {
        // Delayed Job - este job é executado somente uma vez mas não
        // imediatamente após algum tempo

        var jobId = BackgroundJob.Schedule(() =>
       Console.WriteLine("Seu produto foi incluído no checkout !"), TimeSpan.FromSeconds(20));

        return $"Job ID: {jobId}. Produto adicionado ao seu checkout com sucesso!";
    }

    [HttpGet]
    [Route("produtopagamento")]
    public String ProdutoPagamento()

    {
        //Fire and Forget Job - este job é executado apenas uma vez
        var parentjobId = BackgroundJob.Enqueue(() =>
              Console.WriteLine("Seu pagamento foi realizado com sucesso!"));

        //Continuations Job - Este job é executado quando o job pai é executado
        BackgroundJob.ContinueJobWith(parentjobId, () =>
               Console.WriteLine("Pagamento do produto enviado!"));

        return "Você concluiu o pagamento e o recibo foi enviado para o seu email id!";
    }

    [HttpGet]
    [Route("ofertasdiarias")]
    public String OfertasDiarias()

    {
        //Recurring Job - este job é executado muitas vezes em um cronograma especificado
        RecurringJob.AddOrUpdate(() =>
            Console.WriteLine("Envio de produtos similares e sugestões de compra"), Cron.Daily);

        return "## Oferta enviada! ##";
    }
}

Neste código, criamos diferentes endpoints com base em cenários de produtos, como quando um usuário faz login no site de compras,  recebe uma mensagem de boas-vindas imediatamente usando o job fire-and-forget.

Depois disso, criamos outro endpoint relacionado ao checklist do produto. Que quando o usuário adicionar um novo produto à lista de verificação, ele será notificado e lembrado após alguns segundos, como se você estivesse adicionando um novo produto à sua lista de verificação.

No terceiro endpoint, criamos um job para pagamento. Quando o usuário concluir o processo, ele receberá um e-mail imediatamente usando o job Fire-and-Forget e, posteriormente, quando este job for executado, o job de Continuação será executado, que é o job filho e que é executado após o job pai.

Finalmente, no último endpoint, queremos enviar ofertas de produtos e para isso usamos um job recorrente que será executado continuamente em segundo plano após as condições Cron especificadas.

Ao executar o projeto podemos verificar que no banco de dados foram criadas as tabelas usadas pelo Hangfire:

Os endpoints serão exibidos na interface do Swagger conforme abaixo:

Podemos também abrir o painel do Hangfire para gerenciar trabalhos em execução em segundo plano. Para isso podemos acessar o mesmo endereço de execução da API usando outra janela do navegador :  https://localhost:7046/hangfire

Agora vamos executar os endpoints da API um por um e verificar os jobs recém-criados no painel do Hangfire.

Primeiro, vamos acionar o endpoint de login da interface do usuário do swagger. Em seguida, ele criará um trabalho e executará esse trabalho imediatamente, conforme mostrado nas imagens abaixo :

Selecionando  Tarefas -> Concluido ,  temos a relação das tarefas concluidas e selecionando o job de id igual a 29 teremos os detalhes deste job:

Assim no Dashabord do Hangfire podemos ver todos os detalhes sobre trabalhos como sucesso, agendamento, falha e processamento.

Agora, vamos acionar o endpoint  GET api/produtos/produtochecktout que vai agendar um job em segundo plano e será executado uma vez após um intervalo de tempo especificado :

A seguir vamos acionar o endpoint GET api/produtos/produtopagamento vai vai criar um job continuação e executá-lo. Depois disso, seu job pai será executado conforme mostrado na imagem. Aqui, o primeiro job pai deve ser executado e, depois, o job filho imediato, que é o job de continuação, é executado :

Para concluir vamos executar o endpoint GET api/produtos/ofertasdiarias e veremos como o trabalho recorrente é executado um por um.

Dessa forma vimos os principais tipos de jobs existentes no Hangfire que podemos usar para agendar trabalhos em segundo plano de acordo com nossos requisitos.

E estamos conversados...

Pegue o projeto aqui: ApiHangFire.zip

"Nada, em toda a criação, está oculto aos olhos de Deus. Tudo está descoberto e exposto diante dos olhos daquele a quem havemos de prestar contas."
Hebreus 4:13

Referências:


José Carlos Macoratti