TEMEL
Recurring Jobs (Cron)
Recurring job'lar CRON ifadelerine göre periyodik olarak çalıştırılan görevlerdir.
Karar Rehberi
| Durum | Öneri | Örnek veya gerekçe |
|---|---|---|
| Günlük rapor | Uygun | Her gün 08:00 satış özeti |
| DB temizliği | Uygun | Haftalık soft-delete purge |
| Health check ping | Uygun | Her 5 dk uptime monitor |
| Event-driven tetikleme | Uygun değil: Mesaj kuyruğu kullan | Sipariş gelince stok düş |
| Gerçek zamanlı stream | Uygun değil: Cron uygun değil | WebSocket push |
CRON İfadeleri
| İfade | Anlamı | Hangfire Helper |
|---|---|---|
* * * * * |
Her dakika | Cron.Minutely |
0 * * * * |
Her saat başı | Cron.Hourly |
0 9 * * * |
Her gün 09:00 | Cron.Daily(9) |
0 9 * * 1-5 |
Hafta içi 09:00 | Cron.Daily(9) + custom |
0 0 * * 0 |
Her Pazar gece yarısı | Cron.Weekly |
0 0 1 * * |
Ayın 1'i gece yarısı | Cron.Monthly |
Kullanım
// Program.cs veya Startup'ta
RecurringJob.AddOrUpdate<IDailyReportService>(
"daily-sales-report", // Unique job ID
svc => svc.GenerateAsync(),
Cron.Daily(9), // Her gün 09:00 UTC
new RecurringJobOptions
{
TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Turkey Standard Time")
});
RecurringJob.AddOrUpdate<IDbMaintenanceService>(
"weekly-purge-deleted",
svc => svc.PurgeSoftDeletedAsync(TimeSpan.FromDays(30)),
"0 3 * * 0", // Her Pazar 03:00
new RecurringJobOptions
{
TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Turkey Standard Time"),
MisfireHandling = MisfireHandlingMode.Ignorable
});
// Job'ı kaldır
RecurringJob.RemoveIfExists("daily-sales-report");
// Hemen tetikle (bir sonraki schedule'ı beklemeden)
RecurringJob.TriggerJob("daily-sales-report");MisfireHandling
Uygulama kapalıyken bir recurring job'ın zamanı geçerse ne olur?
| Mod | Davranış | Kullanım |
|---|---|---|
Relaxed (varsayılan) |
Kaçırılan job çalıştırılır | Rapor, bildirim — "geç de olsa çalışsın" |
Ignorable |
Kaçırılan job atlanır | Monitoring ping — eski veri anlamsız |
Strict |
Kaçırılan her instance çalıştırılır | Fatura kesilmesi — hiçbiri atlanmamalı |
TimeZone uyarısı: Varsayılan UTC'dir. Türkiye'de sabah 9'da çalışmasını istiyorsanız mutlaka TimeZone parametresi verin. Aksi halde UTC 09:00 = Türkiye 12:00 olur.
Eş zamanlı çalışma riski: Recurring job'un bir önceki instance'ı henüz bitmeden yeni instance tetiklenebilir (uzun süren job + kısa cron aralığı). Önlemek için [DisableConcurrentExecution(timeoutInSeconds: 300)] attribute'ü ekleyin — bu, aynı job'ın aynı anda birden fazla instance'ının çalışmasını engeller. (Core — ücretsiz)
Ace alternatifi: Daha gelişmiş concurrency control istiyorsanız (dinamik resource-based locking, semaphore ile N-concurrent limit, rate limiting): Hangfire.Throttling paketi (Ace lisansı) → [Mutex("job-key")], [Semaphore("pool", limit: 5)]. Fark: DisableConcurrentExecution distributed lock tutar (timeout'a kadar bloklar), [Mutex] ise job'u reschedule eder (worker'ı bloklamaz).
Örnek: Bir SaaS uygulamasında her tenant için ayrı recurring job tanımlanır: daily-report-tenant-{tenantId}. Böylece her müşterinin raporu kendi timezone'unda doğru saatte oluşturulur. Tenant silindiğinde RemoveIfExists ile job da temizlenir.