public override async Task RunCore()
        {
            TimeSpan hold = TimeSpan.FromMinutes(90);

            var messages = Queue.GetMessages(32, hold).ToList();

            var qClient = Account.CreateCloudQueueClient();
            var queue   = qClient.GetQueueReference(CantonConstants.CatalogPageQueue);

            while (messages.Count > 0)
            {
                foreach (var message in messages)
                {
                    JObject work           = JObject.Parse(message.AsString);
                    Uri     galleryPageUri = new Uri(work["uri"].ToString());
                    int     cantonCommitId = work["cantonCommitId"].ToObject <int>();
                    Log("started cantonCommitId: " + cantonCommitId);

                    try
                    {
                        // read the gallery page
                        JObject galleryPage = await GetJson(galleryPageUri);

                        // graph modififactions
                        GraphAddon[] addons = new GraphAddon[0];
                        //GraphAddon[] addons = new GraphAddon[] {
                        //        new OriginGraphAddon(galleryPageUri.AbsoluteUri, cantonCommitId),
                        //        new GalleryGraphAddon(galleryPage)
                        //    };

                        string id      = galleryPage["id"].ToString();
                        string version = galleryPage["version"].ToString();

                        DateTime?published      = null;
                        JToken   publishedToken = null;
                        if (galleryPage.TryGetValue("published", out publishedToken))
                        {
                            published = publishedToken.ToObject <DateTime>();
                        }

                        // download the nupkg
                        FileInfo nupkg = await GetNupkg(id, version);

                        Action <Uri> handler = (resourceUri) => QueuePage(resourceUri, Schema.DataTypes.PackageDetails, cantonCommitId, queue);

                        // create the new catalog item
                        using (var stream = nupkg.OpenRead())
                        {
                            // Create the core catalog page graph and upload it
                            using (CatalogPageCreator writer = new CatalogPageCreator(Storage, handler, addons))
                            {
                                CatalogItem catalogItem = Utils.CreateCatalogItem(stream, published, null, nupkg.FullName);
                                writer.Add(catalogItem);
                                await writer.Commit(DateTime.UtcNow);
                            }
                        }

                        // clean up
                        nupkg.Delete();
                    }
                    catch (Exception ex)
                    {
                        LogError("Unable to build catalog page for: " + galleryPageUri.AbsoluteUri + " Error: " + ex.ToString());
                    }
                    finally
                    {
                        _queueTasks.Enqueue(Queue.DeleteMessageAsync(message));

                        bool status = false;
                        if (!_workQueueStatus.TryRemove(cantonCommitId, out status) || status == false)
                        {
                            // we have to send something, the job on the other side should recognize https://failed/
                            QueuePage(new Uri("https://failed/"), Schema.DataTypes.PackageDetails, cantonCommitId, queue);

                            LogError("Unable to build catalog page for: " + galleryPageUri.AbsoluteUri);
                        }
                    }
                }

                // get the next work item
                if (_run)
                {
                    messages = Queue.GetMessages(32, hold).ToList();
                }
                else
                {
                    messages = new List <CloudQueueMessage>();
                }

                // let deletes catch up
                Task task = null;
                while (_queueTasks.TryDequeue(out task))
                {
                    task.Wait();
                }
            }

            // final wait
            Task curTask = null;

            while (_queueTasks.TryDequeue(out curTask))
            {
                curTask.Wait();
            }
        }
        public override async Task RunCore(CancellationToken cancellationToken)
        {
            TimeSpan hold = TimeSpan.FromMinutes(90);

            var messages = Queue.GetMessages(32, hold).ToList();

            var qClient = Account.CreateCloudQueueClient();
            var queue = qClient.GetQueueReference(CantonConstants.CatalogPageQueue);

            while (messages.Count > 0)
            {
                foreach (var message in messages)
                {
                    JObject work = JObject.Parse(message.AsString);
                    Uri galleryPageUri = new Uri(work["uri"].ToString());
                    int cantonCommitId = work["cantonCommitId"].ToObject<int>();
                    Log("started cantonCommitId: " + cantonCommitId);

                    try
                    {
                        // read the gallery page
                        JObject galleryPage = await GetJson(galleryPageUri);

                        // graph modififactions
                        GraphAddon[] addons = new GraphAddon[0];
                        //GraphAddon[] addons = new GraphAddon[] { 
                        //        new OriginGraphAddon(galleryPageUri.AbsoluteUri, cantonCommitId),
                        //        new GalleryGraphAddon(galleryPage)
                        //    };

                        string id = galleryPage["id"].ToString();
                        string version = galleryPage["version"].ToString();

                        DateTime? published = null;
                        JToken publishedToken = null;
                        if (galleryPage.TryGetValue("published", out publishedToken))
                        {
                            published = publishedToken.ToObject<DateTime>();
                        }

                        // download the nupkg
                        FileInfo nupkg = await GetNupkg(id, version);

                        Action<Uri> handler = (resourceUri) => QueuePage(resourceUri, Schema.DataTypes.PackageDetails, cantonCommitId, queue);

                        // create the new catalog item
                        using (var stream = nupkg.OpenRead())
                        {
                            // Create the core catalog page graph and upload it
                            using (CatalogPageCreator writer = new CatalogPageCreator(Storage, handler, addons))
                            {
                                CatalogItem catalogItem = Utils.CreateCatalogItem(stream, published, null, nupkg.FullName);
                                writer.Add(catalogItem);
                                await writer.Commit(DateTime.UtcNow, null, cancellationToken);
                            }
                        }

                        // clean up
                        nupkg.Delete();
                    }
                    catch (Exception ex)
                    {
                        LogError("Unable to build catalog page for: " + galleryPageUri.AbsoluteUri + " Error: " + ex.ToString());
                    }
                    finally
                    {
                        _queueTasks.Enqueue(Queue.DeleteMessageAsync(message));

                        bool status = false;
                        if (!_workQueueStatus.TryRemove(cantonCommitId, out status) || status == false)
                        {
                            // we have to send something, the job on the other side should recognize https://failed/
                            QueuePage(new Uri("https://failed/"), Schema.DataTypes.PackageDetails, cantonCommitId, queue);

                            LogError("Unable to build catalog page for: " + galleryPageUri.AbsoluteUri);
                        }
                    }
                }

                // get the next work item
                if (_run)
                {
                    messages = Queue.GetMessages(32, hold).ToList();
                }
                else
                {
                    messages = new List<CloudQueueMessage>();
                }

                // let deletes catch up
                Task task = null;
                while (_queueTasks.TryDequeue(out task))
                {
                    task.Wait();
                }
            }

            // final wait
            Task curTask = null;
            while (_queueTasks.TryDequeue(out curTask))
            {
                curTask.Wait();
            }
        }