Pular para o conteúdo principal

Hangfire - processamento em background fácil no .NET

A necessidade de realizar uma tarefa em segundo plano é muito comum, seja para gravar um arquivo, enviar um e-mail, executar um processo de banco pesado, enfim, qualquer coisa que não deve "bloquear" o usuário no thread principal, e é aí que o Hangfire entra, ele recebe tarefas e as trata em filas realizando a execução em background e mais:

  • As tarefas entram em uma fila e a execução ocorre na sequência;
  • Uma execução só é considerada "falha" quando as tentativas já se esgotaram (por padrão são 10);
  • Dá para criar uma tarefa simplesmente a colocando na fila;
  • Dá para criar um fluxo de execução de tarefas constante dentro de um intervalo;
  • Dá para agendar a execução de tarefas;
  • Dá para condicionar a execução de tarefas após o sucesso de outra tarefa;
  • Todo o fluxo é tratado em tabelas do próprio Hangfire, podendo ser gerido em vários bancos de dados (relacionais ou não);
  • Os registros referentes as tarefas possuem um tempo limitado de vida, depois de concluidos são apagados (por padrão 1 dia);
  • É disponibilizado um dashboard para acompanhar as tarefas;

Instalação

Para esse post será criada uma aplicação web, uma API padrão sem funcionalidades, e o Hangfire vai usar o SqlServer para suas tabelas, então para nosso caso precisaremos dos seguintes pacotes:

Configuração

Em resumo precisamos apenas alterar o Startup, configurando, adicionando e usando o HangFire:

Em "ConfigureServices":

            services.ConfigureHangfire(HostingEnvironment, Configuration);

            services.AddHangfireServer();

Em "Configure":

            app.UseHangfireDashboard();

            new HangfireExamples().StartExamples();

Execução única (assim que possível)

Esse recurso permite que uma tarefa seja incluida na fila sendo executada assim que possível, se a fila estiver vazia ela é executada de imediato, no exemplo abaixo executaremos o método "FireAnfForgetExample":

BackgroundJob.Enqueue(() => FireAnfForgetExample(null));

Execução recorrente

Aqui temos a capacidade de programar uma tarefa para ser executada de tempos em tempos, no exemplo abaixo executaremos o método "RecurringJobExample" de minuto em minuto:

RecurringJob.AddOrUpdate(() => RecurringJobExample(null), Cron.Minutely);

Execução agendada

Caso a necessidade seja a de agendar uma execução futura podemos fazer com o exemplo abaixo, onde o método "DelayedJobExample" é executado em uma semana:

BackgroundJob.Schedule(() => DelayedJobExample(null), TimeSpan.FromDays(7));

Execução contínua

Esse último recurso nos permite condicionar a execução de uma terefa ao sucesso de uma outra, para isso primeiro precisamos pegar o ID da tarefa "principal" e informa-lo para a tarefa "condicional", no exemplo abaixo executamos o método "ContinuationTaskFirst" e caso ele seja concluido com sucesso o método "ContinuationTaskSecond" será executado:

var jobId = BackgroundJob.Enqueue(() => ContinuationTaskFirst(null));

BackgroundJob.ContinueJobWith(jobId, () => ContinuationTaskSecond(null));

Dashboard

Como mencionado o Hangfire fornece uma aplicação web que nos permite acompanhar toda movimentação, basta acessar "url_site/hangfire":

  • Painel de monitoramento com gráficos em tempo real e histórico:
  • Página de Tarefas para consultar "Enfileiradas", "Agendadas", "Processando", "Concluido", "Em falha", "Removidas" e "Aguardando";
  • Página de Retentativas para ver o que ainda não deu certo de ser executado;
  • Página de Tarefas recorrentes para ver o que está configurado como "recorrente";
  • Página de Servidores para ver onde o Hangfire esta rodando;

Conclusão

O Hangfire é uma forma bem poderosa e simples de se trabalhar com filas de execução em segundo plano, fornecendo inclusive uma série de ferramentas para acompanhamento desse trabalho, é sem dúvidas uma das maneiras mais simples de tratar essa questão.

Projeto de exemplo

Fonte

Comentários

Mais visitadas

Aplicação Flask usando Nginx e Gunicorn

Aplicação Flask usando Nginx e Gunicorn Se você já desenvolveu uma aplicação Flask básica, sabe que o servidor de desenvolvimento embutido não é ideal para produção. Ele não é projetado para lidar com altos volumes de tráfego ou conexões simultâneas. Para tornar sua aplicação Flask mais robusta e pronta para produção, podemos usar o Gunicorn como servidor de aplicação e o Nginx como proxy reverso. Neste artigo, vamos adaptar o exemplo anterior ( Criando uma Aplicação CRUD com Flask, PostgreSQL e Docker ) para incluir o Nginx e o Gunicorn. O que são Nginx e Gunicorn? Gunicorn O Gunicorn (Green Unicorn) é um servidor de aplicação WSGI que roda aplicações Python como o Flask. Ele é eficiente e simples de configurar, lidando com múltiplas requisições ao mesmo tempo, algo que o servidor embutido do Flask não faz bem. Nginx O Nginx é um servidor web que atua como um proxy reverso. Ele recebe requisições HTTP e as encaminha ao Gunicorn. Além disso, o Nginx pode: Servir arquivos ...

Como Verificar se um Objeto Existe (Delphi)

Em alguns momentos surge a necessidade de verificar se um determinado objeto existe, ou seja se já foi criado, principalmente quando se trabalha com criação dinâmica em tempo de execução, então vamos ao exemplo: - Vamos criar uma variável, um vetor do tipo caixa de texto: var Minha_caixa : array of TEdit; - Em seguida definir o tamanho desse vetor, no caso será dez: setLength(Minha_caixa, 10) - Agora iremos criar nossa caixa de texto: // lembrando que o vetor inicia em zero // logo o índice final é o tamanho total - 1 for vl_i := 0 to Length(Minha_caixa) -1 do begin Minha_caixa[vl_i] := TEdit.Create(self); with Minha_caixa[vl_i] do begin Parent := Self; Name := 'Caixa_N'+IntToStr(vl_i); Text := 'Esta é a '+IntToStr(vl_i)+' º caixa !'; ReadOnly := true; Height := 21; Width := ...

Iniciar e Parar Serviços do Windows (Delphi)

Em certas ocasiões nos deparamos com a necessidade de manipular determinadas atividades do SO, como iniciar ou parar um banco de dados, ou qualquer outro serviço que esteja funcionando no momento. Segue abaixo um código que encontrei na Internet para tal finalidade (não me recordo à fonte, assim que eu a encontrar colocarei). Iniciar Serviço: uses WinSvc; // // start service // // return TRUE if successful // // sMachine: //   machine name, ie: \SERVER //   empty = local machine // // sService //   service name, ie: Alerter // function ServiceStart(   sMachine,   sService : string ) : boolean; var   //   // service control   // manager handle   schm,   //   // service handle   schs   : SC_Handle;   //   // service status   ss     : TServiceStatus;   //   // te...