2012-06-13 40 views
12

Ví dụ: Quy tắc kinh doanh quy định rằng khách hàng sẽ nhận được thông báo xác nhận (email hoặc tương tự) khi đặt hàng.CQRS - Thời điểm gửi tin nhắn xác nhận?

Cho phép nói rằng NewOrderRegisteredEvent được gửi đi từ miền và được người nhận sự kiện gửi thông báo xác nhận. Khi đó được thực hiện một số xử lý sự kiện khác ném một ngoại lệ hoặc cái gì khác đi sai và đơn vị công việc được cuộn lại. Bây giờ chúng tôi đã gửi cho người dùng một thông báo xác nhận cho một cái gì đó đã được khôi phục.

Cách "cqrs" giải quyết các vấn đề như thế này nơi bạn muốn làm điều gì đó sau khi một đơn vị công việc đã được cam kết? Một yếu tố phức tạp khác là phát lại các sự kiện. Tôi không muốn gửi lại thông báo xác nhận cũ bất cứ khi nào tôi phát lại các sự kiện được ghi lại để xây dựng chế độ xem/chiếu mới.

Lý thuyết tốt nhất của tôi cho đến nay: Tôi vừa mới bắt đầu nhìn vào thế giới hấp dẫn của cqrs và tự hỏi liệu đây có phải là điều gì đó sẽ được thực hiện như một câu chuyện hay không? Nếu một saga giống như một máy nhà nước, nơi mỗi quá trình chuyển đổi chỉ có thể diễn ra một lần duy nhất thì tôi đoán rằng sẽ giải quyết vấn đề này? Tôi chỉ có một thời gian khó hình dung thế nào điều này sẽ phù hợp với nhau với xe buýt lệnh và miền kiện ..

+1

Đặt thông báo "gửi email" cho tác vụ. Nếu uow cuộn lại, do đó, việc gửi đi của tin nhắn (để lưu trữ bền). Một cái gì đó khác chọn lên các tin nhắn và làm thingy email. Btw, không cqrs liên quan. Đồng bằng tính toán phân tán thông thường. –

+0

Đối với phát lại sự kiện, KHÔNG BAO GIỜ gây ra loại hành vi này. Nếu impl của bạn. không, bạn đang làm sai. –

+0

Điều đó có ý nghĩa, nhưng tôi quan tâm đến điều này trong ngữ cảnh cqrs. "Tin nhắn" là gì? Và ai/những gì sẽ nhặt nó tại, và khi nào? Nó sẽ là tốt đẹp để tận dụng để lưu trữ sự kiện để tránh giới thiệu một cơ chế lưu trữ để theo dõi thông tin liên lạc đi. – Kimble

Trả lời

16
  1. Sự kiện chỉ xảy ra sau khi giao dịch được hoàn tất. Nếu có gì sai và có một sự quay lại, thì sự kiện đó không xảy ra từ một quan điểm bên ngoài. Vì vậy nó không nên được xuất bản ở tất cả. Mặc dù sự kiện OrderRegistrationFailed có thể được xuất bản nếu cần.

  2. Bạn sẽ không muốn gửi thư trừ khi lệnh đã được thực thi thành công. Đầu tiên là một vài lý do tại sao trình xử lý lệnh - như được đề xuất trong câu trả lời khác - sẽ là địa điểm sai: Trong một số trường hợp, trình xử lý lệnh sẽ không thể biết liệu lệnh này có thành công hay không. Có trình xử lý lệnh gọi gửi thư cũng sẽ đặt kiến ​​thức quá trình bên trong trình xử lý lệnh, điều này sẽ phá vỡ SRM và quá chặt chẽ các quy tắc nghiệp vụ với lớp ứng dụng.

    Thư phải được gửi sau sự kiện, tức là từ trình xử lý sự kiện.

    Để ngăn trình xử lý này kích hoạt trong khi phát lại, bạn chỉ có thể không đăng ký. Điều này hoạt động tương tự như cách bạn kiểm tra ứng dụng của mình. Bạn chỉ đăng ký các trình xử lý mà bạn thực sự cần.

    hệ thống
    • Sản xuất -> đăng ký tất cả các event handler
    • thử nghiệm -> đăng ký chỉ xử lý sự kiện thử nghiệm
    • Replay -> đăng ký chỉ xử lý chiếu/denormalization

Một - thậm chí còn lỏng lẻo hơn, mặc dù phức tạp hơn một chút - khả năng sẽ có một số Saga xử lý các NewOrderRegisteredEvent và đưa ra lệnh SendMail cho ứng dụng ngữ cảnh bị giới hạn (nhờ, Yves Reynhout, để chỉ ra điều này trong các bình luận của câu hỏi).

+1

Đây là một trong những câu trả lời hay nhất tôi đã nhận được ở đây trên stackoverflow! Vì vậy, các sự kiện miền sẽ được đệm ở đâu đó và chỉ được xuất bản bên ngoài miền (để chiếu/de-bình thường hóa) khi các sự kiện đã được ghi thành công vào nhật ký sự kiện? Tôi đoán rằng việc ghi vào cửa hàng sự kiện xảy ra bên trong một giao dịch (thường) được khởi tạo bởi một trình xử lý lệnh/bộ chặn không? – Kimble

+0

Về cơ bản có, lưu trữ một hoặc nhiều sự kiện/(trong bản ghi sự kiện hoặc cửa hàng sự kiện, hãy cẩn thận để không nhầm lẫn giữa hai) sẽ là phần cuối cùng của giao dịch. Chỉ sau khi lưu trữ thành công nó/chúng sẽ được gửi đi và xử lý, thậm chí có thể không đồng bộ. –

+0

Sự khác nhau giữa nhật ký sự kiện và cửa hàng là gì? Tôi khá chắc chắn rằng tôi đã nhìn thấy những người đang được sử dụng thay thế cho nhau khi đọc về cqrs .. – Kimble

2

Có hai giải pháp có khả năng

1) xuất bản của sự kiện và việc xử lý sự kiện (ví dụ: email) là một phần của một giao dịch duy nhất. Trong trường hợp này, khung giao dịch của bạn sẽ xử lý nó cho bạn. Nếu email không thành công thì sự kiện sẽ được khôi phục. Bạn có thể thử lại lệnh. Đây là khái niệm sạch sẽ và dễ suy nghĩ. Không có sự kiện nào xuất bản xong cho đến khi tất cả mọi người có điều gì đó để nói về nó đều có tiếng nói của họ. Tuy nhiên thực tế nói, điều này có thể gây đau đớn, vì nó thường liên quan đến các giao dịch phân tán. Đây là những khó khăn để đi qua. Ứng dụng email của bạn có thể đăng ký cùng một giao dịch với cơ sở dữ liệu đang giữ các sự kiện của bạn không?

2) Việc xuất bản sự kiện là giao dịch, nhưng các trình xử lý sự kiện mỗi giao dịch có giao dịch theo cách riêng của họ. Trình xử lý sự kiện gửi email có thể theo dõi những sự kiện mà nó đã xem. Nếu nó bị hỏng, nó sẽ yêu cầu các sự kiện cũ và xử lý chúng. Bạn có thể đưa ra quyết định kinh doanh về việc một thỏa thuận lớn như thế nào nếu mọi người có email bị thiếu hoặc trùng lặp. (Đối với giao dịch liên quan đến tiền, câu trả lời có thể là bạn không nên cho phép.)

Giải pháp (2) thường là những gì bạn thấy được quảng cáo trong vòng kết nối DDD/CQRS vì nó là giải pháp kết hợp lỏng lẻo hơn. Giải pháp (1) là khá thực tế trong một hệ thống nhỏ, nơi sự kiện lưu trữ và các dự trong một cơ sở dữ liệu duy nhất và các dự báo không thay đổi thường xuyên. Giải pháp (2) cho phép một bộ xử lý sự kiện đa dạng hoạt động theo cách riêng của chúng. Giải pháp (1) có thể gây ra rất nhiều mối quan tâm không chồng chéo để trở thành bị cản trở. Trong trường hợp này, quy tắc kinh doanh đặt hàng của bạn không hoàn thành cho đến khi nhiều điều kỳ lạ xảy ra trong việc gửi email được thực hiện. Đối với một điều, nó có thể làm chậm bạn xuống một chút.

Nếu việc gửi email thú vị hơn "đã xem sự kiện, gửi email", thì bạn nói đúng, bạn có thể có một câu chuyện hoặc luồng công việc trên tay. Email trong các hoạt động lớn thường là một hệ thống phức tạp theo đúng nghĩa của nó mà bạn không phải thực hiện nhiều. Bạn chỉ cần chắc chắn rằng bạn đặt email của bạn vào một hàng đợi yêu cầu của một số loại (sử dụng cách tiếp cận (2)), và hệ thống email có khả năng làm retries/batching/spam avoidance/làm việc qua đêm/etc.

+0

Cảm ơn câu trả lời dài! Giao dịch phân tán là một nỗi đau. Về giải pháp thứ hai, liệu điều đó có liên quan đến việc giới thiệu một cơ chế lưu trữ mới để theo dõi các email mà nó đã gửi, hoặc là phổ biến để tận dụng các cửa hàng sự kiện cho điều này không? Tôi thấy một số vấn đề tiềm ẩn với trình xử lý sự kiện xuất bản sự kiện của riêng họ. Đặc biệt trong khi phát lại, sự kiện "gửi email x" sẽ đến sau sự kiện đã kích hoạt email ngay từ đầu. – Kimble

+0

Nếu bạn muốn gửi e-mail thực sự giao dịch, thì bạn sẽ phải xử lý bằng cách nào đó. Có lẽ bằng cách lưu danh tính của một email bạn đã gửi thành công vào đĩa.Nhưng không phải hầu hết các hoạt động email cấp thương mại đều đảm bảo giao hàng nếu bạn viết thư bạn cần vào hàng đợi nào đó? –

+0

Gửi e-mail giao dịch thật sự là cách ra khỏi phạm vi ngay bây giờ. Tôi đã chỉ tò mò về cách vấn đề này đã được xử lý trong cqrs, đặc biệt là kết hợp với sự kiện phát lại. Nhưng, vâng, việc đặt email trên hàng đợi và lưu trữ một id tương quan trong cửa hàng sự kiện sẽ đi một chặng đường dài trong việc đảm bảo phân phối. – Kimble

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