Asp.Net Mvc ve Zamanlanmış Görevler (Scheduled Task)

Öncelikle sorun hakkında biraz konuşalım. Üzerinde çalıştığım projede belli zamanlarda email göndermesi gerekiyor. İlk olarak bir uygulama yapayım diye düşündüm, sunucu üzerinde çalışsın ve zamanlanmış olarak email göndersin. Ondan sonra kapanma riski olduğunu daha doğrusu sunucu yeniden başlatıldığı zaman uygulama çalışmaz diye düşünüp servis olabilir diye düşündüm. Ama bu da kulağı tersten tutmak gibi geldi. Daha basit ve daha pratik bir çözüm olması gerekiyordu. Sonuçta gelişmiş(mature) bir yapı üzerinde çalışıyoruz ve bunun mutlaka farklı bir çözümleri olması lazım değil mi? 

İnternette biraz araştırma yaptığım zaman tam aradığım gibi olmasa da biraz üzerinde çalışarak kullanışlı bir yöntem olduğunu fark ettim. HttpContext.Current.Cache.Add fonksiyonu ile eklediğimiz bir nesnenin süresi dolduğu zaman onRemoveCallback delegate ile bize bildirebiliyor. Yani şöyle söyleyeyim kendiniz bir tane nesne ekleyip ona TimeSpan ile ne kadar süre sonra süresinin dolacağını söyleyip birde nesne silindiği zaman nereye bilgi verileceğini ayarlarsanız alın işte size zamanlanmış görevler :) Şu ana kadar bir sorun yok değil mi? Bunu biraz daha ilerletelim her 10 dakikada bir sistem içerisinde ki mesajları yada uyarıları kaydetmesini yapalım. Bunda sürekli olarak cache‘e yeni nesne ekleyip bunu sildirmemiz lazım, bunu da kendini sürekli çağıran (recursive) fonksiyon ile yapabiliriz. Ama burada da bir sorun var. HttpContext ne yazık ki sadece uygulama başladığı yada istemci tarafından istek gönderilince HttpContext.Current dolduruluyor. Yani recursive olarak çağırdığımız zaman ne yazık ki null olacak ve exception fırlatacak :) Ama bunu da çözümü var HttpContext.Current yerine HttpRuntime.Cache kullanırsanız hiç bir şekilde sorun yaşamazsnız :)

Şimdi bütün bu kadar bilgi yeterli. Buna yönelik yaptığım küçük bir yapıyı da sizinle paylaşmak istiyorum.

Uygulama başladığı zaman belli bir klasörde ki DLL’ler taranacak ve içlerinde zamanlanmış görev olan nesneler yaratılıp sisteme dahil edilecek. Bunun için oluşturacağımız nesnenin net özelliklerini çıkartmamız lazım, yani yapısını.

    public interface IJob : IDisposable
{
void Init();
string ConfigFileName { get; }
bool Executing { get; }
string JobName { get; }
JobExecuteResult Execute();
TimeSpan[] ExecuteTimes();
}

Şöyle bir durum var, bu işin belli bir ayar dosyasının da olması gerekiyor. Yapılacak işin detayı gibi düşünebiliriz. Bunu da şöyle yapabiliriz

   public interface IJob : IJob where T : IJobConfig, new()
{
T Config { get; }
}
public interface IJobConfig
{

}

Bunlar şu an için yeterli. Birde test amaçlı olarak iş sınıfı ve ayar sınıfını oluşturalım.

public class DummyConfig : IJobConfig
{
public TimeSpan Sure { get; set; }

public DummyConfig()
{
this.Sure = new TimeSpan(0, 10, 0);
}
}

public class DummyJob : JobBase
{
public override void Dispose()
{

}

public override JobExecuteResult Execute()
{
/*

NE YAPMAK İSTİYORSAN YAP

*/
new JobExecuteResult
{
Success = true
};
}

public override TimeSpan[] ExecuteTimes()
{
return new[] {this.Config.Sure};
}
}

JobExecuteResult ve JobBase sınıflarını boşverin şimdilik. ExecuteTimes ile ne sıklıkla iş çalıştırılacağını belirliyoruz, Execute ile de işin yapılmasını sağlıyoruz. Şimdi birde bunları çalıştıracak ve kontrol edecek birşeyler lazım değil mi?

    public interface IJobExecuter : IDisposable
{
void StartJobs();
void StartJob(IJob job);
JobExecuteResult ForceExecute(IJob job);
}

Bu şekilde bir sınıf işimizi görür herhalde. Bundan sonrası için çok fazla anlatmaya gerek yok.

Son olarak global.asax içerisine aşağıda ki kodu eklemeniz gerekiyor.

protected void Application_Start()
{
IJobExecuter jobExecuter = new JobExecuter(new JobProvider());
jobExecuter.StartJobs();
}

Şu an için burada paylaşmak için ufak bir iki test kodu yazdım ama yeterli değil. Eğer bir sorunuz olursa yada bir sıkıntı çıkarsa yardımcı olurum.

Buyurun bu da indirme linki.

Facebook Comments

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir