public async Task<Guid> PostCheckout(List<CustomerOrderItem> cart)
        {
            ServiceEventSource.Current.Message("Now printing cart for POSTCHECKOUT...");
            foreach (CustomerOrderItem item in cart)
            {
                ServiceEventSource.Current.Message("Guid {0}, quantity {1}", item.ItemId.ToString(), item.Quantity.ToString());
            }

            Guid orderId = Guid.NewGuid();
            ServiceUriBuilder builder = new ServiceUriBuilder(CustomerOrderServiceName);

            //We create a unique Guid that is associated with a customer order, as well as with the actor that represents that order's state.
            ICustomerOrderActor customerOrder = ActorProxy.Create<ICustomerOrderActor>(new ActorId(orderId), builder.ToUri());

            try
            {
                await customerOrder.SubmitOrderAsync(cart);
                ServiceEventSource.Current.Message("Customer order submitted successfully. ActorOrderID: {0} created", orderId);
            }
            catch (InvalidOperationException ex)
            {
                ServiceEventSource.Current.Message("Web Service: Actor rejected {0}: {1}", customerOrder, ex);
                throw;
            }
            catch (Exception ex)
            {
                ServiceEventSource.Current.Message("Web Service: Exception {0}: {1}", customerOrder, ex);
                throw;
            }

            return orderId;
        }
        public Task<string> GetOrderStatus(Guid customerOrderId)
        {
            ServiceUriBuilder builder = new ServiceUriBuilder(CustomerOrderServiceName);
            ICustomerOrderActor customerOrder = ActorProxy.Create<ICustomerOrderActor>(new ActorId(customerOrderId), builder.ToUri());

            try
            {
                return customerOrder.GetStatusAsync();
            }
            catch (Exception ex)
            {
                ServiceEventSource.Current.Message("Web Service: Exception {0}: {1}", customerOrder, ex);

                throw;
            }
        }
        public Task<bool> CreateInventoryItem(string description, decimal price, int number, int reorderThreshold, int max)
        {
            InventoryItem i = new InventoryItem(description, price, number, reorderThreshold, max);

            ServiceUriBuilder builder = new ServiceUriBuilder(InventoryServiceName);
            IInventoryService inventoryServiceClient = ServiceProxy.Create<IInventoryService>(builder.ToUri(), i.Id.GetPartitionKey());

            try
            {
                return inventoryServiceClient.CreateInventoryItemAsync(i);
            }
            catch (Exception ex)
            {
                ServiceEventSource.Current.Message("Web Service: Exception creating {0}: {1}", i, ex);
                throw;
            }
        }
        public async Task<IEnumerable<InventoryItemView>> GetStore()
        {
            ServiceUriBuilder builder = new ServiceUriBuilder(InventoryServiceName);
            Uri serviceName = builder.ToUri();

            List<InventoryItemView> itemList = new List<InventoryItemView>();

            ServicePartitionList partitions = await fc.QueryManager.GetPartitionListAsync(serviceName);

            foreach(Partition p in partitions)
            {
                long minKey = (p.PartitionInformation as Int64RangePartitionInformation).LowKey;
                IInventoryService inventoryServiceClient = ServiceProxy.Create<IInventoryService>(minKey, serviceName);
                itemList.AddRange(await inventoryServiceClient.GetCustomerInventoryAsync());
            }

            return itemList;
        }
 /// <summary>
 /// Adding this method to support DI/Testing 
 /// We need to do some work to create the actor object and make sure it is constructed completely
 /// In local testing we can inject the components we need, but in a real cluster
 /// those items are not established until the actor object is activated. Thus we need to 
 /// have this method so that the tests can have the same init path as the actor would in prod
 /// </summary>
 /// <returns></returns>
 public async Task InternalActivateAsync(ICodePackageActivationContext context, IServiceProxyFactory proxyFactory)
 {
     this.tokenSource = new CancellationTokenSource();
     this.builder = new ServiceUriBuilder(context, InventoryServiceName);
     this.ServiceProxyFactory = proxyFactory;
 }
        /// <summary>
        /// Drains the queue of completed restock requests sends them to InventoryService.
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            IReliableQueue<RestockRequest> completedRequests = await this.StateManager.GetOrAddAsync<IReliableQueue<RestockRequest>>(CompletedRequestsQueueName);

            while (!cancellationToken.IsCancellationRequested)
            {
                using (ITransaction tx = this.StateManager.CreateTransaction())
                {
                    ConditionalResult<RestockRequest> result = await completedRequests.TryDequeueAsync(tx, TxTimeout, cancellationToken);

                    if (result.HasValue)
                    {
                        ServiceUriBuilder builder = new ServiceUriBuilder(InventoryServiceName);
                        IInventoryService inventoryService = ServiceProxy.Create<IInventoryService>(result.Value.ItemId.GetPartitionKey(), builder.ToUri());

                        await inventoryService.AddStockAsync(result.Value.ItemId, result.Value.Quantity);

                        ServiceEventSource.Current.ServiceMessage(
                            this,
                            "Adding stock to inventory service. ID: {0}. Quantity: {1}",
                            result.Value.ItemId,
                            result.Value.Quantity);
                    }

                    // This commits the dequeue operations.
                    // If the request to add the stock to the inventory service throws, this commit will not execute
                    // and the items will remain on the queue, so we can be sure that we didn't dequeue items
                    // that didn't get saved successfully in the inventory service.
                    // However there is a very small chance that the stock was added to the inventory service successfully,
                    // but service execution stopped before reaching this commit (machine crash, for example).
                    await tx.CommitAsync();
                }

                await Task.Delay(CompletedRequestsBatchInterval, cancellationToken);
            }
        }
        private async Task PeriodicInventoryCheck(CancellationToken cancellationToken)
        {
            IReliableDictionary<InventoryItemId, InventoryItem> inventoryItems =
                await this.stateManager.GetOrAddAsync<IReliableDictionary<InventoryItemId, InventoryItem>>(InventoryItemDictionaryName);

            while (!cancellationToken.IsCancellationRequested)
            {
                ServiceEventSource.Current.ServiceMessage(this, "Checking inventory stock for {0} items.", await inventoryItems.GetCountAsync());

                foreach (InventoryItem item in inventoryItems.Select(x => x.Value))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    try
                    {
                        //Check if stock is below restockThreshold and if the item is not already on reorder
                        if ((item.AvailableStock <= item.RestockThreshold) && !item.OnReorder)
                        {
                            ServiceUriBuilder builder = new ServiceUriBuilder(RestockRequestManagerServiceName);

                            IRestockRequestManager restockRequestManagerClient = ServiceProxy.Create<IRestockRequestManager>(0, builder.ToUri());

                            // we reduce the quantity passed in to RestockRequest to ensure we don't overorder   
                            RestockRequest newRequest = new RestockRequest(item.Id, (item.MaxStockThreshold - item.AvailableStock));

                            InventoryItem updatedItem = new InventoryItem(
                                item.Description,
                                item.Price,
                                item.AvailableStock,
                                item.RestockThreshold,
                                item.MaxStockThreshold,
                                item.Id,
                                true);

                            // TODO: this call needs to be idempotent in case we fail to update the InventoryItem after this completes.
                            await restockRequestManagerClient.AddRestockRequestAsync(newRequest);

                            // Write operations take an exclusive lock on an item, which means we can't do anything else with that item while the transaction is open.
                            // If something blocks before the transaction is committed, the open transaction on the item will prevent all operations on it, including reads.
                            // Once the transaction commits, the lock is released and other operations on the item can proceed.
                            // Operations on the transaction all have timeouts to prevent deadlocking an item, 
                            // but we should do as little work inside the transaction as possible that is not related to the transaction itself.
                            using (ITransaction tx = this.stateManager.CreateTransaction())
                            {
                                await inventoryItems.TryUpdateAsync(tx, item.Id, updatedItem, item);

                                await tx.CommitAsync();
                            }

                            ServiceEventSource.Current.ServiceMessage(
                                this,
                                "Restock order placed. Item ID: {0}. Quantity: {1}",
                                newRequest.ItemId,
                                newRequest.Quantity);
                        }
                    }
                    catch (Exception e)
                    {
                        ServiceEventSource.Current.ServiceMessage(this, "Failed to place restock order for item {0}. {1}", item.Id, e.ToString());
                    }
                }

                await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
            }
        }
        /// <summary>
        /// This method takes in a list of CustomerOrderItem objects. Using a Service Proxy to access the Inventory Service,
        /// the method iterates onces through the order and tries to remove the quantity specified in the order from inventory. 
        /// If the inventory has insufficient stock to remove the requested amount for a particular item, the entire order is 
        /// marked as backordered and the item in question is added to a "backordered" item list, which is fulfilled in a separate 
        /// method. 
        /// 
        /// In its current form, this application addresses the question of race conditions to remove the same item by making a rule
        /// that no order ever fails. While an item that is displayed in the store may not be available any longer by the time an order is placed,
        /// the automatic restock policy instituted in the Inventory Service means that our FulfillOrder method and its sub-methods can continue to 
        /// query the Inventory Service on repeat (with a timer in between each cycle) until the order is fulfilled. 
        /// 
        /// </summary>
        /// <returns>The number of items put on backorder after fulfilling the order.</returns>
        internal async Task FulfillOrderAsync()
        {
            ServiceUriBuilder builder = new ServiceUriBuilder(InventoryServiceName);

            await this.SetOrderStatusAsync(CustomerOrderStatus.InProcess);

            IList<CustomerOrderItem> orderedItems = await this.StateManager.GetStateAsync<IList<CustomerOrderItem>>(OrderItemListPropertyName);

            ActorEventSource.Current.ActorMessage(this, "Fullfilling customer order. ID: {0}. Items: {1}", this.Id.GetGuidId(), orderedItems.Count);

            foreach (CustomerOrderItem tempitem in orderedItems)
            {
                ActorEventSource.Current.Message("OrderContains:{0}", tempitem);
            }

            //We loop through the customer order list. 
            //For every item that cannot be fulfilled, we add to backordered. 
            foreach (CustomerOrderItem item in orderedItems.Where(x => x.FulfillmentRemaining > 0))
            {
                IInventoryService inventoryService = ServiceProxy.Create<IInventoryService>(builder.ToUri(), item.ItemId.GetPartitionKey());

                //First, check the item is listed in inventory.  
                //This will avoid infinite backorder status.
                if ((await inventoryService.IsItemInInventoryAsync(item.ItemId, this.tokenSource.Token)) == false)
                {
                    await this.SetOrderStatusAsync(CustomerOrderStatus.Canceled);
                    return;
                }

                int numberItemsRemoved =
                    await
                        inventoryService.RemoveStockAsync(
                            item.ItemId,
                            item.Quantity,
                            new CustomerOrderActorMessageId(
                                new ActorId(this.Id.GetGuidId()),
                                await this.StateManager.GetStateAsync<long>(RequestIdPropertyName)));

                item.FulfillmentRemaining -= numberItemsRemoved;
            }

            IList<CustomerOrderItem> items = await this.StateManager.GetStateAsync<IList<CustomerOrderItem>>(OrderItemListPropertyName);
            bool backordered = false;

            // Set the status appropriately
            foreach (CustomerOrderItem item in items)
            {
                if (item.FulfillmentRemaining > 0)
                {
                    backordered = true;
                    break;
                }
            }

            if (backordered)
            {
                await this.SetOrderStatusAsync(CustomerOrderStatus.Backordered);
            }
            else
            {
                await this.SetOrderStatusAsync(CustomerOrderStatus.Shipped);
            }

            ActorEventSource.Current.ActorMessage(
                this,
                "{0}; Fulfilled: {1}. Backordered: {2}",
                await this.GetOrderStatusAsStringAsync(),
                items.Count(x => x.FulfillmentRemaining == 0),
                items.Count(x => x.FulfillmentRemaining > 0));

            long messageRequestId = await this.StateManager.GetStateAsync<long>(RequestIdPropertyName);
            await this.StateManager.SetStateAsync<long>(RequestIdPropertyName, ++messageRequestId);
        }