Utilizando o Hangfire com o .NET para tornar o gerenciamento de tarefas de segundo plano mais fácil
Tags: hangfire, dotnet, tutorial, braziliandevs
Published: 2023-01-27 20:16:14

Este tutorial discutirá como utilizar o Hangfire, um projeto open-source, no ambiente .NET para gerenciar tarefas de segundo plano em projetos principais como APIs ou aplicativos web. É comum que os desenvolvedores enfrentem desafios ao lidar com essas tarefas sem comprometer a clareza, organização e manutenção do projeto. O Hangfire é uma ferramenta incrível que permite agendar essas tarefas sem causar confusão. O tutorial irá mostrar como começar a trabalhar com o Hangfire e o .NET.

## O que é um trabalho em segundo plano no .NET

Um "job em background" em .NET é uma tarefa ou processo que é executado sem interferir na interface do usuário ou no desempenho do aplicativo principal. Essas tarefas geralmente são executadas em segundo plano, ou em outras palavras, de forma assíncrona, enquanto o usuário continua a utilizar o aplicativo. Alguns exemplos comuns de tarefas em segundo plano incluem: atualizações automáticas, envio de e-mails em massa, geração de relatórios, etc. O Hangfire é uma ferramenta que permite agendar e gerenciar essas tarefas em segundo plano de forma fácil e eficiente.

## O que é Hangfire?

Hangfire é uma biblioteca de código aberto que permite agendar eventos em segundo plano de seu aplicativo com facilidade. É muito flexível (obrigado por isso) e oferece vários recursos que facilitam muito o agendamento de trabalhos. Na verdade, você pode agendar um método ou função em segundo plano em uma linha. É uma biblioteca que você não deve perder se precisar executar tarefas em segundo plano.

## Hangfire e .NET

Hangfire é um software open-source para agendamento e gerenciamento de tarefas em background (ou "jobs") em aplicativos .NET. Ele permite que você agende tarefas para serem executadas em momentos específicos ou com intervalos regulares, além de oferecer recursos para monitorar e gerenciar essas tarefas em execução. Isso pode ser útil para tarefas como envio de e-mails, limpeza de dados antigos, etc.

## Para configurar o Hangfire em um projeto .NET Web API, você precisará seguir os seguintes passos:

1. Adicionar as dependências do Hangfire ao seu projeto, geralmente fazendo o download do pacote NuGet do Hangfire e adicionando-o à sua solução.
2. Configurar o Hangfire no arquivo Startup.cs da sua aplicação Web API. Isso incluirá adicionar o serviço do Hangfire ao container de injeção de dependência e adicionar as configurações de middleware do Hangfire ao pipeline de configuração do seu aplicativo.
3. Criar uma classe ou método para gerenciar as tarefas em background. Isso pode ser feito adicionando uma classe que herda de IBackgroundJob, e implementando seus métodos, ou criando métodos estáticos que contenham as tarefas.
4. Agendar as tarefas em background usando o Hangfire. Isso pode ser feito usando o método BackgroundJob.Enqueue() ou o método RecurringJob.AddOrUpdate() para agendar tarefas recorrentes.
5. Inicie o Hangfire e acompanhe as tarefas agendadas e em execução, usando o painel de administração do Hangfire, que pode ser acessado através da URL /hangfire.
6. Por fim, é importante lembrar que é necessário configurar o banco de dados para armazenar as informações de agendamento e execução das tarefas do Hangfire.

## Estrutura do Hangfire no banco de dados

O Hangfire cria várias tabelas no banco de dados para gerenciar as informações relacionadas aos trabalhos agendados. 

- As tabelas principais incluem:
    - `Job`: contém informações sobre cada trabalho agendado, como o nome do trabalho, a data de criação e o status atual.
    - `JobQueue`: contém informações sobre a fila de trabalhos pendentes, incluindo a data e hora da próxima execução.
    - `State`: contém informações sobre o status atual de cada trabalho, como se ele foi concluído ou cancelado.
- Além dessas tabelas, o Hangfire também cria tabelas adicionais:
    - As tabelas criadas pelo Hangfire para armazenar dados de log e monitoramento são:
        - `JobParameter`: Armazena os parâmetros associados a cada trabalho.
        - `Server`: Armazena informações sobre os servidores atuais e anteriores que gerenciam os trabalhos.
        - `Counter`: Armazena contadores globais e agregados.
        - `AggregatedCounter`: Armazena contadores agregados de forma agrupada.
        - `Set`: Armazena conjuntos de dados.
        - `List`: Armazena listas de dados.
        - `Hash`: Armazena dados hash.
        - `Schema`: Armazena informações sobre o esquema atual do banco de dados.
    - As tabelas criadas pelo Hangfire para recuperação de falhas são:
        - `FailedJob`: Armazena informações sobre trabalhos que falharam, incluindo a exceção gerada e a data da falha.

## Painel Hangfire seguro se exposto ao público

Se você planeja expor o Hangfire Dashboard publicamente, é óbvio que deseja proteger sua interface. O painel está expondo nomes de métodos com dados confidenciais sobre métodos, ids de parâmetros, etc. O Hangfire tornou o painel seguro pronto para uso, permitindo apenas solicitações locais. Isso pode ser alterado se você precisar acessar o painel remotamente implementando sua própria versão de `IDashboardAuthorizationFilter()`. Consulte a documentação oficial sobre segurança do painel, se precisar que esse recurso seja implementado.

## Os diferentes tipos de jobs do Hangfire

No Hangfire, existem três tipos básicos de jobs:

1. `Job Recurrente`: Jobs que são executados de forma recorrente em um determinado intervalo de tempo. Por exemplo, um job que é executado todos os dias às 8h.
    1. Exemplo:  Verificação diária de novos usuários cadastrados em um site. Esse job poderia ser programado para ser executado todas as noites às 23h, e a cada execução, ele verificaria se há novos usuários cadastrados no site desde a última vez que foi executado. Se houver novos usuários, ele poderia enviar um e-mail para o administrador do site notificando-o dos novos cadastros.
        
        Para criar esse job recorrente no Hangfire, você poderia usar o método **`RecurringJob.AddOrUpdate`** da seguinte forma:
        
        ```csharp
        RecurringJob.AddOrUpdate(
            "CheckNewUsers",
            () => CheckNewUsers(),
            "0 23 * * *"
        );
        ```
        
        Neste exemplo, "CheckNewUsers" é o nome do job, **`CheckNewUsers`**
         é o método que será executado, e "0 23 * * *" é a expressão CRON que indica que o job deve ser executado todas as noites às 23h.
        
2. `Job Atrasado`: Jobs que são agendados para serem executados em um momento específico no futuro. Por exemplo, um job que é agendado para ser executado daqui a 1 hora.
    1. Exemplo: Sistema de lembretes para eventos. Suponha que você tenha um aplicativo web que permite que os usuários criem eventos e adicionem lembretes para eles. Cada vez que um usuário cria um evento, você poderia criar um job atrasado para enviar um e-mail de lembrete para ele alguns dias antes do evento.
        
        Para criar esse job atrasado no Hangfire, você poderia usar o método **`BackgroundJob.Schedule`** da seguinte forma:
        
        ```csharp
        var reminderTime = eventDate.AddDays(-3);
        BackgroundJob.Schedule(
            () => SendReminderEmail(eventId),
            reminderTime
        );
        ```
        
        Neste exemplo, **`SendReminderEmail`** é o método que será executado e **`reminderTime`** é a data e hora em que o job será executado, 3 dias antes do evento.
        
3. `Job Continuo`: Jobs que são executados uma única vez e não são recorrentes. Esses jobs são úteis quando você precisa executar uma tarefa de forma rápida e não precisa se preocupar com o agendamento.
    1. Exemplo: Sistema de processamento de pedidos. Suponha que você tenha um aplicativo web onde os usuários podem fazer pedidos e que esses pedidos precisam passar por vários processos antes de serem concluídos. Cada processo pode ser representado por um job diferente e os jobs precisam ser executados em sequência.
        
        Para criar esses jobs de Continuation no Hangfire, você poderia usar o método **`BackgroundJob.ContinueWith`** da seguinte forma:
        
        ```csharp
        var process1Id = BackgroundJob.Enqueue(() => Process1(orderId));
        BackgroundJob.ContinueWith(process1Id, () => Process2(orderId));
        BackgroundJob.ContinueWith(process1Id, () => Process3(orderId));
        ```
        
        Neste exemplo, **`Process1`**, **`Process2`** e **`Process3`** são os métodos que serão executados, e **`orderId`** é o id do pedido. O primeiro job é enfileirado usando **`BackgroundJob.Enqueue`**, e os outros dois jobs são adicionados como Continuations do primeiro, usando **`BackgroundJob.ContinueWith`**. Dessa forma, o processo 2 e 3 serão executados após o término do processo 1.
        
        Com Continuations, é possível garantir que os jobs sejam executados em sequência, e também pode-se criar fluxos de trabalho complexos, onde cada tarefa é realizada após a conclusão de uma tarefa anterior.
        

Além disso, existem alguns tipos de jobs mais avançados no Hangfire, como:

1. Jobs agendados com prioridade: Jobs agendados com prioridade podem ser executados primeiro que os jobs normais.
2. Job com tempo de vida: Jobs com tempo de vida são jobs que só podem ser executados uma vez e depois são removidos.
3. Jobs com dependência: Jobs com dependência só podem ser executados depois que outros jobs específicos tenham sido concluídos.
4. Jobs com falhas: jobs que são executados após uma falha.
5. Job com retries: Jobs que são executados novamente após uma falha.
6. Jobs com continuidade: Jobs que são executados após uma falha.

Esses tipos de jobs avançados podem ser criados usando as APIs fornecidas pelo Hangfire, como o **`BackgroundJob.EnqueueWithPriority`**, **`BackgroundJob.Schedule`** e **`BackgroundJob.ContinueWith`**.