Làm cách nào để xử lý các tác dụng phụ trong Tìm nguồn sự kiện?


14

Giả sử rằng chúng tôi muốn triển khai một hệ thống con bảo mật nhỏ cho một ứng dụng tài chính cảnh báo người dùng qua email nếu phát hiện một mẫu lạ. Trong ví dụ này, mẫu sẽ bao gồm ba giao dịch như được mô tả. Hệ thống con bảo mật có thể đọc các sự kiện từ hệ thống chính từ hàng đợi.

Những gì tôi muốn nhận được là một cảnh báo là hậu quả trực tiếp của các sự kiện xảy ra trong hệ thống, không có biểu diễn trung gian mô hình trạng thái hiện tại của mẫu.

  1. Giám sát kích hoạt
  2. Xử lý giao dịch
  3. Xử lý giao dịch
  4. Xử lý giao dịch
  5. Thông báo được kích hoạt (id: 123)
  6. Email để gửi thông báo (cho id: 123)
  7. Xử lý giao dịch

Có điều này trong tâm trí, tôi nghĩ nguồn cung cấp sự kiện có thể áp dụng ở đây rất tốt, mặc dù tôi có một câu hỏi mà không có câu trả lời rõ ràng. Cảnh báo được kích hoạt trong ví dụ có tác dụng phụ rõ ràng, một email cần được gửi, một tình huống chỉ nên xảy ra một lần. Do đó, điều đó không nên xảy ra khi phát lại tất cả các sự kiện của tổng hợp.

Ở một mức độ nào đó, tôi thấy email cần được gửi tương tự như các vật liệu được tạo bởi phía truy vấn mà tôi đã thấy rất nhiều lần trong tài liệu tìm nguồn cung ứng CQRS / Sự kiện, với sự khác biệt không quá tinh tế.

Trong tài liệu này, phía truy vấn được xây dựng từ các trình xử lý sự kiện có thể tạo ra sự cụ thể hóa của trạng thái tại một điểm nhất định đọc lại tất cả các sự kiện. Tuy nhiên, trong trường hợp này, điều đó không thể được thực hiện chính xác như thế vì những lý do đã giải thích trước đó. Ý tưởng rằng mọi trạng thái là nhất thời không áp dụng tốt ở đây . Chúng ta cần ghi lại thực tế là một cảnh báo đã được gửi đi đâu đó.

Một giải pháp dễ dàng cho tôi sẽ là có một bảng hoặc cấu trúc khác trong đó bạn lưu giữ các bản ghi thông báo đã được kích hoạt trước đó. Khi chúng tôi có ID, chúng tôi sẽ có thể kiểm tra xem một cảnh báo có cùng ID được đưa ra trước đó hay không. Có thông tin này sẽ làm cho SendAlertCommand trở nên bình thường. Một số lệnh có thể được ban hành, nhưng tác dụng phụ sẽ chỉ xảy ra một lần.

Ngay cả khi có giải pháp đó trong đầu, tôi cũng không biết liệu đây có phải là một gợi ý rằng có điều gì đó không ổn với kiến ​​trúc này cho vấn đề này không.

  • Cách tiếp cận của tôi có đúng không?
  • Có nơi nào tôi có thể tìm thêm thông tin về điều này?

Thật kỳ lạ khi tôi không thể tìm thấy thêm thông tin về điều này. Có lẽ tôi đã sử dụng từ ngữ sai.

Cảm ơn bạn rất nhiều!

Câu trả lời:


12

Làm cách nào để xử lý các tác dụng phụ trong Tìm nguồn sự kiện?

Phiên bản ngắn: mô hình miền không thực hiện các tác dụng phụ. Nó theo dõi họ. Tác dụng phụ được thực hiện bằng cách sử dụng một cổng kết nối với ranh giới; khi email được gửi, bạn gửi xác nhận trở lại mô hình miền.

Điều này có nghĩa là email được gửi bên ngoài giao dịch cập nhật luồng sự kiện.

Chính xác ở đâu, bên ngoài, là một vấn đề của hương vị.

Về mặt khái niệm, bạn có một luồng các sự kiện như

EmailPrepared(id:123)
EmailPrepared(id:456)
EmailPrepared(id:789)
EmailDelivered(id:456)
EmailDelivered(id:789)

Và từ luồng này, bạn có thể tạo một nếp gấp

{
    deliveredMail : [ 456, 789 ],
    undeliveredMail : [123]
}

Nếp gấp cho bạn biết những email nào chưa được xác nhận, vì vậy bạn gửi lại chúng:

undeliveredMail.each ( mail -> {
    send(mail);
    dispatch( new EmailDelivered.from(mail) );
}     

Thực tế, đây là một cam kết hai giai đoạn: bạn đang sửa đổi SMTP trong thế giới thực và sau đó bạn đang cập nhật mô hình.

Mẫu trên cung cấp cho bạn một mô hình phân phối ít nhất một lần. Nếu bạn muốn nhiều nhất một lần, bạn có thể xoay nó

undeliveredMail.each ( mail -> {
    commit( new EmailDelivered.from(mail) );
    send(mail);
}     

Có một rào cản giao dịch giữa việc làm cho EmailPrepared bền và thực sự gửi email. Cũng có một rào cản giao dịch giữa việc gửi email và làm cho EmailDeliver được bền.

Tin nhắn đáng tin cậy của Udi Dahan với các giao dịch phân tán có thể là điểm khởi đầu tốt.


2

Bạn cần tách 'Sự kiện thay đổi trạng thái' khỏi 'Hành động'

Một Nhà nước tổ chức sự kiện Thay đổi là một sự kiện thay đổi trạng thái của đối tượng. Đây là những người bạn lưu trữ và phát lại.

Một hành động là một cái gì đó đối tượng làm cho những thứ khác. Chúng không được lưu trữ như một phần của Tìm nguồn sự kiện.

Một cách để làm điều này là với các trình xử lý sự kiện, bạn có nối dây hay không tùy thuộc vào việc bạn có muốn chạy Hành động hay không.

public class Monitor
{
    public EventHander SoundAlarm;
    public void MonitorEvent(Event e)
    {
        this.eventcount ++;
        if(this.eventcount > 10)
        {
             this.state = "ALARM!";
             if(SoundAlarm != null) { SoundAlarm();}
        }
    }
}

Bây giờ trong dịch vụ giám sát của tôi, tôi có thể có

public void MonitorServer()
{
    var m = new Monitor(events); //11 events
    //alarm has not been sounded because the event handler wasn't wired up
    //but the internal state is correctly set to "ALARM!"
    m.SoundAlarm += this.SendAlarmEmail;
    m.MonitorEvent(e); //email is sent
}

Nếu bạn cần đăng nhập các email đã gửi, thì bạn có thể làm như vậy như là một phần của SendAlarmEmail. Nhưng chúng không phải là sự kiện theo nghĩa của Tìm nguồn sự kiện

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.