Ejemplo n.º 1
0
        /// <summary>
        /// Retrieves a customer-specific view (defined in the InventoryItemView class in the Fabrikam Common namespace)
        /// af all items in the IReliableDictionary in InventoryService. Only items with a CustomerAvailableStock greater than
        /// zero are returned as a business logic constraint to reduce overordering.
        /// </summary>
        /// <returns>IEnumerable of InventoryItemView</returns>
        public async Task <IEnumerable <InventoryItemView> > GetCustomerInventoryAsync()
        {
            IReliableDictionary <InventoryItemId, InventoryItem> inventoryItems =
                await this.stateManager.GetOrAddAsync <IReliableDictionary <InventoryItemId, InventoryItem> >(InventoryItemDictionaryName);

            ServiceEventSource.Current.Message("Called GetCustomerInventory to return InventoryItemView");

            PrintInventoryItems(inventoryItems);

            IEnumerable <InventoryItemView> results = inventoryItems.Select(x => (InventoryItemView)x.Value).Where(x => x.CustomerAvailableStock > 0);

            List <InventoryItemView> resultList = results.ToList <InventoryItemView>();

            foreach (InventoryItemView tempResult in resultList)
            {
                ServiceEventSource.Current.Message("{0}|{1}", tempResult.Id, tempResult.Description);
            }

            return(results);
        }
Ejemplo n.º 2
0
        private async Task PeriodicInventoryCheck(CancellationToken cancellationToken)
        {
            IReliableDictionary <InventoryItemId, InventoryItem> inventoryItems =
                await this.stateManager.GetOrAddAsync <IReliableDictionary <InventoryItemId, InventoryItem> >(InventoryItemDictionaryName);

            if (this.storageType == StorageTypes.Azure)
            {
                await this.InitializeAsync(cancellationToken);
            }

            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());
                    }

                    if (this.storageType == StorageTypes.Local)
                    {
                        await this.StateManager.BackupAsync(this.BackupCallbackAsync);
                    }
                    else
                    {
                        await this.StateManager.BackupAsync(this.BackupCallbackAzureAsync);
                    }
                }

                await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
            }
        }