मैं अक्षतंतु और इवेंट सोर्सिंग के बारे में सीख रहा हूं और मुझे लगता है कि मैंने आखिरकार इसका हिस्सा समझ लिया है और यह मेरे दिमाग में समझ में आता है, लेकिन मैं यह सुनिश्चित करना चाहता हूं कि इसके बारे में मेरी समझ सही है और मैं कोई गलती नहीं कर रहा हूं। कोड काम करता है, और मैं अपनी 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();
}
}
मैं जो समझ सकता हूं उससे:
मेरी
TestRunner
कक्षा में, कमांड गेटवे कमांड बस का उपयोग करकेissueCardCommand
को इसकेCommandHandler
पर भेजता है, जो तबGiftCard
समुच्चय का एक नया उदाहरण बना रहा है। इसCommandHandler
में हम कोई भी तर्क कर सकते हैं, और फिर हम इसapply
विधि का उपयोग करते हैं।apply(event)
विधि का उपयोगCardIssuedEvent
कोGiftCard
के दायरे मेंEventMessage
के रूप में प्रकाशित करने के लिए किया जाता है और यह उस विशेष घटना के लिएEventSourcingHandler
को भी आमंत्रित करता है, तो इस मामले मेंonCardIssuedEvent
। यह EventMessage को EventBus पर प्रकाशित करता है और EventHandlers को भेजा जाता है।@EventSourcingHandler onCardIssuedEvent
में, हमGiftCard
समुच्चय में कोई भी राज्य परिवर्तन कर सकते हैं और हम स्प्रिंग Jpa का उपयोग करकेDOMAIN_EVENT_ENTRY
तालिका में भी घटना को जारी रख रहे हैं।एक बार यह
CommandHandler
निष्पादित हो जाने के बाद, समग्र वस्तु अब मौजूद नहीं है।अब मेरी
TestRunner
कक्षा में फिर से, कमांड गेटवेRedeemCardCommand
को उसकेCommandHandler
पर भेजता है और चूंकि पहला कमांड अब मौजूद नहीं है, खाली नो आर्ग्स कंस्ट्रक्टर का उपयोग वस्तुओं को बनाने के लिए किया जाता है। अक्षतंतु ढांचा इसDOMAIN_EVENT_ENTRY
तालिका से सभी घटनाओं को पुनः प्राप्त करता है और यह वर्तमान स्थिति प्राप्त करने के लिएGiftCard
कुल उदाहरण के लिए सभी घटनाओं (इवेंटसोर्सिंग हैंडलर) को फिर से चलाता है (यही कारण है कि@AggregateIdentifier
है जरूरी)।RedeemCardCommandHandler
विधि को तब क्रियान्वित किया जाता है, यह किसी भी तर्क को निष्पादित करता है और घटना को लागू करता है, जो कुल के भीतर प्रकाशित होता है और यहEventSourcingHandler
को आमंत्रित करता है। यहEventSourcingHandler
फिरGiftCard
की स्थिति को अपडेट करता है /DOMAIN_EVENT_ENTRY
टेबल पर बना रहता है।
क्या इवेंट सोर्सिंग के काम करने के तरीके के बारे में मेरी समझ सही है?
2 जवाब
आइए मैं आपको इस यात्रा के माध्यम से मार्गदर्शन करने का प्रयास करता हूं!
आपकी समझ लगभग पूरी तरह से सही है। बेहतर समझ के लिए मैं इसे केवल इवेंट सोर्सिंग और एक्सॉन में विभाजित करना चाहूंगा।
- इवेंट सोर्सिंग
संक्षेप में, इवेंट सोर्सिंग अतीत में हुई घटनाओं के इतिहास के माध्यम से किसी एप्लिकेशन की स्थिति को संग्रहीत करने का एक तरीका है। ध्यान रखें कि आपके पास अन्य पैटर्न भी हैं, उदाहरण के लिए स्टेट स्टोर्ड एग्रीगेट्स। आपके उदाहरण में आप इवेंट सोर्सिंग का उपयोग कर रहे हैं इसलिए @EventSourcingHandler
s क्यों हैं। अब अगले विषय पर।
- एक्सोन
मेरा सुझाव है कि आप इस अद्भुत ब्लॉग को पढ़ें। हमारे सहयोगियों में से एक, विशेष रूप से इसमें शामिल स्लाइड डेक, और आप एक्सॉन फ्रेमवर्क के अंदर एक संदेश की यात्रा देखेंगे!
अब आपकी बात पर, कुछ ऐसी बातें हैं जिन्हें मैं पहले ही स्पष्ट कर देना चाहता हूँ:
- सही है, आप एक
Command
भेजते हैं और चूंकि एनोटेट की गई विधि एक कंस्ट्रक्टर है, यह आपके लिए एक एग्रीगेट बनाएगी।CommandHanlder
व्यावसायिक तर्क और सत्यापन के लिए सही स्थान हैं। - यहां
apply
संदेश को आंतरिक रूप से प्रकाशित करेगा (इस परAggregate
लेकिन साथ ही उनकेEntities
/AggregateMember
) और बाद मेंEventBus
पर। जावाडोक से:
ईवेंट को तुरंत समग्र पर लागू किया जाना चाहिए और अन्य ईवेंट हैंडलर्स के लिए प्रकाशन के लिए शेड्यूल किया जाना चाहिए।
चूंकि हम इवेंट सोर्सिंग के बारे में बात कर रहे हैं, सभी
EventSourcingHandler
को कॉल किया जाएगा औरAggregate
की स्थिति को संशोधित/अपडेट किया जाएगा। यह महत्वपूर्ण है क्योंकि, जैसा कि पहले कहा गया है, इस तरह से आप जब भी जरूरत हो अपनी समग्र स्थिति का पुनर्निर्माण करते हैं। लेकिन घटना का बने रहना यहां नहीं होता है, यह पहले से ही होना तय था जब यह प्रक्रिया पूरी हो जाएगी।सही।
भी सही। इसका संबंध सामान्य रूप से ईवेंट सोर्सिंग से है और यह आपके
Aggregate
का पुनर्निर्माण कैसे करता है।घटना के प्रकाशित/सहेजने/निरंतर होने के संबंध में, बिंदु 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
को आपको सत्यापन केवल तभी करना चाहिए जब इस कुल के पास रिडीम करने के लिए पर्याप्त 'पैसा' हो :)
हाँ, ऐसा लगता है कि आप कमांड गेटवे का सही उपयोग कर रहे हैं, और समुच्चय में सही सामग्री के साथ सही तरीके से व्याख्या की गई है! आप वितरित लेनदेन के लिए सागा डिज़ाइन पैटर्न का उपयोग कर रहे हैं जो 2PC (दो-चरण प्रतिबद्ध) से बहुत बेहतर है, इसलिए प्रत्येक चरण अगले चरण को कॉल करने का सही तरीका है।
जब तक आरंभिक गाथा पद्धति को @StartSaga
के साथ एनोटेट किया जाता है, और अंतिम को @EndSaga
के साथ एनोटेट किया जाता है, तब तक चरण क्रम में काम करेंगे, साथ ही रोलबैक ठीक से काम करना चाहिए
saveAndWait
फ़ंक्शन वास्तव में एक CompletableFuture
देता है, इसलिए यदि आप चाहते हैं, तो आप डीबग मोड में थ्रेड्स के माध्यम से कदम उठा सकते हैं और थ्रेड को तब तक रोक सकते हैं जब तक कि पूरी गाथा पूरी न हो जाए यदि आप यही करना चाहते हैं .
मेरी एकमात्र चिंता यह है कि - क्या आप एक्सॉन सर्वर को इवेंट सोर्सर के रूप में उपयोग कर रहे हैं, या अन्य इवेंट बस या सोर्सर जो एक्सॉन सपोर्ट करता है? मानक एक्सॉन सर्वर के साथ एकमात्र समस्या यह है कि यह एक Free Tier
उत्पाद है, और वे Axon Server Enterprise
जैसे बेहतर, अधिक समर्थित संस्करण की पेशकश कर रहे हैं (जो अधिक सुविधाएं प्रदान करता है - बुनियादी ढांचे के लिए बेहतर) - इसलिए यदि आप हैं किसी कंपनी के लिए ऐसा कर रहे हैं, तो वे उच्च स्तरीय में अतिरिक्त सहायता के लिए भुगतान करने को तैयार हो सकते हैं ...
एक्सॉन फ्रेमवर्क वास्तव में स्प्रिंग एएमक्यूपी का समर्थन करता है, जो उपयोगी है क्योंकि तब, आप भुगतान के लिए Axon Server
से बंधे होने के बजाय अपने स्वयं के बुनियादी ढांचे पर बेहतर नियंत्रण रख सकते हैं - जो कि मैं वास्तव में अच्छा नहीं हूं या नहीं।
यदि आप इसे कस्टम इवेंट बस/सोर्सर के साथ काम करने के लिए प्राप्त कर सकते हैं, तो आपका सिस्टम बहुत अच्छा होगा - एक्सॉन पर विकास की आसानी के संयोजन में।
जब तक एग्रीगेट्स के पास उन पर सही एनोटेशन हैं, और आप गेटवे को सही तरीके से ऑटोवायर करने का आदेश देते हैं, तो सब कुछ ठीक काम करना चाहिए। मेरी एकमात्र चिंता यह है कि अभी तक Axon Framework
के लिए पर्याप्त समर्थन नहीं है...
संबंधित सवाल
नए सवाल
spring-boot
स्प्रिंग बूट एक ऐसा ढांचा है, जो पूर्ण न्यूनतम उपद्रव के साथ आसानी से वसंत-संचालित, उत्पादन-ग्रेड अनुप्रयोगों और सेवाओं को बनाने की अनुमति देता है। यह स्प्रिंग प्लेटफ़ॉर्म के नए और अनुभवी उपयोगकर्ताओं के लिए काम करने के लिए डिज़ाइन किए गए स्प्रिंग प्लेटफ़ॉर्म के बारे में एक राय लेता है।