จะสร้างรูทรวมใหม่ใน CQRS ได้อย่างไร?


10

เราควรสร้างรูทรวมใหม่ในสถาปัตยกรรม cqrs อย่างไร ในตัวอย่างนี้ฉันต้องการสร้างรากรวม AR2 ใหม่ที่เก็บการอ้างอิงถึงหนึ่ง AR1

ฉันกำลังสร้าง AR2 โดยใช้วิธี AR1 เป็นจุดเริ่มต้น จนถึงตอนนี้ฉันเห็นตัวเลือกน้อย:

  1. Inside method ใน AR1 createAr2RootOpt1ฉันสามารถโทรnew AR2()และบันทึกออบเจ็กต์นี้ไปยัง db imediatelly โดยใช้บริการโดเมนที่มีที่เก็บข้อมูล
  2. ฉันสามารถปล่อยเหตุการณ์ในรากรวมแรกเช่น SholdCreateAR2Eventและจากนั้นก็มีเทพนิยายไร้สัญชาติที่ตอบสนองต่อสิ่งนี้และออกคำสั่งCreateAR2Commandที่ได้รับการจัดการและสร้าง AR2 และปล่อยออกAR2CreatedEventมา ในกรณีของการใช้การจัดหาเหตุการณ์SholdCreateAR2Eventจะไม่ถูกเก็บไว้ในที่จัดเก็บกิจกรรมเนื่องจากจะไม่ส่งผลกระทบต่อสถานะของการรวมรากแรก (หรือเราควรบันทึกสิ่งนี้ไว้ในที่จัดเก็บกิจกรรม)

    class AR1{
        Integer id;
        DomainService ds;
    
        //OPTION 1
        void createAr2RootOpt1(){
            AR2 ar2 = new AR2();
            ds.saveToRepo(ar2);
        }
    
        //OPTION 2
        void createAr2RootOpt2(){
            publishEvent(new SholdCreateAR2Event());    //we don't need this event. Shoud it still be preserved in event store?
        }
    }
    
    class AR2{
        Integer id;
        Integer ar1Id;
    
        void handle(CreateAR2Command command){
            //init this AR with values and save
            publishEvent(AR2CreatedEvent());    //used for projections afterwards and saved inside AR2 event store
        }
    }
    
    class Saga{
        void handle(SholdCreateAR2Event ev){
            emitCommand(new CreateAR2Command());
        }
    }
    

วิธีใดที่เหมาะสมกว่าในการทำเช่นนี้

คำตอบ:


2

ฉันคิดว่าไม่มีตัวเลือก 2 เป็นวิธีการแก้ไขที่มีขนาดเล็ก แต่มีความสำคัญ: AR1ไม่ควรปล่อยเหตุการณ์ที่มีวัตถุประสงค์เพื่อสร้างAR2แต่ควรจะปล่อยAR1WasCreatedเหตุการณ์ AR1เหตุการณ์นี้ควรได้รับการยืนยันในการจัดเก็บเหตุการณ์ที่เกิดขึ้นในขณะที่มันเป็นเหตุการณ์ที่สำคัญการทำเครื่องหมายการเกิดของ จากนั้นSagalistent Whould สำหรับAR1WasCreatedเหตุการณ์และการสร้างคำสั่งในการสร้าง:AR2CreateAR2Command

ตัวเลือกที่ 1 ผิดมาก Aggregateคุณไม่ควรฉีดชนิดของการบริการโดเมนที่ใน Aggregatesควรบริสุทธิ์โดยไม่มีผลข้างเคียงอื่น ๆ ที่เกิดจากเหตุการณ์

PS ฉันไม่เคยปล่อยออกมาจากเหตุการณ์ที่เกิดขึ้นสร้างของที่Aggregateเป็นมีความแตกต่างระหว่างการสร้างอินสแตนซ์ของวัตถุ (ในความรู้สึกของการเขียนโปรแกรมภาษา) และการสร้าง (เกิดถ้าคุณต้องการ) Aggregateของ ฉันส่งเหตุการณ์จากhandleเมธอดเท่านั้น(เมื่อจัดการ a command)


คุณหมายถึงAR1WasCreatedอะไร มันควรจะเป็นAR2WasCreatedอย่างไร นอกจากนี้ถ้าฉันใช้ตรรกะของคุณฉันปล่อยเหตุการณ์AR2WasCreatedก่อนที่มันจะถูกสร้างขึ้นจริง? และการบันทึกเหตุการณ์นี้ไว้ในบันทึกเหตุการณ์ของ AR1 ดูเหมือนว่ามีปัญหาเนื่องจากฉันไม่ต้องการข้อมูลนี้ใน AR1 (ไม่ได้แก้ไขอะไรใน AR1)
Bojan Vukasovic

ตกลง 3 ปีต่อมา มันจะไปAR1WasCreated-> SAGA (มีกฎถ้า A1 ถูกสร้างขึ้นแล้วสร้าง A2) -> ->CreateAR2Command AR2WasCreated
Bojan Vukasovic

@BojanVukasovic ฉันดีใจที่มันทำงานได้ดีในขณะที่ฉันเขียน :)
Constantin Galbenu

2

เราควรสร้างรูทรวมใหม่ในสถาปัตยกรรม cqrs อย่างไร

รูปแบบการสร้างมีความแปลก

Udi Dahan มีสิ่งที่มีประโยชน์บางอย่างที่จะพูดเกี่ยวกับปัญหาที่เกิดขึ้นโดยทั่วไป: อย่าสร้างรากรวม จุดพื้นฐานที่การรวมนั้นไม่เพียง แต่โผล่ออกมาจากที่ใดและมีภาษาโดเมนที่อธิบายลักษณะที่ปรากฏซึ่งควรบันทึกในรูปแบบโดเมนของคุณ

โดยที่มันมีแนวโน้มที่จะถูกบิดคือเอนทิตีในรูปแบบโดเมนของคุณที่กำลังประมวลผลคำสั่งไม่ใช่เอนทิตีที่ได้รับการแก้ไขโดยการทำธุรกรรม นั่นไม่ผิดหรอก เป็นเรื่องแปลก (เทียบกับกรณีที่คุณขอให้นิติบุคคลแก้ไขตัวเอง

วิธีที่สองของคุณก็โอเค "เหตุการณ์ที่เราเพิ่มโดยไม่มีการบันทึกลงในฐานข้อมูล" บางครั้งเรียกว่า "กิจกรรมโดเมน"

แนวคิดพื้นฐานที่ว่าภายในธุรกรรมเดียวกันตัวจัดการคำสั่งจะยกเหตุการณ์ซึ่งเดินทางไปตามรถบัสไปยังตัวจัดการเหตุการณ์ที่อนุญาตให้การรวมครั้งที่สองเพื่อสร้างตัวเอง คุณอาจได้รหัสที่ดีกว่ากัน

หมายเหตุ: ในระบบที่มาจากเหตุการณ์คุณมักจะไม่ใช้เหตุการณ์ด้วยวิธีนี้

ในกรณีของการใช้การจัดหาเหตุการณ์ ShouldCreateAR2Event จะไม่ถูกเก็บไว้ในที่จัดเก็บเนื่องจากมันจะไม่ส่งผลกระทบต่อสถานะของรูทรวมครั้งแรก

หมายเหตุ: ชื่อเหตุการณ์มักจะอยู่ในช่วงเวลาที่ผ่านมา - ShouldCrateAR2 มีการสะกดผิด

ใช่ถ้าคุณเพียงแค่โยนเหตุการณ์ไปยังซิงโครนัสบัสเพื่อเรียกใช้รหัสระยะไกลคุณไม่ควรบันทึกเหตุการณ์นั้นในสมุดบันทึก มันเป็นเพียงรายละเอียดการนำไปปฏิบัติในระดับนี้

หรือว่าเราควรจะเก็บมันไว้ใน Event Store?

หลีกเลี่ยงการแก้ไขสตรีมเหตุการณ์สองเหตุการณ์ที่แตกต่างกันในธุรกรรมเดียวกัน หากการสร้างนี้แสดงถึงการเปลี่ยนแปลงของ AR1 คำตอบปกติก็คือการแก้ไข AR1 ในการทำธุรกรรมนี้โดยมีผู้สมัครสมาชิกแบบอะซิงโครนัสกับกิจกรรมเหล่านั้นที่รับผิดชอบการยิงคำสั่งเพื่อสร้าง AR2

การจัดการคำสั่ง Idempotent ช่วยได้มากที่นี่


ขอบคุณสำหรับคำตอบ. อีกสิ่งหนึ่งที่ไม่ชัดเจน 100% - ต่อมาถ้าฉันต้องใช้ AR2 เป็นอาร์กิวเมนต์ของ AR1 ฉันควรผ่านสิ่งนี้อย่างไร - เนื่องจาก CQRS ระบุว่า AR ควรใช้สำหรับการเขียนเท่านั้นและไม่ทำการสืบค้น แต่ฉันไม่มีตัวเลือกอื่นนอกเหนือจากการใช้AR1.doSmthn(AR2 param)เนื่องจากการฉายภาพการอ่านที่ฉันสร้างไม่มีข้อมูลที่สมบูรณ์ที่ฉันต้องการ (เฉพาะ AR2 เท่านั้นที่มีข้อมูลที่สมบูรณ์)
Bojan Vukasovic

> "ใช่ถ้าคุณเพิ่งจะโยนเหตุการณ์ไปยังซิงโครนัสบัสเพื่อเรียกใช้รหัสระยะไกลคุณไม่ควรบันทึกเหตุการณ์นั้นในสมุดบันทึก" ฉันคิดว่าการประหยัดมันมีคุณค่าอย่างแท้จริงเมื่อคุณรู้ว่ากระบวนการนี้เริ่มต้นขึ้นเพื่อให้บางสิ่งเกิดขึ้นตอนนี้คุณสามารถติดตามได้ว่าสิ่งนี้เสร็จสมบูรณ์จริงหรือไม่ แต่ฉันคิดว่ามันขึ้นอยู่กับกรณีการใช้งาน
Chaosekie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.