मैं अक्षतंतु और इवेंट सोर्सिंग के बारे में सीख रहा हूं और मुझे लगता है कि मैंने आखिरकार इसका हिस्सा समझ लिया है और यह मेरे दिमाग में समझ में आता है, लेकिन मैं यह सुनिश्चित करना चाहता हूं कि इसके बारे में मेरी समझ सही है और मैं कोई गलती नहीं कर रहा हूं। कोड काम करता है, और मैं अपनी DOMAIN_EVENT_ENTRY तालिका में भी ईवेंट देख सकता हूं।

मैं अपना कोड नीचे पोस्ट करूंगा (दस्तावेज़ों से सरल गिफ्टकार्ड उदाहरण) और अपनी विचार प्रक्रिया की व्याख्या करूंगा। अगर मैं इसे सही ढंग से नहीं समझ पाया हूं, तो क्या आप उस हिस्से को सही तरीके से समझने में मेरी मदद कर सकते हैं।

मैंने आदेश/घटनाओं को शामिल नहीं किया है क्योंकि वे आईडी, राशि के लिए फ़ील्ड के साथ बहुत सरल हैं

पहले मेरा कोड:

टेस्ट रनर.जावा

package com.example.demoaxon;

import java.util.UUID;

import org.axonframework.commandhandling.gateway.CommandGateway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class TestRunner implements CommandLineRunner {
    
    private final CommandGateway commandGateway;
    
    @Autowired
    public TestRunner(CommandGateway commandGateway) {
        this.commandGateway = commandGateway;
    }
    
    @Override
    public void run(String... args) throws Exception {
        log.info("send command");
        String id = UUID.randomUUID().toString();
        commandGateway.sendAndWait(new IssueCardCommand(id,100));
        commandGateway.sendAndWait(new RedeemCardCommand(id,90));
        
    }
}

गिफ्टकार्ड.जावा

package com.example.demoaxon;

import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.eventsourcing.EventSourcingHandler;
import org.axonframework.modelling.command.AggregateIdentifier;
import static org.axonframework.modelling.command.AggregateLifecycle.apply;
import org.axonframework.spring.stereotype.Aggregate;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@NoArgsConstructor
@Aggregate
@Slf4j
public class GiftCard {
    
    @AggregateIdentifier
    private String giftCardId;
    private Integer amount;
    
    @CommandHandler
    public GiftCard(IssueCardCommand cmd) {
        log.info("handling {}",cmd);
        apply(new CardIssuedEvent(cmd.getCardId(),cmd.getAmount()));
    }
    
    @EventSourcingHandler
    public void onCardIssuedEvent(CardIssuedEvent evt) {
        log.info("applying {}",evt);
        this.giftCardId = evt.getCardId();
        this.amount = evt.getAmount();
    }
    
    @CommandHandler
    public void redeemCardCommandHandler(RedeemCardCommand cmd) {
        log.info("handling {}",cmd);
        this.amount -= cmd.getAmount();
        apply(new CardRedeemedEvent(cmd.getCardId(),cmd.getTransactionId(),this.amount));
    }
    
    @EventSourcingHandler
    public void onCardRedeemedEvent(CardRedeemedEvent evt) {
        log.info("applying {}",evt);
        this.amount = evt.getAmount();
    }   
}

मैं जो समझ सकता हूं उससे:

  1. मेरी TestRunner कक्षा में, कमांड गेटवे कमांड बस का उपयोग करके issueCardCommand को इसके CommandHandler पर भेजता है, जो तब GiftCard समुच्चय का एक नया उदाहरण बना रहा है। इस CommandHandler में हम कोई भी तर्क कर सकते हैं, और फिर हम इस apply विधि का उपयोग करते हैं।

  2. apply(event) विधि का उपयोग CardIssuedEvent को GiftCard के दायरे में EventMessage के रूप में प्रकाशित करने के लिए किया जाता है और यह उस विशेष घटना के लिए EventSourcingHandler को भी आमंत्रित करता है, तो इस मामले में onCardIssuedEvent। यह EventMessage को EventBus पर प्रकाशित करता है और EventHandlers को भेजा जाता है।

  3. @EventSourcingHandler onCardIssuedEvent में, हम GiftCard समुच्चय में कोई भी राज्य परिवर्तन कर सकते हैं और हम स्प्रिंग Jpa का उपयोग करके DOMAIN_EVENT_ENTRY तालिका में भी घटना को जारी रख रहे हैं।

  4. एक बार यह CommandHandler निष्पादित हो जाने के बाद, समग्र वस्तु अब मौजूद नहीं है।

  5. अब मेरी TestRunner कक्षा में फिर से, कमांड गेटवे RedeemCardCommand को उसके CommandHandler पर भेजता है और चूंकि पहला कमांड अब मौजूद नहीं है, खाली नो आर्ग्स कंस्ट्रक्टर का उपयोग वस्तुओं को बनाने के लिए किया जाता है। अक्षतंतु ढांचा इस DOMAIN_EVENT_ENTRY तालिका से सभी घटनाओं को पुनः प्राप्त करता है और यह वर्तमान स्थिति प्राप्त करने के लिए GiftCard कुल उदाहरण के लिए सभी घटनाओं (इवेंटसोर्सिंग हैंडलर) को फिर से चलाता है (यही कारण है कि @AggregateIdentifier है जरूरी)।

  6. RedeemCardCommandHandler विधि को तब क्रियान्वित किया जाता है, यह किसी भी तर्क को निष्पादित करता है और घटना को लागू करता है, जो कुल के भीतर प्रकाशित होता है और यह EventSourcingHandler को आमंत्रित करता है। यह EventSourcingHandler फिर GiftCard की स्थिति को अपडेट करता है / DOMAIN_EVENT_ENTRYटेबल पर बना रहता है।

क्या इवेंट सोर्सिंग के काम करने के तरीके के बारे में मेरी समझ सही है?

4
amasuKAKAROT 7 जिंदा 2021, 16:52

2 जवाब

सबसे बढ़िया उत्तर

आइए मैं आपको इस यात्रा के माध्यम से मार्गदर्शन करने का प्रयास करता हूं!

आपकी समझ लगभग पूरी तरह से सही है। बेहतर समझ के लिए मैं इसे केवल इवेंट सोर्सिंग और एक्सॉन में विभाजित करना चाहूंगा।

  • इवेंट सोर्सिंग

संक्षेप में, इवेंट सोर्सिंग अतीत में हुई घटनाओं के इतिहास के माध्यम से किसी एप्लिकेशन की स्थिति को संग्रहीत करने का एक तरीका है। ध्यान रखें कि आपके पास अन्य पैटर्न भी हैं, उदाहरण के लिए स्टेट स्टोर्ड एग्रीगेट्स। आपके उदाहरण में आप इवेंट सोर्सिंग का उपयोग कर रहे हैं इसलिए @EventSourcingHandlers क्यों हैं। अब अगले विषय पर।

  • एक्सोन

मेरा सुझाव है कि आप इस अद्भुत ब्लॉग को पढ़ें। हमारे सहयोगियों में से एक, विशेष रूप से इसमें शामिल स्लाइड डेक, और आप एक्सॉन फ्रेमवर्क के अंदर एक संदेश की यात्रा देखेंगे!

अब आपकी बात पर, कुछ ऐसी बातें हैं जिन्हें मैं पहले ही स्पष्ट कर देना चाहता हूँ:

  1. सही है, आप एक Command भेजते हैं और चूंकि एनोटेट की गई विधि एक कंस्ट्रक्टर है, यह आपके लिए एक एग्रीगेट बनाएगी। CommandHanlder व्यावसायिक तर्क और सत्यापन के लिए सही स्थान हैं।
  2. यहां apply संदेश को आंतरिक रूप से प्रकाशित करेगा (इस पर Aggregate लेकिन साथ ही उनके Entities/AggregateMember) और बाद में EventBus पर। जावाडोक से:

ईवेंट को तुरंत समग्र पर लागू किया जाना चाहिए और अन्य ईवेंट हैंडलर्स के लिए प्रकाशन के लिए शेड्यूल किया जाना चाहिए।

  1. चूंकि हम इवेंट सोर्सिंग के बारे में बात कर रहे हैं, सभी EventSourcingHandler को कॉल किया जाएगा और Aggregate की स्थिति को संशोधित/अपडेट किया जाएगा। यह महत्वपूर्ण है क्योंकि, जैसा कि पहले कहा गया है, इस तरह से आप जब भी जरूरत हो अपनी समग्र स्थिति का पुनर्निर्माण करते हैं। लेकिन घटना का बने रहना यहां नहीं होता है, यह पहले से ही होना तय था जब यह प्रक्रिया पूरी हो जाएगी।

  2. सही।

  3. भी सही। इसका संबंध सामान्य रूप से ईवेंट सोर्सिंग से है और यह आपके Aggregate का पुनर्निर्माण कैसे करता है।

  4. घटना के प्रकाशित/सहेजने/निरंतर होने के संबंध में, बिंदु 3 पर की गई टिप्पणियों के साथ भी सही करें।


आपके कोड पर एक और छोटा पक्ष नोट: आप इसे अपने @CommandHandler पर कर रहे हैं

@CommandHandler
public void redeemCardCommandHandler(RedeemCardCommand cmd) {
    log.info("handling {}", cmd);
    this.amount -= cmd.getAmount(); // you should not do this here
    apply(new CardRedeemedEvent(cmd.getCardId(), cmd.getTransactionId(), this.amount));
}

यह राज्य परिवर्तन @EventSourcingHandler में किया जाना चाहिए। @CommandHandler को आपको सत्यापन केवल तभी करना चाहिए जब इस कुल के पास रिडीम करने के लिए पर्याप्त 'पैसा' हो :)

3
Steven 15 जिंदा 2021, 19:27

हाँ, ऐसा लगता है कि आप कमांड गेटवे का सही उपयोग कर रहे हैं, और समुच्चय में सही सामग्री के साथ सही तरीके से व्याख्या की गई है! आप वितरित लेनदेन के लिए सागा डिज़ाइन पैटर्न का उपयोग कर रहे हैं जो 2PC (दो-चरण प्रतिबद्ध) से बहुत बेहतर है, इसलिए प्रत्येक चरण अगले चरण को कॉल करने का सही तरीका है।

जब तक आरंभिक गाथा पद्धति को @StartSaga के साथ एनोटेट किया जाता है, और अंतिम को @EndSaga के साथ एनोटेट किया जाता है, तब तक चरण क्रम में काम करेंगे, साथ ही रोलबैक ठीक से काम करना चाहिए

saveAndWait फ़ंक्शन वास्तव में एक CompletableFuture देता है, इसलिए यदि आप चाहते हैं, तो आप डीबग मोड में थ्रेड्स के माध्यम से कदम उठा सकते हैं और थ्रेड को तब तक रोक सकते हैं जब तक कि पूरी गाथा पूरी न हो जाए यदि आप यही करना चाहते हैं .

मेरी एकमात्र चिंता यह है कि - क्या आप एक्सॉन सर्वर को इवेंट सोर्सर के रूप में उपयोग कर रहे हैं, या अन्य इवेंट बस या सोर्सर जो एक्सॉन सपोर्ट करता है? मानक एक्सॉन सर्वर के साथ एकमात्र समस्या यह है कि यह एक Free Tier उत्पाद है, और वे Axon Server Enterprise जैसे बेहतर, अधिक समर्थित संस्करण की पेशकश कर रहे हैं (जो अधिक सुविधाएं प्रदान करता है - बुनियादी ढांचे के लिए बेहतर) - इसलिए यदि आप हैं किसी कंपनी के लिए ऐसा कर रहे हैं, तो वे उच्च स्तरीय में अतिरिक्त सहायता के लिए भुगतान करने को तैयार हो सकते हैं ...

एक्सॉन फ्रेमवर्क वास्तव में स्प्रिंग एएमक्यूपी का समर्थन करता है, जो उपयोगी है क्योंकि तब, आप भुगतान के लिए Axon Server से बंधे होने के बजाय अपने स्वयं के बुनियादी ढांचे पर बेहतर नियंत्रण रख सकते हैं - जो कि मैं वास्तव में अच्छा नहीं हूं या नहीं।

यदि आप इसे कस्टम इवेंट बस/सोर्सर के साथ काम करने के लिए प्राप्त कर सकते हैं, तो आपका सिस्टम बहुत अच्छा होगा - एक्सॉन पर विकास की आसानी के संयोजन में।

जब तक एग्रीगेट्स के पास उन पर सही एनोटेशन हैं, और आप गेटवे को सही तरीके से ऑटोवायर करने का आदेश देते हैं, तो सब कुछ ठीक काम करना चाहिए। मेरी एकमात्र चिंता यह है कि अभी तक Axon Framework के लिए पर्याप्त समर्थन नहीं है...

1
Ben Neighbour 10 जिंदा 2021, 17:59