Please, imagine you have a method like the following:
public void PlaceOrder(Order order)
{
this.SaveOrderToDataBase(order);
this.bus.Publish(new OrderPlaced(Order));
}
After the order is saved to the database, an event is published to the message queuing system, so other subsystems on the same or another machine can process it.
But, what happens if this.bus.Publish(new OrderPlaced(Order))
call fails? Or the machine crashes just after saving the order into the database? The event is not published and other subsystems cannot process it. This is unacceptable. If this happens I need to ensure that the event is eventually published.
What are the acceptable strategies can I use? Which is the best one?
NOTE: I don't want to use distributed transactions.
EDIT:
Paul Sasik is very close, and I think I can achieve 100%. This is what I thought:
first create a table Events in the database like the following:
CREATE TABLE Events (EventId int PRIMARY KEY)
You may want to use guids instead of int, or you may use sequences or identities.
Then do the following pseudocode:
open transaction
save order and event via A SINGLE transaction
in case of failure, report error and return
place order in message queue
in case of failure, report error, roll back transaction and return
commit transaction
All events must include EventId. When event subscribers receive an event, they first check EventId existence in database.
This way you get 100% realiability, not only 99.999%