2011-09-05 31 views
12

Tôi đang cố gắng tìm hiểu những gì sẽ xảy ra khi xây dựng lại mô hình bằng cách phát lại sự kiện từ EventStore, đặc biệt khi sự kiện có thể kích hoạt các sự kiện khác xảy ra. Ví dụ:Event Sourcing: Sự kiện kích hoạt người khác và xây dựng lại trạng thái

Ví dụ: người dùng đã thực hiện 10 lần mua hàng nên được quảng bá cho khách hàng ưu tiên và nhận email cung cấp cho họ một số quảng cáo nhất định.

Chúng tôi rõ ràng không muốn gửi email mỗi khi chúng tôi xây dựng lại mô hình cho người dùng đó, nhưng làm cách nào để chúng tôi dừng điều này khi chúng tôi phát lại số PurchaseMadeEvent?

Trả lời

8

Chuỗi sự kiện có thể rất phức tạp và dễ dàng vượt quá tầm kiểm soát, vì vậy, tôi tránh nó càng nhiều càng tốt. Ví dụ: trong trường hợp bạn mô tả tôi sẽ tăng UserPromotedEvent (thậm chí có thể sử dụng số PromoteUserCommand), tuy nhiên tôi sẽ không xem xét việc gửi email thực tế/vật lý như một phần của miền của tôi. Thay vào đó, tôi sẽ tạo thêm trình xử lý/denormalizer cho UserPromotedEvent để đăng ký nhu cầu gửi email với một số kiểm tra bổ sung khá có thể. Sau đó, một quy trình khác sẽ thu thập thông tin về các email chưa được xử lý và gửi chúng. Cách tiếp cận này sẽ giảm thiểu các vấn đề có thể xảy ra với cổng email không thể truy cập/mở rộng hoàn toàn.

Nói chung hơn - nhu cầu chuỗi sự kiện thường xuyên chỉ ra rằng bạn nên cân nhắc triển khai Saga cho quy trình.

2

Khi bạn phát lại sự kiện, bạn sẽ không phát lại tất cả logic miền đi kèm với việc tạo các sự kiện đó. Thông thường trong phương pháp miền của bạn, bạn sẽ tăng một sự kiện; việc nâng cao sự kiện đó sau đó sẽ cập nhật trạng thái tổng thể của đối tượng miền đó.

Ví dụ:

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; 
    } 
} 

Trong ví dụ này, khi các sự kiện của tôi được tái hiện lại, xử lý OnPurchaseMade Sự kiện này sẽ được thực hiện, chứ không phải các nhà xây dựng đối tượng miền. Tương tự với PurchaseUpdatedEvent - trình xử lý sự kiện của nó sẽ được thực thi chứ không phải phương thức miền đã tăng sự kiện.

Sự kiện chứa mọi thứ bạn cần cập nhật mô hình miền (và áp dụng các cập nhật cho mô hình đã đọc). Các phương thức miền được thực thi đưa bạn đến mức một sự kiện có thể được nâng lên.

Tôi hy vọng điều này sẽ hữu ích. Hãy cho tôi biết nếu tôi cần cung cấp thêm thông tin.

Chúc may mắn !!

6

Bạn không nên tăng sự kiện từ trình xử lý sự kiện - chỉ cần không làm điều đó! Bạn nên sử dụng sagas để thay thế.

Trong trường hợp của bạn, saga đăng ký PurchaseMadeEvent và các vấn đề PromoteCustomer COMMAND, điều này gây ra sự kiện CustomerPromoted. Một lần nữa, có một câu chuyện khác đăng ký sự kiện CustomerPromoted và gửi lệnh SendEmailToPromotedCustomer. Khi bạn đang phát lại sự kiện - chỉ cần không đăng ký saga cho sự kiện CustomerPromoted.

Đây là tất cả về sự khác biệt giữa lệnh và sự kiện. Điều quan trọng là phải hiểu nó. Sự kiện cho biết những gì đã xảy ra, lệnh cho biết điều gì sẽ xảy ra.

+0

Tôi nhận ra đây là câu trả lời khá cũ nhưng, Saga sẽ biết cách phát hành lệnh 'PromoteCustomer' khi nhận được' PurchaseMadeEvent' như thế nào?Điều này dựa vào (theo mô tả của OP) về khách hàng đã thực hiện 10 lần mua hàng, đó là logic miền mà Saga không nên chứa. Có lẽ luôn kích hoạt 'TestToPromoteCustomer' và để tổng hợp thực hiện kiểm tra để thực sự thực hiện chương trình khuyến mãi? Điều này cảm thấy một chút vụng về mặc dù .. Cảm ơn cho bất kỳ cái nhìn sâu sắc –

+0

Vâng, bạn nói đúng, saga nên gửi lệnh TestToPromoteCustomer. Tôi nghĩ rằng nó hoàn toàn OK để hy sinh tinh khiết cho bảo trì. – xelibrion

Các vấn đề liên quan