Etkinlik Kaynaklandırma'daki yan etkilerle nasıl başa çıkabilirim?


14

Bir garip kalıp tespit edildiğinde kullanıcıları e-posta ile uyaran bir finansal uygulama için küçük bir güvenlik alt sistemi uygulamak istediğimizi varsayalım. Bu örnekte, desen tasvir edildiği gibi üç işlemden oluşacaktır. Güvenlik alt sistemi ana sistemdeki olayları bir kuyruktan okuyabilir.

Almak istediğim, modelin mevcut durumunu modelleyen bir ara temsil olmaksızın, sistemde meydana gelen olayların doğrudan bir sonucu olan bir uyarıdır.

  1. İzleme etkinleştirildi
  2. İşlem gerçekleştirildi
  3. İşlem gerçekleştirildi
  4. İşlem gerçekleştirildi
  5. Uyarı tetiklendi (id: 123)
  6. Gönderilen uyarı için e-posta (kimlik için: 123)
  7. İşlem gerçekleştirildi

Bunu göz önünde bulundurarak, net bir cevabı olmayan bir sorum olsa da, olay kaynaklarının burada çok iyi uygulanabileceğini düşündüm. Örnekte tetiklenen uyarının net bir yan etkisi vardır, bir e-postanın gönderilmesi gerekir, bu sadece bir kez gerçekleşmesi gereken bir durumdur. Bu nedenle, bir agreganın tüm olaylarını tekrar oynatırken gerçekleşmemelidir.

Bir dereceye kadar, CQRS / Olay kaynak literatüründe pek çok kez gördüğüm sorgu tarafının oluşturduğu materyalizasyonlara benzer şekilde gönderilmesi gereken e-postayı, o kadar ince olmayan bir farkla görüyorum.

Bu literatürde, sorgu tarafı, tüm olayları tekrar okuyarak belirli bir noktada durumun gerçekleşmesini sağlayabilen olay işleyicilerinden oluşturulmuştur. Ancak bu durumda, bu daha önce açıklanan nedenlerle tam olarak aynı şekilde gerçekleştirilemez. Her devletin geçici olduğu fikri burada pek de geçerli değil . Bir yere bir uyarı gönderildiğini kaydetmemiz gerekiyor.

Benim için kolay bir çözüm, daha önce tetiklenen uyarıların kayıtlarını tuttuğunuz farklı bir tablo veya yapıya sahip olmak olurdu. Bir kimliğimiz olduğu için, aynı kimliğe sahip bir uyarının daha önce yayınlanıp yayınlanmadığını kontrol edebiliriz. Bu bilgilere sahip olmak SendAlertCommand idempotent yapar. Birkaç komut verilebilir, ancak yan etki sadece bir kez olur.

Bu çözümü göz önünde bulundursak bile, bunun bu mimaride bu sorun için bir sorun olup olmadığını gösteren bir ipucu olup olmadığını bilmiyorum.

  • Yaklaşımım doğru mu?
  • Bununla ilgili daha fazla bilgi bulabileceğim bir yer var mı?

Bununla ilgili daha fazla bilgi bulamadığım garip. Belki de yanlış ifadeler kullanıyorum.

Çok teşekkür ederim!

Yanıtlar:


12

Etkinlik Kaynaklandırma'daki yan etkilerle nasıl başa çıkabilirim?

Kısa sürüm: alan adı modeli yan etki yapmaz. Bu izler onları. Yan etkiler, sınıra bağlanan bir bağlantı noktası kullanılarak gerçekleştirilir; e-posta gönderildiğinde, bildirimi etki alanı modeline geri gönderirsiniz.

Bu, e-postanın olay akışını güncelleyen işlemin dışına gönderildiği anlamına gelir .

Tam olarak, dışarıda bir tat meselesi.

Yani kavramsal olarak,

EmailPrepared(id:123)
EmailPrepared(id:456)
EmailPrepared(id:789)
EmailDelivered(id:456)
EmailDelivered(id:789)

Ve bu akıştan bir katlama oluşturabilirsiniz

{
    deliveredMail : [ 456, 789 ],
    undeliveredMail : [123]
}

Kapak, hangi e-postaların onaylanmadığını söyler, bu yüzden onları tekrar gönderirsiniz:

undeliveredMail.each ( mail -> {
    send(mail);
    dispatch( new EmailDelivered.from(mail) );
}     

Etkili bir şekilde, bu iki aşamalı bir taahhüttür: SMTP'yi gerçek dünyada değiştiriyorsunuz ve sonra modeli güncelliyorsunuz.

Yukarıdaki desen size en az bir kez dağıtım modeli sunar. En fazla bir kez isterseniz, ters çevirebilirsiniz

undeliveredMail.each ( mail -> {
    commit( new EmailDelivered.from(mail) );
    send(mail);
}     

EmailPrepared'i dayanıklı hale getirmek ve aslında e-postayı göndermek arasında bir işlem engeli var. Ayrıca, e-postayı göndermek ve EmailDelivered'i dayanıklı hale getirmek arasında bir işlem engeli de vardır.

Udi Dahan'ın Dağıtılmış İşlemlerle Güvenilir Mesajlaşması iyi bir başlangıç ​​noktası olabilir.


2

'Durum Değişikliği Etkinlikleri'ni' İşlemler'den ayırmanız gerekiyor

Bir Devlet Değişim Olay nesnenin durumunu değiştiren bir olaydır. Bunlar sakladığınız ve oynattığınızlardır.

Bir Eylem nesne başka şeyler için yaptığı bir şeydir. Bunlar, Olay Sağlamanın bir parçası olarak saklanmaz.

Bunu yapmanın bir yolu, Eylemleri çalıştırmak isteyip istemediğinize bağlı olarak bağladığınız veya işlemediğiniz olay işleyicileridir.

public class Monitor
{
    public EventHander SoundAlarm;
    public void MonitorEvent(Event e)
    {
        this.eventcount ++;
        if(this.eventcount > 10)
        {
             this.state = "ALARM!";
             if(SoundAlarm != null) { SoundAlarm();}
        }
    }
}

Şimdi izleme servisimde

public void MonitorServer()
{
    var m = new Monitor(events); //11 events
    //alarm has not been sounded because the event handler wasn't wired up
    //but the internal state is correctly set to "ALARM!"
    m.SoundAlarm += this.SendAlarmEmail;
    m.MonitorEvent(e); //email is sent
}

Gönderilen e-postaları günlüğe kaydetmeniz gerekiyorsa, bunu SendAlarmEmail'in bir parçası olarak yapabilirsiniz. Ancak bunlar Etkinlik Kaynaklandırma anlamında olaylar değildir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.