Cron Jobs — Hangfire com dotnet 6 -Prática
Vimos no artigo anterior os conceitos de um cron job, tais como suas terminologias e uma breve explicação do que é o Hangfire.
Se você ainda não viu esse artigo, clique aqui para ver.
Pois bem, nesse artigo vou apresentar a forma como eu costumo estruturar meu projeto e também como faço a configuração do Hangfire utilizando o .Net 6 pra isso, então, sem mais delongas, vamos nessa!
Criando o Projeto com .NET 6
- Inicie o Visual Studio e clique em Create a new Project.
2. Escolha o tipo de projeto: ASP.NET Core Web API.
3. Escolha um Nome para seu projeto, nosso exemplo irá se chamar: hangfire-dotnet-sample e então defina o local onde seu projeto irá ficar no seu computador. Agora clique em Next.
Selecione .Net 6.0 (Long-term support) na opção framework. Habilite a opção do docker e então clique em Create.
Uma vez feito os passos acima, deveremos ter algo semelhante a imagem abaixo.
Neste momento, iremos buscar as bibliotecas:
- Hangfire
- Hangfire.MemoryStorage
- Hangfire.Dashboard.Basic.Authentication
Após a instalação, poderemos ver as bibliotecas nas dependências do projeto.
Agora iremos incluir a configuração do Hangfire na classe Program.cs
Essa configuração ocorre em dois pontos da classe, uma para Services e outra para App, conforme a imagem abaixo.
Mude o launch do projeto para hangfire_dotnet_sample conforme imagem abaixo.
Uma última configuração no serviço, no arquivo launchSettings.json, modifique o valor da propriedade launchUrl para hangfire.
Após essa última configuração, ao executarmos a aplicação pressinando a tecla “F5” poderemos ver o endpoint “/hangfire” que configuramos na inicialização do projeto sendo apresentada no browser solicitando usuário e senha como também configuramos na classe programs.cs , conforme imagem abaixo.
Após informar usuário e senha, deveremos poder ver o dashboard do hangfire sendo apresentado.
Opa sucesso, a configuração do Hangfire no nosso projeto ocorreu tudo conforme esperado.
Ai você deve estar se perguntando: “Ok, e agora eu faço o que com isso, como eu crio uma rotina pra rodar no hangfire?”
Calma jovem Jedi, vamos fazer isso agora, segue comigo.
Antes de iniciarmos essa parte da implementação, gostaria de reforça um conceito muito importante que faz com que o Hangfire seja uma ferramenta poderosa e flexível.
Na Hangifire temos os seguintes itens: Jobs e Queues.
O Job é sua rotina de trabalho, e nessa rotina de Trabalho você pode ter diversas Queues que são as tarefas desse trabalho. Vamos fazer um breve exercício.
Pense que você precisa criar um Job para buscar informações de uma determinada fonte de dados e salvar essas mesmas informações em sua base de dados como se fosse uma base fria de informação, para que a sua aplicação frontend receba os dados dessa sua base fria.
Esse job que chamaremos de ProductsJob precisa buscar informações de listagem de produtos de Renda Fixa, Renda Variável e Fundos por exemplo. E cada uma dessas informações pode vir de fontes de dados diferentes.
Para você conseguir desacoplar melhor seu job, para cada tipo de produto podemos criar uma Queue especifica que irei chamar com os seguintes nomes Renda Fixa = FixedIncomeQueue, Renda Variável = EquityQueue e Fundos = FundQueue, e com isso separar a responsabilidade de cada uma delas em uma fila diferente. Perceba a importância do conceito de Jobs e Queues no Hangfire.
Uma vez esclarecido, bora pra implementação.
Para simular a integração com um serviço que retorne as informações de Produtos para o nosso job, vamos criar um serviço de integração que irá simular essa busca de dados para nós, essa integração irá se chamar InvestmentProductIntegration.
Primeiramente vamos criar uma pasta com o nome Integration e dentro dela vamos criar uma interface com o nome IInvestmentProductIntegration e criar uma classe com o nome InvestmentProductIntegration conforme a sequência de imagens abaixo.
Na interface IInvestmentProductIntegration vamos criar 3 métodos conforme imagem abaixo.
Na classe InvestmentProductIntegration vamos implementar a interface acima conforme a imagem abaixo.
Agora vamos fazer a injeção de dependência dessa classe e interface na nossa classe program.cs conforme imagem abaixo.
Agora vamos fazer a criação das nossas Queues que serão:
- FixedIncomeQueue
- EquityQueue
- FundQueue
Para melhorar a visualização de nossas classes e interfaces, para as interfaces eu irei criar uma pasta chamada Domain e dentro da pasta domain iremos criar uma pasta chamada Interfaces e é dentro dessa pasta que iremos criar todas as nossas interfaces e vamos aproveitar pra remover para essa pasta a interface que criamos anteriormente para a camada de integração IInvestmentProductIntegration . Conforme imagem abaixo.
Perceba que a interface IInvestmentProductIntegration foi removida da pasta Integration e incluida na pasta Interfaces dentre da pasta Domain, blz.
Em cada uma das interfaces IFixedIncomeQueue, IEquityQueue e IFundQueue vamos incluir a interface IQueue conforme imagem abaixo.
Agora, vamos criar uma pasta chamada Queues na raiz da aplicação, e dentro dela vamos criar as seguintes classes:
- FixedIncomeQueue.cs
- EquityQueue.cs
- FundQueue.cs
E para cada classe criada vamos incluir sua respectiva interface e fazer sua implementação conforme imagens abaixo.
Veja que os métodos criados estão lançando um exceção de NotImplementationException vamos resolver isso em alguns instantes.
Agora iremos fazer a configuração de injeção de dependência dessas classes e suas interfaces na classe program.cs conforme imagem abaixo
Agora vamos fazer a comunicação das Queues com o Serviço InvestmentProductIntegration de Integração que criamos, conforme imagem abaixo.
Bom, ainda falta criar os Jobs, então vamos lá.
Dentro da pasta Interface lá na pasta Domain, vamos criar duas Interfaces que são:
- IJob.cs
- IProductJob.cs
A Interface IProductJob irá herdar da interface IJob conforme imagem abaixo.
Agora vamos criar uma pasta chamada Jobs na raiz a aplicação e dentro dela vamos criar uma classe chamada ProductsJob e essa classe irá herdar da interface IProdutctJob que criamos no passo anterior.
Agora vamos fazer a comunicação do Job com as Queues criadas anteriormente que ele irá executar.
Então da mesma, forma, vamos configurar a injeção de dependência da classe ProductsJob na classe program.cs.
Bom nesse momento, falta apenas um passo a ser feito para concluir a implmentação da nossa rotina de buscar produtos, porém precisamos tomar uma decisão.
Que tipo de Job estamos querendo criar?
E qual tipo de CronJob esse serviço se encaixa?
Vamos relembrar os tipos de jobs que temos.
Há diversos tipos de jobs disponibilizados no Hangfire, para esse nosso exemplo vamos considerar que essa é uma rotina que precisará se executada diariamente pelo menos uma vez.
Uma vez que decidimos vamos fazer essa configuração.
Na classe program.cs abaixo da configuração “FIM DA CONFIGURAÇÃO APP — HANGIFIRE” que fizemos no Inicio desse artigo.
Vamos fazer a seguinte implementação.
Vamos utilizar o serviceProvider pra buscar uma instância do nosso job ProductsJob no container de injeção de dependência.
Agora iremos utilizar a classe RecurringJob que é disponibilizada pelo próproio Hangfire que instalamos na aplicação no incio do artigo e iremos fazer a seguinte configuração informando o Job que irá ser executado, a periodiciade de execução que é diariamente e o TimeZone que iremos informar o Universal.
Depois de tudo, a configuração deverá ficar conforme a imagem abaixo.
Agora após executarmos a aplicação podermos ver no dashboard do hangfire na aba de Tarefas recorrentes o nosso job.
E quando o Job estiver rodando poderemos ver sua execução sendo feita na aba Tarefa.
E após todo esse percurso a solution da nossa aplicação deverá estar dessa forma.
Quanto código hein rs.
Bom pessoal era isso que eu tinha para mostrar pra vocês. Espero que tenha ficado claro como configurar o hangfire em um projeto .NET e também como eu faço pra organizar a estrutura de jobs e queues com o intuito de deixar simples a adição de uma nova queue ou mesmo um novo job.
Para acessar o respositório com todos este código é só clicar aqui.
Peço por gentileza para deixar uma estrela no repositório para que ele possa ganhar engajamento e com isso alcançar outros devs que possam se beneficiar desse conteúdo.
Me siga aqui no medium e no linkedIn para não perder nenhum artigo. Está vindo coisas boas por ai.
Agradeço por terem chegado até aqui comigo, até a próxima galera, um abraço =].