public async Task <IHttpActionResult> PostOrder([FromBody] TicketOrder order) { var error = ""; var handler = HandlersFactory.GetProfilerHandler(TheSettingService, TheLoggerService); handler.Start(LOG_TAG, "PostOrder", GetServiceProperties()); try { TicketOrder.Validate(order); ServiceLocationService locator = new ServiceLocationService(); UriBuilderService builder = new UriBuilderService(Constants.ContosoEventsApplicationInstance, Constants.ContosoEventsTicketOrderServiceName); ITicketOrderService dispenderService = locator.Create <ITicketOrderService>(builder.ToUri()); return(Ok(await dispenderService.EnqueueOrder(order))); } catch (Exception ex) { error = ex.Message; return(BadRequest(ex.Message)); } finally { handler.Stop(error); } }
public async Task ProcessOrder(TicketOrder order) { var error = ""; var handler = HandlersFactory.GetProfilerHandler(SettingService, LoggerService); handler.Start(LOG_TAG, "ProcessOrder", GetActorProperties()); try { if (order == null) { handler.Info("Process order is null"); return; } var state = await this.StateManager.GetStateAsync <TicketOrder>(ActorStatePropertyName); state = order; // Validate the order bool isValid = true; try { TicketOrder.Validate(state); } catch (Exception e) { state.Note = e.Message; isValid = false; } if (isValid) { // Validate the event TicketEvent tEvent = await this.DataStoreService.GetEventById(order.EventId); if (tEvent == null) { state.FulfillDate = null; state.IsFulfilled = false; state.Note = "The Event ID is not valid!"; //TODO: Exercise 6 - Task 1 //state.Status = OrderStatuses.Invalid; } else { state.PricePerTicket = tEvent.PricePerTicket; state.Currency = tEvent.Currency; state.Price = state.Tickets * state.PricePerTicket; // Locate the event actor IEventActor eventActor = this.ActorLocationService.Create <IEventActor>(new ActorId(order.EventId), Constants.ContosoEventsApplicationName); bool isAvailable = await eventActor.ReserveTickets(order); if (isAvailable || !SettingService.IsTicketAvailabilityCheck()) { // Charge credit card string confirmationNumber = await this.PaymentProcessorService.Authorize(order); if (!string.IsNullOrEmpty(confirmationNumber)) { state.PaymentProcessorConfirmation = confirmationNumber; state.FulfillDate = DateTime.Now; state.IsFulfilled = true; //TODO: Exercise 6 - Task 1 //state.Status = OrderStatuses.Fufilled; } else { state.FulfillDate = null; state.IsFulfilled = false; state.Note = "Credit card failed to authorize!"; await eventActor.FailTickets(order); //TODO: Exercise 6 - Task 1 //state.Status = OrderStatuses.CreditCardDenied; } } else { state.FulfillDate = null; state.IsFulfilled = false; state.Note = "Event Tickets are exhausted!"; //TODO: Exercise 6 - Task 1 //state.Status = OrderStatuses.TicketsExhausted; } } } else { state.FulfillDate = null; state.IsFulfilled = false; //TODO: Exercise 6 - Task 1 //state.Status = OrderStatuses.Invalid; } // Make sure the state is saved await SetEntityStateAsync(state); // Externalize the state await this.ExternalizationService.Externalize(state); // Notify the user await this.NotificationService.Notify(state); } catch (Exception ex) { error = ex.Message; } finally { handler.Stop(error); if (!string.IsNullOrEmpty(error)) { this.HealthReporterService.SendReportForService(HealthState.Error, GetHealthErrorMessage("ProcessOrder", error)); } } }
// ITicketDispenserService Interface Implementation public async Task <string> EnqueueOrder(TicketOrder order) { var error = ""; var handler = HandlersFactory.GetProfilerHandler(SettingService, LoggerService); handler.Start(LOG_TAG, "EnqueueOrder", GetServiceProperties()); string orderId = Guid.NewGuid().ToString(); bool blProceed = true; try { // Do some sanity checking TicketOrder.Validate(order); // Quick check to see if tickets are available if (SettingService.IsTicketAvailabilityCheck()) { IEventActor eventActor = this.ActorLocationService.Create <IEventActor>(new ActorId(order.EventId), Constants.ContosoEventsApplicationName); if (!await eventActor.CheckTickets(order)) { handler.Info("Processing order - Event Id: " + order.EventId + " - Order Id: " + orderId + " - tickets: " + order.Tickets + " - Tickets are exhausted!"); // Do not throw an exception because we will get a health issue // throw new Exception("Tickets are exhausted!"); // Need to alert the admin only as tickets are exhausted // Prevent proceeding with the order blProceed = false; // Reset the order id to indicate to the Web API client that the order did not go through orderId = ""; } } if (blProceed) { order.Id = orderId; handler.Info("Processing order - Event Id: " + order.EventId + " - Order Id: " + orderId + " - tickets: " + order.Tickets); //TODO: Task 2.1 - Get (or create) a reliable queue called "OrderQueue" in this partition. //var requests = await this.StateManager./*...complete this...*/<IReliableQueue<TicketOrder>>(OrderQueueName); var requests = await this.StateManager.GetOrAddAsync <IReliableQueue <TicketOrder> >(OrderQueueName); //TODO: Task 2.2 - Create a new transaction scope //using (var tx = this.StateManager./*...complete this...*/) //{ // TODO: Task 2.3 - Enqueue the order to the reliable queue within the transaction //await requests.EnqueueAsync(/*...complete this...*/, /*...complete this...*/); // TODO: Task 2.4 - Commit the transaction if enqueue was successful //await tx./*...complete this...*/(); //} using (var tx = this.StateManager.CreateTransaction()) { await requests.EnqueueAsync(tx, order); await tx.CommitAsync(); } } } catch (Exception ex) { error = ex.Message; throw ex; } finally { handler.Stop(error); if (!string.IsNullOrEmpty(error)) { this.HealthReporterService.SendReportForService(HealthState.Error, GetHealthErrorMessage("EnqueueOrder", error)); } } return(orderId); }