Cara menjadwalkan pekerjaan menggunakan Quartz.NET di ASP.NET Core

Saat mengerjakan aplikasi web, Anda akan sering kali perlu menjalankan tugas tertentu di latar belakang. Dalam beberapa kasus, ini akan menjadi tugas yang harus dijalankan pada interval waktu yang telah ditentukan.

Quartz.NET adalah port .NET open source dari kerangka kerja penjadwalan pekerjaan Java yang populer. Ini telah digunakan untuk waktu yang lama dan memberikan dukungan yang sangat baik untuk bekerja dengan ekspresi Cron. Anda dapat mempelajari lebih lanjut tentang Quartz.NET dari posting sebelumnya di sini. 

Artikel ini menyajikan diskusi tentang bagaimana kita dapat bekerja dengan Quartz.NET di ASP.NET Core untuk menjadwalkan pekerjaan latar belakang.

Untuk bekerja dengan contoh kode yang disediakan dalam artikel ini, Anda harus menginstal Visual Studio 2019 di sistem Anda. Jika Anda belum memiliki salinannya, Anda dapat mengunduh Visual Studio 2019 di sini. 

Buat proyek ASP.NET Core API

Pertama, mari buat proyek ASP.NET Core di Visual Studio. Dengan asumsi Visual Studio 2019 diinstal di sistem Anda, ikuti langkah-langkah yang diuraikan di bawah ini untuk membuat proyek ASP.NET Core baru di Visual Studio.

  1. Luncurkan Visual Studio IDE.
  2. Klik "Buat proyek baru".
  3. Di jendela "Buat proyek baru", pilih "Aplikasi Web Inti ASP.NET" dari daftar templat yang ditampilkan.
  4. Klik Next.
  5. Di jendela "Configure your new project" yang ditampilkan berikutnya, tentukan nama dan lokasi untuk proyek baru tersebut.
  6. Klik Buat.
  7. Di jendela "Buat Aplikasi Web ASP.NET Core Baru", pilih .NET Core sebagai runtime dan ASP.NET Core 2.2 (atau yang lebih baru) dari daftar drop-down di bagian atas. Saya akan menggunakan ASP.NET Core 3.0 di sini.
  8. Pilih "API" sebagai template proyek untuk membuat aplikasi ASP.NET Core API baru. 
  9. Pastikan kotak centang "Aktifkan Dukungan Docker" dan "Konfigurasi untuk HTTPS" tidak dicentang karena kami tidak akan menggunakan fitur tersebut di sini.
  10. Pastikan Autentikasi disetel sebagai "Tanpa Autentikasi" karena kami juga tidak akan menggunakan autentikasi.
  11. Klik Buat. 

Ini akan membuat proyek ASP.NET Core API baru di Visual Studio. Pilih folder solusi Controllers di jendela Solution Explorer dan klik “Add -> Controller…” untuk membuat controller baru bernama DefaultController.

Selanjutnya, untuk bekerja dengan Quartz, Anda harus menginstal paket Quartz dari NuGet. Anda dapat melakukan ini baik melalui manajer paket NuGet di dalam Visual Studio 2019 IDE, atau dengan menjalankan perintah berikut di konsol manajer paket NuGet:

Instal-Paket Kuarsa

Pekerjaan Quartz.NET, pemicu, dan penjadwal 

Tiga konsep utama di Quartz.NET adalah pekerjaan, pemicu, dan penjadwal. Sebuah pekerjaan berisi kode untuk menjalankan tugas atau pekerjaan yang akan dilakukan. Pekerjaan diwakili oleh kelas yang mengimplementasikan antarmuka IJob. Pemicu digunakan untuk menentukan jadwal dan detail pekerjaan lainnya. Anda dapat memanfaatkan pemicu untuk menentukan bagaimana pekerjaan harus dijalankan. Penjadwal adalah komponen yang bertanggung jawab untuk melakukan polling dan menjalankan pekerjaan berdasarkan jadwal yang telah ditentukan sebelumnya.

Buat penjadwal menggunakan Quartz.NET

Perlu dicatat bahwa Anda dapat memiliki beberapa penjadwal dalam satu aplikasi. Namun, kami hanya akan menggunakan satu penjadwal di sini demi kesederhanaan. Cuplikan kode berikut mengilustrasikan bagaimana Anda dapat membuat instance penjadwal.

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

Setelah penjadwal dibuat, Anda dapat menggunakan kode berikut di metode ConfigureServices dari file Startup.cs untuk menambahkan contoh penjadwal sebagai layanan tunggal.

services.AddSingleton (scheduler);

Mulai dan hentikan penjadwal menggunakan Quartz.NET

Untuk memulai dan menghentikan penjadwal, kami akan memanfaatkan layanan hosting. Untuk melakukan ini, Anda perlu membuat kelas yang mengimplementasikan antarmuka IHostingService seperti yang ditunjukkan dalam cuplikan kode yang diberikan di bawah ini.

kelas publik CustomQuartzHostedService: IHostedService

{

        pribadi hanya baca IScheduler _scheduler;

        public CustomQuartzHostedService (IScheduler scheduler)

        {

            _scheduler = penjadwal;

        }

        public async Task StartAsync (CancellationToken cancellationToken)

        {

            menunggu _scheduler? .Start (cancellationToken);

        }

        public async Task StopAsync (CancellationToken cancellationToken)

        {

            menunggu _scheduler? .Shutdown (cancellationToken);

        }

 }

Perhatikan bahwa Anda harus mendaftarkan layanan yang dihosting di kumpulan layanan di metode ConfigureServices menggunakan cuplikan kode yang diberikan di bawah ini.

services.AddHostedService ();

Berikut adalah metode ConfigureServices yang diperbarui untuk referensi Anda:

public void ConfigureServices (layanan IServiceCollection)

{

    services.AddControllers ();

    var scheduler =

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

    services.AddSingleton (scheduler);

    services.AddHostedService ();

}

Buat pekerjaan menggunakan Quartz.NET

Seperti yang saya katakan sebelumnya, sebuah pekerjaan adalah kelas yang mengimplementasikan antarmuka IJob dan berisi metode Execute (). Metode Execute () menerima turunan dari tipe IJobExecutionContext.

Cuplikan kode berikut menggambarkan kelas pekerjaan yang berisi metode Execute () asynchronous juga. Metode ini berisi kode yang sesuai dengan tugas yang harus dilakukan pekerjaan Anda.

[DisallowConcurrentExecution]

public class NotificationJob: IJob

    {

        pribadi hanya baca ILogger _logger;

        Public NotificationJob (ILogger logger)

        {

            _logger = logger;

        }

        Eksekusi Tugas publik (konteks IJobExecutionContext)

        {

            _logger.LogInformation ("Halo dunia!");

            return Task.CompletedTask;

        }

    }

Buat pabrik pekerjaan menggunakan Quartz.NET

Pabrik pekerjaan adalah kelas yang mewarisi antarmuka IJobFactory dan mengimplementasikan metode NewJob () dan ReturnJob (). Cuplikan kode berikut dapat digunakan untuk membuat kelas pabrik yang dapat membuat dan mengembalikan instance pekerjaan.

kelas publik CustomQuartzJobFactory: IJobFactory

    {

        pribadi hanya baca IServiceProvider _serviceProvider;

        public CustomQuartzJobFactory (IServiceProvider serviceProvider)

        {

            _serviceProvider = serviceProvider;

        }

        public IJob NewJob (TriggerFiredBundle triggerFiredBundle,

        Penjadwal IScheduler)

        {

            var jobDetail = triggerFiredBundle.JobDetail;

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

        }

        public void ReturnJob (pekerjaan IJob) {}

    }

Perhatikan bahwa penerapan ini tidak memanfaatkan penggabungan pekerjaan. Jika Anda ingin menggunakan penggabungan pekerjaan, Anda harus mengubah metode NewJob () dan kemudian mengimplementasikan metode ReturnJob ().

Buat kelas JobMetadata untuk menyimpan metadata pekerjaan Anda

Kami akan menggunakan kelas khusus untuk menyimpan metadata yang terkait dengan pekerjaan, yaitu, Id pekerjaan, nama, dll. Kelas berikut mewakili kelas metadata pekerjaan.

public class JobMetadata

    {

        Public Guid JobId {get; set; }

        public Type JobType {get; }

        string publik JobName {get; }

        string publik CronExpression {get; }

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

        string cronExpression)

        {

            JobId = Id;

            JobType = jobType;

            JobName = jobName;

            CronExpression = cronExpression;

        }

    }

Buat layanan yang dihosting untuk memulai dan menghentikan penjadwal Quartz.NET

Selanjutnya, kita perlu menerapkan layanan yang dihosting. Layanan yang dihosting adalah kelas yang mengimplementasikan antarmuka IHostedService dan memulai penjadwal Quartz. Daftar kode berikut menggambarkan kelas layanan yang dihosting khusus.

kelas publik CustomQuartzHostedService: IHostedService

    {

        private readonly ISchedulerFactory schedulerFactory;

        pribadi hanya baca IJobFactory jobFactory;

        private readonly JobMetadata jobMetadata;

        public CustomQuartzHostedService (ISchedulerFactory

            schedulerFactory,

            JobMetadata jobMetadata,

            IJobFactory jobFactory)

        {

            this.schedulerFactory = schedulerFactory;

            this.jobMetadata = jobMetadata;

            this.jobFactory = jobFactory;

        }

        public IScheduler Scheduler {get; set; }

        public async Task StartAsync (CancellationToken cancellationToken)

        {

            Scheduler = menunggu schedulerFactory.GetScheduler ();

            Scheduler.JobFactory = jobFactory;

            var job = CreateJob (jobMetadata);

            var trigger = CreateTrigger (jobMetadata);

            menunggu Scheduler.ScheduleJob (job, trigger, cancellationToken);

            menunggu Scheduler.Start (cancellationToken);

        }

        public async Task StopAsync (CancellationToken cancellationToken)

        {

            menunggu Scheduler? .Shutdown (cancellationToken);

        }

        private ITrigger CreateTrigger (JobMetadata jobMetadata)

        {

            return TriggerBuilder.Create ()

            .WithIdentity (jobMetadata.JobId.ToString ())

            .WithCronSchedule (jobMetadata.CronExpression)

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

            .Membangun();

        }

        private IJobDetail CreateJob (JobMetadata jobMetadata)

        {

            mengembalikan JobBuilder

            .Create (jobMetadata.JobType)

            .WithIdentity (jobMetadata.JobId.ToString ())

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

            .Membangun();

        }

    }

Potongan kode berikut menunjukkan kode lengkap dari metode ConfigureServices dari kelas Startup.

public void ConfigureServices (layanan IServiceCollection)

{

services.AddControllers ();

services.AddSingleton ();

services.AddSingleton ();

services.AddSingleton ();

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

services.AddHostedService ();

}

Dan hanya itu yang harus Anda lakukan! Saat Anda menjalankan aplikasi, Anda akan mengamati bahwa metode Execute () dari kelas NotificationJob berjalan sekali setiap 10 detik.

Quartz.NET adalah pilihan yang baik untuk mengimplementasikan penjadwal dalam aplikasi Anda. Anda dapat memanfaatkan fitur persistensi di Quartz.NET untuk menyimpan pekerjaan Anda di database seperti SQL Server, PostgreSQL, atau SQLite.