protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            Logger.Debug(nameof(this.RunAsync));

            try
            {
                if (this.Partition.PartitionInfo.Kind != ServicePartitionKind.Int64Range)
                {
                    throw new ApplicationException("Partition kind is not Int64Range");
                }

                Int64RangePartitionInformation partitionInfo = (Int64RangePartitionInformation) this.Partition.PartitionInfo;
                int lowId = (int) partitionInfo.LowKey;
                int highId = (int) partitionInfo.HighKey;

                //bulk-import test data from CSV files
                Logger.Debug("attempting to bulk-import data");

                //get or create the "products" dictionary
                this.productsCollection =
                    await this.StateManager.GetOrAddAsync<IReliableDictionary<int, Product>>(ProductsCollectionName);
                //get or create the purchaseLog collection
                this.purchaseLog =
                    await this.StateManager.GetOrAddAsync<IReliableDictionary<string, ProductPurchase>>(OrdersCollectionName);

                if (!TimeSpan.TryParse(ConfigurationHelper.ReadValue("AppSettings", "ProcessOrdersInterval"), out this.processOrdersInterval))
                {
                    this.processOrdersInterval = TimeSpan.FromSeconds(3);
                }

                //check if data has been imported
                using (ITransaction tx = this.StateManager.CreateTransaction())
                {
                    if (await this.productsCollection.GetCountAsync(tx) <= 0)
                    {
                        Logger.Debug("Importing products with productId from {0} to {1}...", lowId, highId);

                        //bulk-import the data
                        BulkDataSource dataSource = new BulkDataSource();
                        foreach (Product p in dataSource.ReadProducts(lowId, highId))
                        {
                            await this.productsCollection.AddAsync(tx, p.ProductId, p);
                        }

                        await tx.CommitAsync();
                    }
                }

                // launch watcher thread
                await this.DispatchPurchaseLogAsync(cancellationToken);
            }
            catch (Exception ex)
            {
                Logger.Error(ex, nameof(this.RunAsync));
                throw;
            }
        }
        public static void Main(string[] args)
        {
            try
            {
                ThreadPool.SetMinThreads(10000, 500);
                ServicePointManager.DefaultConnectionLimit = int.MaxValue;
                ServicePointManager.UseNagleAlgorithm = false;
                ServicePointManager.Expect100Continue = false;

                if (args.Length == 0)
                {
                    throw new ArgumentException("Invalid number of input parameters");
                }

                else if (args[0].Equals("purchase"))
                {
                    LoadClientTest loadTest = new LoadClientTest();
                    IEnumerable<string> ids = args.Skip(1);
                    loadTest.ProductIdsToPurchase.AddRange(ids.Select(int.Parse));
                    loadTest.Purchase_MultipleProductsInParametersRandomly_Nothing();
                }
                else if (args[0].Equals("reorder"))
                {
                    int quantityPerProduct = 1;
                    int delayMs = -1;

                    if (args.Length > 1)
                    {
                        quantityPerProduct = Convert.ToInt32(args[1]);
                    }
                    if (args.Length > 2)
                    {
                        delayMs = Convert.ToInt32(args[2]);
                    }

                    LoadClientTest loadTest = new LoadClientTest();

                    // Re stock items on command line
                    if (args.Length > 3)
                    {
                        IEnumerable<string> ids = args.Skip(3);
                        loadTest.ProductIdsToOrder.AddRange(ids.Select(int.Parse));
                    }
                    else
                    {
                        // Re stock all items
                        BulkDataSource bulkDataSource = new BulkDataSource();
                        loadTest.ProductIdsToOrder.AddRange(bulkDataSource.ReadAllProducts().Select(p => p.ProductId));
                    }

                    loadTest.Order_MultipleProductsInParameters(quantityPerProduct, delayMs);
                }
                else if (args[0].Equals("stream"))
                {
                    LoadClientTest.TestProtocolType testProtocolType = LoadClientTest.TestProtocolType.WebSockets;
                    int threadCount = 1;
                    int iterationsPerThread = 1;
                    int delayMs = -1;
                    int maxProductsPerThread = -1;

                    // Read Parameters
                    if (args.Length > 1)
                    {
                        if (args[1].ToLower().Equals("http"))
                        {
                            testProtocolType = LoadClientTest.TestProtocolType.Http;
                        }
                        else if (args[1].ToLower().Equals("websockets") || args[1].ToLower().Equals("websocket"))
                        {
                            testProtocolType = LoadClientTest.TestProtocolType.WebSockets;
                        }
                        else
                        {
                            throw new ArgumentException("Invalid streaming protocol 'http|websockets'");
                        }
                    }
                    if (args.Length > 2)
                    {
                        threadCount = Convert.ToInt32(args[2]);
                    }
                    if (args.Length > 3)
                    {
                        iterationsPerThread = Convert.ToInt32(args[3]);
                    }
                    if (args.Length > 4)
                    {
                        maxProductsPerThread = Convert.ToInt32(args[4]);
                    }
                    if (args.Length > 5)
                    {
                        delayMs = Convert.ToInt32(args[5]);
                    }

                    // Print parameters
                    Console.WriteLine(
                        "Streaming: Protocol={0}\r\nThreadCount={1}\r\niterationsPerThread={2}\r\nMax Products per Thread={3}\r\nThread sleep={4}ms",
                        args[1],
                        threadCount,
                        iterationsPerThread,
                        maxProductsPerThread,
                        delayMs);


                    // Initialize and launch test...
                    LoadClientTest loadTest = new LoadClientTest();
                    BulkDataSource bulkDataSource = new BulkDataSource();
                    foreach (Product p in bulkDataSource.ReadAllProducts())
                    {
                        loadTest.ProductIdsToPurchase.Add(p.ProductId);
                    }
                    loadTest.Purchase_MultipleProductsInParametersRandomly_Stream(
                        testProtocolType,
                        threadCount,
                        iterationsPerThread,
                        maxProductsPerThread,
                        delayMs);
                }
                else
                {
                    throw new ArgumentException("Invalid input parameters");
                }
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("Please enter: purchase or reorder and a list of numbers");
                Console.WriteLine("To purchase: purchase 771 772 773 774");
                Console.WriteLine("To reorder: reorder (Items per Product) (Thread sleep in Milliseconds None=-1) [771 772 773 774 ...]");
                Console.WriteLine(
                    "To stream: stream http|websockets threadcount iterationsperthread [Max # Products per Thread (Default=-1 All)] [Thread sleep in Milliseconds (Default=-1 None)]");
            }

            if (System.Diagnostics.Debugger.IsAttached)
            {
                Console.ReadLine();
            }
        }