> ## Content Index
> Fetch the complete content index at: https://www.azurebrasil.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Utilizando o Quartz.NET com um Job Store compartilhado
- URL: https://www.azurebrasil.cloud/blog/utilizando-o-quartz/
- Published: 2023-08-10T14:17:41.000Z
- Updated: 2023-08-10T14:17:41.000Z
- Author: Talles Valiatti

No post de hoje, iremos criar uma simples aplicação utilizando o [Quartz.NET](https://www.quartz-scheduler.net/?ref=azurebrasil.cloud) para rodar processos em *backgroud.* Ainda vamos utilizar um [Job Store](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/job-stores.html?ref=azurebrasil.cloud) compartilhado em um banco de dados [](https://www.postgresql.org/?ref=azurebrasil.cloud)[Postgre](https://www.postgresql.org/?ref=azurebrasil.cloud)Sql, permitindo que os *jobs* possam rodar em mais de uma instância da aplicação.

Essa funcionalidade permite que caso alguma instância não possa executar o processo de *backgroud* (alguma indisponibilidade, por exemplo)*,* esse *job* será atribuído a uma outra instância automaticamente. Garantido uma resiliência e escalabilidade as nossas soluções.

Antes do começar, recomendo uma leitura sobre alguns itens:

- [Quartz.NET](https://www.quartz-scheduler.net/?ref=azurebrasil.cloud);
- *[Job Stores](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/job-stores.html?ref=azurebrasil.cloud)*;
- *[ADO.NET Job Store](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/job-stores.html?ref=azurebrasil.cloud#ado-net-job-store-adojobstore)*;
- [*Cron trigger*.](https://www.quartz-scheduler.net/documentation/quartz-1.x/tutorial/crontriggers.html?ref=azurebrasil.cloud)

Vamos lá!

Inicialmente vamos criar um diretório raiz para nosso projeto.

```
mkdir QuartzJobScheduling

```

Dentro desse diretório, vamos iniciar um projeto em .NET do tipo *[worker](https://learn.microsoft.com/en-us/dotnet/core/extensions/workers?pivots=dotnet-7-0&ref=azurebrasil.cloud)*.

```
dotnet new worker
```

Vamos adicionar alguns pacotes NuGet por meio do comando *[dotnet add package.](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-add-package?ref=azurebrasil.cloud)*

```
dotnet add package Quartz.Extensions.Hosting
dotnet add package Quartz.Serialization.Json
dotnet add package Npgsq
```

Devemos criar uma instância do PostgreSQL localmente para ser usado por nossa aplicação. Nesse post, eu criei esse banco de dados por meio de um [docker compose](https://hub.docker.com/%5F/postgres?ref=azurebrasil.cloud) dentro do meu [raspberry pi](https://www.raspberrypi.org/?ref=azurebrasil.cloud) (quem sabe isso não vale um post, ein?!), porém isso pode ser feito de [várias outras formas](https://www.postgresql.org/download/?ref=azurebrasil.cloud).

Dentro do PostgreSQL recém criado, vamos criar um *database* chamado *quartz.*

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/08/Group-1134.png)

Como mostrado na imagem acima, estou utilizando o [Azure Data Studio](https://azure.microsoft.com/pt-br/products/data-studio?ref=azurebrasil.cloud).

Os *schemas* requisitados pelo *Job Storage* do Quartz podem sem encontrados no caminho abaixo:

```
https://github.com/quartznet/quartznet/blob/main/database/tables/tables_postgres.sql
```

Basta executar os *scritps* SQL no banco recém-criado, que teremos o seguinte resultado:

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/08/Screen-Shot-2023-08-07-at-15.51.45.png)

Feito isso, já podemos ir ao código da aplicação. Vamos inicialmente criar um método de extensão para configurar o Quartz:

- Habilitamos a injeção de dependências dentro dos jobs por meio do *UseMicrosoftDependencyInjectionJobFactory;*
- Configuramos o *JobStorage* com o método *UsePersistentStore*. Ele irá utilizar o banco de dados recém-criado como persistência;
- Configuramos um *job (*Classe *MyJob.cs* que iremos implementar), com a chave "MyJob" e que será executado a cada 5 segundos.

```
using Quartz;
using Quartz.Impl.AdoJobStore;

namespace QuartzJobScheduling.Jobs;

public static class JobConfigurations
{
    public static IServiceCollection AddJobs(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddQuartz(q =>
        {
            q.UseMicrosoftDependencyInjectionJobFactory();
            
            q.SchedulerId = Guid.NewGuid().ToString();
            q.SchedulerName = "Scheduler";
            
            q.UsePersistentStore(opts => 
            {
                opts.UseClustering();

                opts.UseJsonSerializer();

                opts.UsePostgres(o => 
                {
                    o.UseDriverDelegate<PostgreSQLDelegate>();
                    o.ConnectionString = configuration!.GetConnectionString("DefaultConnection");
                    o.TablePrefix = "qrtz_";
                });
            });

            var jobKey = new JobKey("MyJob");
            
            q.AddJob<MyJob>(opts => opts.WithIdentity(jobKey));
            
            q.AddTrigger(opts => opts
                .ForJob(jobKey)
                .WithIdentity("MyJob-trigger")
                .WithCronSchedule("0/5 * * * * ?")); // run every 5 seconds            
        });
 
        services.AddQuartzHostedService(options =>
        {
            options.WaitForJobsToComplete = true;
        });

        return services;
    }
}
```

Vamos agora criar o *job* declarado acima. Ele basicamente irá fazer o log da instância da aplicação que está executando o job e ainda informará quando que essa execução foi realizada.

```
using Quartz;

namespace QuartzJobScheduling.Jobs;

public class MyJob : IJob
{
    private readonly ILogger<MyJob> _logger;

    public MyJob(ILogger<MyJob> logger)
    {
        _logger = logger;
    }

    public Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation($"InstanceId:{context.FireInstanceId} - {DateTime.Now}");

        return Task.CompletedTask;
    }
}
```

Devemos colocar essas classes em um novo diretório chamado *Jobs.*

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/08/Screen-Shot-2023-08-07-at-15.35.23.png)

Vamos ainda adicionar a *connections string* do banco de dados PostgreSQL ao appsettings.json do nosso projeto.

```
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=raspberrypi.local;Database=quartz;Port=5432;User Id=postgres;Password=<Your-Password>"
  }
}

```

Para finalizar, devemos chamar o [método de extensão](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods?ref=azurebrasil.cloud) criado anteriormente no *Program.cs.*

```
using QuartzJobScheduling.Jobs;

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((builder, services)=>
    {
        services.AddJobs(builder.Configuration);
    })
    .Build();

host.Run();

```

Todo o desenvolvimento está feito. É hora de fazermos os testes.

Para isso, vamos simular duas instâncias da aplicação rodando simultaneamente. Devemos fazer o *[publish](https://learn.microsoft.com/pt-br/dotnet/core/tools/dotnet-publish?ref=azurebrasil.cloud)* da aplicação duas vezes:

```
dotnet publish -o publishOne
dotnet publish -o publishTwo
```

Vamos abrir dois terminais, e em cada terminal, rodar o seguinte [comando](https://learn.microsoft.com/pt-br/dotnet/core/tools/dotnet-run?ref=azurebrasil.cloud) dentro de cada diretório publicado anteriormente:

```
dotnet QuartzJobScheduling.dll

```

![](https://storage.ghost.io/c/00/52/0052dced-0017-4d07-b190-1f5c48e0ab59/content/images/2023/08/Group-1135-1.png)

Podemos observar que as execuções (a cada 5 segundos) estão sendo distribuídas entre as instâncias ativas do nosso aplicativo.

Tudo ocorreu conforme o planejado!

Você já pode baixar o projeto por esse [](https://github.com/TallesValiatti/LinqGroupJoin?ref=azurebrasil.cloud)[link](https://github.com/TallesValiatti/QuartzJobScheduling?ref=azurebrasil.cloud), e não esquece de me seguir no [LinkedIn](https://www.linkedin.com/in/tallesvaliatti/?ref=azurebrasil.cloud)!

Até a próxima, abraços!