Konuyu Açan
#1
Sipariş kaydını transaction içinde oluşturup e-postayı ya da ödeme servisine bildirimi hemen gönderdiğim bir kod tabanı devralmıştım. İlk bakışta sorun yoktu; ama dış servis başarılı olup veritabanı transaction’ı rollback olursa sistemde olmayan sipariş için bildirim gitmesi mümkün. Tersine, transaction commit olduktan hemen sonra uygulama çökerse kuyruk işi hiç oluşturulmayabiliyor.
Basit senaryolarda işi commit sonrasına bırakmak iyi bir başlangıç:
Fakat commit ile dispatch arasındaki çökme ihtimali hâlâ duruyor. Daha kritik akışlarda outbox yaklaşımı bu yüzden hoşuma gidiyor: Siparişle birlikte aynı transaction’da bir “gönderilecek olay” kaydı yazılıyor; ayrı bir worker bunu okuyup kuyruğa iletiyor ve başarılı olunca işaretliyor. Böylece uygulama yeniden başlasa bile bekleyen kayıt kaybolmuyor.
Worker aynı olayı birden fazla kez işleyebileceğinden, tüketici tarafını da idempotent tasarlamak gerekiyor. Siz PHP projelerinde bu sınırı nasıl yönetiyorsunuz: commit sonrası dispatch yeterli mi, yoksa outbox kullandığınız oldu mu?
Basit senaryolarda işi commit sonrasına bırakmak iyi bir başlangıç:
KOD
123456789101112131415
$pdo->beginTransaction();
try {
// Siparişi ve ilgili kayıtları oluştur.
$pdo->commit();
$queue->dispatch('siparis_bildir', ['siparis_id' => $id]);
} catch (Throwable $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
throw $e;
}
Fakat commit ile dispatch arasındaki çökme ihtimali hâlâ duruyor. Daha kritik akışlarda outbox yaklaşımı bu yüzden hoşuma gidiyor: Siparişle birlikte aynı transaction’da bir “gönderilecek olay” kaydı yazılıyor; ayrı bir worker bunu okuyup kuyruğa iletiyor ve başarılı olunca işaretliyor. Böylece uygulama yeniden başlasa bile bekleyen kayıt kaybolmuyor.
Worker aynı olayı birden fazla kez işleyebileceğinden, tüketici tarafını da idempotent tasarlamak gerekiyor. Siz PHP projelerinde bu sınırı nasıl yönetiyorsunuz: commit sonrası dispatch yeterli mi, yoksa outbox kullandığınız oldu mu?