This project is meant for learning event-driven architecture using MassTransit.
The CoffeeShop is the front-of-house POS system where orders for coffee and/or bakery items are submitted. The Barista will fulfill orders for coffees. The Bakery will fulfill orders for bakery items. It's up to the CoffeeShop domain to coordinate the Barista and Bakery domains to successfully fulfill an order.
Web projects are meant for dumb interfaces that communicate to smart APIs.
API projects house available commands within a specific domain as well as the ability to query for state. These projects are only allowed to read from the database. Any write actions are propagated as events that the corresponding Coordinator project will persist to the database.
Saga projects are state machines that listen for events and issue commands. For example, when an OrderCreated event occurs, the CoffeeShop.Saga
project would initialize a new instance of a state machine for that specific order. The state machine would track events in the system that are related to the order and issue commands when necessary.
Coordinator projects are used to accept events and translate them into a new domain. These projects handle writes to the database for that domain. For example, the Barista.Coordinator
listens for a coffees ordered event from the CoffeeShop.Saga
. It then translates that into multiple rows in the Barista database because the order may contain multiple coffees and the Barista domain acts on one coffee at a time.
EventContracts projects are used for communication contracts. CoffeeShop
, as the coordinating domain, knows about the contracts from other domains. However, the sub-domains do not need to be concerned with higher-level domains. This keeps the sub-domains of Barista and Bakery simpler while pushing the complexity of coordination up to the CoffeeShop
.
First compose the back-end before the front-end. That way, the back-end services have some time to start. Bonus: you can keep the back-end services running even when you tear down the front-end.
docker-compose -f compose-backend.yml up
In another terminal window (if you're not using the -d
switch):
docker-compose -f compose-frontend.yml up
The websites are available at:
- CoffeeShop
http://localhost:5010
- Barista
http://localhost:5011
- Bakery
http://localhost:5012
The APIs are available at:
- CoffeeShop
http://localhost:5000
- Barista
http://localhost:5001
- Bakery
http://localhost:5002
Go to the CoffeeShop website and click the green button in the bottom-right with a plus-sign in it. Fill out the form and click Submit
. In order to complete the order, navigate to the Barista and Bakery sites and complete the requests for coffees and bagels, respectively. Once all coffees and bagels have been fulfilled, the original order on the CoffeeShop website will begin to pulse purple.
curl -d '{ "CustomerName": "Phil", "Coffees": [ { "Type": "Black", "NumberOfSugars": 0, "NumberOfCreamers": 0 } ] }' -H 'Content-Type: application/json' http://localhost:5000/Orders
You can then query the CoffeeShop.Api
, Barista.Api
, and the Bakery.Api
to see the request as it's broken down from a full order to the separate domains.
curl -i -H 'Accept: application/json' http://localhost:5000/Orders
curl -i -H 'Accept: application/json' http://localhost:5001/Coffees
curl -i -H 'Accept: application/json' http://localhost:5002/Bagels
Once the Barista has some coffees to make, POST to complete each coffee.
curl -d '{ "id": "57c60899-2f7e-4b72-b11f-bed0f5b19b95", "originalOrderId": "8ee26d33-9960-42b9-b896-981fe103c702", "type": "Black", "numberOfSugars": 0, "numberOfCreamers": 0, "isComplete": true }' -H 'Content-Type: application/json' http://localhost:5001/Coffees/57c60899-2f7e-4b72-b11f-bed0f5b19b95
Once the Bakery has some bagels to make, POST to complete each coffee.
curl -d '{ "id": "043c6bcc-9e92-4aba-8098-bf8f816ea7de", "orderId": "8ee26d33-9960-42b9-b896-981fe103c702", "type": "Boring", "hasCreamCheese": false, "hasLox": false, "isComplete": true }' -H 'Content-Type: application/json' http://localhost:5002/Bagels/043c6bcc-9e92-4aba-8098-bf8f816ea7de
Using an application like Postman makes it a bit easier to set up the requests and see the results in a sane way.