public IFetchedJob Dequeue([NotNull] string[] queues, CancellationToken cancellationToken)
        {
            if (queues is null)
            {
                throw new ArgumentNullException(nameof(queues));
            }
            if (queues.Length == 0)
            {
                throw new ArgumentException(CoreStrings.ArgumentExceptionCollectionCannotBeEmpty,
                                            nameof(queues));
            }

            var waitHandles = new[]
            {
                cancellationToken.WaitHandle,
                NewItemInQueueEvent,
            };

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var expireAt = DateTime.UtcNow - _storage.SlidingInvisibilityTimeout;
                using (var context = _storage.CreateContext())
                {
                    var queueItem = DequeueFunc(context, queues, expireAt);
                    if (queueItem != null)
                    {
                        queueItem.FetchedAt = DateTime.UtcNow;
                        try
                        {
                            context.SaveChanges();
                            return(new EFCoreFetchedJob(_storage, queueItem));
                        }
                        catch (DbUpdateConcurrencyException)
                        {
                            continue;
                        }
                    }
                }

                WaitHandle.WaitAny(
                    waitHandles,
                    _storage.QueuePollInterval);
            }
        }
        public void Execute(CancellationToken cancellationToken)
        {
            _logger.Debug(CoreStrings.CountersAggregatorExecuteStarting(nameof(HangfireCounter)));
            int removedCount;

            do
            {
                removedCount = 0;
                using (var context = _storage.CreateContext())
                {
                    var lookup = GetCountersToRemoveFunc(context).
                                 ToLookup(x => x.Key);

                    foreach (var items in lookup)
                    {
                        var count = items.Count();
                        if (count > 1)
                        {
                            context.RemoveRange(items);
                            context.Add(new HangfireCounter
                            {
                                Key      = items.Key,
                                Value    = items.Sum(x => x.Value),
                                ExpireAt = items.Max(x => x.ExpireAt),
                            });
                            removedCount += count;
                        }
                    }
                    try
                    {
                        context.SaveChanges();
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        // Someone else has removed at least one record. Database wins.
                        continue;
                    }
                }
                cancellationToken.ThrowIfCancellationRequested();
            }while (removedCount > 0);

            _logger.Trace(CoreStrings.CountersAggregatorExecuteCompleted(nameof(HangfireCounter)));
            cancellationToken.WaitHandle.WaitOne(_storage.CountersAggregationInterval);
        }