public async Task PlaceOrder() { // Generate unique ID which will be persisted in this routine. var transationId = Guid.NewGuid(); var price = 10; var itemId = "Whole Coffee Beans 1lb"; var quantity = 1; // !!! LOOK HERE !!! // This is implementation of the Saga Pattern. // Remember, any step will be re-tried if the process fails abruptly. // 1. First, make sure that payment can be made. // This is a call to a service #1. await _paymentProcessor.Credit(transationId, price); try { // 2. Then, reserve the item being purchased. // This is a call to a service #2. await _warehouse.ReserveItem(transationId, itemId, quantity); // 3. Well, they are out of stock. // The OutOfStockException is thrown. } catch { // 4. Refund the cost of an item. // Perform a compensating action on service #1. await _paymentProcessor.Debit(transationId, price); } // All in all, this async method (a routine) acts as an orchestrator. // Invoking and subscribing to continuations of async methods of two // services can be viewed as sending commands and listening to events. }
// The simplified saga implementation in one method (orchestration). public virtual async Task PlaceOrder() { // Generate unique ID which will be persisted in this method. var transationId = Guid.NewGuid(); var price = 10; var itemId = "Whole Coffee Beans 1lb"; var quantity = 1; // 1. First, make sure that payment can be made. // This is a call to a service #1. await _paymentProcessor.Credit(transationId, price); try { // 2. Then, reserve the item being purchased. // This is a call to a service #2. await _warehouse.ReserveItem(transationId, itemId, quantity); // 3. Well, they are out of stock. // The OutOfStockException is thrown. } catch { // 4. Refund the cost of an item. // Perform a compensating action on service #1. await _paymentProcessor.Debit(transationId, price); } // All in all, this async method (a routine) acts as an orchestrator. // Invoking and subscribing to continuations of async methods of two // services can be viewed as sending commands and listening to events. // Unlike using regular synchronous service client (e.g. http), this // method is guaranteed to reliably execute when message passing is used. }