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

Semasa mengerjakan aplikasi web, anda sering kali perlu melaksanakan tugas-tugas tertentu di latar belakang. Dalam beberapa kes, ini akan menjadi tugas yang harus dilaksanakan pada selang waktu yang telah ditentukan.

Quartz.NET adalah port .NET sumber terbuka dari kerangka kerja penjadualan pekerjaan Java yang popular. Telah digunakan untuk waktu yang lama dan memberikan sokongan yang sangat baik untuk bekerja dengan ekspresi Cron. Anda boleh mengetahui lebih lanjut mengenai Quartz.NET dari catatan terdahulu di sini. 

Artikel ini memaparkan perbincangan mengenai bagaimana kita dapat bekerjasama dengan Quartz.NET di ASP.NET Core untuk menjadualkan pekerjaan latar belakang.

Untuk bekerja dengan contoh kod yang disediakan dalam artikel ini, anda harus memasang Visual Studio 2019 di sistem anda. Sekiranya anda belum mempunyai salinannya, anda boleh memuat turun Visual Studio 2019 di sini. 

Buat projek ASP.NET Core API

Pertama, mari buat projek Teras ASP.NET di Visual Studio. Dengan mengandaikan Visual Studio 2019 dipasang di sistem anda, ikuti langkah-langkah yang digariskan di bawah untuk membuat projek Teras ASP.NET baru di Visual Studio.

  1. Lancarkan ID Studio Visual.
  2. Klik pada "Buat projek baru."
  3. Di tetingkap "Buat projek baru", pilih "Aplikasi Web Inti ASP.NET" dari senarai templat yang dipaparkan.
  4. Klik Seterusnya.
  5. Di tetingkap "Konfigurasikan projek baru anda" yang ditunjukkan di sebelah, tentukan nama dan lokasi untuk projek baru.
  6. Klik Buat.
  7. Di tetingkap "Buat Aplikasi Web Teras ASP.NET Baru", pilih .NET Core sebagai jangka masa dan ASP.NET Core 2.2 (atau lebih baru) dari senarai lungsur di bahagian atas. Saya akan menggunakan ASP.NET Core 3.0 di sini.
  8. Pilih "API" sebagai templat projek untuk membuat aplikasi ASP.NET Core API baru. 
  9. Pastikan bahawa kotak centang "Aktifkan Docker Support" dan "Configure for HTTPS" tidak dicentang kerana kami tidak akan menggunakan fitur tersebut di sini.
  10. Pastikan bahawa Pengesahan ditetapkan sebagai "Tanpa Pengesahan" kerana kami juga tidak akan menggunakan pengesahan.
  11. Klik Buat. 

Ini akan membuat projek ASP.NET Core API baru di Visual Studio. Pilih folder penyelesaian Pengawal di tetingkap Penyelesaian Penyelesaian dan klik "Tambah -> Pengawal ..." untuk membuat pengawal baru bernama DefaultController.

Seterusnya, untuk bekerjasama dengan Quartz, anda harus memasang pakej Quartz dari NuGet. Anda boleh melakukannya sama ada melalui pengurus pakej NuGet di dalam Visual Studio 2019 IDE, atau dengan melaksanakan perintah berikut di konsol pengurus pakej NuGet:

Pasang-Kuarsa Pakej

Pekerjaan, pencetus, dan penjadual Quartz.NET 

Tiga konsep utama dalam Quartz.NET adalah pekerjaan, pencetus, dan penjadual. Pekerjaan mengandungi kod untuk melaksanakan tugas atau tugas yang akan dilakukan. Pekerjaan diwakili oleh kelas yang menerapkan antara muka IJob. Pencetus digunakan untuk menentukan jadual dan perincian pekerjaan yang lain. Anda boleh memanfaatkan pencetus untuk menentukan bagaimana tugas itu harus dilaksanakan. Penjadual adalah komponen yang bertanggungjawab untuk mengundi dan melaksanakan pekerjaan berdasarkan jadual yang telah ditentukan.

Buat penjadual menggunakan Quartz.NET

Perlu diingatkan bahawa anda dapat memiliki banyak penjadwalan dalam aplikasi. Walau bagaimanapun, kami hanya akan menggunakan satu penjadual di sini demi kesederhanaan. Coretan kod berikut menggambarkan bagaimana anda boleh membuat instance penjadual.

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

Setelah penjadual dibuat, anda dapat menggunakan kod berikut dalam metode ConfigureServices dari fail Startup.cs untuk menambahkan contoh penjadual sebagai layanan tunggal.

perkhidmatan.AddSingleton (penjadual);

Mulakan dan hentikan penjadual menggunakan Quartz.NET

Untuk memulakan dan menghentikan penjadual, kami akan memanfaatkan perkhidmatan hosting. Untuk melakukan ini, anda perlu membuat kelas yang menerapkan antara muka IHostingService seperti yang ditunjukkan dalam coretan kod yang diberikan di bawah.

kelas awam CustomQuartzHostedService: IHostedService

{

        IScheduler _scheduler yang dibaca secara peribadi;

        public CustomQuartzHostedService (penjadual IScheduler)

        {

            _scheduler = penjadual;

        }

        async awam Tugas StartAsync (PembatalanToken pembatalanToken)

        {

            tunggu _scheduler?. Mulakan (pembatalanToken);

        }

        async awam Task StopAsync (PembatalanToken pembatalanToken)

        {

            tunggu _scheduler?. Shutdown (pembatalanToken);

        }

 }

Perhatikan bahawa anda harus mendaftarkan perkhidmatan yang dihoskan dalam koleksi perkhidmatan dalam kaedah ConfigureServices menggunakan potongan kode yang diberikan di bawah.

perkhidmatan.AddHostedService ();

Berikut adalah kaedah ConfigureServices yang dikemas kini untuk rujukan anda:

kekosongan awam ConfigureServices (perkhidmatan IServiceCollection)

{

    perkhidmatan.AddControllers ();

    var scheduler =

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

    perkhidmatan.AddSingleton (penjadual);

    perkhidmatan.AddHostedService ();

}

Buat pekerjaan menggunakan Quartz.NET

Seperti yang saya katakan sebelumnya, pekerjaan adalah kelas yang menerapkan antara muka IJob dan mengandungi kaedah Execute (). Kaedah Execute () menerima contoh jenis IJobExecutionContext.

Coretan kod berikut menggambarkan kelas pekerjaan yang mengandungi kaedah Execute () asynchronous juga. Kaedah ini mengandungi kod yang sesuai dengan tugas yang harus dilakukan oleh pekerjaan anda.

[LarangPerundanganConturrentExecution]

kelas awam PemberitahuanJob: IJob

    {

        ILogger _logger peribadi baca;

        public NotificationJob (ILogger logger)

        {

            _logger = pembalak;

        }

        Jalankan Tugas awam (konteks IJobExecutionContext)

        {

            _logger.LogInformation ("Hello world!");

            mengembalikan Task.CompletedTask;

        }

    }

Buat kilang pekerjaan menggunakan Quartz.NET

Kilang pekerjaan adalah kelas yang mewarisi antara muka IJobFactory dan melaksanakan kaedah NewJob () dan ReturnJob (). Coretan kod berikut dapat digunakan untuk membuat kelas kilang yang dapat membuat dan mengembalikan instance pekerjaan.

kelas awam CustomQuartzJobFactory: IJobFactory

    {

        IServiceProvider _serviceProvider yang dibaca secara peribadi;

        awam CustomQuartzJobFactory (IServiceProvider serviceProvider)

        {

            _serviceProvider = serviceProvider;

        }

        awam IJob NewJob (TriggerFiredBundle triggerFiredBundle,

        Penjadual IScheduler)

        {

            var jobDetail = triggerFiredBundle.JobDetail;

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

        }

        kekosongan awam ReturnJob (pekerjaan IJob) {}

    }

Perhatikan bahawa pelaksanaan ini tidak memanfaatkan penyatuan pekerjaan. Sekiranya anda ingin menggunakan penyatuan pekerjaan, anda harus mengubah kaedah NewJob () dan kemudian melaksanakan kaedah ReturnJob ().

Buat kelas JobMetadata untuk menyimpan metadata pekerjaan anda

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

JobMetadata kelas awam

    {

        JobId Panduan awam {dapatkan; menetapkan; }

        jenis awam Jenis Pekerjaan {get; }

        rentetan awam JobName {get; }

        rentetan awam CronExpression {get; }

        JobMetadata awam (Id Panduan, Jenis JobType, string jobName,

        rentetan cronExpression)

        {

            JobId = Id;

            Jenis pekerjaan = Jenis pekerjaan;

            JobName = nama kerja;

            CronExpression = cronExpression;

        }

    }

Buat perkhidmatan yang dihoskan untuk memulakan dan menghentikan penjadual Quartz.NET

Seterusnya, kita perlu melaksanakan perkhidmatan yang dihoskan. Perkhidmatan yang dihoskan adalah kelas yang menerapkan antara muka IHostedService dan memulakan penjadual Quartz. Penyenaraian kod berikut menggambarkan kelas perkhidmatan yang dihoskan khas.

kelas awam CustomQuartzHostedService: IHostedService

    {

        jadual penjadual persendirian ISchedulerFactory schedulerFactory;

        pekerjaan peribadi IJobFactory readonlyFactory;

        kerja peribadi JobMetadata kerjaMetadata;

        awam CustomQuartzHostedService (ISchedulerFactory

            kilang penjadual,

            JobMetadata jobMetadata,

            Pekerjaan IJobFactory)

        {

            ini.schedulerFactory = schedulerFactory;

            ini.jobMetadata = jobMetadata;

            ini.jobFactory = jobFactory;

        }

        Penjadual IScheduler awam {dapatkan; menetapkan; }

        async awam Tugas StartAsync (PembatalanToken pembatalanToken)

        {

            Penjadual = tunggu penjadualFactory.GetScheduler ();

            Penjadual.JobFactory = jobFactory;

            var job = CreateJob (jobMetadata);

            var trigger = CreateTrigger (jobMetadata);

            tunggu Scheduler.ScheduleJob (tugas, pencetus, pembatalanToken);

            tunggu Scheduler.Start (pembatalanToken);

        }

        async awam Task StopAsync (PembatalanToken pembatalanToken)

        {

            tunggu Penjadual? .Patutan (pembatalanToken);

        }

        PrivateTrigger ITrigger (JobMetadata jobMetadata)

        {

            kembali TriggerBuilder.Create ()

            .WithIdentity (jobMetadata.JobId.ToString ())

            .WithCronSchedule (jobMetadata.CronExpression)

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

            .Bangun ();

        }

        IJobDetail CreateJob peribadi (JobMetadata jobMetadata)

        {

            kembalikan JobBuilder

            .Ciptakan (jobMetadata.JobType)

            .WithIdentity (jobMetadata.JobId.ToString ())

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

            .Bangun ();

        }

    }

Coretan kod berikut menunjukkan kod lengkap kaedah ConfigureServices kelas Startup.

kekosongan awam ConfigureServices (perkhidmatan IServiceCollection)

{

perkhidmatan.AddControllers ();

perkhidmatan.AddSingleton ();

perkhidmatan.AddSingleton ();

perkhidmatan.AddSingleton ();

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

perkhidmatan.AddHostedService ();

}

Dan itu yang mesti anda buat! Semasa anda menjalankan aplikasi, anda akan melihat bahawa kaedah Execute () dari kelas NotificationJob berjalan 10 hari sekali.

Quartz.NET adalah pilihan yang baik untuk melaksanakan penjadwalan dalam aplikasi anda. Anda boleh memanfaatkan ciri kegigihan di Quartz.NET untuk menyimpan pekerjaan anda dalam pangkalan data seperti SQL Server, PostgreSQL, atau SQLite juga.