DDD, Saga & Tìm nguồn cung ứng sự kiện: Hành động bù có thể đơn giản là xóa trên cửa hàng sự kiện không?


15

Tôi nhận ra câu hỏi trên có thể làm tăng một vài "cái gì đó", nhưng hãy để tôi cố gắng giải thích:

Tôi đang cố gắng tập trung vào một vài khái niệm liên quan, về cơ bản là mô hình Saga ( http://www.rgoarchitects.com/Files/SOAPotypes/Saga.pdf ) kết hợp với tìm nguồn cung cấp sự kiện (Khái niệm DDD : http://en.wikipedia.org/wiki/Domain-driven_design )

Một bài đăng hay kết hợp nó với nhau: https://blog.jonathanoliver.com/cqrs-sagas-with-event-source-part-ii-of-ii/

Tôi sẽ nhận được câu hỏi trong một phút, nhưng tôi nghĩ rằng tôi phải cố gắng tóm tắt những gì tôi hiểu về nó trước tiên (điều này có thể sai, vì vậy hãy sửa nếu đó là trường hợp) vì điều này có thể ảnh hưởng đến lý do tại sao tôi Đặt câu hỏi để bắt đầu với:

  1. Mẫu Saga là một loại nhà môi giới đưa ra một hành động (người dùng cuối, tự động, v.v. về cơ bản là bất cứ thứ gì sẽ thay đổi dữ liệu) sẽ phân chia hành động đó trong các hoạt động kinh doanh và gửi từng hoạt động này dưới dạng tin nhắn đến Message Bus. lần lượt gửi nó đến các gốc tổng hợp tương ứng để được chăm sóc.
  2. Những gốc tổng hợp này có thể hoạt động hoàn toàn tự động (phân tách mối quan tâm tốt đẹp, khả năng mở rộng lớn, v.v.)
  3. Bản thân một cá thể Saga không chứa bất kỳ logic kinh doanh nào, được chứa trong các gốc tổng hợp mà nó gửi các hoạt động tới. 'Logic' duy nhất có trong Saga là 'process'-logic, (thường được triển khai dưới dạng StHRachine), xác định dựa trên các hành động nhận được (cũng như các sự kiện tiếp theo) phải làm gì (ví dụ: hoạt động nào sẽ gửi)
  4. Các mô hình Saga thực hiện một loại mô hình giao dịch phân tán. Tức là: khi một trong những gốc tổng hợp (một lần nữa hoạt động tự chủ, mà không biết về sự tồn tại của mỗi bà mẹ), toàn bộ hành động có thể phải được khôi phục.
  5. Điều này được thực hiện bằng cách có tất cả các gốc tổng hợp, sau khi hoàn thành báo cáo hoạt động của họ trở lại Saga. (Trong trường hợp thành công cũng như lỗi)
  6. Trong trường hợp tất cả các gốc tổng hợp trả lại thành công, stHRachine nội bộ nếu Saga xác định việc cần làm tiếp theo (hoặc quyết định nó đã hoàn thành)
  7. Trong trường hợp thất bại, Saga phát hành cho tất cả các gốc tổng hợp tham gia vào hành động cuối cùng, cái gọi là Hành động đền bù, nghĩa là: một hành động hoàn tác hành động cuối cùng mà mỗi gốc tổng hợp đã làm.
  8. Điều này có thể chỉ đơn giản là thực hiện 'Trừ 1 phiếu' nếu hành động đó là "cộng 1 phiếu" nhưng nó có thể phức tạp hơn như khôi phục một blogpost về phiên bản trước đó.
  9. Tìm nguồn cung cấp sự kiện (xem blogpost kết hợp cả hai) nhằm mục đích lưu lại kết quả của từng hoạt động mà mỗi gốc tổng hợp thực hiện cho Cửa hàng sự kiện tập trung (các thay đổi được gọi là 'sự kiện' trong ngữ cảnh này)
  10. Cửa hàng Sự kiện này là 'phiên bản duy nhất của sự thật' và có thể được sử dụng để phát lại trạng thái của tất cả các thực thể chỉ bằng cách lặp lại các sự kiện được lưu trữ (về cơ bản giống như nhật ký sự kiện)
  11. Kết hợp cả hai (nghĩa là: cho phép các gốc tổng hợp sử dụng Nguồn sự kiện để thuê ngoài lưu các thay đổi của chúng trước khi báo cáo lại cho Saga) cho phép nhiều khả năng hay, một trong những vấn đề liên quan đến câu hỏi của tôi ...

Tôi cảm thấy mình cần phải rời khỏi vai mình, vì điều đó rất nhiều để nắm bắt trong một lần. Với bối cảnh / suy nghĩ này (một lần nữa, xin vui lòng sửa nếu sai)

câu hỏi: Khi một gốc tổng hợp nhận được một Hành động bù và nếu gốc tổng hợp đó đã thuê ngoài các thay đổi trạng thái của nó bằng cách sử dụng Nguồn sự kiện, thì tất cả các tình huống sẽ chỉ là xóa sự kiện cuối cùng trong Kho sự kiện cho điều đó cho rễ tổng hợp? (Giả sử việc thực hiện liên tục cho phép xóa)

Điều đó sẽ có ý nghĩa với tôi rất nhiều (và sẽ là một lợi ích tuyệt vời khác của sự kết hợp này) nhưng như tôi đã nói tôi có thể đưa ra những giả định này dựa trên sự hiểu biết không chính xác / không đầy đủ về các khái niệm này.

Tôi hy vọng điều này đã không quá dài dòng.

Cảm ơn.

Câu trả lời:


9

Bạn không nên xóa các sự kiện từ cửa hàng sự kiện của bạn. Chúng đại diện cho một cái gì đó đã xảy ra. Nếu một cái gì đó xảy ra bây giờ, thì bạn cũng nên biết nó, do đó thêm một sự kiện sẽ buộc tổng hợp của bạn quay trở lại một số trạng thái trước đó. Thật đáng tiếc khi xóa thông tin khỏi cơ sở dữ liệu của bạn.

nghĩ về ví dụ của giỏ hàng từ greg young và các mặt hàng bị loại bỏ. Có thể ngày mai thông tin về hành động bù có thể có giá trị ..

Đối với câu chuyện, mọi thứ đều chính xác, theo như tôi biết bản thân mình. Bạn nên nghĩ về saga như một cỗ máy nhà nước. Nó chỉ làm điều đó.

Đó là một Lệnh mà saga đang ban hành để nói với tổng hợp để làm một cái gì đó. Hành động này sẽ có một sự kiện. Sự kiện này có thể là hành động khắc phục bạn cần hoặc có thể cần phải được chuẩn hóa trong chế độ xem để một số người dùng sẽ thấy nó để quyết định phải làm gì.

Nó phụ thuộc vào quy tắc kinh doanh của bạn. Hoặc, có một cách khắc phục dễ dàng: gốc tổng hợp biết rằng trong trường hợp đó, bạn làm điều đó hoặc lựa chọn quá phức tạp để được thực hiện theo chương trình (chi phí phát triển quá cao) và do đó, bạn có thể đề xuất điều này cho một số người dùng, người có thể chọn giữa các hành động khác nhau. Tất cả mọi thứ phụ thuộc vào bối cảnh của hành động bù. Đây là quy tắc kinh doanh thuần túy. Chúng ta nên làm gì trong trường hợp này hoặc trường hợp đó. Đây là một cái gì đó để hỏi chuyên gia tên miền của bạn, và sau đó chọn với anh ta, nếu tốt hơn là phát triển một giải pháp tự động hoặc nếu giải pháp đó là hỏi người dùng Ronald R., bởi vì anh ta là người thường trả lời câu hỏi này.


Làm thế nào tổng hợp sẽ biết trạng thái nào để hoàn nguyên? Nó sẽ được phép truy vấn đối với cửa hàng sự kiện hay cái gì đó?
Geert-Jan

Nó không nên hoàn nguyên nhưng thêm một sự kiện khác. Đó là một Lệnh mà saga đang ban hành để nói với tổng hợp để làm một cái gì đó. Hành động này sẽ có một sự kiện.
Arthis

Vâng tôi hiểu. "Hoàn nguyên" có lẽ không được chọn. Hãy xem xét những điều sau: Tôi có thể muốn sử dụng Nguồn sự kiện với Sagas để lập mô hình, trong số những thứ khác, luồng xuất bản / phê duyệt tài liệu. Điều gì xảy ra nếu một biên tập viên đã gửi một hành động ChangeBlogBody cuối cùng vẫn tồn tại dưới dạng sự kiện BlogBodyChanged đến Cửa hàng sự kiện. Sau đó, vì một số lý do, Hành động đền bù được ban hành. Làm thế nào để Tổng hợp biết được sự kiện bù nào để kích hoạt kết quả trong nội dung của Nội dung Blog như trước khi hành động ChangeBlogBody được ban hành?
Geert-Jan

Nó phụ thuộc vào quy tắc kinh doanh của bạn. Hoặc, có một cách khắc phục dễ dàng: gốc tổng hợp biết rằng trong trường hợp đó, bạn làm điều đó hoặc lựa chọn quá phức tạp để được thực hiện theo chương trình (chi phí phát triển quá cao) và do đó, bạn có thể đề xuất điều này cho một số người dùng, người có thể chọn giữa các hành động khác nhau.
Arthis

Tất cả mọi thứ phụ thuộc vào bối cảnh của hành động bù. Đây là quy tắc kinh doanh thuần túy. Chúng ta nên làm gì trong trường hợp này hoặc trường hợp đó. Đây là một cái gì đó để hỏi chuyên gia tên miền của bạn, và sau đó chọn với anh ta, nếu tốt hơn là phát triển một giải pháp tự động hoặc nếu giải pháp đó là hỏi người dùng Ronald R., bởi vì anh ta là người thường trả lời câu hỏi này.
Arthis

6

Để hoàn thiện, tôi nghĩ sẽ bao gồm một đoạn có liên quan từ Martin Fowler về các cách để hoàn nguyên trạng thái:

Cũng như các sự kiện tự phát về phía trước, việc chúng có thể tự đảo ngược cũng rất hữu ích.

Reversal là đơn giản nhất khi sự kiện được đúc dưới dạng một sự khác biệt. Một ví dụ về điều này sẽ là "thêm $ 10 vào tài khoản của Martin", trái ngược với "đặt tài khoản của Martin thành $ 110". Trong trường hợp trước tôi có thể đảo ngược bằng cách trừ 10 đô la, nhưng trong trường hợp sau tôi không có đủ thông tin để tạo lại giá trị trong quá khứ của tài khoản.

Nếu các sự kiện đầu vào không tuân theo cách tiếp cận khác biệt, thì sự kiện đó sẽ đảm bảo nó lưu trữ mọi thứ cần thiết để đảo ngược trong quá trình xử lý. Bạn có thể làm điều này bằng cách lưu trữ các giá trị trước đó trên bất kỳ giá trị nào được thay đổi hoặc bằng cách tính toán và lưu trữ sự khác biệt về sự kiện.

Từ: http://martinfowler.com/eaaDev/EventSource.html


1

Về mặt khái niệm:

  • Sự kiện là một cái gì đó đã xảy ra. Quá khứ không thể thay đổi.
  • Lệnh là một cái gì đó để làm. Lệnh có thể không xảy ra (có thể bị từ chối).

Chúng tôi chỉ có thể thay đổi trạng thái trong tương lai của mình bằng cách thực hiện một lệnh khác (Hành động bù) sẽ dẫn đến trạng thái thay đổi trạng thái của ứng dụng.

Để "không nhầm lẫn" câu hỏi, hãy nghĩ về cụm từ này "xóa sự kiện cuối cùng":

  • Điều gì xảy ra nếu sự kiện cuối cùng không phải là sự kiện phải bị xóa? Điều gì xảy ra nếu các sự kiện khác xảy ra sau khi một sự kiện bị xóa? Những sự kiện này cũng phải được thay đổi (vì trạng thái cơ sở của chúng sẽ thay đổi bằng cách xóa sự kiện trước chúng).
  • Điều gì nếu sự kiện được gửi đến hệ thống bên ngoài? Bạn có thể không có quyền truy cập để sửa trạng thái của nó ngoài việc gửi một sự kiện khác.

Nói tóm lại, bạn không có tùy chọn để xóa các sự kiện trong mẫu CQRS.

Bạn có thể thu nhỏ Cửa hàng sự kiện của mình bằng cách tạo trạng thái ảnh chụp nhanh (dựa trên tất cả các sự kiện dẫn đến trạng thái đó), nhưng khía cạnh vật lý này không liên quan gì đến khái niệm sự kiện.


0

Geert-Jan, tôi cũng nghĩ rằng hành động bồi thường chỉ có thể xóa (các) sự kiện tương ứng. Nó có ý nghĩa và nó cho thấy một lợi ích khác của mẫu thiết kế Tìm kiếm sự kiện: triển khai dễ dàng hơn mẫu thiết kế Giao dịch bù.

Một số người nói rằng việc xóa sự kiện vi phạm "nguyên tắc" tìm nguồn cung ứng sự kiện hoặc CQRS. Tôi nghĩ đó là một khái quát hạn chế. Tôi nghĩ sẽ ổn khi xóa một sự kiện nếu nó được tạo trong phạm vi giao dịch toàn cầu đang bị hủy. Hãy xem xét mã giả:

try {
    newEvents = processMycommand(myCommand)
    for (Event newEvent : newEvents)
        EventStore.insertEvent(newEvent);
} catch (Exception e) {
    EventStore.rollback();
}

Giả sử cửa hàng sự kiện của bạn là một cơ sở dữ liệu giao dịch. Trong mã giả, bạn có thể tưởng tượng tình huống bạn chèn sự kiện đầu tiên, nhưng khi cố gắng chèn sự kiện thứ hai, một Ngoại lệ đã bị ném. Lệnh rollback tự nhiên sẽ hoàn nguyên việc chèn sự kiện đầu tiên. Điều đó có hợp lý không?

Nếu nó hợp lý cho một giao dịch cơ sở dữ liệu ACID (giao dịch với cam kết / rollback), tại sao nó không hợp lý cho một giao dịch bù?

Khi thực hiện giao dịch Saga toàn cầu, các thay đổi dữ liệu có thể được hoàn tác (bằng cách bù). Không cần phải giữ sự kiện được tạo trong quá trình giao dịch vì giao dịch không hoàn thành.

Bây giờ, nếu phần bù cố gắng xóa một sự kiện và sự kiện đó không phải là sự kiện mới nhất trên một đối tượng, thì việc xóa sẽ không xảy ra. Nhưng nói chung, điều đó khó có thể xảy ra, đặc biệt là trong các giải pháp chuyên sâu về đọc.


0

Hãy chơi với suy nghĩ rằng bộ lưu trữ sự kiện chỉ là dữ liệu bạn muốn lưu. Ví dụ, chúng ta có thể có một ổ cứng, chúng ta có thể bắt đầu từ đầu và ghi dữ liệu lên nó. Mỗi lần chúng tôi nhận được một sự kiện, chúng tôi sẽ nối thêm dữ liệu trước đó, vì vậy chúng tôi chỉ tiếp tục ghi vào đĩa nơi chúng tôi dừng lần trước. Khi chúng tôi muốn xóa một sự kiện chúng tôi quay lại, hãy xóa phần đó khỏi đĩa và để lại một khoảng trống. Di chuyển trở lại làm chậm lưu trữ sự kiện của chúng tôi, nhưng chúng ta có thể sống với điều đó. Nếu chúng ta sử dụng một hệ thống tập tin, nó sẽ cố gắng lấp đầy khoảng trống với các sự kiện sau, vì vậy chúng ta sẽ có một bộ lưu trữ bị phân mảnh chậm hoặc chúng ta có thể thực hiện phân mảnh. Không ai trong số họ là một cái gì đó chúng tôi thích. Nếu chúng ta đang nói về cơ sở dữ liệu, bạn sẽ có được điều này nếu bạn sử dụng cơ sở dữ liệu quan hệ thay vì cơ sở dữ liệu chỉ nối thêm để lưu trữ các sự kiện của bạn:

nhập mô tả hình ảnh ở đây ref: https://cambridge-intellect.com/browing-time-series-data-to-life-with-keylines/

Tất nhiên bởi một trang web bình thường, điều này không thành vấn đề, nhưng những giải pháp này được thiết kế cho các trang web lớn như facebook, google, v.v ... Vì vậy, thực sự câu hỏi không có ý nghĩa gì, bởi vì bạn sẽ xóa một sự kiện trong cơ sở dữ liệu chỉ như thế nào và làm thế nào bạn gọi bồi thường gì đó như xây dựng cỗ máy thời gian và quay ngược thời gian để thay đổi hoặc ngăn chặn sự kiện ???

Afaik. cách duy nhất để giải quyết vấn đề này là tạo một bộ lưu trữ sự kiện mới trong đó bạn loại trừ các sự kiện bạn không muốn có và sau đó loại bỏ bộ lưu trữ sự kiện cũ. Nhưng đây là một giải pháp cực đoan để loại bỏ một sự kiện duy nhất. Nếu chúng ta đang nói về GDPR, thì giải pháp tốt tương đối duy nhất tôi biết là lưu trữ dữ liệu cá nhân được mã hóa trong bộ lưu trữ sự kiện và xóa khóa mã hóa khỏi cơ sở dữ liệu khác.

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.