jbogard / AdventureWorksCosmos

MIT License
96 stars 28 forks source link

[Question] When is a domain event also an integration event? #1

Open markphillips100 opened 5 years ago

markphillips100 commented 5 years ago

@jbogard I'm hoping this is the right forum for this question? It is related to the code in this repo but do tell me if it isn't.

Some background.

I use the outbox pattern (from eshop guidance) in order to guarantee persistence of an integration event along with my domain state changes. My domain is simple (CRUD) and doesn't actually have domain events as such but I still need (in some cases) to persist the state changes and integration events to ensure downstream microservices can react to the integration events. This has been working well for me and I'm happy that if I needed to refactor for domain events then I could encapsulate all cross-aggregate state changes and their integration event persistence in the one transaction, with the obligatory publish of integration events outside of the transaction.

I've been keen on how to handle the outbox pattern in a nosql db for a while. I posted a question on the eshop repo here in this regard. I never thought to actually include the pattern within the document itself but after your blog and recent NDC videos a light-bulb went off.

Now to my question.

In the context of this repo's code and use cases and comparing previous uses of the outbox pattern, are the events that are persisted really domain events or are they integration events considering they are published/handled outside of the persistence transaction?

jbogard commented 5 years ago

For me, never. I don't re-use domain events as integration events.

On Tue, Apr 2, 2019 at 9:01 PM Mark notifications@github.com wrote:

@jbogard https://github.com/jbogard I'm hoping this is the right forum for this question? It is related to the code in this repo but do tell me if it isn't.

Some background.

I use the outbox pattern (from eshop https://github.com/dotnet-architecture/eShopOnContainers guidance) in order to guarantee persistence of an integration event along with my domain state changes. My domain is simple (CRUD) and doesn't actually have domain events as such but I still need (in some cases) to persist the state changes and integration events to ensure downstream microservices can react to the integration events. This has been working well for me and I'm happy that if I needed to refactor for domain events then I could encapsulate all cross-aggregate state changes and their integration event persistence in the one transaction, with the obligatory publish of integration events outside of the transaction.

I've been keen on how to handle the outbox pattern in a nosql db for a while. I posted a question on the eshop repo here https://github.com/dotnet-architecture/eShopOnContainers/issues/501 in this regard. I never thought to actually include the pattern within the document itself but after your blog and recent NDC videos a light-bulb went off.

Now to my question.

In the context of this repo's code and use cases and comparing previous uses of the outbox pattern, are the events that are persisted really domain events or are they integration events considering they are published/handled outside of the persistence transaction?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/jbogard/AdventureWorksCosmos/issues/1, or mute the thread https://github.com/notifications/unsubscribe-auth/AAGYMrhAFU3hnqCrWGzYKfnCbTCve2JYks5vdAtzgaJpZM4cZdE- .

markphillips100 commented 5 years ago

I tend to agree. So in the context of this repo, if I need to publish integration events for downstream microservices to consume I could just simply have a domain event handler that publishes an explicit integration event considering the domain event has already happened (persisted). Would you agree?

oatsoda commented 2 years ago

I'd like to know thoughts on how you'd dispatch Integration Events in these examples?

An additional collection on the DocumentBase for IntegrationOutbox? With different Events or Handlers from the Domain Events (potentially a generic service bus enqueuer)?

And dispatch them after all the Domain Events have been dispatched? Though what about when Domain Events fail, should the Integration Events somehow be linked to the Domain Events and only be dispatched if the Domain Event succeeded? (Seems like perhaps it shouldn't care as Integration Events shouldn't be dependent on the Domain)

jbogard commented 2 years ago

Have a domain event handler turn around and publish an integration event. Integration events tend to have their own outboxes separate from anything else - Mass Transit, NServiceBus, Jasper etc. all support it now. In fact with those outboxes, and better support for multi-document transactions, the need for the granular outbox like you see in this example is a lot lot lower.

oatsoda commented 2 years ago

better support for multi-document transactions

You're talking about Cosmos here? I know that same-container has transaction support, but I wasn't aware of anything cross-container?

jbogard commented 2 years ago

better not great

It used to only have transactions inside javascript sprocs

oatsoda commented 2 years ago

Sadly I'm on SQL API, so I think the only improvement is same Container + Partition (I think the Mongo API has more elaborate improvements). Which I guess is something, but not unless I want to completely restructure and migrate data!

Out of interest - how would you deal with Domain Events when Deleting a DO? I presume it would require soft delete in order to preserve the Outbox until it's deleted? Then maybe set a TTL on the Doc so it eventually gets auto deleted by Cosmos?

Sorry for all the questions! (Would love to pick your brains further ;))

jbogard commented 2 years ago

Oh great question - I haven't actually had to deal with that - we didn't delete anything, it would just have a status of "Closed" or "Shipped". I imagine a soft delete would do the trick, though.

rdinogit commented 2 years ago

I believe I share the same confusion about the separation between domain and integration events. I only started to get to know DDD recently, so my lack of knowledge could also be the source of my confusion.

The question that may help me achieve clarity is:

The reason why I ask is because when looking at OrderFulfillment I see StockRequest being sent. If I understand correctly, StockRequest in this context is a Command which is something I would not expect to see defined in a Domain layer as opposed to Domain Events.

If the answer to the question is 'yes', then can I see Fulfillments as just a coordinator service that does not adhere to the DDD principles and just makes use of Events and Commands defined in the context of all the participating services?

Thanks in advance.

jbogard commented 2 years ago

https://github.com/jbogard/presentations/tree/master/ConsistencyAndAgreementInMicroservices/AdventureWorksDistributed

Short answer, yes. This example was because Cosmos/MongoDB didn't support multi-document transactions.