이벤트 소싱에서 프로세스 관리자를 구현하는 방법


14

CQRS 및 이벤트 소싱의 개념을 배우기 위해 작은 예제 응용 프로그램을 만들고 있습니다. 나는이 Basket집계과 Product독립적으로 작동합니다 집계를.

다음은 구현을 보여주는 의사 코드입니다.

Basket { BasketId; OrderLines; Address; }

// basket events
BasketCreated { BasketId; }
ItemAdded { BasketId; ProductId; Quantity }
AddItemSucceeded { BasketId; ProductId; Quantity }
AddItemRevoked { BasketId; ProductId; Quantity }
ItemRemoved { BasketId; ProductId; Quantity }
CheckedOut { BasketId; Address }

Product { ProductId; Name; Price; }

// product events
ProductReserved { ProductId; Quantity }
ProductReservationFailed { ProductId; Quantity }
ProductReservationCancelled { ProductId; Quantity; }

명령은 과거 시제가 아닌 명령형 이름을 사용하여 이벤트와 매우 유사합니다.

현재 이들은 독립적으로 잘 작동합니다. 나는 command를 발행 하고 집계 AddItem에서 ItemAdded이벤트를 생성 Basket하여 '바구니'의 상태와 관련이 있습니다. 마찬가지로 제품의 경우 명령 및 이벤트가 정상적으로 작동합니다.

이제 이것을 명령과 이벤트 측면에서 이와 같은 프로세스로 결합하고 싶습니다.

프로세스 관리자는 다음을 수행합니다.

on BasketCreated: CreateShoppingProcess
on ItemAdded: ReserveProduct
on ProductReserved: SucceedAddingItem // does nothing, but needs to be there so that the basket knows it can check out
on ProductReservationFailed: RevokeAddItem
on RemoveItem: CancelProductReservation
on Checkout: CreateOrder // create an order and so on...

내가 찾을 수없는 질문은 다음과 같습니다.

  1. 프로세스 관리자를 유지해야합니까? 마치 것 같지만 확실하지 않습니다
  2. 그렇다면 프로세스 관리자의 이벤트를 저장해야합니다. 그러나 듣고있는 이벤트는 집합에 연결됩니다. 프로세스 ID를 추가합니까? 프로세스 관리자만을위한 별도의 이벤트가 있습니까? 이 작업을 수행하고 가능한 한 건조하게 유지하는 방법
  3. ProductReserved이벤트의 바구니가 무엇인지 어떻게 알 수 있습니까? BasketId그것들도 켜도 괜찮 습니까? 아니면 유출 정보입니까?
  4. 이벤트 간의 관계를 유지하려면 ItemAdded어떤 ProductReserved이벤트 를 생성 했는지 어떻게 알 수 있습니까? 나는 통과 EventId합니까? 이상해 보인다 ...
  5. Basket간단한 집계 대신 프로세스 관리자로 구현해야합니까 ?

더 많은 연구를 한 후에 나는 이것에 도달했습니다. 사가는 자체 이벤트를 유지하고 외부의 이벤트를 듣는 것입니다. 기본적으로, 그것은 작은 세계 밖에서 일어나는 사건에 반응 할 수있는 집합체입니다.

프로세스 관리자는 외부에서 이벤트를 처리하고 명령을 보냅니다. correlationId와 같은 공통 식별자를 공유하는 집계에서 발생한 이벤트에서 히스토리를 다시 빌드 할 수 있습니다.


시스템에서 일련의 명령으로 구성된 기존의 비공식적 사용 사례를 설명하는 공식 프로세스를 인코딩하려고하는 것 같습니다. 그렇게하면 기존 명령 외에도 많은 중복 명령 및 이벤트가 생성되는 것처럼 보입니다. 그게 당신의 의도입니까? 코드의 프로세스로 사물을 공식화해야하는 비즈니스 요구 사항은 무엇입니까? 도메인에서이 프로세스와 그에 대한 이유를 본격적인 개념으로 식별해야하는 것은 무엇입니까?
guillaume31

이것은 상대적으로 독립적 인 두 골재가 함께 작동하는 방법을 배우는 목적으로 완전히 구성된 프로젝트입니다. 따라서 실제 "비즈니스 요구 사항"은 없으며 가능한 한 이러한 명령과 이벤트에서 중복성을 피하려고합니다. 따라서 프로세스 관리자와 혼동되는 것은 집계가 이미 처리하고있는 작업을 반복해서는 안되기 때문입니다. 그러나 어떻게 든이 두 집계 간의 연결을 유지해야합니다. 인과 관계를 사용하면 도움이 될 것 같지만 시도해야합니다.
Ivan Pintar

답변:


14

Rinat Abdullin이 발전하는 비즈니스 프로세스 에 대해 쓴 내용을 검토하십시오 . 특히, 빠르게 변화하는 환경에서 비즈니스 프로세스를 개발하기위한 그의 권장 사항에 주목하십시오. 프로세스 관리자는 화면을 응시하는 사람을 자동으로 대체합니다.

프로세스 관리자의 저의 정신 모델은 보류중인 명령 목록을 쿼리 할 수있는 이벤트 소스 투영입니다.

프로세스 관리자를 유지해야합니까? 마치 것 같지만 확실하지 않습니다

읽기 모델입니다. 필요할 때마다 이벤트 히스토리에서 프로세스 관리자를 재구성 할 수 있습니다. 또는 업데이트 한 스냅 샷처럼 취급 할 수 있습니다.

그렇다면 프로세스 관리자의 이벤트를 저장해야합니다.

아니오-프로세스 관리자는 관리자 입니다. 자체적으로 유용한 것은 없습니다. 대신 집계가 작업을 수행하도록 지시합니다 (즉, 기록장을 변경).

ProductReserved 이벤트 용 바구니가 무엇인지 어떻게 알 수 있습니까? 이것에 대해 BasketId를 갖는 것이 괜찮습니까? 아니면 누출 정보입니까?

확실한. 참고 : 대부분의 "실제"쇼핑 도메인에서는 주문을 처리하기 전에 재고 예약을 요구하지 않습니다. 비즈니스에 불필요한 경합을 추가합니다. 귀하의 비즈니스에서 주문을 수락 한 후 드문 경우이지만 주문이 필요한 시간 내에 주문을 이행 할 수 없다는 점에 대해 사과 할 가능성이 높습니다.

이벤트 간의 관계를 유지하려면 어떻게 어떤 ItemAdded가 어떤 ProductReserved 이벤트를 생성했는지 어떻게 알 수 있습니까?

메시지에는 메타 데이터가 있습니다. 특히 대화를 추적 하기 위해 causationIdentifier (어떤 명령이 어떤 이벤트를 생성했는지 식별 할 수 있음)와 correlationIdentifier를 포함 할 수 있습니다 .

예를 들어, 프로세스 관리자는 명령에서 자체 ID를 correlationId로 작성합니다. 명령의 상관 ID 사본으로 생성 된 이벤트 및 프로세스 관리자는 자체 correlationId가있는 모든 이벤트를 구독합니다.

간단한 집계 대신 바스켓을 프로세스 관리자로 구현해야합니까?

내 추천은 아니오입니다. 그러나 Udi Dahan은 검토해야한다는 의견이 다릅니다. 즉, CQRS는 집계가 사 가스 인 경우에만 의미가 있습니다. Udi는 프로세스 관리자가 지배적 인 철자가 된 곳에서 사가를 사용했습니다.

프로세스 관리자가 집계를 검색해야합니까?

그렇지 않습니까? 프로세스 관리자는 주로 도메인 상태가 아닌 오케스트레이션과 관련이 있습니다. 프로세스의 인스턴스는 관찰 된 모든 이벤트의 히스토리 형태로 "상태"를 갖게됩니다. 이벤트 Z에 대한 응답으로 수행 할 올바른 것은 이벤트 X 및 Y를 보았는지 여부에 따라 다릅니다. 따라서 해당 상태의 표현 (평평한 것이거나 관찰 된 이벤트의 기록 일 수 있음)을 저장하고로드 할 수 있어야합니다.

(때문에 나는 "정말"라고 집계가 막연하게 그것을 충분히 관찰 된 이벤트의 목록 항에 완전히 잘못이 아니라고 정의되어 있습니다 에 "집합"의 차이는 구현보다 더 의미입니다 -. 우리는로드 프로세스 상태를 다음에 어떤 메시지를 결정 도메인 상태를 담당하는 시스템의 일부에게 보내 십시오. 여기에 약간의 손길이 있습니다.)

따라서 PM은 한 가지 유형의 상태 관리를 다른 유형에 비해 사용할 필요가 없습니다. 왜냐하면 재생 중에는 일을하는 것에 만 책임이 있기 때문입니다.

상태 관리는 수행자가 아니라 추적기의 추적자입니다. 프로세스 관리자가 신호를 방출하지 않아야하는 상황에서는 세계에 비활성 연결을 제공합니다. 다시 말해서, dispatch(command)no-op입니다.


1
당신은 말합니다 : 필요할 때마다 이벤트 히스토리에서 프로세스 관리자를 다시 빌드 할 수 있습니다 ... 그러나 다시 빌드하려면 이벤트를 저장해야합니다. 아니면 집계의 이벤트에서 다시 작성해야합니까? 내가 어려움을 겪고있는 부분은 : 집계를 사용하면 이벤트에 집계 ID가 있으며 해당 집계 ID가있는 모든 이벤트를 찾아 쉽게 다시 작성할 수 있습니다. 그러나 프로세스 관리자를 위해 어떻게해야합니까? 프로세스 관리자를 위해 그렇게해야합니까? 또는 프로세스 관리자가 발생한 이벤트를 기반으로 무언가를 결정해야 할 때 집계를 찾아야합니까?
Ivan Pintar

내가 놓친 것은 이벤트 소싱에서 인과 관계라는 개념이었습니다. 일단 그것을 살펴보면 네 번째 질문에 대한 당신의 대답은 마침내 의미가 있습니다.
Ivan Pintar

1
@IvanPintar의 첫 코멘트에 대한 답변을 원합니다. 프로세스 관리자가 집계를 검색해야합니까? 그들이 처리하는 이벤트를 기반으로 자체적으로 구축해야합니까? 이 경우 이벤트 처리기는 부작용이 없어야합니다.
Jeff

@Jeff 프로세스 관리자가 수행 한 한 가지 예에서, 각각의 처리 된 이벤트, 일종의 읽기 모델로 업데이트 된 자체 스토리지가있었습니다. 이 작업은 간단하고 이미 처리 한 내용을 쉽게 추적 할 수 있습니다. 다른 예에서, 프로세스 관리자는 집계 이벤트로 빌드 된 자체 이벤트를 작성하고 저장했습니다. 위와 비슷하지만 상태는 이벤트 소스입니다. 프로세스 관리자가 유지하는 상태의 복잡성에 따라 둘 중 하나를 수행하는 것이 더 쉬울 수 있습니다. 첫 번째 접근 방식이 더 간단하다는 것을 알았습니다.
Ivan Pintar

흥미 롭기 때문에 프로세스 관리자가 이벤트에 응답하고 결국 명령을 디스패치하는 한 개발자에게 달려 있습니다.
Jeff

2

당신이 찾고있는 것은 "사가 (Saga)"라는 패턴을 가지고 있는데, 이것은 본질적으로 프로세스 관리자입니다.

Saga는 상관 된 명령 사이의 상태를 유지할 수 있기 때문에 장기 실행 프로세스에도 완벽합니다.

Sagas에 관한 훌륭한 기사가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.