0

I'm building a bookstore point of sale system, and trying to use layer architecture / DDD for the first time. Books are my aggregates, and DDD ensures that my books can only be created in such a way that the business rules around creation are satisfied. However, another business rule is that two book inventory items can't have the same SKU. I've therefore set up domain events, BookCreated or BookSkuUpdated, which ultimately are subscribed to by a domain service that checks for duplicates and marks them if they're found. Eventual consistency, and so far so good.

My question is how to integrate this domain behavior into my web app. When the book is created, the code flows from infra (my controller) to application layer (the create book use case) to domain (book aggregate) then back to application layer and infra so it can be displayed to the client. No problem, ultimately request -> response. However, my domain events are set up with a little callback queue that creates a new code flow which STARTS in the domain, with creation of the domain event, and ultimately results in a subscriber kicking off a new application layer use case (updateDuplicateSku). Because my persistence is a single repo I can save the new duplicateSku warning to the repo, but can't for the life of me figure out how to push that view to the client. Instead of the use case returning to the controller, which has the request and response objects, the use case was kicked off in the domain so doesn't have any knowledge of the client.

In short - is there a good way for domain event callbacks to make eventual consistency changes to the domain and push those changes to a client with server sent events or websockets?

  • Just to clarify - I suppose I'm asking whether Domain Events can get access to a req and res from a client API call, so that "eventual consistency" changes to the domain can be published to the client, using something like server sent events. Is that an appropriate use of Domain Events? It feels like I'd have to pass the req / res objects to the Aggregate that triggers the domain event so they could be stored in the event, which seems like a crazy thing to have to do (you'd only do that if you knew there would be domain events you were triggering, which defeats the point of domain events)... – Connor Burke Mar 02 '22 at 04:31
  • It feels like Domain Events causing model changes that ultimately should be pushed to view is a common enough situation that my hope is that there's an elegant design solution I haven't thought of – Connor Burke Mar 02 '22 at 04:32

1 Answers1

1

Domain Events allow aggregates to react to a change in another aggregate without coupling them. So using a domain event handler (updateDuplicateSku) to detect duplicates sounds fine.

Next, updateDuplicateSku should publish an integration event (i.e. SKUMarkedAsDuplicate). The purpose of integration events is to propagate committed transactions and to update additional subsystems. In this case, an integration event would be handled by a websocket server, which is in turn responsible for pushing changes back to the client.

All the communication is asynchronous in nature so you cannot use req and res variables from a client API call.

pgorecki
  • 639
  • 6
  • 8