private void timer_elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            this.Log().Info(() => "Checking for packages to validate.");
            
            try
            {
                var submittedPackagesUri = NuGetService.get_service_endpoint_url(_configurationSettings.PackagesUrl, SERVICE_ENDPOINT);

                // such a fun, dynamically generated name
                var service = new FeedContext_x0060_1(submittedPackagesUri)
                {
                    Timeout = 70
                };

                var cdnCacheTimeout = DateTime.UtcNow.AddMinutes(-31);
                // this only returns 30-40 results at a time but at least we'll have something to start with
                IQueryable<V2FeedPackage> packageQuery =
                    service.Packages.Where(
                        p => p.Created < cdnCacheTimeout
                             && (p.PackageValidationResultStatus == null || p.PackageValidationResultStatus == "Pending" || p.PackageValidationResultStatus == "Unknown")
                        );

                // specifically reduce the call to 30 results so we get back results faster from Chocolatey.org
                IList<V2FeedPackage> packagesToValidate = packageQuery.Take(30).ToList();
                if (packagesToValidate.Count == 0) this.Log().Info("No packages to validate.");
                else this.Log().Info("Pulled in {0} packages for validation.".format_with(packagesToValidate.Count));

                foreach (var package in packagesToValidate.or_empty_list_if_null())
                {
                    this.Log().Info(() => "========== {0} v{1} ==========".format_with(package.Id, package.Version));
                    this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                    EventManager.publish(new ValidatePackageMessage(package.Id, package.Version));
                }
            }
            catch (Exception ex)
            {
                Bootstrap.handle_exception(ex);
            }

            this.Log().Info(() => "Finished checking for packages to validate. Sleeping for {0} minute(s).".format_with(TIMER_INTERVAL / 60000));
            
            _timer.Start();
        }
        private void timer_elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            this.Log().Info(() => "Checking for packages to cleanup (remind/reject).");

            try
            {
                var submittedPackagesUri = NuGetService.get_service_endpoint_url(_configurationSettings.PackagesUrl, SERVICE_ENDPOINT);

                // such a fun, dynamically generated name
                var service = new FeedContext_x0060_1(submittedPackagesUri)
                {
                    Timeout = 70
                };

                var twentyDaysAgo = DateTime.UtcNow.AddDays(-20);
                
                // this only returns 30-40 results at a time but at least we'll have something to start with

                //this is not a perfect check but will capture most of the items that need cleaned up.
                IQueryable<V2FeedPackage> packageQuery =
                    service.Packages.Where(
                        p => p.Created < twentyDaysAgo
                            && p.PackageStatus == "Submitted"
                            && p.PackageSubmittedStatus == "Waiting"
                            && (p.PackageCleanupResultDate == null)
                            && ((p.PackageReviewedDate != null && p.PackageReviewedDate < twentyDaysAgo) 
                                ||
                                (p.PackageReviewedDate == null && p.PackageTestResultStatusDate < twentyDaysAgo)
                                )
                        );

                //int totalCount = packageQuery.Count();

                // specifically reduce the call to 30 results so we get back results faster from Chocolatey.org
                IList<V2FeedPackage> packages = packageQuery.Take(30).ToList();
                if (packages.Count == 0) this.Log().Info("No packages to remind.");
                else this.Log().Info("Pulled in {0} packages for reminders.".format_with(packages.Count));

                foreach (var package in packages.or_empty_list_if_null())
                {
                    this.Log().Info(() => "========== {0} v{1} ==========".format_with(package.Id, package.Version));
                    this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                    EventManager.publish(new ReminderPackageMessage(package.Id, package.Version));
                }

                var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15);
                IQueryable<V2FeedPackage> packageQueryForReject =
                     service.Packages.Where(
                         p => p.PackageCleanupResultDate < fifteenDaysAgo
                             && p.PackageStatus == "Submitted"
                             && p.PackageSubmittedStatus == "Waiting"
                         );
                
                // specifically reduce the call to 30 results so we get back results faster from Chocolatey.org
                IList<V2FeedPackage> packagesForReject = packageQueryForReject.Take(30).ToList();
                if (packagesForReject.Count == 0) this.Log().Info("No packages to reject.");
                else this.Log().Info("Pulled in {0} packages for rejection.".format_with(packages.Count));

                foreach (var package in packagesForReject.or_empty_list_if_null())
                {
                    this.Log().Info(() => "========== {0} v{1} ==========".format_with(package.Id, package.Version));
                    this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                    EventManager.publish(new RejectPackageMessage(package.Id, package.Version));
                }
            }
            catch (Exception ex)
            {
                Bootstrap.handle_exception(ex);
            }

            this.Log().Info(() => "Finished checking for packages to cleanup. Sleeping for {0} minute(s).".format_with(TIMER_INTERVAL / 60000));

            _timer.Start();
        }
        private void timer_elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            this.Log().Info(() => "Checking for packages to verify.");

            try
            {
                var submittedPackagesUri = NuGetService.get_service_endpoint_url(_configurationSettings.PackagesUrl, ServiceEndpoint);

                var lastPackage = string.Empty;

                //for (var i = 0; i < 10; i++)
                //{
                this.Log().Info(() => "Grabbing next available package for verification.");

                var service = new FeedContext_x0060_1(submittedPackagesUri)
                {
                    Timeout = 70
                };

                var cacheTimeout = DateTime.UtcNow.AddMinutes(-31);
                // this only returns 40 results at a time but at least we'll have something to start with
                IQueryable<V2FeedPackage> packageQuery =
                    service.Packages.Where(p => p.Created < cacheTimeout);

                if (AdditionalPackageSelectionFilters != null) packageQuery = AdditionalPackageSelectionFilters.Invoke(packageQuery);

                //int total = packageQuery.Count();
                //packageQuery = packageQuery.Where(p => p.Id == "");

                packageQuery = packageQuery.OrderBy(p => p.Created);

                // let's specifically reduce the call to 30 results so we get back results faster from Chocolatey.org
                IList<V2FeedPackage> packagesToValidate = packageQuery.Take(30).ToList();

                if (packagesToValidate.Count == 0)
                {
                    this.Log().Info("No packages to verify.");
                    //break;
                }

                //remove the random for now, we'll just grab the top result
                //this.Log().Info("Pulled in {0} packages, picking one at random to verify.".format_with(packagesToValidate.Count));

                //var skip = new Random().Next(packagesToValidate.Count);
                //if (skip < 0) skip = 0;
                //packagesToValidate = packagesToValidate.Skip(skip).Take(1).ToList();

                //var package = packagesToValidate.FirstOrDefault();
                //if (package == null) continue;

                //var packageId = "{0}:{1}".format_with(package.Id, package.Version);
                //if (lastPackage == packageId)
                //{
                //    this.Log().Info("Already verified {0} v{1} recently.".format_with(package.Title, package.Version));
                //    continue;
                //}
                //lastPackage = packageId;

                //this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                //EventManager.publish(new VerifyPackageMessage(package.Id, package.Version));

                foreach (var package in packagesToValidate.or_empty_list_if_null())
                {
                    this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                    EventManager.publish(new VerifyPackageMessage(package.Id, package.Version));
                }
                // }
            }
            catch (Exception ex)
            {
                Bootstrap.handle_exception(ex);
            }

            this.Log().Info(() => "Finished checking for packages to verify. Sleeping for {0} minutes.".format_with(TIMER_INTERVAL / 60000));

            _timer.Start();
        }