Kuarsa dalam ASP.NET Core

pengantar


Saya tahu bahwa ada banyak artikel dan beberapa tutorial tentang hal ini, saya bahkan tidak berbicara tentang dokumentasi resmi, tetapi ketika mengerjakan proyek terbaru saya, saya menemukan masalah yang sangat menarik, yang tidak banyak disebutkan. Hari ini kita akan berbicara tentang masalah menggunakan Ketergantungan Injeksi dan Kuarsa dalam proyek Core ASP.NET.

Semuanya dimulai dengan fakta bahwa saya tidak berpikir bahwa masalah dapat muncul dan saya akan segera mengatakan bahwa saya mencoba menggunakan berbagai pendekatan: Saya menambahkan semua kelas yang termasuk dalam layanan Kuarsa dan menggunakannya melalui DI - oleh (tetapi tidak sepenuhnya, ternyata nanti), saya mencoba menambahkan HostedService - tidak berhasil (pada akhirnya saya akan melampirkan beberapa tautan bagus ke artikel bermanfaat tentang bekerja dengan Quartz) dan sebagainya. Saya sudah berpikir bahwa saya memiliki masalah dengan pemicunya - tidak juga. Dalam artikel singkat ini saya akan mencoba membantu mereka yang mungkin memiliki masalah yang sama dan berharap solusi saya akan membantu mereka dalam pekerjaan mereka di masa depan. Di akhir pendahuluan, saya ingin menambahkan bahwa saya akan sangat berterima kasih jika di komentar mereka yang mengenal baik teknologi memberikan beberapa saran yang akan membantu meningkatkan apa yang telah saya usulkan.

Kuarsa


Buat proyek (atau ambil yang sudah jadi - tidak masalah) dan tambahkan dua folder dan beberapa kelas ke dalamnya:

Kuarsa
--DataJob.cs
--DataScheduler.cs
--JobFactory.cs
Pekerja
--EmailSender
--IEmailSender

Dalam antarmuka IEmailSender, yang akan berfungsi sebagai contoh , buat satu metode untuk mengirim surat ke surat:

public interface IEmailSender
    {
        Task SendEmailAsync(string email, string subject, string message);
    }

Sekarang kami menjelaskan kelas yang akan mengimplementasikan antarmuka ini:

public class EmailSender : IEmailSender
    {
        
        public Task SendEmailAsync(string email, string subject, string message)
		{
			var from = "****@gmail.com";
			var pass = "****";
            SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
			client.DeliveryMethod = SmtpDeliveryMethod.Network;
			client.UseDefaultCredentials = false;
			client.Credentials = new System.Net.NetworkCredential(from, pass);
			client.EnableSsl = true;
			var mail = new MailMessage(from, email);
			mail.Subject = subject;
			mail.Body = message;
			mail.IsBodyHtml = true;
			return client.SendMailAsync(mail);
		}
    }

Sekarang kita menggambarkan kelas-kelas DataJob.cs, DataScheduler.cs, JobFactory.cs. Kelas DataJob akan mengimplementasikan antarmuka IJob.

 public class DataJob : IJob
    {
        private readonly IServiceScopeFactory serviceScopeFactory;

        public DataJob(IServiceScopeFactory serviceScopeFactory)
        {
            this.serviceScopeFactory = serviceScopeFactory;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            using (var scope = serviceScopeFactory.CreateScope())
            {
                var emailsender = scope.ServiceProvider.GetService<IEmailSender>();
                
                 await emailsender.SendEmailAsync("example@gmail.com","example","hello")
            }
        }
    }

Seperti yang kita lihat bidang tipe IServiceScopeFactory, kita akan mendapatkan layanan langsung dari Startup. Pendekatan inilah yang membantu saya memecahkan masalah saya, maju dan jelaskan kelas DataScheduler di mana kami akan menambahkan pekerjaan dan pemicu di Sheduler dari kuarsa itu sendiri:

public static class DataScheduler
    {
        
        public static async void Start(IServiceProvider serviceProvider)
        {
            IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler();
            scheduler.JobFactory = serviceProvider.GetService<JobFactory>();
            await scheduler.Start();

            IJobDetail jobDetail = JobBuilder.Create<DataJob>().Build();
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("MailingTrigger", "default")
                .StartNow()
                .WithSimpleSchedule(x => x
                .WithIntervalInMinutes(1)
                .RepeatForever())
                .Build();

            await scheduler.ScheduleJob(jobDetail, trigger);
        }

Dan sekarang kelas JobFactory, yang mengimplementasikan antarmuka IJobFactory:

 public class JobFactory : IJobFactory
    {
        protected readonly IServiceScopeFactory serviceScopeFactory;

        
        public JobFactory(IServiceScopeFactory serviceScopeFactory)
        {
            this.serviceScopeFactory = serviceScopeFactory;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            using (var scope = serviceScopeFactory.CreateScope())
            {
                var job = scope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob;
                return job;
            }
            
        }

        public void ReturnJob(IJob job)
        {
           //Do something if need
        }
    }

Seperti yang Anda lihat, saya, pada kenyataannya, mendapatkan semua dependensi langsung dari serviceScopeFactory. Semuanya hampir siap, masih harus mengubah kelas Program:

public class Program
    {
        public static void Main(string[] args)
        {
            var host = BuildWebHost(args);
            using (var scope = host.Services.CreateScope())
            {
                var serviceProvider = scope.ServiceProvider;
                try
                {
                    DataScheduler.Start(serviceProvider);
                }
                catch (Exception)
                {
                    throw;
                }
            }
            host.Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
           WebHost.CreateDefaultBuilder(args)
               .UseStartup<Startup>()
               .Build();
    }

Dan tambahkan yang berikut ini ke Startup dalam metode ConfigureServices:

   services.AddTransient<JobFactory>();
   services.AddScoped<DataJob>();
   services.AddScoped<IEmailSender,EmailSender>();

Selesai Sekarang ketika Anda memulai aplikasi, kami membuat tugas yang akan diaktifkan setiap menit. Nilai dapat diubah dalam DataScheduler.Start (juga dapat ditentukan dalam detik, jam atau menggunakan CRON). Untuk setiap tugas baru dengan pendekatan ini, Anda perlu membuat kelas baru yang akan mengimplementasikan IJob dan mendaftarkan tugas DataScheduler baru. Anda juga dapat membuat kelas Penjadwal terpisah untuk tugas baru.

Saya akan sangat senang jika saya dapat membantu seseorang, tetapi di sini ada beberapa artikel bermanfaat tentang Quartz dan penggunaannya:

Membuat layanan yang di-hosting dengan Quartz.NET dengan ASP.NET Core
Menggunakan layanan scoped di dalam layanan yang di-hosting dengan Quartz.NET dengan ASP.NET Core

Source: https://habr.com/ru/post/undefined/


All Articles