12 Ağu 2025·6 dk okuma

Bildirimlerde güvenilirlik: tetikleyiciler vs arka plan işçileri

Tetikleyiciler ile arka plan worker'ları hangi durumlarda bildirimler için daha güvenli olduğunu, yeniden denemeler, transaction sınırları ve çift gönderimi önleme konularında pratik rehberle öğrenin.

Bildirimlerde güvenilirlik: tetikleyiciler vs arka plan işçileri

Gerçek uygulamalarda bildirim teslimatı neden bozulur

Bildirimler basit gibi görünür: bir kullanıcı bir şey yapar, sonra bir e-posta veya SMS gider. Gerçek başarısızlıkların çoğu zamanlama ve çoğaltma ile ilgilidir. Mesajlar veri gerçekten kaydedilmeden önce gönderilir veya kısmi bir hata sonrasında iki kez gönderilir.

“Bildirim” birçok şeyi kapsar: e-posta makbuzları, SMS tek seferlik kodlar, push bildirimleri, uygulama içi mesajlar, Slack veya Telegram pingleri ya da başka bir sisteme webhook. Ortak sorun hep aynı: veritabanı değişikliğini uygulamanızın dışındaki bir şeyle koordine etmeye çalışıyorsunuz.

Dış dünya düzensizdir. Sağlayıcılar yavaş olabilir, zaman aşımı döndürebilir veya isteği kabul edip uygulamanız başarı yanıtını hiç almayabilir. Kendi uygulamanız istek sırasında çökebilir veya yeniden başlayabilir. Hatta “başarılı” gönderimler altyapı yeniden denemeleri, worker yeniden başlatmaları veya kullanıcının tekrar butona basması nedeniyle yeniden çalıştırılabilir.

Kırık bildirim teslimatının yaygın nedenleri arasında ağ zaman aşımı, sağlayıcı arızaları veya rate limitleri, hatalı anda uygulama yeniden başlatmaları, aynı gönderim mantığını benzersiz bir korunma olmadan tekrar çalıştıran yeniden denemeler ve veritabanı yazımı ile dış gönderimin tek bir birleşik adım olarak tasarlandığı tasarımlar bulunur.

İnsanlar “güvenilir bildirim” dediğinde genellikle iki şeyden birini kastediyorlar:

  • tam olarak bir kez teslim (exactly once), veya
  • en azından hiçbir zaman çoğaltma olmaması (çoğaltmalar genelde gecikmeden daha kötüdür).

Hem hızlı hem de kusursuz güvenli olmak zordur, bu yüzden hız, güvenlik ve karmaşıklık arasında tavizler verirsiniz.

Bu yüzden tetikleyiciler ile arka plan worker'ları seçimi sadece bir mimari tartışma değildir. Bu, ne zaman bir gönderime izin verildiği, hataların nasıl yeniden denendiği ve bir şey ters gittiğinde e-posta veya SMS çoğaltmalarının nasıl önlendiği ile ilgilidir.

Tetikleyiciler ve arka plan worker'ları: ne anlama gelir

Tetikleyicilerle worker'ları karşılaştırırken aslında bildirim mantığının nerede çalıştığını ve bunu tetikleyen eyleme ne kadar sıkı bağlı olduğunu karşılaştırıyorsunuz.

Tetikleyici “X olduğunda şimdi yap” demektir. Birçok uygulamada bu, aynı web isteği içinde bir e-posta veya SMS göndermek anlamına gelir. Tetikleyiciler veritabanı seviyesinde de olabilir: bir satır eklendiğinde veya güncellendiğinde veritabanı trigger'ı otomatik çalışır. Her iki tür de anlık hissi verir ama onları tetikleyen şeyin zamanlamasını ve sınırlarını miras alırlar.

Arka plan worker'ı ise “yakında yap, ama ön planda değil” demektir. Kuyruktan işler çeken ve bunları tamamlamaya çalışan ayrı bir süreçtir. Ana uygulamanız ne olması gerektiğini kaydeder, sonra hızlıca döner; worker ise e-posta veya SMS sağlayıcısını çağırmak gibi daha yavaş ve hata yapmaya eğilimli işleri halleder.

Bir “iş” worker'ın işlediği iş birimidir. Genellikle kime bildirileceği, hangi şablon, hangi verilerin doldurulacağı, mevcut durum (queued, processing, sent, failed), kaç deneme yapıldığı ve bazen planlı zaman gibi bilgileri içerir.

Tipik bir bildirim akışı şöyledir: mesaj detaylarını hazırlarsınız, bir iş kuyruğa atarsınız, sağlayıcı üzerinden gönderirsiniz, sonucu kaydedersiniz, sonra yeniden deneme, durdurma veya birini uyarmaya karar verirsiniz.

Transaction sınırları: ne zaman gerçekten güvenlidir gönderim

Transaction sınırı, “kaydetmeyi denedik” ile “gerçekten kaydedildi” arasındaki çizgidir. Veritabanı commit edilene kadar değişiklik geri alınabilir. Bu önemli çünkü bildirimleri geri almak zordur.

Commit'ten önce e-posta veya SMS gönderirseniz, hiç gerçekleşmemiş bir şey hakkında birine mesaj atmış olabilirsiniz. Bir müşteri “Parolanız değiştirildi” veya “Siparişiniz onaylandı” mesajı alabilir, sonra yazma bir kısıt hatası veya zaman aşımı nedeniyle başarısız olur. Şimdi kullanıcı kafası karışır ve destek çözmek zorunda kalır.

Veritabanı trigger'ından göndermek cazip görünür çünkü veri değiştiğinde otomatik çalışır. Fakat tuzak şu ki trigger'lar aynı transaction içinde çalışır. Eğer transaction rollback olursa, sağlayıcıyı zaten aramış olabilirsiniz.

Veritabanı trigger'ları ayrıca gözlemlenmesi, test edilmesi ve güvenli şekilde yeniden denenmesi daha zor olan yapılar olma eğilimindedir. Ve yavaş dış çağrılar yaptıklarında beklenenden daha uzun süre kilit tutabilir ve veritabanı sorunlarını teşhis etmeyi zorlaştırabilir.

Daha güvenli bir yaklaşım outbox fikridir: bildirim niyetini veri olarak kaydedin, commit edin, sonra gönderin.

İş değişikliğini yapar ve aynı transaction içinde mesajı (kime, ne, hangi kanal, ayrıca benzersiz bir anahtar) tanımlayan bir outbox satırı eklersiniz. Commit'ten sonra bir arka plan worker bekleyen outbox satırlarını okur, mesajı gönderir ve onları gönderildi olarak işaretler.

Düşük etkili, yanlış olmanın kabul edilebilir olduğu bilgilendirici mesajlar için hemen göndermek yine uygun olabilir, örneğin “İsteğiniz işleniyor.” Ancak nihai durumu temsil etmesi gereken herhangi bir şey için commit'ten sonra bekleyin.

Yeniden denemeler ve hata işleme: hangi yaklaşım nerede avantajlıdır

Çoğunlukla belirleyici faktör yeniden denemelerdir.

Tetikleyiciler: hızlı ama hatalara karşı kırılgan

Çoğu tetikleyici tabanlı tasarımın iyi bir yeniden deneme hikâyesi yoktur.

Bir trigger bir e-posta/SMS sağlayıcısını çağırır ve çağrı başarısız olursa genelde iki kötü seçenek kalır:

  • transaction'ı başarısız kılmak (orijinal güncellemeyi engellemek), veya
  • hatayı yutmak (bildirimi sessizce kaybetmek).

Güvenilirliğin önemli olduğu durumlarda ikisi de kabul edilemez.

Trigger içinde döngü veya gecikme denemek transaction'ları daha uzun açık tutarak, kilit sürelerini artırarak ve veritabanını yavaşlatarak işleri daha da kötüleştirebilir. Ve veritabanı veya uygulama gönderim ortasında ölürse, sağlayıcının isteği alıp almadığını çoğu zaman söyleyemezsiniz.

Arka plan worker'ları: yeniden denemeler için tasarlanmış

Worker, gönderimi kendi durumu olan ayrı bir görev olarak ele alır. Bu da hangi durumlarda yeniden deneneceğini doğal olarak belirlemeyi kolaylaştırır.

Pratik bir kural olarak, geçici hataları yeniden denersiniz (zaman aşımı, geçici ağ sorunları, sunucu hataları, rate limit'lerde daha uzun bekleme). Kalıcı problemleri (geçersiz telefon numaraları, hatalı e-postalar, abonelik iptalleri gibi sert reddedilmeler) genelde yeniden denemezsiniz. “Bilinmeyen” hatalar için deneme sayısını sınırlayıp durumu görünür yaparsınız.

Backoff, yeniden denemelerin işleri daha da kötüleştirmesini engeller. Küçük bir bekleme ile başlayın, sonra her seferinde artırın (örneğin 10s, 30s, 2m, 10m) ve sabit bir deneme sayısından sonra durun.

Bunu dağıtımlar ve yeniden başlatmalara dayanıklı yapmak için her iş ile yeniden deneme durumunu depolayın: deneme sayısı, sonraki deneme zamanı, son hata (kısa ve okunabilir), son deneme zamanı ve pending, sending, sent, failed gibi net bir durum.

Uygulamanız gönderim ortasında yeniden başlarsa, bir worker takılmış işleri (örneğin sending durumu ve eski zaman damgası) yeniden kontrol edip güvenle yeniden deneyebilir. Bu noktada idempotentlik olmazsa yeniden denemeler çift gönderime neden olabilir.

E-posta ve SMS'te çiftleri engelleme: idempotentlik

Yeniden deneme kurallarını netleştirin
Backoff, deneme sayısı ve kalıcı hataları yönetmek için sürükle-bırak mantığı kullanın.
Başlayın

Idempotentlik, aynı “bildirim gönder” eylemini birden çok kez çalıştırabilmeniz ve kullanıcının yine sadece bir kez almasını sağlamanız demektir.

Klasik çoğaltma vakası bir zaman aşımıdır: uygulamanız bir sağlayıcıyı çağırır, istek zaman aşımına uğrar ve kodunuz yeniden dener. İlk istek aslında başarılı olmuşsa, yeniden deneme çift oluşturur.

Pratik bir çözüm her mesaja kararlı bir anahtar vermek ve o anahtarı tek gerçek kaynak olarak kullanmaktır. İyi anahtarlar mesajın ne anlama geldiğini tanımlar, deneme zamanını değil.

Yaygın yaklaşımlar şunlardır:

  • “Bu mesajın var olması gerektiğine karar verdiğiniz anda” oluşturulan üretilmiş bir notification_id, veya
  • iş mantığından türetilmiş bir anahtar örneğin order_id + template + recipient (sadece gerçekten benzersizliği tanımlıyorsa).

Sonra bir gönderim defteri (çoğunlukla outbox tablosu) tutun ve tüm yeniden denemelerden önce ona bakın. Durumları basit ve görünür tutun: created (kararlaştırıldı), queued (hazır), sent (onaylı), failed (onaylı başarısız), canceled (artık gerek yok). Kritik kural her idempotency anahtarı için yalnızca bir aktif kayıt olmasına izin vermektir.

Sağlayıcı tarafı idempotentliği destekliyorsa yardımcı olur ama kendi defterinizin yerini almaz. Yeniden denemelerinizi, dağıtımlarınızı ve worker yeniden başlatmalarınızı yine sizin ele almanız gerekir.

Ayrıca “bilinmeyen” sonuçları birinci sınıf kabul edin. Bir istek zaman aşımına uğradıysa, hemen yeniden göndermeyin. Onu onay bekleyen olarak işaretleyin ve mümkünse sağlayıcı teslimat durumunu kontrol ederek güvenli şekilde yeniden deneyin. Eğer doğrulayamıyorsanız, geciktirin ve iki kez göndermek yerine birini uyarın.

Güvenli varsayılan desen: outbox + arka plan worker (adım adım)

Güvenli bir varsayılan isterseniz, outbox deseni artı worker hemen hemen her durumda kazandırır. Bu, gönderimi iş değişikliğinizin dışına çıkarırken bildirim niyetinin kaydedilmesini garanti eder.

Akış

“Bildirim gönder” eylemini bir eylem olarak ateşlemek yerine veriye dönüştürün.

İş değişikliğini (örneğin sipariş durumu güncellemesi) normal tablolarınızda kaydedersiniz. Aynı veritabanı transaction'ında alıcı, kanal (email/SMS), şablon, payload ve bir idempotency anahtarı ile bir outbox kaydı da eklersiniz. Transaction commit edilir. Bu noktadan önce hiçbir şey gönderilmemelidir.

Arka plan worker düzenli olarak bekleyen outbox satırlarını alır, gönderir ve sonucu kaydeder.

Aynı satırı iki worker'ın almaması için basit bir "claim" adımı ekleyin. Bu, durumu processing olarak değiştirmek veya kilitleme zaman damgası kullanmak olabilir.

Çoğaltmaları engelleme ve hataları ele alma

Çoğaltmalar genellikle gönderim başarılı ama uygulamanız "sent" kaydını yazmadan çökünce olur. Bunu "sent" işaretlemesini tekrar etmekten zarar gelmeyecek şekilde yapmakla çözersiniz.

Benzersizlik kuralı kullanın (örneğin idempotency anahtarına ve kanala unique constraint). Net kurallarla yeniden deneyin: sınırlı denemeler, artan gecikmeler ve sadece yeniden denenebilir hatalara izin verin. Son denemeden sonra işi bir dead-letter durumuna (örneğin failed_permanent) taşıyın ki biri inceleyip elle yeniden işleyebilsin.

İzleme basit kalabilir: pending, processing, sent, retrying ve failed_permanent sayıları ile en eski pending zaman damgası.

Somut örnek: bir sipariş “Packed”ten “Shipped”e geçtiğinde, sipariş satırını güncellersiniz ve order-4815-shipped gibi bir idempotency anahtarı ile tek bir outbox satırı oluşturursunuz. Worker gönderim ortasında çökse bile, yeniden denemeler ikinci bir gönderim yapmaz çünkü “sent” yazması o benzersiz anahtar tarafından korunur.

Ne zaman arka plan worker'ları daha iyi bir seçimdir

Üretime hazır akışlar oluşturun
Bildirim mantığını tutarlı tutarken gerçek backend ve uygulama kodu üretin.
AppMaster ile İnşa Et

Veritabanı trigger'ları veri anında değiştiğinde tepki vermede iyidir. Ancak iş “gerçek dünyadaki düzensizliklere rağmen güvenilir şekilde bir bildirimi teslim etmek” ise, arka plan worker'ları size genelde daha fazla kontrol sağlar.

Worker'lar zaman tabanlı gönderimler (hatırlatmalar, derlemeler), rate limit ve backpressure ile yüksek hacim, sağlayıcı değişkenliğine tolerans (429 limitleri, yavaş yanıtlar, kısa kesintiler), çok adımlı iş akışları (gönder, teslimatı bekle, sonra takip et) veya uzlaşma gerektiren çapraz sistem olayları için daha uygundur.

Basit bir örnek: müşteriden tahsilat yapıyorsunuz, sonra SMS makbuzu gönderiyorsunuz, sonra e-posta faturayı gönderiyorsunuz. Eğer SMS gateway sorunundan dolayı SMS başarısız olursa, siparişin ödenmiş kalmasını ve daha sonra güvenli bir yeniden denemeyi istersiniz. Bu mantığı trigger içinde koymak, “veri doğru” ile “üçüncü taraf şu an müsait” durumunu karıştırma riski taşır.

Arka plan worker'lar operasyonel kontrolü de kolaylaştırır. Bir olaya müdahale ederken bir kuyruğu durdurabilir, hataları inceleyebilir ve gecikmeli yeniden denemeler yapabilirsiniz.

Kaçırılan veya çift mesajlara neden olan yaygın hatalar

Her denemeyi takip edin
pending, processing, sent ve failed gibi durumlara sahip basit bir defter oluşturun.
Şimdi Başlayın

Güvenilmez bildirimlerin en hızlı yolu, “nerede uygunsa orada gönder” demek ve sonra yeniden denemelerin sizi kurtaracağını ummaktır. Tetikleyiciler veya worker'lar kullanın fark etmez; hatalar ve durumla ilgili ayrıntılar kullanıcıya bir mesaj, iki mesaj veya hiç mesaj gitmemesini belirler.

Yaygın bir tuzak, veritabanı trigger'ından gönderip bunun başarısız olamayacağını varsaymaktır. Trigger'lar aynı veritabanı transaction'ı içinde çalışır, bu nedenle yavaş bir sağlayıcı çağrısı yazmayı geciktirebilir, zaman aşımına sokabilir veya tabloları beklenenden daha uzun süre kilitleyebilir. Daha kötüsü, gönderim başarısız olup transaction rollback olursa, sağlayıcı ilk çağrıyı gerçekten kabul etmişse daha sonra yeniden denemede iki kez gönderebilirsiniz.

Tekrar eden olarak karşınıza çıkan hatalar:

  • Her şeyi aynı şekilde yeniden denemek, kalıcı hatalar dahil (kötü e-posta, engellenmiş numara).
  • “Queued” ile “sent”i ayırmamak, böylece çökmeden sonra neyin güvenle yeniden deneneceğini bilememek.
  • Dedup için timestamp kullanmak; bu durumda yeniden denemeler doğal olarak benzersizliği atlar.
  • Sağlayıcı çağrılarını kullanıcı istek yoluna koymak (checkout ve form gönderimi gateway beklememeli).
  • Sağlayıcı zaman aşımını “teslim edilmedi” olarak değerlendirmek, oysa çoğu zaman durum “bilinmiyor”.

Basit örnek: bir SMS gönderirsiniz, sağlayıcı zaman aşımına uğrar ve siz yeniden denersiniz. Eğer ilk istek gerçekten başarılıysa, kullanıcı iki kod alır. Çözüm, notification_id gibi sabit bir idempotency anahtarı kaydetmek, gönderimi önce queued olarak işaretlemek ve yalnızca kesin başarı yanıtından sonra sent olarak işaretlemektir.

Göndermeden önce hızlı kontroller

Çoğu bildirim hatası araçla değil zamanlama, yeniden deneme ve eksik kayıtlarla ilgilidir.

Yayınlamadan önce şu temel maddeleri doğrulayın:

  • Gönderim, yazma sırasında değil commit'ten sonra gerçekleşiyor. Eğer yazma sırasında gönderir ve sonra rollback olursa, kullanıcı olmayan bir şey hakkında bilgilendirilir.
  • Her bildirimin benzersiz bir idempotency anahtarı var ve depolamada kopyalar reddediliyor.
  • Yeniden denemeler güvenli: sistem aynı işi tekrar çalıştırsa bile en çok bir kez gönderir.
  • Her deneme kaydediliyor (durum, last_error, zaman damgaları).
  • Denemeler sınırlandırılmış, takılı kalan öğelerin incelenip yeniden işlenebileceği net bir yer var.

Worker'ı kasıtlı olarak yeniden başlatma davranışını test edin. Gönderim ortasında worker'ı öldürün, yeniden başlatın ve çift gönderim olmadığını doğrulayın. Aynı testi veritabanı yük altındayken de yapın.

Doğrulama için basit bir senaryo: kullanıcı telefon numarasını değiştirir, sonra SMS doğrulama gönderirsiniz. SMS sağlayıcısı zaman aşımına uğrarsa uygulamanız yeniden deneyecektir. İyi bir idempotency anahtarı ve deneme kaydıyla ya bir kez gönderirsiniz ya da daha sonra güvenle tekrar denersiniz — ama spama uğratmazsınız.

Örnek senaryo: sipariş güncellemeleri ve çift gönderim olmaması

Güvenli varsayılanı uygulayın
Veri modeli, iş mantığı ve izleme için UI ile örnek deseni hızlıca prototipleyin.
AppMaster'ı Deneyin

Bir mağaza iki tür mesaj gönderir: (1) ödeme sonrası hemen bir sipariş onay e-postası ve (2) paket yola çıktığında ve teslim edildiğinde SMS güncellemeleri.

Çok erken gönderdiğinizde (örneğin veritabanı trigger'ı içinde) neyin yanlış gittiğine bakalım: ödeme adımı orders satırını yazar, trigger müşteriye e-posta gönderir, sonra ödeme capture birkaç saniye sonra başarısız olur. Şimdi gerçek olmayan bir sipariş için “Siparişiniz için teşekkürler” e-postası olmuş olur.

Tersi problem de şöyle olur: teslimat durumu “Out for delivery” olarak değişir, SMS sağlayıcınızı çağırırsınız ve sağlayıcı zaman aşımına uğrar. Mesajın gönderilip gönderilmediğini bilmiyorsunuz. Hemen yeniden dener ve ilk istek aslında başarılıysa iki SMS riski alırsınız; yeniden denemezseniz hiç SMS gitmemiş olur.

Daha güvenli akış outbox kaydı + arka plan worker kullanır. Uygulama siparişi veya durum değişikliğini commit eder ve aynı transaction içinde “kullanıcı Y'ye X şablonu, kanal SMS, idempotency anahtarı Z ile gönder” gibi bir outbox satırı yazar. Sadece commit'ten sonra worker mesajları teslim eder.

Basit zaman çizelgesi şöyle olur:

  • Ödeme başarılı olur, transaction commit edilir ve onay e-postası için outbox satırı kaydedilir.
  • Worker e-postayı gönderir ve sağlayıcı mesaj ID'si ile outbox'ı sent olarak işaretler.
  • Teslimat durumu değişir, transaction commit edilir ve SMS güncellemesi için outbox satırı kaydedilir.
  • Sağlayıcı zaman aşımına uğrar, worker outbox'ı yeniden denenebilir olarak işaretler ve aynı idempotency anahtarıyla daha sonra tekrar dener.

Yeniden denemede outbox satırı tek gerçek kaynak olur. Yeni bir "gönder" isteği oluşturmazsınız, mevcut işi tamamlamaya çalışırsınız.

Destek için de bu daha açıktır. Hata mesajlarını (timeout, kötü numara, engellenmiş e-posta), kaç deneme yapıldığını ve çift göndermeden güvenle yeniden denemenin mümkün olup olmadığını görebilirler.

Sonraki adımlar: bir desen seçin ve temiz uygulayın

Bir varsayılan seçin ve bunu yazılı hale getirin. Tutarsız davranış genelde tetikleyiciler ve worker'ların karışık kullanılmasıyla ortaya çıkar.

Küçük başlayın: bir outbox tablosu ve bir worker döngüsü. İlk hedef hız değil, doğruluk olsun: göndermek istediğinizi saklayın, commit'ten sonra gönderin ve sağlayıcı onaylayana kadar yalnızca sent olarak işaretlemeyin.

Basit bir uygulama planı:

  • Olayları tanımlayın (order_paid, ticket_assigned) ve hangi kanalları kullanabileceklerini belirleyin.
  • event_id, recipient, payload, status, attempts, next_retry_at, sent_at içeren bir outbox tablosu ekleyin.
  • Bekleyen satırları sorgulayan, gönderen ve durumu tek bir yerde güncelleyen bir worker oluşturun.
  • Her mesaj için benzersiz bir anahtar ile idempotency ekleyin ve “zaten gönderildiyse bir şey yapma” mantığı koyun.
  • Hataları yeniden denenebilir (zaman aşımı, 5xx) ve yeniden denenmemesi gereken (kötü numara, engellenmiş e-posta) olarak ayırın.

Hacmi ölçeklendirmeden önce temel görünürlüğü ekleyin. Bekleyen sayısını, hata oranını ve en eski bekleyen mesajın yaşını takip edin. Eğer en eski bekleyen sürekli büyürse, muhtemelen bir takılmış worker, sağlayıcı kesintisi veya mantık hatası vardır.

Eğer AppMaster ile inşa ediyorsanız (appmaster.io), bu desen net şekilde haritalanır: Outbox'u Data Designer'da modelleyin, iş güncellemesi ve outbox satırını tek bir transaction'da yazın, sonra gönderme-ve-yeniden-deneme mantığını ayrı bir arka plan süreçte çalıştırın. Bu ayrım, sağlayıcılar veya dağıtımlar sorun çıkardığında bile bildirim teslimatının güvenilir kalmasını sağlar.

SSS

Bildirimler için trigger mı yoksa arka plan worker mı kullanmalıyım?

Arka plan worker'ları genelde daha güvenli varsayılandır çünkü gönderimler yavaş ve hata yapmaya eğilimlidir; worker'lar yeniden denemeler ve görünürlük için tasarlanmıştır. Trigger'lar hızlı olabilir ama tetikleyen işlemle sıkı bağlı oldukları için hatalar ve çift gönderimler temiz şekilde yönetilmesi zor olur.

Veritabanı commit'ten önce bildirim göndermek neden riskli?

Riskli çünkü veritabanı yazması hâlâ geri alınabilir. Commit öncesi gönderim, kullanıcıyı gerçekte olmamış bir sipariş, parola değişikliği veya ödeme hakkında bilgilendirebilir ve bir kez gönderilmiş bir e-posta veya SMS'i geri almak mümkün değildir.

Veritabanı trigger'ından göndermenin en büyük sorunu nedir?

Trigger veritabanındaki aynı transaction içinde çalışır. Bir e-posta/SMS sağlayıcısına çağrı yaparsa ve transaction daha sonra başarısız olursa, gerçekte kalıcı olmayan bir değişiklik hakkında gerçek bir mesaj göndermiş olabilirsiniz; veya yavaş bir dış çağrı yüzünden transaction'ı tıkayabilirsiniz.

Outbox deseni nedir, sade bir ifadeyle?

Outbox deseni, gönderme niyetini veritabanında bir satır olarak saklamaktır; bu satırı iş değişikliğiyle aynı transaction içinde eklersiniz. Commit'ten sonra bir worker bekleyen outbox satırlarını okur, mesajı gönderir ve "sent" olarak işaretler; böylece zamanlama ve yeniden denemeler daha güvenli olur.

Bir e-posta/SMS sağlayıcısı isteği zaman aşımına uğradığında ne yapmalıyım?

Sağlayıcı zaman aşımına uğradığında gerçek sonuç sıklıkla “bilinmiyor”dur, doğrudan “başarısız” değil. İyi bir sistem denemeyi kaydeder, aynı mesaj kimliğiyle güvenli şekilde geciktirir ve yeniden dener; böylece hemen yeniden gönderip çift gönderme riski almazsınız.

Yeniden denemeler olduğunda çift e-posta veya SMS nasıl engellenir?

Idempotency kullanın: her bildirime mesajın ne anlama geldiğini gösteren sabit bir anahtar verin (deneme zamanını değil). Bu anahtarı outbox gibi bir defterde saklayın ve her anahtar için yalnızca bir aktif kayıt olacak şekilde zorlayın, böylece yeniden denemeler aynı mesajı tamamlar, yeni bir tane oluşturmaz.

Hangi hataları yeniden denemeli, hangilerini kalıcı saymalıyım?

Zaman aşımı, 5xx yanıtları veya rate limit gibi geçici hataları yeniden deneyin (uygun beklemeyle). Geçersiz adresler, engellenmiş numaralar veya sert bounce gibi kalıcı hataları yeniden denemeyin; bunları başarısız olarak işaretleyin ve veriyi düzeltmek için görünür yapın.

Arka plan worker'lar gönderim sırasında yeniden başlama veya çökme durumlarını nasıl ele alır?

Arka plan worker'ı sending durumunda uzun süre kalmış işleri tarayıp onları yeniden denemeye alabilir ve backoff ile tekrar deneyebilir. Bu ancak her işin deneme sayısı, zaman damgaları ve son hata gibi durum bilgisini kaydetmesi ve idempotency sayesinde çift gönderimin engellenmesi durumunda güvenlidir.

Bildirim teslimatını gözlemlenebilir yapmak için hangi iş verilerine ihtiyacım var?

Cevap: yeniden denemede güvenli olup olmadığı sorusuna cevap verebilmek demektir. Bunun için pending, processing, sent ve failed gibi açık durumlar, deneme sayısı ve son hata kaydı tutun. Bu, destek ve hata ayıklama işlemlerini pratik kılar ve sistemin tahmine dayalı değil kontrollü toparlanmasını sağlar.

Bu deseni AppMaster'ta nasıl uygularım?

AppMaster'ta (appmaster.io) bir outbox tablosu modelleyin, iş güncellemesini ve outbox satırını aynı transaction içinde yazın, ardından gönderme ve yeniden deneme mantığını ayrı bir arka plan işleminde çalıştırın. Her mesaj için bir idempotency anahtarı tutun ve denemeleri kaydedin, böylece dağıtımlar, yeniden denemeler ve worker restart'ları çift gönderime yol açmaz.

Başlaması kolay
Harika bir şey yaratın

Ücretsiz planla AppMaster ile denemeler yapın.
Hazır olduğunuzda uygun aboneliği seçebilirsiniz.

Başlayın