Hur man schemalägger jobb med Quartz.NET i ASP.NET Core

När du arbetar med webbapplikationer måste du ofta utföra vissa uppgifter i bakgrunden. I vissa fall kommer detta att vara uppgifter som ska utföras med fördefinierade tidsintervall.

Quartz.NET är en .NET-port med öppen källkod för det populära Java-schemaläggningsramverket. Den har använts länge och ger utmärkt stöd för att arbeta med Cron-uttryck. Du kan lära dig mer om Quartz.NET från ett tidigare inlägg här. 

Den här artikeln presenterar en diskussion om hur vi kan arbeta med Quartz.NET i ASP.NET Core för att schemalägga bakgrundsjobb.

För att arbeta med kodexemplen i den här artikeln bör du ha Visual Studio 2019 installerat i ditt system. Om du inte redan har en kopia kan du ladda ner Visual Studio 2019 här. 

Skapa ett ASP.NET Core API-projekt

Låt oss först skapa ett ASP.NET-kärnprojekt i Visual Studio. Förutsatt att Visual Studio 2019 är installerat i ditt system, följ stegen nedan för att skapa ett nytt ASP.NET-kärnprojekt i Visual Studio.

  1. Starta Visual Studio IDE.
  2. Klicka på "Skapa nytt projekt."
  3. I fönstret "Skapa nytt projekt" väljer du "ASP.NET Core Web Application" från listan över mallar som visas.
  4. Klicka på Nästa.
  5. I fönstret "Konfigurera ditt nya projekt" som visas nedan anger du namn och plats för det nya projektet.
  6. Klicka på Skapa.
  7. I fönstret "Skapa ny ASP.NET Core-webbapplikation" väljer du .NET Core som körtid och ASP.NET Core 2.2 (eller senare) från rullgardinsmenyn högst upp. Jag använder ASP.NET Core 3.0 här.
  8. Välj “API” som projektmall för att skapa en ny ASP.NET Core API-applikation. 
  9. Se till att kryssrutorna "Aktivera Docker-support" och "Konfigurera för HTTPS" är avmarkerade eftersom vi inte använder dessa funktioner här.
  10. Se till att autentisering är inställd som "Ingen autentisering" eftersom vi inte heller använder autentisering.
  11. Klicka på Skapa. 

Detta skapar ett nytt ASP.NET Core API-projekt i Visual Studio. Välj Controllers-lösningsmappen i Solution Explorer-fönstret och klicka på "Lägg till -> Controller ..." för att skapa en ny controller med namnet DefaultController.

Därefter bör du installera Quartz-paketet från NuGet för att arbeta med Quartz. Du kan göra detta antingen via NuGet-pakethanteraren i Visual Studio 2019 IDE eller genom att utföra följande kommando på NuGet-pakethanterarkonsolen:

Installera-paket kvarts

Quartz.NET-jobb, utlösare och schemaläggare 

De tre huvudkoncepten i Quartz.NET är jobb, utlösare och schemaläggare. Ett jobb innehåller koden för att utföra en uppgift eller ett jobb som ska utföras. Ett jobb representeras av en klass som implementerar IJob-gränssnittet. En utlösare används för att specificera schemat och andra detaljer för ett jobb. Du kan dra nytta av en trigger för att ange hur jobbet ska utföras. Schemaläggaren är den komponent som är ansvarig för avfrågning och utförande av jobb baserat på fördefinierade scheman.

Skapa en schemaläggare med Quartz.NET

Det bör noteras att du kan ha flera schemaläggare i en applikation. Vi använder dock bara en schemaläggare här för enkelhets skull. Följande kodavsnitt illustrerar hur du kan skapa en schemaläggarinstans.

var scheduler = StdSchedulerFactory.GetDefaultScheduler (). GetAwaiter (). GetResult ();

När schemaläggaren har skapats kan du använda följande kod i ConfigureServices-metoden i Startup.cs-filen för att lägga till schemaläggarinstansen som en singleton-tjänst.

services.AddSingleton (schemaläggare);

Starta och stoppa en schemaläggare med Quartz.NET

För att starta och stoppa schemaläggaren utnyttjar vi en värdtjänst. För att göra detta måste du skapa en klass som implementerar IHostingService-gränssnittet som visas i kodavsnittet nedan.

offentlig klass CustomQuartzHostedService: IHostedService

{

        privat readonly IScheduler _scheduler;

        offentlig CustomQuartzHostedService (schemaläggare för IScheduler)

        {

            _scheduler = schemaläggare;

        }

        public async Task StartAsync (CancellationToken cancellationToken)

        {

            väntar på _scheduler? .Start (cancellationToken);

        }

        public async Task StopAsync (CancellationToken cancellationToken)

        {

            väntar på _scheduler? .Shutdown (cancellationToken);

        }

 }

Observera att du bör registrera den värdtjänsten i servicesamlingen i ConfigureServices-metoden med hjälp av kodavsnittet nedan.

services.AddHostedService ();

Här är den uppdaterade ConfigureServices-metoden för din referens:

public void ConfigureServices (IServiceCollection services)

{

    tjänster.AddControllers ();

    var schemaläggare =

    StdSchedulerFactory.GetDefaultScheduler (). GetAwaiter (). GetResult ();

    services.AddSingleton (schemaläggare);

    services.AddHostedService ();

}

Skapa ett jobb med Quartz.NET

Som jag sa tidigare är ett jobb en klass som implementerar IJob-gränssnittet och innehåller Execute () -metoden. Metoden Execute () accepterar en instans av typen IJobExecutionContext.

Följande kodavsnitt illustrerar en jobbklass som också innehåller en asynkron Execute () -metod. Den här metoden innehåller koden som motsvarar den uppgift som ditt jobb ska utföra.

[DisallowConcurrentExecution]

public class NotificationJob: IJob

    {

        privat readonly ILogger _logger;

        public NotificationJob (ILogger logger)

        {

            _logger = logger;

        }

        public Task Execute (IJobExecutionContext context)

        {

            _logger.LogInformation ("Hej världen!");

            returnera Task.CompletedTask;

        }

    }

Skapa en jobbfabrik med Quartz.NET

En jobbfabrik är en klass som ärver IJobFactory-gränssnittet och implementerar metoderna NewJob () och ReturnJob (). Följande kodavsnitt kan användas för att skapa en fabriksklass som kan skapa och returnera en jobbinstans.

offentlig klass CustomQuartzJobFactory: IJobFactory

    {

        privat readonly IServiceProvider _serviceProvider;

        public CustomQuartzJobFactory (IServiceProvider serviceProvider)

        {

            _serviceProvider = serviceProvider;

        }

        offentlig IJob NewJob (TriggerFiredBundle triggerFiredBundle,

        IScheduler schemaläggare)

        {

            var jobDetail = triggerFiredBundle.JobDetail;

            returnera (IJob) _serviceProvider.GetService (jobDetail.JobType);

        }

        offentligt ogiltigt ReturnJob (IJob-jobb) {}

    }

Observera att den här implementeringen inte utnyttjar jobbpoolen. Om du vill använda jobbpooling bör du ändra metoden NewJob () och sedan implementera ReturnJob () -metoden.

Skapa en JobMetadata-klass för att lagra dina jobbmetadata

Vi använder en anpassad klass för att lagra metadata relaterade till ett jobb, dvs jobb-id, namn, etc. Följande klass representerar jobbmetadataklassen.

offentlig klass JobMetadata

    {

        public Guid JobId {get; uppsättning; }

        public Type JobType {get; }

        public string JobName {get; }

        offentlig sträng CronExpression {get; }

        public JobMetadata (Guid Id, Type jobType, string jobName,

        string cronExpression)

        {

            JobId = Id;

            JobType = jobType;

            JobName = jobName;

            CronExpression = cronExpression;

        }

    }

Skapa en värdtjänst för att starta och stoppa Quartz.NET-schemaläggaren

Därefter måste vi implementera en värdtjänst. En värdtjänst är en klass som implementerar IHostedService-gränssnittet och startar Quartz-schemaläggaren. Följande kodlista illustrerar en anpassad värdklass.

offentlig klass CustomQuartzHostedService: IHostedService

    {

        privat readonly ISchedulerFactory schedulerFactory;

        privat readonly IJobFactory jobFactory;

        privat readonly JobMetadata jobMetadata;

        public CustomQuartzHostedService (ISchedulerFactory

            schemaläggareFabrik,

            JobMetadata jobbMetadata,

            IJobFactory jobFactory)

        {

            this.schedulerFactory = schedulerFactory;

            this.jobMetadata = jobMetadata;

            this.jobFactory = jobFactory;

        }

        public IScheduler Scheduler {get; uppsättning; }

        public async Task StartAsync (CancellationToken cancellationToken)

        {

            Scheduler = väntar på schedulerFactory.GetScheduler ();

            Scheduler.JobFactory = jobFactory;

            var jobb = CreateJob (jobMetadata);

            var trigger = CreateTrigger (jobMetadata);

            väntar på Scheduler.ScheduleJob (jobb, trigger, cancellationToken);

            väntar på Scheduler.Start (cancellationToken);

        }

        public async Task StopAsync (CancellationToken cancellationToken)

        {

            väntar på schemaläggaren? .Stäng av (cancellationToken);

        }

        privat ITrigger CreateTrigger (JobMetadata jobMetadata)

        {

            returnera TriggerBuilder.Create ()

            .WithIdentity (jobMetadata.JobId.ToString ())

            .WithCronSchedule (jobMetadata.CronExpression)

            .WithDescription ($ "{jobMetadata.JobName}")

            .Bygga();

        }

        privat IJobDetail CreateJob (JobMetadata jobMetadata)

        {

            returnera JobBuilder

            .Create (jobMetadata.JobType)

            .WithIdentity (jobMetadata.JobId.ToString ())

            .WithDescription ($ "{jobMetadata.JobName}")

            .Bygga();

        }

    }

Följande kodavsnitt visar den fullständiga koden för ConfigureServices-metoden i startklassen.

public void ConfigureServices (IServiceCollection services)

{

tjänster.AddControllers ();

tjänster.AddSingleton ();

tjänster.AddSingleton ();

tjänster.AddSingleton ();

services.AddSingleton (ny JobMetadata (Guid.NewGuid (), typeof (NotificationJob), "Notification Job", "0/10 * * * *?"));

services.AddHostedService ();

}

Och det är allt du behöver göra! När du kör applikationen ser du att metoden Execute () i NotificationJob-klassen körs var 10: e sekund.

Quartz.NET är ett bra val för att implementera schemaläggare i dina applikationer. Du kan dra nytta av uthållighetsfunktionen i Quartz.NET för att också lagra dina jobb i en databas som SQL Server, PostgreSQL eller SQLite.