วิธีจัดการกับผลข้างเคียงใน CRQS เมื่อเล่นซ้ำเหตุการณ์


10

ว่ากันว่าใน CQRS มันง่ายที่จะแก้ไขข้อบกพร่องคุณเพียงแค่ปรับใช้ใหม่แล้วเล่นซ้ำเหตุการณ์

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

คุณจะแก้ไขปัญหานี้อย่างไร

คำตอบ:


6

คุณต้องแยกความแตกต่างอย่างชัดเจนระหว่างเหตุการณ์ที่แก้ไขสถานะของโมเดลการอ่านของคุณและเหตุการณ์ (อาจ) การปรับเปลี่ยนสถานะของระบบภายนอก ตรวจสอบให้แน่ใจว่าคุณไม่มี "เหตุการณ์แบบผสม" ที่แก้ไขทั้งสองสถานะเข้าด้วยกัน ด้วยวิธีนี้คุณสามารถเล่นซ้ำเหตุการณ์ของคุณใน "โหมดเล่นซ้ำ" โดยที่เหตุการณ์เหล่านั้นสำหรับระบบภายนอกจะไม่เริ่มทำงานอีกครั้ง ในโหมดนี้คุณยัง "จำลอง" เหตุการณ์ใด ๆ ที่เริ่มต้นโดยระบบภายนอก (ตอนนี้คุณจะนำพวกเขาออกจากคิวเล่นซ้ำแทน)

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


"อย่าลืมขั้นตอนการปรับใช้ซ้ำหมายถึงการรีเซ็ตสถานะของรูปแบบการอ่านเป็นเวลาก่อนหน้าซึ่งอาจเป็นสิ่งที่คุณไม่สามารถทำได้ (หรือต้องทำ) สำหรับสถานะของระบบภายนอก" -> แต่ถ้าฉันต้องการให้เล่นซ้ำลองระบบภายนอกที่ล้มเหลวเช่นการส่ง ในกรณีนี้การปรับใช้การเล่นซ้ำของฉันไม่เพียง แต่จะรีเซ็ตสถานะของรูปแบบการอ่าน แต่ยังทำให้เกิดเหตุการณ์ภายนอกสิ่งนี้ฟังดูเป็นธรรมหรือฉันกำลังทำอะไรบางอย่างหายไปหรือไม่
Jas

2
@Jas: คุณไม่ต้องการใช้ "เล่นซ้ำ" เพื่อลองการเรียกระบบภายนอกที่ล้มเหลวอีกครั้ง คุณใช้ "เล่นซ้ำ" เพื่อทำให้โมเดลการอ่านของระบบของคุณอยู่ในสภาพเดิมเหมือนเดิม ซึ่งหมายความว่าในกรณีที่มีการร้องขอการจัดส่งที่ล้มเหลวระบบของคุณจะได้รับแจ้งก่อนหน้านี้เกี่ยวกับความล้มเหลวนี้และเก็บข้อมูลนั้นไว้ที่ใดที่หนึ่ง การเล่นซ้ำทำให้แน่ใจว่าข้อมูลนี้ยังคงอยู่หลังจาก "ปรับใช้ซ้ำ & การเล่นซ้ำ" ดังนั้นหลังจากการเล่นซ้ำระบบของคุณอาจใช้กลยุทธ์ "ลองส่งใหม่ในกรณีที่เกิดความล้มเหลว" (ซึ่งไม่เกี่ยวข้องกับ CQRS ระบบการสั่งซื้อที่แข็งแกร่งควรมีกลยุทธ์ดังกล่าว)
Doc Brown

ที่น่าสนใจนี่คือสิ่งที่ฉันคิดไว้ในใจทำเพียงแค่สงสัยว่ามี "รูปแบบ" เกี่ยวกับเรื่องนี้ดังนั้นฉันไม่ได้คิดค้นใหม่ล้อ!
Jas

3

จากบทความการจัดหางานของ Martin Fowler

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

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

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


2

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

ในการเลือกตัวอย่างที่เฉพาะเจาะจงลองพิจารณาว่าวิธี "ผลกระทบข้างเคียง" อย่างน้อยหนึ่งครั้งอาจมีผลอย่างไร

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

ดังนั้นโมเดลโดเมนจะติดตามสิ่งที่ต้องทำ แต่ปล่อยให้ทำจริงกับแอปพลิเคชัน

ในบริบทของการรันคำสั่งแนวคิดพื้นฐานจะมีลักษณะเหมือนกัน ผลข้างเคียงที่เกิดขึ้นจริงเกิดขึ้นนอกธุรกรรมที่อัพเดตโมเดล

ดังนั้นการทดสอบหน่วยสำหรับแบบจำลองของคุณอาจดูเหมือน

{
    // 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()
}

ประเด็นหลักที่นี่เป็น

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