Olayları tekrar oynatırken CRQS'de yan etkiler nasıl ele alınır?


10

CQRS'de bir hatayı düzeltmenin kolay olduğu, sadece yeniden konuşlandırıp olayları tekrar oynadığınız söylenir.

Ancak, olaylardan biri, kontrolünüzde olmayan harici bir sistemin müşteriye yalnızca bir öğe göndermesine neden olursa, öğeyi iki kez gönderirseniz ne olur?

Bunu nasıl çözersiniz?

Yanıtlar:


6

Okuma modelinizin durumunu değiştiren olaylar ile harici sistemlerin durumunu değiştiren (potansiyel olarak) olaylar arasında net bir ayrım yapmanız gerekir. Her iki durumu birlikte değiştiren "karma etkinlikler" olmadığından emin olun. Bu şekilde, etkinliklerinizi harici sistem için bu etkinliklerin yeniden başlatılmadığı belirli bir "yeniden oynatma modunda" yeniden oynatabilirsiniz. Bu modda, ilk olarak harici sistem tarafından başlatılmış olan olayları da "simüle edersiniz" (şimdi onları tekrarlama kuyruğundan alırsınız).

Unutmayın, yeniden konuşlandırma adımı, aslında okuma modelinin durumunu daha önceki bir zamana sıfırlamak anlamına gelir. Bu muhtemelen harici sistemlerin durumu için yapabileceğiniz (veya yapmanız gereken) bir şey değildir.


"Unutmayın, yeniden konuşlandırma adımı, aslında okuma modelinin durumunu daha erken bir zamana sıfırlamak anlamına gelir. Bu muhtemelen harici sistemlerin durumu için yapabileceğiniz (veya yapmanız gereken) bir şey değildir." -> ama tekrarlamamın gönderim gibi başarısız harici sistem çağrılarını yeniden denemesini istersem ne olur? bu durumda benim yeniden dağıtım sadece okuma modeli durumunu sıfırlamak değil, aynı zamanda dış olaylara neden olur, bu adil görünüyor veya bir şey eksik mi?
Jas

2
@Jas: başarısız bir harici sistem çağrısını yeniden denemek için "tekrar" işlevini kötüye kullanmak istemezsiniz. Kendi sisteminizin okuma modelini daha önce olduğu gibi elde etmek için "tekrar" ifadesini kullanırsınız. Bu, gönderimin başarısız olması durumunda sisteminize daha önce bu hata hakkında bilgi verildiği ve bu bilgilerin durumunun herhangi bir yerinde saklandığı anlamına gelir. Tekrar, bu bilginin "yeniden konuşlandır & tekrar oynat" işleminden sonra hala orada olmasını sağlar. Yeniden oynatmadan sonra, sisteminiz bir "arıza durumunda nakliyeyi yeniden dene" stratejisi uygulayabilir (ki bu CQRS ile ilgisi yoktur, herhangi bir sağlam sipariş sisteminin böyle bir stratejisi olmalıdır).
Doc Brown

İlginç, bu aklımda ne vardı, sadece bu konuda bir "desen" olup olmadığını merak ediyordu, bu yüzden tekerleği yeniden icat yok!
Jas

3

Martin Fowler'ın olay kaynağı makalesinden:

Olay Sağlama'nın temel fikri, bir uygulamanın durumundaki her değişikliğin bir olay nesnesinde yakalanmasını sağlamak ve bu olay nesnelerinin kendilerinin, uygulama durumuyla aynı yaşam boyu uygulandıkları sırayla depolanmalarıdır.

Dolayısıyla, sisteminizin durumunu belirli bir ana geri yüklemeniz gerektiğinde , o ana kadar olay işleyicileri değil depolanan durumu yeniden oynatırsınız .

Bununla birlikte, sadece durum verileriyle çalışıyorsanız, harici sistem üzerinde herhangi bir etkisi olmamalıdır. Etkinlik deponuzda tetikleyiciler veya izleyiciler yoksa, bu durumda geri yükleme süresi boyunca bunları devre dışı bırakmalısınız. Harici sistem üzerinde hiçbir kontrolünüz olmadığını söylediğiniz için, sistemlerinde hangi yan etkilerin olabileceğini bilmediğiniz için, açık API'yı kullanarak durumunu geri yükleme girişimi olmamalıdır. Geri yükleme sistemi ara duruma getirirse (örn. Harici sistemdeki başarısız işlemler nedeniyle) bu, olay tekrarının sorumlulukları dahilinde olmamalıdır.


2

Ancak, olaylardan biri, kontrolünüzde olmayan harici bir sistemin müşteriye yalnızca bir öğe göndermesine neden olursa, öğeyi iki kez gönderirseniz ne olur?

Belirli bir örnek seçmek için, yan etkilere "en az bir kez" yaklaşımının nasıl işleyebileceğini düşünelim.

State currentState = State.InitialState
for(Event e : events) {
    currentState = currentState.apply(e)
}
for(SideEffect s : currentState.querySideEffects()) {
    performSideEffect(s)

Böylece etki alanı modeli ne yapılması gerektiğini izler; ancak gerçek işi uygulamaya bırakır

Komut çalıştırma bağlamında, temel fikir aynı görünüyor. Gerçek yan etkiler , modeli güncelleyen işlemin dışında gerçekleşir .

Böylece modeliniz için birim testleri şöyle görünebilir:

{
    // Given
    State currentState = State.InitialState

    // When
    Events events = List.of(OrderPlaced)

    // Then
    List.of(SendEmail) === currentState.applyAll(events).querySideEffects()
}

{
    // Given
    State currentState = State.InitialState

    // When
    Events events = List.of(OrderPlaced, EmailSent)

    // Then
    List.EMPTY === currentState.applyAll(events).querySideEffects()
}

Burada ana noktalar

  • Modelin güncellenmesi yan etkisizdir; gerçek yan etkiler, modeli güncelleyen işlemin dışında gerçekleşir.
  • Yan etkinin sonucunu açıklayan bir olayın geri gelmesi gerekir.
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.