Temporal ve Kuyruklarla Dağıtık Cron Job Tasarımı
Tek bir sunucuda çalışan klasik cron işleri basit ve etkilidir. Ancak modern backend sistemlerinde çoklu pod, otomatik ölçeklenme, rolling deploy ve bölgesel arızalar devreye girdiğinde "her saat başı çalışsın" gereksinimi beklenenden çok daha karmaşık hale gelir. İş aynı anda iki kez çalışabilir, deploy sırasında atlanabilir, üst üste bindirip veri tutarsızlığı oluşturabilir veya başarısız retry fırtınasıyla bağımlı servisleri zorlayabilir.
Bu nedenle dağıtık cron problemini sadece zamanlayıcı olarak değil, dayanıklı bir iş orkestrasyonu problemi olarak ele almak gerekir. Temporal ve kuyruk tabanlı worker modeli bu noktada güçlü bir çözüm sunar. Planlama niyeti kalıcı hale gelir, iş akışı adımları geçmişte tutulur, hata durumlarında yeniden başlatma deterministic şekilde yapılır ve süreç bir makineye bağımlı olmaktan çıkar.
Naif cron yaklaşımının sınırları
Dağıtık ortamlarda sık görülen sorunlar:
- Autoscale sonrası birden fazla instance'ın aynı işi tetiklemesi.
- Restart veya deploy penceresinde planlı çalışmanın kaçırılması.
- Idempotent olmayan handler'ların yan etkileri tekrar uygulaması.
- Uzun süren işin bir sonraki periyotla çakışması.
- Hangi job'ın ne zaman çalıştığının izlenememesi.
Leader election kullanan mimariler bile ağ bölünmesi, heartbeat gecikmesi veya saat kayması gibi durumlarda risk üretebilir. Temel mesele "kim çalıştırıyor?" sorusunun ötesinde, "çalıştırma niyeti dayanıklı mı?" sorusudur.
Temporal ile güvenilir zamanlama
Temporal'da schedule, belirli zaman kurallarına göre workflow başlatır. Workflow ise olay geçmişiyle birlikte kalıcı olarak tutulur. Worker çökse bile akış kaybolmaz; başka bir worker aynı geçmişten devam edebilir. Bu, geleneksel cron'da manuel checkpoint koduyla çözmeye çalıştığımız birçok problemi ortadan kaldırır.
Bu modelin sağladıkları:
- En az bir kez tetikleme garantisine uygun deterministic replay.
- Activity bazlı kontrollü retry ve backoff.
- Workflow ve activity seviyesinde timeout tanımları.
- Kısmi başarısızlıklarda telafi (compensation) akışları.
Özellikle faturalama, mutabakat, raporlama export'u gibi kritik periyodik işlerde bu davranış fark yaratır.
Kuyruk entegrasyonu ve backpressure
Planlı işlerin önemli bir kısmı zamanla kuyruklara fan-out eder. Burada sınırsız mesaj üretmek en sık yapılan hatadır. Zamanlayıcı yükü tek seferde aşağı akış servislere boşaltırsa, kısa süreli bir pik tüm sistemi dengesiz hale getirebilir.
Daha güvenli desen:
- Temporal schedule bir koordinatör workflow başlatır.
- Koordinatör iş listesi çıkarır.
- İşler idempotency anahtarıyla kuyruğa yazılır.
- Tüketiciler visibility timeout ve retry politikasıyla işler.
- Sonuçlar workflow durumuna geri raporlanır.
Bu yaklaşımda zamanlama güvenilir kalır, throughput yönetimi ise tüketici havuzuna ve kuyruk politikasına bırakılır.
Idempotency olmadan güvenilirlik olmaz
Dağıtık sistemlerde "exactly once" çoğu senaryoda teorik bir hedeftir. Pratikte en az bir kez çalıştırma (at-least-once) modelini kabul edip handler'ları idempotent tasarlamak gerekir. Deterministik bir anahtar (tenant + period + taskType) üretip tamamlanan işleri kalıcı depoda işaretlemek, tekrar çalıştırmalarda yan etkiyi engeller.
Dış servis çağrılarında da aynı prensip geçerlidir. Outbound request kimliğini saklamak ve retry sırasında aynı idempotency token'ı kullanmak; çift fatura, mükerrer bildirim ve tekrar muhasebe kaydı gibi kritik hataları önler.
Operasyonel kontrol düzlemi
Kod kadar önemli olan bir diğer katman operasyondur:
- Planlanan ve gerçekleşen job sayıları için dashboard.
- Kaçırılan tetiklemeler ve retry patlamaları için alarm.
- Dead-letter queue görünürlüğü ve replay araçları.
- Incident anında schedule pause/resume prosedürü.
- Elle tetikleme ve atlama işlemleri için audit kayıtları.
Temporal görünürlük API'leri ile kuyruk metrikleri birlikte kullanıldığında ekip şu üç soruya hızlı yanıt verebilir: ne çalışmalıydı, ne çalıştı, şu an nerede blokaj var?
Eski cron'dan geçiş
Büyük bir yeniden yazım şart değil. İlk adımda etkisi yüksek ve hata maliyeti büyük job'ları hedefleyin. Legacy handler'ları idempotent hale getirip Temporal workflow içinden çağırın. Güven arttıkça makine seviyesindeki cron tanımlarını kademeli kaldırın.
Önerilen sıra:
- Handler idempotency'sini tamamla.
- Tetikleme sahipliğini Temporal schedule'a al.
- Kuyruk buffering ve tüketici sınırlarını ekle.
- Gözlemlenebilirlik ve runbook'ları tamamla.
- Legacy cron girişlerini kapat.
Dağıtık cron tasarımı, sadece yeni bir zamanlayıcı seçmek değildir. Zaman tabanlı iş süreçlerini gerçek arıza koşullarında güvenilir hale getirme problemidir. Temporal ve kuyruk odaklı mimari, bu problemi ölçekli sistemlerde yönetilebilir bir mühendislik pratiğine dönüştürür.
İlgili Yazılar
Temporal ile Dayanıklı Workflow Orkestrasyonu
Uzun süren ve birden fazla servise yayılan iş süreçlerini Temporal ile güvenilir, tekrar çalıştırılabilir ve gözlemlenebilir biçimde yönetmenin pratik yol haritası.
Idempotency Key ve Exactly-Once Miti: Dagitik Sistemlerde Gercekci Yaklasim
Retry kaynakli tekrar istekleri guvenli yonetmek, yan etkileri tekillemek ve production'da idempotent write API tasarlamak icin pratik rehber.
WebSocket Horizontal Scaling: Presence, Fan-out ve State Senkronizasyonu
WebSocket tabanli sistemleri yatayda buyuturken node senkronizasyonu, sticky session ve mesaj dagitim stratejileri.