Oyun Kitabı
Ödeme Mutabakat Worker İnşası (Odeme Mutabakat Worker İnsasi)
Sweeper'lar drift'i nasıl iyileştirir: PSP başarılı derken local kayıt expired olabilir; aged FinalizePending nasıl toparlanır.
Dağıtık Ödeme Motoru (Distributed Payment Engine)
Bolum 14 / 22
Capture ile complete arasındaki boşluğu kapatan dağıtık ödeme mimarisi serisi.
Önceki bölümde lease mekanizmasıyla bir işin nasıl güvenle sahiplenildiğini gördük. Fakat en sağlam lease bile bir gerçeği değiştiremez: bazen worker, PSP'den kesin bir yanıt almadan önce zaman aşımına uğrar, süreç çöker veya lease süresi dolar ve iş 'expired' olarak işaretlenir — tam da PSP tarafında ödeme gerçekten başarılı olmuşken.
Bu, mutabakat (reconciliation) worker'ının var olma nedenidir: local sistem ile PSP'nin kendi kayıtları arasındaki sürüklenmeyi (drift) periyodik olarak tarayıp düzelten bir sweeper.
Local kayıt: Payment #123 → Expired
PSP kaydı: Payment #123 → Succeeded
│
▼
Mutabakat worker sürüklenmeyi tespit eder
│
▼
Local kayıt → Captured olarak düzeltilir
Kavramlar ilk geçtiği yerde
📦 Reconciliation (Mutabakat)
İki bağımsız kaynağın (local sistem ve PSP) kayıtlarını karşılaştırıp farkı düzeltme süreci.
📦 Drift (Sürüklenme)
Local durumun PSP'nin gerçek kaydından farklılaşması; genellikle bir hata veya zaman aşımı sonucu.
📦 Sweeper
Belirli bir kritere uyan (örn. 'aged' veya 'expired') kayıtları periyodik olarak tarayan arka plan işi.
📦 FinalizePending
Ödemenin PSP tarafında sonuçlanmış olabileceği ama local sistemde henüz kesin bir duruma geçmediği ara statü.
Mutabakat, gerçek zamanlı bir düzeltme değildir; bir güvenlik ağıdır. Ana akış (webhook, senkron yanıt) çoğu zaman doğru çalışır; mutabakat, o 'çoğu zaman'ın dışında kalan azınlığı temizler.
Sürüklenmenin gerçek kaynakları
Sürüklenme nadiren rastgele olur; genellikle belirli, tekrar eden senaryolardan gelir: worker PSP'ye isteği gönderir, yanıt gelmeden önce süreç çöker; ağ hatası nedeniyle yanıt hiç ulaşmaz ama PSP tarafında işlem tamamlanmıştır; ya da lease süresi PSP'nin yanıt süresinden daha kısa ayarlanmıştır ve iş erken 'expired' olarak işaretlenir.
Senaryo 1: Worker çöktü
Request gönderildi → PSP işledi → Worker cevabı hiç okuyamadı
Senaryo 2: Ağ hatası
Request gönderildi → PSP işledi → yanıt ağda kayboldu
Senaryo 3: Lease erken doldu
Request gönderildi → PSP yavaş yanıt verdi → lease expired → job stuck watcher tarafından sıfırlandı → ama PSP zaten başarılı olmuştu
Her üç senaryoda da ortak nokta şu: local kayıt belirsiz veya yanlış bir statüde kalırken, PSP'nin kendi kaydı gerçek sonucu zaten bilir.
Sweeper'ın sorgusu: hangi kayıtları taramalı
Mutabakat worker'ı her kaydı sürekli PSP ile karşılaştırmaz — bu maliyetlidir ve gereksizdir. Yalnızca 'şüpheli' kayıtları hedefler: belirli bir yaşı geçmiş (aged) ve hâlâ ara bir statüde (FinalizePending, Expired, uzun süredir Processing) kalan kayıtlar.
SELECT id, provider_ref FROM payments
WHERE status IN ('FinalizePending', 'Expired')
AND updated_at < now() - interval '10 minutes';
'10 dakika' eşiği rastgele değildir; normal akışın ne kadar sürede sonuçlanması gerektiğine dair bir SLA'dan gelir. Bu eşiğin altındaki kayıtlar henüz 'şüpheli' değildir, sadece yavaş olabilir.
PSP'yi sorgulama ve karar verme
Her aday kayıt için worker, PSP'nin durum sorgulama API'sini (varsa) veya kendi arşivlenmiş webhook geçmişini kontrol eder. Üç sonuç mümkündür:
PSP: Succeeded → local kaydı Captured'a taşı, semantik event yayınla
PSP: Failed → local kaydı Failed'a taşı
PSP: Not Found / Unknown → local kaydı gerçekten sonuçsuz say, telafi akışına yönlendir
Burada kritik nokta, bu geçişin de idempotent olması gerektiğidir: mutabakat worker'ı aynı kaydı iki kez işlese bile sonuç değişmemelidir (örneğin kayıt zaten Captured ise tekrar aynı event'i yayınlamamalıdır).
Alerting: sweeper sessizce çalışmamalı
Mutabakat worker'ının bulduğu her sürüklenme, bir gözlemlenebilirlik sinyali üretmelidir. Sürüklenme sayısı aniden artıyorsa, bu genellikle ana akışta (webhook işleme, lease süresi, ağ) bir sorun olduğuna işaret eder — mutabakat bu sorunu gizlememeli, görünür kılmalıdır.
| Metrik | Ne anlatır |
|---|---|
| Taranan aday kayıt sayısı | Ana akışın ne kadar 'temiz' çalıştığı |
| Düzeltilen sürüklenme sayısı | Gerçek veri tutarsızlığı hacmi |
| Hâlâ çözülemeyen kayıt sayısı | Manuel inceleme gerektiren kuyruk |
Sık karıştırılan ayrımlar
❌ Mutabakat gerçek zamanlı bir düzeltmedir
✓ Mutabakat periyodik bir güvenlik ağıdır, ana akışın yerini almaz
❌ Sürüklenme sayısı sıfır olmalı, aksi halde sistem bozuk
✓ Düşük ve stabil bir sürüklenme oranı normaldir; artan oran bir sinyaldir
❌ Her kayıt PSP ile karşılaştırılmalı
✓ Sadece 'aged' ve ara statüdeki kayıtlar hedeflenmeli
Ana akış ile mutabakatın rolü
| Boyut | Ana akış (webhook/senkron) | Mutabakat worker |
|---|---|---|
| Hız | Saniyeler | Dakikalar-saatler |
| Kapsam | Her ödeme | Sadece şüpheli/aged kayıtlar |
| Amaç | Normal yol | Güvenlik ağı |
Mutabakat worker'ı kurarken kontrol listesi
- Sweeper sorgusu, 'aged' eşiğini iş SLA'sına göre mi belirliyor, yoksa rastgele bir sayı mı?
- PSP'yi sorgulama işlemi, kendi rate limit ve retry politikasına uyuyor mu?
- Sürüklenme düzeltmesi idempotent mi — aynı kayıt iki kez işlense sonuç değişmiyor mu?
- Düzeltilemeyen kayıtlar (PSP'de de bulunamayan) görünür bir kuyruğa mı düşüyor?
- Sürüklenme sayısı bir metrik olarak izleniyor ve ani artışlarda alarm üretiyor mu?
Bu yazıdan aklında ne kalmalı
- Mutabakat, ana akışın yedeği değil tamamlayıcısıdır; ana akış çoğu zaman doğru çalışır, sweeper kalan azınlığı temizler.
- Sweeper her kaydı değil, yaş ve statü kriterine uyan şüpheli kayıtları hedefler.
- PSP sorgusu sonrası düzeltme idempotent olmalı ve kendi retry disiplinine uymalıdır.
- Sürüklenme sayısı bir gözlemlenebilirlik sinyalidir; sessizce sıfıra yaklaşması beklenir, ani artış bir uyarıdır.
Bir mutabakat worker'ı, sistemin ne kadar mükemmel olduğunu değil, ne kadar dürüst olduğunu gösterir.
Bir sonraki bölümde bu sürüklenmenin en can sıkıcı biçimini ele alıyoruz: müşteri PSP tarafında ücretlendirildi ama sistemde hiçbir sipariş yok — ve bunu güvenle nasıl iyileştiririz?
SSS
Sık sorulan sorular
Reconciliation (Mutabakat) nedir?
İki bağımsız kaynağın (local sistem ve PSP) kayıtlarını karşılaştırıp farkı düzeltme süreci.
Drift (Sürüklenme) nedir?
Local durumun PSP'nin gerçek kaydından farklılaşması; genellikle bir hata veya zaman aşımı sonucu.
"Mutabakat gerçek zamanlı bir düzeltmedir" doğru mu?
Mutabakat periyodik bir güvenlik ağıdır, ana akışın yerini almaz
Bu bölüm neyi sabitler?
Bu, mutabakat (reconciliation) worker'ının var olma nedenidir: local sistem ile PSP'nin kendi kayıtları arasındaki sürüklenmeyi (drift) periyodik olarak tarayıp düzelten bir sweeper. Mutabakat, ana akışın yedeği değil tamamlayıcısıdır; ana akış çoğu zaman doğru çalışır, sweeper kalan azınlığı temizler. Önceki bölümde lease mekanizmasıyla bir işin nasıl güvenle sahiplenildiğini gördük. Fakat en sağlam lease bile bir gerçeği değiştiremez: bazen worker, PSP'den kesin bir yanıt almadan önce zaman aşımına uğrar, süreç çöker veya lease süresi dolar ve iş 'expired' olarak işaretlenir — tam da PSP tarafında ödeme gerçekten başarılı olmuşken.
Ogrenilen Muhendislik Prensipleri
- Mutabakat ana akışın yedeği değil tamamlayıcısıdır.
- Sweeper her kaydı değil, aged ve şüpheli kayıtları hedefler.
- Sürüklenme sayısı bir sinyaldir; sessizce sıfıra yaklaşması, ani artışı ise uyarı gerektirir.
Okumaya devam et
Okumaya devam et
Seride sonraki yazi
Ödendi Ama Sipariş Yok: İyileştirme
Olay müdahale kılavuzu: müşteri ücretlendirildi ama sipariş oluşmadı; çok-niyetli sepet karmaşası; dedup'ı dikkatle temizlemek.
Seride sonraki yazi
Lease ile Veritabanı Destekli İşler
Conditional UPDATE ile lease alma, sıkışmış işleri kurtaran watcher ve neden yalnızca mesaj Nack etmek production ödemede yetmez.
Ayni seriden
Neden Eventual Consistency Dağıtık Transaction'dan Üstün
PSP, sipariş ve finans arasında 2PC kurmak bir tuzaktır. Saga ve mutabakat, dağıtık ödeme tutarlılığının gerçek cevabıdır.