I'm new to NServiceBus and trying to find the best way to model a scenario which uses compensating transactions.
For example, say I have a typical BookHotel scenario:
In the happy case, the messaging flow would proceed as follows:
- BookHotelCommand --> BookHotelSaga
- BookFlightCommand --> Reply IFlightBookedMessage
- BookRentalCommand --> Reply IRentalBookedMessage
- ReplyToOriginator --> HotelBookedMessage
How would I model compensating transactions in the above flow? I was initially thinking of calling a "UnbookHotelSaga" in one of the replies above, based on some business conditions. However, I seem to be running into some challenges with getting this working. Can someone with Saga experience comment if this is the right approach.
Here is the scenario I was thinking would work by calling another Saga:
- BookHotelCommand --> BookHotelSaga
- BookFlightCommand --> Reply IFlightBookedMessage
- BookRentalCommand --> (condition satisfied) --> UnbookHotelCommand --> UnbookHotelSaga
- UnbookRentalCommand --> Reply IUnbookRentalMessage
- UnbookFlightCommand --> Reply IUnbookFlightMessage
- UnbookHotelCommand --> ReplyToOriginator --> UnbookedHotelMessage
Can someone please advise on the best-practices approach to implementing compensating transactions?
I'm not really sure I understand the long running process and what it should do. Some more information on functionality would probably help.
One of the first things I noticed was mentioning of
IUnbookRentalMessage
. First of all, don't useI
at the start of messages. The fact that they can be interfaces, has to do with polymorphism and multiple inheritance features of .NET. Messages themselves have no technical meaning on the wire and you should therefore not include theI
.Also, commands are in imperative tense and events in past tense. So
BookFlight
for a command andFlightBooked
for an event.You could theoretically create multiple sagas that all take part in a single long running business process. A saga called
BookingPolicy
orBookingProcess
orBookingSaga
to orchestrate the entire process. AndFlightBookingPolicy
for the flight andHotelBookingPolicy
for the hotel.If you start out with a
BookFlight
command, theFlightBookingPolicy
could publish an event calledFlightBooked
. TheBookingPolicy
could use that event to start its own instance of the saga. So for example, the (ASP.NET) website that sends all the commands, would not have to know about theBookingPolicy
. It just sends the appropriate commands with the appropriate data. The same goes for hotel, car, etc.Then at some point, the website sends a
CommitBooking
orFinishUpMyVacation
command, which does arrive at theBookingPolicy
saga and that finalizes the entire booking. It sends an eventBookingFinishingUp
or something. Based on that event, some handler might deduct money from a creditcard. Another handler does integration with 3rd parties to actually submit the vacation. Another handler sends out emails. Etcetera.Finally when the
BookingPolicy
(or even another saga) is finished, theBookingPolicy
saga will publish an event calledBookingFinished
and the appropriateFlightBookingPolicy
andHotelBookingPolicy
andCarBookingPolicy
also wrap up and end their work. Whatever that may be.Does that make sense? If you want, you can also continue the conversation on https://discuss.particular.net/ or [email protected].