Teknik Muhabbetler #7 (Cron Job,IHostedService, EasyCronJob)

“İnsanlar ne yaptığınızla değil neden yaptığınızla ilgilenir.”
Teknik muhabbetler serisinin bu yazısına son zamanlarda okuduğum ve mesleğe karşı bakış açımı değiştiren “Neden İle Başla” kitabından bir cümle ile başlamak istedim. Bu cümlede geçen insanlar kelimesi oldukça soyut. Kim bu insanlar? Eşimiz, ailemiz, müşterilerimiz, takım arkadaşlarımız bazen ise kendimiz. Her ne olursa olsun bu insanlara ilham vermek veya bakış açılarını zenginleştirmek istiyorsanız onlara “Neden” sorusunun önemini anlatın. Yeter mi? Hayır. Sizler de her zaman “Neden” sorusunun önemini bilen insanlarla ömrümünüzü geçirin. Bu yazıda teknik bir konu üzerinde neden sorusunu soracağız. Bu soruyu sormakla kalmayıp bir çözüm önerisi sunmaya çalışacağız. Bu kadar felsefe yeter. Hadi başlayalım. 🎉

Sektörde bir BackEnd Developer olarak çalışıyorsanız mutlaka CronJob, ScheduledJob veya RecurringJob kavramlarını duymuşsunuzdur. Kısaca özetlemek gerekirse “Bir görevi uygulamaya gelen isteklerden bağımsız bir şekilde tamamlayan zamanlanmış iş parçacıklarıdır.” diyebiliriz.
Örneğin;
- Doğum tarihi bugün olan kullanıcıların hepsine email gönder.
- Bir gün önce gerçekleşen başarılı siparişlerin toplam tutarını hesapla.
- Gün içinde randevusu olan kullanıcılara hatırlatma bildirimi gönder.
vb.
Bu tarz işlerde eğer .Net ekosistemine hakim bir geliştiriciyseniz aklınıza hemen Hangfire veya Quartz kütüphaneleri gelir. Ben günlük hayatta genellikle Hangfire kullanıyorum. Tabii birbirlerine göre avantajları/dezavantajları vardır ancak bu yazının konusu bu iki kütüphaneyi karşılaştırmak değil.

.Net Core 2.1'in piyasaya sürülmesiyle arka plan işlerimizi IHostedService üzerinde barındırabiliriz. Hadi öğrenelim. 🧐

Cron işlerimizi tanımlarken kullandığımız Cron Expression olarak isimlendirilen ifadeleri öğrenmekte fayda var. Konuyu çok uzatmadan ilgili wikepedia linkini buraya bırakıyorum. Oluşturduğumuz cron ifadelerinin ne anlama geldiğini öğrenmek için şu siteyi ziyaret edebilirsiniz.

Oluşturduğumuz cron ifadelerini parse etmek ve kullanmak için Hangfire tarafından geliştirilmiş Cronos kütüphanesini kullanacağız.
Cron işlerinin tanımlanması ve çalıştırılması için bir base sınıfa ihtiyacımız var. Daha sonra bu base sınıfı kullanıp kendi cron işlerimizi tanımlayacağımız için Abstract class yapmakta fayda var. Sanırım Interface ile Abstract arasındaki farkları herkes biliyordur. 🧐

Biraz kod üzerinden konuşalım.✨

CronJobService isimli bir abstract class oluşturduk ve constructor içerisinde cron ifademizi ve TimeZoneInfo bilgimizi aldık. Cronos tam bu aşamada işimizi kolaylaştırıyor. Cronos yardımıyla string olarak gelen değeri gerçek bir cron ifadesine dönüştürebiliyoruz. Cron ifademizi oluşturduktan sonra System.Timers üzerinden gelen Timer yapısını kullanarak ilgili cron ifadesinden ürettiğimiz zaman dilimi için cron işimizi schedule ediyoruz.

Timer System.ComponentModel inheritance alan bir sınıf. Component sınıfının ise IDisposible arayüzünden türediğini görüyoruz. Bu sebeple işimiz bittikten sonra timer nesnemizi dispose etmek daha scalable bir uygulama yapmamızı sağlayacaktır.
Timer yani zamanlayıcı aracılığıyla oluşturduğumuz cron ifadesinin çalışma anını yakalayabiliyoruz. Cron işini çalıştırdıktan sonra tekrarlanabilmesi için yeniden schedule etmek gerektiğini unutmayalım.

IHostedService arayüzünü unutmayalım tabii. Uygulamamız çalıştığı anda StartAsync yordamı çalışır ve ilgili cron işini schedule eder. StopAsync ise tam tersi timer nesnemizi dispose ederek GC için uygun olacak şekilde serbest bırakır.

Artık CronJobService soyut sınıfımızı kullanarak cron işlerimizi oluşturabiliriz. Endişelenmeyin bu yapıları sizin için bir kütüphane haline getirdim. 🎉 EasyCronJob ile yapmanız gerekenler kendi cron işinizi oluşturmak ve Startup.cs içerisinde istediğiniz cron değerini ayarlamak.
Hadi EasyCronJob kütüphanesini yakından tanıyalım. 💡🧐

Öncelikle Nuget üzerinden EasyCronJob kütüphanesini uygulamamıza indirelim.
Install-Package EasyCronJob.Core -Version 1.0.0
Kendi cron işinizi tanımlayın. Tanımladığınız işin gövde kısmını DoWork yordamına ekleyebilirsiniz. Ek olarak StartAsync ve StopAsync yordamları içine işin başladığını ve bittiğini görmek için log ekleyebilirsiniz.

Örnek olması için Console üzerine log yazan bir cron işi tanımladım.

Artık yapmamız gereken tek şey Startup.cs içerisinde cron işimizi tanımlamak.

Tanımladığım cron ifadesinin ne anlamına geldiğini yazının başında paylaştığım crontab.guru sitesinden görebilirsiniz.

Örnekte bir tane cron işi oluşturup çalıştırdım ancak siz istediğiniz kadar cron işi tanımlayabilirsiniz. Unutmamanız gereken konu ise her bir cron işimizi Startup.cs üzerinde tanımlamanız gerektiğidir.

Kapanış bölümünde ise neden EasyCronJob kullanalım sorusuna yanıt oluşturmaya çalışacağım ve son olarak EasyCronJob kütüphanesinin cyclomatic complexity değerlerini sizlerle paylaşacağım.

Ben günlük hayatımda background işler için Hangfire tercih ediyorum. Sağladığı arayüz ve database üzerinde işlerin tanımlanması benim işlerimi çok rahatlatıyor. Hatta microservice mimarisinde concurrency sorununu bile çözüyor. Hangfire üzerinde tanımladığınız işler fail olduğunda hangfire default on kere bu işi tekrar deniyor. Tabii siz isterseniz bu değeri değiştirebiliyorsunuz. Fail olan işlerinizi dashboard üzerinden tekrar çalıştırabiliyorsunuz. Yani anlayacağınız hangfire background işleri yönetmekte oldukça başarılı. Henüz paralı sürümünü kullanacak kadar zengin olmadım ama free özelliklerinin yanı sıra ücretli özellikleri de hayatımızı oldukça kolaylaştırıyor.
Tabii hiç bir üretici “benim yoğurdum ekşi demez” 😊
Bu kütüphane hangfire veya Quartz gibi advance kütüphanelerle karşılaştırılamaz. Hafta sonu projelerinde veya hızlı ve basit olmasını istediğiniz cron işlerinizde kullanabiliriniz. EasyCronJob sadece IHostedService üzerinden bize sağlanan iki yordamı evirip çevirip kolayca cron işlerimizi tanımlayabileceğimiz bir arayüz sunuyor.

Meraklısı için code map🗺

Meraklısı için code metrics

Solution Developer — I want to change the world, give me the source code.

Medium independent DevOps publication. Join thousands of aspiring developers and DevOps enthusiasts