コード例 #1
0
        public override async Task <IQueueEntry <T> > DequeueAsync(CancellationToken cancellationToken)
        {
            _logger.Trace("Queue {type} dequeuing item...", typeof(T).Name);
            _logger.Trace("Queue count: {0}", _queue.Count);

            if (_queue.Count == 0 && !cancellationToken.IsCancellationRequested)
            {
                _logger.Trace("Waiting to dequeue item...");
                var sw = Stopwatch.StartNew();

                try {
                    using (await _monitor.EnterAsync(cancellationToken))
                        await _monitor.WaitAsync(cancellationToken).AnyContext();
                } catch (TaskCanceledException) {}

                sw.Stop();
                _logger.Trace("Waited for dequeue: {0}", sw.Elapsed.ToString());
            }

            if (_queue.Count == 0)
            {
                return(null);
            }

            _logger.Trace("Dequeue: Attempt");

            QueueEntry <T> info;

            if (!_queue.TryDequeue(out info) || info == null)
            {
                return(null);
            }

            info.Attempts++;
            info.DequeuedTimeUtc = DateTime.UtcNow;

            if (!_dequeued.TryAdd(info.Id, info))
            {
                throw new ApplicationException("Unable to add item to the dequeued list.");
            }

            Interlocked.Increment(ref _dequeuedCount);
            _logger.Trace("Dequeue: Got Item");

            var entry = new QueueEntry <T>(info.Id, info.Value.Copy(), this, info.EnqueuedTimeUtc, info.Attempts);

            await OnDequeuedAsync(entry).AnyContext();

            ScheduleNextMaintenance(DateTime.UtcNow.Add(_workItemTimeout));

            return(entry);
        }
コード例 #2
0
ファイル: InMemoryQueue.cs プロジェクト: jmkelly/Foundatio
        public override void StartWorking(Func <QueueEntry <T>, CancellationToken, Task> handler, bool autoComplete = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            Logger.Trace().Message("Queue {0} start working", typeof(T).Name).Write();

            var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_disposeTokenSource.Token, cancellationToken).Token;

            Task.Run(async() => {
#if DEBUG
                Logger.Trace().Message("WorkerLoop Start {0}", typeof(T).Name).Write();
#endif
                while (!linkedCancellationToken.IsCancellationRequested)
                {
#if DEBUG
                    Logger.Trace().Message("WorkerLoop Signaled {0}", typeof(T).Name).Write();
#endif
                    QueueEntry <T> queueEntry = null;
                    try {
                        queueEntry = await DequeueAsync(cancellationToken: cancellationToken).AnyContext();
                    } catch (Exception ex) {
                        Logger.Error().Message("Error on Dequeue: " + ex.Message).Exception(ex).Write();
                    }

                    if (queueEntry == null)
                    {
                        return;
                    }

                    try {
                        await handler(queueEntry, linkedCancellationToken).AnyContext();
                        if (autoComplete)
                        {
                            await queueEntry.CompleteAsync().AnyContext();
                        }
                    } catch (Exception ex) {
                        Logger.Error().Exception(ex).Message("Worker error: {0}", ex.Message).Write();
                        await queueEntry.AbandonAsync().AnyContext();
                        Interlocked.Increment(ref _workerErrorCount);
                    }
                }
#if DEBUG
                Logger.Trace().Message("WorkLoop End").Write();
#endif
            }, linkedCancellationToken);
        }
コード例 #3
0
        protected override async Task <IQueueEntry <T> > DequeueImplAsync(CancellationToken linkedCancellationToken)
        {
            _logger.Trace("Queue {type} dequeuing item...", _options.Name);
            _logger.Trace("Queue count: {0}", _queue.Count);

            while (_queue.Count == 0 && !linkedCancellationToken.IsCancellationRequested)
            {
                _logger.Trace("Waiting to dequeue item...");
                var sw = Stopwatch.StartNew();

                try {
                    await _autoResetEvent.WaitAsync(GetDequeueCanncellationToken(linkedCancellationToken)).AnyContext();
                } catch (OperationCanceledException) { }

                sw.Stop();
                _logger.Trace("Waited for dequeue: {0}", sw.Elapsed.ToString());
            }

            if (_queue.Count == 0)
            {
                return(null);
            }

            _logger.Trace("Dequeue: Attempt");
            if (!_queue.TryDequeue(out QueueEntry <T> info) || info == null)
            {
                return(null);
            }

            info.Attempts++;
            info.DequeuedTimeUtc = SystemClock.UtcNow;

            if (!_dequeued.TryAdd(info.Id, info))
            {
                throw new Exception("Unable to add item to the dequeued list.");
            }

            Interlocked.Increment(ref _dequeuedCount);
            _logger.Trace("Dequeue: Got Item");

            var entry = new QueueEntry <T>(info.Id, info.Value.DeepClone(), this, info.EnqueuedTimeUtc, info.Attempts);
            await entry.RenewLockAsync();

            await OnDequeuedAsync(entry).AnyContext();

            ScheduleNextMaintenance(SystemClock.UtcNow.Add(_options.WorkItemTimeout));

            return(entry);
        }
コード例 #4
0
ファイル: AzureServiceBusQueue.cs プロジェクト: nj/Foundatio
        private async Task <IQueueEntry <T> > HandleDequeueAsync(BrokeredMessage msg)
        {
            if (msg == null)
            {
                return(null);
            }

            var data = msg.GetBody <T>();

            Interlocked.Increment(ref _dequeuedCount);
            var entry = new QueueEntry <T>(msg.LockToken.ToString(), data, this, msg.EnqueuedTimeUtc, msg.DeliveryCount);

            await OnDequeuedAsync(entry).AnyContext();

            return(entry);
        }
コード例 #5
0
        private async Task <IQueueEntry <T> > HandleDequeueAsync(BrokeredMessage brokeredMessage)
        {
            if (brokeredMessage == null)
            {
                return(null);
            }

            var message = _serializer.Deserialize <T>(brokeredMessage.GetBody <Stream>());

            Interlocked.Increment(ref _dequeuedCount);
            var entry = new QueueEntry <T>(brokeredMessage.LockToken.ToString(), message, this, brokeredMessage.EnqueuedTimeUtc, brokeredMessage.DeliveryCount);

            await OnDequeuedAsync(entry).AnyContext();

            return(entry);
        }
コード例 #6
0
        public override async Task <QueueEntry <T> > DequeueAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            // TODO: use the cancellation token.
            using (var msg = await _queueClient.ReceiveAsync().AnyContext()) {
                if (msg == null)
                {
                    return(null);
                }

                var data = msg.GetBody <T>();
                Interlocked.Increment(ref _dequeuedCount);
                var entry = new QueueEntry <T>(msg.LockToken.ToString(), data, this, msg.EnqueuedTimeUtc, msg.DeliveryCount);
                await OnDequeuedAsync(entry).AnyContext();

                return(entry);
            }
        }
コード例 #7
0
ファイル: InMemoryQueue.cs プロジェクト: derekpitt/Foundatio
        public override async Task CompleteAsync(IQueueEntry <T> entry)
        {
            _logger.Trace("Queue {0} complete item: {1}", typeof(T).Name, entry.Id);

            QueueEntry <T> info = null;

            if (!_dequeued.TryRemove(entry.Id, out info) || info == null)
            {
                throw new ApplicationException("Unable to remove item from the dequeued list.");
            }

            Interlocked.Increment(ref _completedCount);

            await OnCompletedAsync(entry).AnyContext();

            _logger.Trace("Complete done: {0}", entry.Id);
        }
コード例 #8
0
        private async Task <IQueueEntry <T> > HandleDequeueAsync(Message brokeredMessage)
        {
            if (brokeredMessage == null)
            {
                return(null);
            }

            var message = _serializer.Deserialize <T>(brokeredMessage.Body);

            Interlocked.Increment(ref _dequeuedCount);
            var entry = new QueueEntry <T>(brokeredMessage.SystemProperties.LockToken, message, this,
                                           brokeredMessage.ScheduledEnqueueTimeUtc, brokeredMessage.SystemProperties.DeliveryCount);

            await OnDequeuedAsync(entry).AnyContext();

            return(entry);
        }
コード例 #9
0
ファイル: AzureServiceBusQueue.cs プロジェクト: nj/Foundatio
        protected override async Task <string> EnqueueImplAsync(T data)
        {
            if (!await OnEnqueuingAsync(data).AnyContext())
            {
                return(null);
            }

            Interlocked.Increment(ref _enqueuedCount);
            var message = new BrokeredMessage(data);
            await _queueClient.SendAsync(message).AnyContext();

            var entry = new QueueEntry <T>(message.MessageId, data, this, SystemClock.UtcNow, 0);

            await OnEnqueuedAsync(entry).AnyContext();

            return(message.MessageId);
        }
コード例 #10
0
        public override async Task <string> EnqueueAsync(T data)
        {
            if (!await OnEnqueuingAsync(data).AnyContext())
            {
                return(null);
            }

            Interlocked.Increment(ref _enqueuedCount);
            var message = new CloudQueueMessage(await _serializer.SerializeAsync(data));
            await _queueReference.AddMessageAsync(message).AnyContext();

            var entry = new QueueEntry <T>(message.Id, data, this, DateTime.UtcNow, 0);

            await OnEnqueuedAsync(entry).AnyContext();

            return(message.Id);
        }
コード例 #11
0
        protected override async Task <string> EnqueueImplAsync(T data)
        {
            if (!await OnEnqueuingAsync(data).AnyContext())
            {
                return(null);
            }

            Interlocked.Increment(ref _enqueuedCount);
            var message = CloudQueueMessage.CreateCloudQueueMessageFromByteArray(_serializer.SerializeToBytes(data));
            await _queueReference.AddMessageAsync(message).AnyContext();

            var entry = new QueueEntry <T>(message.Id, data, this, SystemClock.UtcNow, 0);

            await OnEnqueuedAsync(entry).AnyContext();

            return(message.Id);
        }
コード例 #12
0
ファイル: RedisQueue.cs プロジェクト: jmkelly/Foundatio
        public override void StartWorking(Func <QueueEntry <T>, CancellationToken, Task> handler, bool autoComplete = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_queueDisposedCancellationTokenSource.Token, cancellationToken).Token;

            Task.Run(async() => {
#if DEBUG
                Logger.Trace().Message($"WorkerLoop Start {_queueName}").Write();
#endif
                while (!linkedCancellationToken.IsCancellationRequested)
                {
#if DEBUG
                    Logger.Trace().Message($"WorkerLoop Pass {_queueName}").Write();
#endif
                    QueueEntry <T> queueEntry = null;
                    try {
                        queueEntry = await DequeueAsync(cancellationToken: cancellationToken).AnyContext();
                    } catch (TimeoutException) { }

                    if (linkedCancellationToken.IsCancellationRequested || queueEntry == null)
                    {
                        continue;
                    }

                    try {
                        await handler(queueEntry, linkedCancellationToken).AnyContext();
                        if (autoComplete)
                        {
                            await queueEntry.CompleteAsync().AnyContext();
                        }
                    } catch (Exception ex) {
                        Logger.Error().Exception(ex).Message("Worker error: {0}", ex.Message).Write();
                        await queueEntry.AbandonAsync().AnyContext();
                        Interlocked.Increment(ref _workerErrorCount);
                    }
                }
#if DEBUG
                Logger.Trace().Message("Worker exiting: {0} Cancel Requested: {1}", _queueName, linkedCancellationToken.IsCancellationRequested).Write();
#endif
            }, linkedCancellationToken);
        }
コード例 #13
0
ファイル: InMemoryQueue.cs プロジェクト: skyhoshi/Foundatio
        protected override async Task <string> EnqueueImplAsync(T data, QueueEntryOptions options)
        {
            string id = Guid.NewGuid().ToString("N");

            _logger.LogTrace("Queue {Name} enqueue item: {Id}", _options.Name, id);

            if (!await OnEnqueuingAsync(data, options).AnyContext())
            {
                return(null);
            }

            var entry = new QueueEntry <T>(id, options?.CorrelationId, data.DeepClone(), this, SystemClock.UtcNow, 0);

            entry.Properties.AddRange(options?.Properties);

            Interlocked.Increment(ref _enqueuedCount);

            if (options?.DeliveryDelay != null && options.DeliveryDelay.Value > TimeSpan.Zero)
            {
                _ = Run.DelayedAsync(options.DeliveryDelay.Value, async() => {
                    _queue.Enqueue(entry);
                    _logger.LogTrace("Enqueue: Set Event");

                    _autoResetEvent.Set();

                    await OnEnqueuedAsync(entry).AnyContext();
                    _logger.LogTrace("Enqueue done");
                }, _queueDisposedCancellationTokenSource.Token);
                return(id);
            }

            _queue.Enqueue(entry);
            _logger.LogTrace("Enqueue: Set Event");

            _autoResetEvent.Set();

            await OnEnqueuedAsync(entry).AnyContext();

            _logger.LogTrace("Enqueue done");

            return(id);
        }
コード例 #14
0
        private async Task <IQueueEntry <T> > HandleDequeueAsync(Message brokeredMessage)
        {
            if (brokeredMessage == null)
            {
                return(null);
            }

            var message = _serializer.Deserialize <T>(brokeredMessage.Body);

            Interlocked.Increment(ref _dequeuedCount);
            var entry = new QueueEntry <T>(brokeredMessage.MessageId, brokeredMessage.CorrelationId, message, this, brokeredMessage.SystemProperties.EnqueuedTimeUtc, brokeredMessage.SystemProperties.DeliveryCount);

            foreach (var property in brokeredMessage.UserProperties)
            {
                entry.Properties.Add(property.Key, property.Value);
            }
            await OnDequeuedAsync(entry).AnyContext();

            return(entry);
        }
コード例 #15
0
        protected override async Task <string> EnqueueImplAsync(T data)
        {
            if (!await OnEnqueuingAsync(data).AnyContext())
            {
                return(null);
            }

            Interlocked.Increment(ref _enqueuedCount);
            var stream = new MemoryStream();

            _serializer.Serialize(data, stream);
            var brokeredMessage = new BrokeredMessage(stream, true);
            await _queueClient.SendAsync(brokeredMessage).AnyContext(); // TODO: See if there is a way to send a batch of messages.

            var entry = new QueueEntry <T>(brokeredMessage.MessageId, data, this, SystemClock.UtcNow, 0);

            await OnEnqueuedAsync(entry).AnyContext();

            return(brokeredMessage.MessageId);
        }
コード例 #16
0
        protected override async Task <string> EnqueueImplAsync(T data)
        {
            if (!await OnEnqueuingAsync(data).AnyContext())
            {
                return(null);
            }

            var message = new SendMessageRequest {
                QueueUrl    = _queueUrl,
                MessageBody = await _serializer.SerializeToStringAsync(data).AnyContext(),
            };

            var response = await _client.Value.SendMessageAsync(message).AnyContext();

            Interlocked.Increment(ref _enqueuedCount);
            var entry = new QueueEntry <T>(response.MessageId, data, this, SystemClock.UtcNow, 0);

            await OnEnqueuedAsync(entry).AnyContext();

            return(response.MessageId);
        }
コード例 #17
0
ファイル: SQSQueue.cs プロジェクト: karanbajaj/Foundatio.AWS
        protected override async Task <string> EnqueueImplAsync(T data, QueueEntryOptions options)
        {
            if (!await OnEnqueuingAsync(data, options).AnyContext())
            {
                return(null);
            }

            var message = new SendMessageRequest {
                QueueUrl    = _queueUrl,
                MessageBody = _serializer.SerializeToString(data)
            };

            if (!String.IsNullOrEmpty(options?.CorrelationId))
            {
                message.MessageAttributes.Add("CorrelationId", new MessageAttributeValue {
                    DataType    = "String",
                    StringValue = options.CorrelationId
                });
            }

            if (options?.Properties != null)
            {
                foreach (var property in options.Properties)
                {
                    message.MessageAttributes.Add(property.Key, new MessageAttributeValue {
                        DataType    = "String",
                        StringValue = property.Value.ToString() // TODO: Support more than string data types
                    });
                }
            }

            var response = await _client.Value.SendMessageAsync(message).AnyContext();

            Interlocked.Increment(ref _enqueuedCount);
            var entry = new QueueEntry <T>(response.MessageId, options?.CorrelationId, data, this, SystemClock.UtcNow, 0);

            await OnEnqueuedAsync(entry).AnyContext();

            return(response.MessageId);
        }
コード例 #18
0
ファイル: RedisQueue.cs プロジェクト: nj/Foundatio
        protected override async Task <string> EnqueueImplAsync(T data)
        {
            string id = Guid.NewGuid().ToString("N");

            _logger.Debug("Queue {_queueName} enqueue item: {id}", _queueName, id);

            if (!await OnEnqueuingAsync(data).AnyContext())
            {
                _logger.Trace("Aborting enqueue item: {id}", id);
                return(null);
            }

            var  now     = SystemClock.UtcNow;
            bool success = await Run.WithRetriesAsync(() => _cache.AddAsync(GetPayloadKey(id), data, _payloadTtl), logger : _logger).AnyContext();

            if (!success)
            {
                throw new InvalidOperationException("Attempt to set payload failed.");
            }

            await Run.WithRetriesAsync(() => _cache.SetAsync(GetEnqueuedTimeKey(id), now.Ticks, _payloadTtl), logger : _logger).AnyContext();

            await Run.WithRetriesAsync(() => Database.ListLeftPushAsync(QueueListName, id), logger : _logger).AnyContext();

            // This should pulse the monitor.
            try {
                await Run.WithRetriesAsync(() => _subscriber.PublishAsync(GetTopicName(), id), logger : _logger).AnyContext();
            } catch { }

            Interlocked.Increment(ref _enqueuedCount);
            var entry = new QueueEntry <T>(id, data, this, now, 0);

            await OnEnqueuedAsync(entry).AnyContext();

            _logger.Trace("Enqueue done");

            return(id);
        }
コード例 #19
0
        protected override async Task <string> EnqueueImplAsync(T data, QueueEntryOptions options)
        {
            string id = Guid.NewGuid().ToString("N");
            bool   isTraceLogLevelEnabled = _logger.IsEnabled(LogLevel.Trace);

            if (isTraceLogLevelEnabled)
            {
                _logger.LogTrace("Queue {Name} enqueue item: {Id}", _options.Name, id);
            }

            if (!await OnEnqueuingAsync(data, options).AnyContext())
            {
                return(null);
            }

            var entry = new QueueEntry <T>(id, options?.CorrelationId, data.DeepClone(), this, SystemClock.UtcNow, 0);

            entry.Properties.AddRange(options?.Properties);

            _queue.Enqueue(entry);
            if (isTraceLogLevelEnabled)
            {
                _logger.LogTrace("Enqueue: Set Event");
            }

            _autoResetEvent.Set();
            Interlocked.Increment(ref _enqueuedCount);

            await OnEnqueuedAsync(entry).AnyContext();

            if (isTraceLogLevelEnabled)
            {
                _logger.LogTrace("Enqueue done");
            }

            return(id);
        }
コード例 #20
0
        private Task WorkerLoop(CancellationToken token)
        {
            Log.Trace().Message("WorkerLoop Start {0}", typeof(T).Name).Write();
            while (!token.IsCancellationRequested)
            {
                if (_queue.Count == 0 || _workerAction == null)
                {
                    _autoEvent.WaitOne(TimeSpan.FromMilliseconds(250));
                }

                Log.Trace().Message("WorkerLoop Signaled {0}", typeof(T).Name).Write();
                QueueEntry <T> queueEntry = null;
                try {
                    queueEntry = Dequeue(TimeSpan.Zero);
                } catch (TimeoutException) { }

                if (queueEntry == null || _workerAction == null)
                {
                    return(TaskHelper.Completed());
                }

                try {
                    _workerAction(queueEntry);
                    if (_workerAutoComplete)
                    {
                        queueEntry.Complete();
                    }
                } catch (Exception ex) {
                    Log.Error().Exception(ex).Message("Worker error: {0}", ex.Message).Write();
                    queueEntry.Abandon();
                    Interlocked.Increment(ref _workerErrorCount);
                }
            }

            return(TaskHelper.Completed());
        }
コード例 #21
0
ファイル: RedisQueue.cs プロジェクト: jmkelly/Foundatio
        public override async Task <QueueEntry <T> > DequeueAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
#if DEBUG
            Logger.Trace().Message($"Queue {_queueName} dequeuing item...").Write();
#endif
            await EnsureMaintenanceRunningAsync().AnyContext();
            await EnsureTopicSubscriptionAsync().AnyContext();

            var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_queueDisposedCancellationTokenSource.Token, cancellationToken).Token;

            RedisValue value = await GetRedisValueAsync(linkedCancellationToken).AnyContext();

            if (linkedCancellationToken.IsCancellationRequested && value.IsNullOrEmpty)
            {
                return(null);
            }
#if DEBUG
            Logger.Trace().Message("Initial list value: {0}", (value.IsNullOrEmpty ? "<null>" : value.ToString())).Write();
#endif
            while (value.IsNullOrEmpty && !linkedCancellationToken.IsCancellationRequested)
            {
#if DEBUG
                Logger.Trace().Message("Waiting to dequeue item...").Write();
                var sw = Stopwatch.StartNew();
#endif
                try {
                    using (await _monitor.EnterAsync(cancellationToken))
                        await _monitor.WaitAsync(cancellationToken).AnyContext();
                } catch (TaskCanceledException) { }
#if DEBUG
                sw.Stop();
                Logger.Trace().Message("Waited for dequeue: {0}", sw.Elapsed.ToString()).Write();
#endif
                value = await GetRedisValueAsync(linkedCancellationToken).AnyContext();

#if DEBUG
                Logger.Trace().Message("List value: {0}", (value.IsNullOrEmpty ? "<null>" : value.ToString())).Write();
#endif
            }

            if (value.IsNullOrEmpty)
            {
                return(null);
            }

            await _cache.SetAsync(GetDequeuedTimeKey(value), DateTime.UtcNow.Ticks, GetDequeuedTimeTtl()).AnyContext();

            try {
                var payload = await _cache.GetAsync <T>(GetPayloadKey(value)).AnyContext();

                if (payload.IsNull)
                {
                    Logger.Error().Message("Error getting queue payload: {0}", value).Write();
                    await _db.ListRemoveAsync(WorkListName, value).AnyContext();

                    return(null);
                }

                var enqueuedTimeTicks = await _cache.GetAsync <long>(GetEnqueuedTimeKey(value), 0).AnyContext();

                var attemptsValue = await _cache.GetAsync <int>(GetAttemptsKey(value), -1).AnyContext();

                var entry = new QueueEntry <T>(value, payload.Value, this, new DateTime(enqueuedTimeTicks, DateTimeKind.Utc), attemptsValue);
                Interlocked.Increment(ref _dequeuedCount);
                await OnDequeuedAsync(entry).AnyContext();

#if DEBUG
                Logger.Debug().Message("Dequeued item: {0}", value).Write();
#endif
                return(entry);
            } catch (Exception ex) {
                Logger.Error().Exception(ex).Message("Error getting queue payload: {0}", value).Write();
                throw;
            }
        }
コード例 #22
0
        protected override async Task <IQueueEntry <T> > DequeueImplAsync(CancellationToken linkedCancellationToken)
        {
            bool isTraceLogLevelEnabled = _logger.IsEnabled(LogLevel.Trace);

            if (isTraceLogLevelEnabled)
            {
                _logger.LogTrace("Queue {Name} dequeuing item... Queue count: {Count}", _options.Name, _queue.Count);
            }

            while (_queue.Count == 0 && !linkedCancellationToken.IsCancellationRequested)
            {
                if (isTraceLogLevelEnabled)
                {
                    _logger.LogTrace("Waiting to dequeue item...");
                }
                var sw = Stopwatch.StartNew();

                try {
                    using (var timeoutCancellationTokenSource = new CancellationTokenSource(10000))
                        using (var dequeueCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(linkedCancellationToken, timeoutCancellationTokenSource.Token)) {
                            await _autoResetEvent.WaitAsync(dequeueCancellationTokenSource.Token).AnyContext();
                        }
                } catch (OperationCanceledException) { }

                sw.Stop();
                if (isTraceLogLevelEnabled)
                {
                    _logger.LogTrace("Waited for dequeue: {Elapsed:g}", sw.Elapsed);
                }
            }

            if (_queue.Count == 0)
            {
                return(null);
            }

            if (isTraceLogLevelEnabled)
            {
                _logger.LogTrace("Dequeue: Attempt");
            }
            if (!_queue.TryDequeue(out var info) || info == null)
            {
                return(null);
            }

            info.Attempts++;
            info.DequeuedTimeUtc = SystemClock.UtcNow;

            if (!_dequeued.TryAdd(info.Id, info))
            {
                throw new Exception("Unable to add item to the dequeued list.");
            }

            Interlocked.Increment(ref _dequeuedCount);
            if (isTraceLogLevelEnabled)
            {
                _logger.LogTrace("Dequeue: Got Item");
            }

            var entry = new QueueEntry <T>(info.Id, info.Value.DeepClone(), this, info.EnqueuedTimeUtc, info.Attempts);
            await entry.RenewLockAsync();

            await OnDequeuedAsync(entry).AnyContext();

            ScheduleNextMaintenance(SystemClock.UtcNow.Add(_options.WorkItemTimeout));

            return(entry);
        }
コード例 #23
0
 private async Task RetryAsync(QueueEntry <T> entry)
 {
     _queue.Enqueue(entry);
     using (await _monitor.EnterAsync())
         _monitor.Pulse();
 }