2011-09-05 21 views
12

मैं इवेंटस्टोर से ईवेंट को दोबारा चलाने के दौरान मॉडल का पुनर्निर्माण करते समय क्या करना चाहिए, विशेष रूप से जब घटनाएं अन्य घटनाओं को ट्रिगर कर सकती हैं, तो मैं अपने सिर को पाने के लिए संघर्ष कर रहा हूं।इवेंट सोर्सिंग: ऐसी घटनाएं जो दूसरों को ट्रिगर करती हैं और पुनर्निर्माण राज्य

उदाहरण के लिए, एक उपयोगकर्ता जिसने 10 खरीदे हैं, को पसंदीदा ग्राहक को पदोन्नत किया जाना चाहिए और उन्हें कुछ प्रचार देने की ईमेल प्राप्त होनी चाहिए।

हम स्पष्ट रूप से नहीं चाहते हैं कि जब भी हम उस उपयोगकर्ता के मॉडल को पुनर्निर्माण करेंगे, तो हम ईमेल को कब भेजना चाहते हैं, लेकिन जब हम अपने 10 वें PurchaseMadeEvent को फिर से चलाते हैं तो हम इसे कैसे रोक सकते हैं?

उत्तर

8

घटनाक्रम श्रृंखला बहुत मुश्किल और आसानी से नियंत्रण से बाहर हो सकती है, इसलिए मैं जितना संभव हो उससे बचूंगा। उदाहरण के लिए परिदृश्य में आप वर्णन कर रहे हैं कि मैं UserPromotedEvent (शायद PromoteUserCommand का उपयोग भी कर दूंगा), हालांकि मैं अपने डोमेन के हिस्से के रूप में ईमेल के वास्तविक/भौतिक प्रेषण पर विचार नहीं करूंगा। इसके बजाय मैं UserPromotedEvent के लिए अतिरिक्त हैंडलर/denormalizer बनाउंगा जो कुछ अतिरिक्त चेक के साथ ईमेल भेजने की आवश्यकता को पंजीकृत करेगा। उसके बाद एक और प्रक्रिया अभी तक संसाधित ईमेल की जानकारी एकत्र नहीं करेगी और उन्हें भेज देगी। यह दृष्टिकोण उन समस्याओं को कम करेगा जो पूरी तरह से सुलभ/स्केलेबल ईमेल गेटवे के साथ नहीं हो सकते हैं।

अधिक सामान्य में - घटनाओं की श्रृंखला की आवश्यकता अक्सर संकेत देती है कि आपको प्रक्रिया के लिए Saga लागू करने पर विचार करना चाहिए।

2

जब आप ईवेंट को फिर से चलाते हैं, तो आप उन सभी डोमेन तर्कों को फिर से नहीं चला रहे हैं जो उन घटनाओं को उत्पन्न करने के साथ-साथ गए थे। आमतौर पर आपके डोमेन विधि में आप एक ईवेंट उठाएंगे; उस घटना को बढ़ाने के बाद उस डोमेन ऑब्जेक्ट की समग्र स्थिति को अपडेट करना चाहिए।

उदाहरण के लिए:

public class Purchase { 
    private int _id; 
    private string _name; 
    private string _address; 
    private double _amount; 

    public Purchase(int id, string name, string address) { 
    //do some business rule checking to determine if event is raised 

    //perhaps send an email or do some logging 
    //etc. 
    if (should_i_raise_event) { 
     ApplyEvent(new PurchaseMadeEvent() { 
     ID = id, 
     Name = name, 
     Address = address 
     }); 
    } 
    } 

    public UpdatePurchase(int id, double amount) { 
    //more checking to see if event is to be raised 
    if (should_i_raise_event) { 
     ApplyEvent(new PurchaseUpdatedEvent() { 
     ID = id, 
     Amount = amount 
     }); 
    } 
    } 

    protected void OnPurchaseMade(PurchaseMadeEvent e){ 
    _id = e.ID; 
    _name = e.Name; 
    _address = e.Address; 
    } 

    protected void OnPurchaseUpdated(PurchaseUpdatedEvent e){ 
    _id = e.ID; 
    _amount = e.Amount; 
    } 
} 

इस उदाहरण में, जब मेरे घटनाओं पुनः बजाया जाता है, OnPurchaseMade ईवेंट हैंडलर निष्पादित हो जाएगा, न कि डोमेन वस्तु निर्माता। PurchaseUpdatedEvent के साथ ही - यह इवेंट हैंडलर निष्पादित हो जाएगा, न कि डोमेन विधि जो घटना को उठाती है।

इस कार्यक्रम में डोमेन मॉडल को अपडेट करने के लिए आवश्यक सब कुछ शामिल है (और पढ़ने के मॉडल में अपडेट लागू करें)। निष्पादित डोमेन विधियां आपको इस बिंदु पर ले जाती हैं कि एक ईवेंट उठाया जा सकता है।

मुझे आशा है कि इस मदद करता है। अगर मुझे और जानकारी प्रदान करने की ज़रूरत है तो मुझे बताएं।

शुभकामनाएं !!

6

आपको ईवेंट हैंडलर से ईवेंट नहीं बढ़ाया जाना चाहिए - बस इसे मत करो! आपको इसके बजाय sagas का उपयोग करना चाहिए।

आपके मामले में, सागा PurchaseMadeEvent के लिए सदस्यता लेता है और PromoteCustomer COMMAND जारी करता है, जो CustomerPromoted ईवेंट होने का कारण बनता है। फिर, एक और गाथा है जो CustomerPromoted ईवेंट के लिए सदस्यता लेती है और SendEmailToPromotedCustomer कमांड भेजती है। जब आप ईवेंट को दोबारा चला रहे हों - बस CustomerPromoted ईवेंट के लिए गाथा की सदस्यता न लें।

यह सब आदेश और घटना के बीच अंतर के बारे में है। इसे समझना महत्वपूर्ण है। घटनाक्रम बताते हैं कि पहले से ही क्या हुआ है, आदेश बताएं कि क्या होगा।

+0

मुझे एहसास है कि यह एक बहुत पुराना जवाब है, लेकिन सागा को 'प्रोमोटेक ग्राहक' आदेश जारी करने के बारे में पता होना चाहिए जब उसे 'खरीदमेडवेन्ट' प्राप्त होता है?यह 10 खरीदारियां बनाने वाले ग्राहक पर (ओपी के विवरण के अनुसार) निर्भर करता है, जो डोमेन तर्क है जिसमें सागा शामिल नहीं होना चाहिए। शायद हमेशा 'testToPromoteCustomer' को आग लगाना और वास्तव में पदोन्नति करने के लिए चेक करने दें? इसमें कुछ समय अनाड़ी लगता है, हालांकि .. किसी भी अंतर्दृष्टि –

+0

के लिए धन्यवाद हाँ, आप कर रहे हैं ठीक है, गाथा TestToPromoteCustomer आदेश भेजने चाहिए। मुझे लगता है कि रखरखाव के लिए शुद्धता बलिदान देना बिल्कुल ठीक है। – xelibrion