public override void StartWorking(Func <IQueueEntry <T>, CancellationToken, Task> handler, bool autoComplete = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

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

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

            Task.Run(async() => {
                _logger.Trace("WorkerLoop Start {0}", typeof(T).Name);

                while (!linkedCancellationToken.IsCancellationRequested)
                {
                    _logger.Trace("WorkerLoop Signaled {0}", typeof(T).Name);

                    IQueueEntry <T> queueEntry = null;
                    try {
                        queueEntry = await DequeueAsync(cancellationToken: cancellationToken).AnyContext();
                    } catch (Exception ex) {
                        _logger.Error(ex, "Error on Dequeue: " + ex.Message);
                    }

                    if (queueEntry == null)
                    {
                        return;
                    }

                    try {
                        await handler(queueEntry, linkedCancellationToken).AnyContext();
                        if (autoComplete)
                        {
                            await queueEntry.CompleteAsync().AnyContext();
                        }
                    } catch (Exception ex) {
                        _logger.Error(ex, "Worker error: {0}", ex.Message);
                        await queueEntry.AbandonAsync().AnyContext();
                        Interlocked.Increment(ref _workerErrorCount);
                    }
                }

                _logger.Trace("WorkLoop End");
            }, linkedCancellationToken);
        }
Example #2
0
        protected virtual Task OnLockRenewedAsync(IQueueEntry <T> entry)
        {
            LastDequeueActivity = SystemClock.UtcNow;

            var lockRenewed = LockRenewed;

            if (lockRenewed == null)
            {
                return(Task.CompletedTask);
            }

            var args = new LockRenewedEventArgs <T> {
                Queue = this, Entry = entry
            };

            return(lockRenewed.InvokeAsync(this, args));
        }
Example #3
0
        protected virtual void StopProcessQueueEntryActivity(IQueueEntry <T> entry)
        {
            if (!entry.Properties.TryGetValue("@Activity", out object a) || !(a is Activity activity))
            {
                return;
            }

            entry.Properties.Remove("@Activity");
            if (QueuesDiagnosticSource.Logger.IsEnabled("ProcessQueueEntry"))
            {
                QueuesDiagnosticSource.Logger.StopActivity(activity, entry);
            }
            else
            {
                activity.Stop();
            }
        }
Example #4
0
        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);
        }
Example #5
0
        protected override void StartWorkingImpl(Func <IQueueEntry <T>, CancellationToken, Task> handler, bool autoComplete, CancellationToken cancellationToken)
        {
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

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

            Task.Run(async() => {
                _logger.Trace("WorkerLoop Start {_queueName}", _queueName);

                while (!linkedCancellationToken.IsCancellationRequested)
                {
                    _logger.Trace("WorkerLoop Signaled {_queueName}", _queueName);

                    IQueueEntry <T> queueEntry = null;
                    try {
                        queueEntry = await DequeueImplAsync(cancellationToken: cancellationToken).AnyContext();
                    } catch (TimeoutException) { }

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

                    try {
                        await handler(queueEntry, linkedCancellationToken).AnyContext();
                        if (autoComplete && !queueEntry.IsAbandoned && !queueEntry.IsCompleted)
                        {
                            await queueEntry.CompleteAsync().AnyContext();
                        }
                    } catch (Exception ex) {
                        Interlocked.Increment(ref _workerErrorCount);
                        _logger.Error(ex, "Worker error: {0}", ex.Message);

                        if (!queueEntry.IsAbandoned && !queueEntry.IsCompleted)
                        {
                            await queueEntry.AbandonAsync().AnyContext();
                        }
                    }
                }

                _logger.Trace("Worker exiting: {0} Cancel Requested: {1}", _queueName, linkedCancellationToken.IsCancellationRequested);
            }, linkedCancellationToken);
        }
Example #6
0
        private async Task <QueueMessageRecoveryStrategy> OnProcessMessageAsync(IQueueEntry <TMessage> queueEntry)
        {
            try
            {
                await OnMessageReceivedAsync(queueEntry).ConfigureAwait(false);

                return(QueueMessageRecoveryStrategy.Complete);
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                return(await TaskHelpers.DefaultIfExceptionAsync(
                           GetRecoveryStrategyAsync,
                           e,
                           QueueMessageRecoveryStrategy.Abandon).ConfigureAwait(false));
            }
        }
Example #7
0
        public override async Task RenewLockAsync(IQueueEntry <T> entry)
        {
            _logger.Debug("Queue {0} renew lock item: {1}", _options.Name, entry.Id);

            var item = entry as QueueEntry <T>;

            _dequeued.AddOrUpdate(entry.Id, item, (key, value) => {
                if (item != null)
                {
                    value.RenewedTimeUtc = item.RenewedTimeUtc;
                }

                return(value);
            });

            await OnLockRenewedAsync(entry).AnyContext();

            _logger.Trace("Renew lock done: {0}", entry.Id);
        }
Example #8
0
        protected virtual async Task OnAbandonedAsync(IQueueEntry <T> entry)
        {
            LastDequeueActivity = SystemClock.UtcNow;

            if (entry is QueueEntry <T> metadata && metadata.DequeuedTimeUtc > DateTime.MinValue)
            {
                metadata.ProcessingTime = SystemClock.UtcNow.Subtract(metadata.DequeuedTimeUtc);
            }

            if (Abandoned != null)
            {
                var args = new AbandonedEventArgs <T> {
                    Queue = this, Entry = entry
                };
                await Abandoned.InvokeAsync(this, args).AnyContext();
            }

            StopProcessQueueEntryActivity(entry);
        }
Example #9
0
        protected virtual Task OnDequeuedAsync(IQueueEntry <T> entry)
        {
            LastDequeueActivity = SystemClock.UtcNow;

            StartProcessQueueEntryActivity(entry);

            var dequeued = Dequeued;

            if (dequeued == null)
            {
                return(Task.CompletedTask);
            }

            var args = new DequeuedEventArgs <T> {
                Queue = this, Entry = entry
            };

            return(dequeued.InvokeAsync(this, args));
        }
Example #10
0
        public override async Task AbandonAsync(IQueueEntry <T> queueEntry)
        {
            var azureQueueEntry = ToAzureEntryWithCheck(queueEntry);

            if (azureQueueEntry.Attempts > _retries)
            {
                await _queueReference.DeleteMessageAsync(azureQueueEntry.UnderlyingMessage).AnyContext();

                await _deadletterQueueReference.AddMessageAsync(azureQueueEntry.UnderlyingMessage).AnyContext();
            }
            else
            {
                // Make the item visible immediately
                await _queueReference.UpdateMessageAsync(azureQueueEntry.UnderlyingMessage, TimeSpan.Zero, MessageUpdateFields.Visibility).AnyContext();
            }

            Interlocked.Increment(ref _abandonedCount);
            await OnAbandonedAsync(queueEntry).AnyContext();
        }
Example #11
0
        public override async Task CompleteAsync(IQueueEntry <T> entry)
        {
            _logger.LogDebug("Queue {Name} complete item: {Id}", _options.Name, entry.Id);
            if (entry.IsAbandoned || entry.IsCompleted)
            {
                throw new InvalidOperationException("Queue entry has already been completed or abandoned");
            }

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

            entry.MarkCompleted();
            Interlocked.Increment(ref _completedCount);
            await OnCompletedAsync(entry).AnyContext();

            _logger.LogTrace("Complete done: {Id}", entry.Id);
        }
Example #12
0
        protected virtual void StartProcessQueueEntryActivity(IQueueEntry <T> entry)
        {
            if (!QueuesDiagnosticSource.Logger.IsEnabled("ProcessQueueEntry") || !QueuesDiagnosticSource.Logger.IsEnabled("ProcessQueueEntry", entry))
            {
                return;
            }

            var activity = new Activity("ProcessQueueEntry");

            activity.AddTag("Id", entry.Id);
            if (!String.IsNullOrEmpty(entry.CorrelationId))
            {
                activity.SetParentId(entry.CorrelationId);
            }

            EnrichProcessQueueEntryActivity(activity, entry);
            QueuesDiagnosticSource.Logger.StartActivity(activity, entry);

            entry.Properties["@Activity"] = activity;
        }
Example #13
0
        protected virtual Task OnAbandonedAsync(IQueueEntry <T> entry)
        {
            if (entry is QueueEntry <T> metadata && metadata.DequeuedTimeUtc > DateTime.MinValue)
            {
                metadata.ProcessingTime = SystemClock.UtcNow.Subtract(metadata.DequeuedTimeUtc);
            }

            var abandoned = Abandoned;

            if (abandoned == null)
            {
                return(Task.CompletedTask);
            }

            var args = new AbandonedEventArgs <T> {
                Queue = this, Entry = entry
            };

            return(abandoned.InvokeAsync(this, args));
        }
Example #14
0
        private static async Task HandleRenewalAsync(
            IQueueEntry <TMessage> queueEntry,
            CancellationToken cancellationToken)
        {
            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    await queueEntry.RenewLockAsync().ConfigureAwait(false);

                    await Task.Delay(5000, cancellationToken).ConfigureAwait(false);
                }
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch
#pragma warning restore CA1031 // Do not catch general exception types
            {
                // no op
            }
        }
Example #15
0
        public override async Task AbandonAsync(IQueueEntry <T> entry)
        {
            _logger.LogDebug("Queue {Name}:{QueueId} abandon item: {Id}", _options.Name, QueueId, entry.Id);

            if (entry.IsAbandoned || entry.IsCompleted)
            {
                throw new InvalidOperationException("Queue entry has already been completed or abandoned");
            }

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

            entry.MarkAbandoned();
            Interlocked.Increment(ref _abandonedCount);
            _logger.LogTrace("Abandon complete: {Id}", entry.Id);

            try {
                await OnAbandonedAsync(entry).AnyContext();
            } finally {
                if (targetEntry.Attempts < _options.Retries + 1)
                {
                    if (_options.RetryDelay > TimeSpan.Zero)
                    {
                        _logger.LogTrace("Adding item to wait list for future retry: {Id}", entry.Id);
                        var unawaited = Run.DelayedAsync(GetRetryDelay(targetEntry.Attempts), () => RetryAsync(targetEntry), _queueDisposedCancellationTokenSource.Token);
                    }
                    else
                    {
                        _logger.LogTrace("Adding item back to queue for retry: {Id}", entry.Id);
                        var unawaited = Task.Run(() => RetryAsync(targetEntry));
                    }
                }
                else
                {
                    _logger.LogTrace("Exceeded retry limit moving to deadletter: {Id}", entry.Id);
                    _deadletterQueue.Enqueue(targetEntry);
                }
            }
        }
Example #16
0
        public override async Task RenewLockAsync(IQueueEntry <T> queueEntry)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug("Queue {Name} renew lock item: {EntryId}", _options.Name, queueEntry.Id);
            }

            var entry   = ToQueueEntry(queueEntry);
            var request = new ChangeMessageVisibilityRequest {
                QueueUrl          = _queueUrl,
                VisibilityTimeout = (int)_options.WorkItemTimeout.TotalSeconds,
                ReceiptHandle     = entry.UnderlyingMessage.ReceiptHandle
            };

            await _client.Value.ChangeMessageVisibilityAsync(request).AnyContext();

            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace("Renew lock done: {EntryId}", queueEntry.Id);
            }
        }
Example #17
0
        public override void StartWorking(Func <IQueueEntry <T>, CancellationToken, Task> handler, bool autoComplete = false, CancellationToken cancellationToken = new CancellationToken())
        {
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

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

            Task.Run(async() => {
                while (!linkedCancellationToken.IsCancellationRequested)
                {
                    IQueueEntry <T> queueEntry = null;
                    try {
                        queueEntry = await DequeueAsync(cancellationToken).AnyContext();
                    }
                    catch (TaskCanceledException) { }

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

                    try {
                        await handler(queueEntry, cancellationToken);
                        if (autoComplete)
                        {
                            await queueEntry.CompleteAsync().AnyContext();
                        }
                    }
                    catch (Exception ex) {
                        _logger.Error(ex, "Worker error: {0}", ex.Message);
                        await queueEntry.AbandonAsync().AnyContext();
                        Interlocked.Increment(ref _workerErrorCount);
                    }
                }

                _logger.Trace("Worker exiting: {0} Cancel Requested: {1}", _queueReference.Name, linkedCancellationToken.IsCancellationRequested);
            }, linkedCancellationToken);
        }
Example #18
0
        public override async Task CompleteAsync(IQueueEntry <T> queueEntry)
        {
            _logger.Debug("Queue {0} complete item: {1}", _options.Name, queueEntry.Id);
            if (queueEntry.IsAbandoned || queueEntry.IsCompleted)
            {
                throw new InvalidOperationException("Queue entry has already been completed or abandoned.");
            }

            var entry   = ToQueueEntry(queueEntry);
            var request = new DeleteMessageRequest {
                QueueUrl      = _queueUrl,
                ReceiptHandle = entry.UnderlyingMessage.ReceiptHandle,
            };

            await _client.Value.DeleteMessageAsync(request).AnyContext();

            Interlocked.Increment(ref _completedCount);
            queueEntry.MarkCompleted();
            await OnCompletedAsync(queueEntry).AnyContext();

            _logger.Trace("Complete done: {0}", queueEntry.Id);
        }
Example #19
0
        public override async Task CompleteAsync(IQueueEntry <T> entry)
        {
            _logger.Debug("Queue {0} complete item: {1}", _queueName, entry.Id);

            var tasks = new List <Task>();
            var batch = Database.CreateBatch();

            tasks.Add(batch.ListRemoveAsync(WorkListName, entry.Id));
            tasks.Add(batch.KeyDeleteAsync(GetPayloadKey(entry.Id)));
            tasks.Add(batch.KeyDeleteAsync(GetAttemptsKey(entry.Id)));
            tasks.Add(batch.KeyDeleteAsync(GetEnqueuedTimeKey(entry.Id)));
            tasks.Add(batch.KeyDeleteAsync(GetDequeuedTimeKey(entry.Id)));
            tasks.Add(batch.KeyDeleteAsync(GetWaitTimeKey(entry.Id)));
            batch.Execute();

            await Task.WhenAll(tasks.ToArray()).AnyContext();

            Interlocked.Increment(ref _completedCount);
            await OnCompletedAsync(entry).AnyContext();

            _logger.Trace("Complete done: {0}", entry.Id);
        }
Example #20
0
        protected virtual Task OnCompletedAsync(IQueueEntry <T> entry)
        {
            var metadata = entry as QueueEntry <T>;

            if (metadata != null && metadata.DequeuedTimeUtc > DateTime.MinValue)
            {
                metadata.ProcessingTime = SystemClock.UtcNow.Subtract(metadata.DequeuedTimeUtc);
            }

            var completed = Completed;

            if (completed == null)
            {
                return(Task.CompletedTask);
            }

            var args = new CompletedEventArgs <T> {
                Queue = this, Entry = entry
            };

            return(completed.InvokeAsync(this, args));
        }
Example #21
0
        public override async Task CompleteAsync(IQueueEntry <T> entry)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug("Queue {Name} complete item: {EntryId}", _options.Name, entry.Id);
            }
            if (entry.IsAbandoned || entry.IsCompleted)
            {
                //_logger.LogDebug("Queue {Name} item already abandoned or completed: {EntryId}", _options.Name, entry.Id);
                throw new InvalidOperationException("Queue entry has already been completed or abandoned.");
            }

            long result = await Run.WithRetriesAsync(() => Database.ListRemoveAsync(_workListName, entry.Id), logger : _logger).AnyContext();

            if (result == 0)
            {
                _logger.LogDebug("Queue {Name} item not in work list: {EntryId}", _options.Name, entry.Id);
                throw new InvalidOperationException("Queue entry not in work list, it may have been auto abandoned.");
            }

            await Run.WithRetriesAsync(() => Task.WhenAll(
                                           Database.KeyDeleteAsync(GetPayloadKey(entry.Id)),
                                           Database.KeyDeleteAsync(GetAttemptsKey(entry.Id)),
                                           Database.KeyDeleteAsync(GetEnqueuedTimeKey(entry.Id)),
                                           Database.KeyDeleteAsync(GetDequeuedTimeKey(entry.Id)),
                                           Database.KeyDeleteAsync(GetRenewedTimeKey(entry.Id)),
                                           Database.KeyDeleteAsync(GetWaitTimeKey(entry.Id))
                                           ), logger : _logger).AnyContext();

            Interlocked.Increment(ref _completedCount);
            entry.MarkCompleted();
            await OnCompletedAsync(entry).AnyContext();

            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace("Complete done: {EntryId}", entry.Id);
            }
        }
Example #22
0
        public override async Task AbandonAsync(IQueueEntry <T> entry)
        {
            _logger.Debug("Queue {_options.Name}:{QueueId} abandon item: {entryId}", _options.Name, QueueId, entry.Id);
            if (entry.IsAbandoned || entry.IsCompleted)
            {
                throw new InvalidOperationException("Queue entry has already been completed or abandoned.");
            }

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

            if (info.Attempts < _options.Retries + 1)
            {
                if (_options.RetryDelay > TimeSpan.Zero)
                {
                    _logger.Trace("Adding item to wait list for future retry: {0}", entry.Id);
                    var unawaited = Run.DelayedAsync(GetRetryDelay(info.Attempts), () => RetryAsync(info));
                }
                else
                {
                    _logger.Trace("Adding item back to queue for retry: {0}", entry.Id);
                    var unawaited = Task.Run(() => RetryAsync(info));
                }
            }
            else
            {
                _logger.Trace("Exceeded retry limit moving to deadletter: {0}", entry.Id);
                _deadletterQueue.Enqueue(info);
            }

            Interlocked.Increment(ref _abandonedCount);
            entry.MarkAbandoned();
            await OnAbandonedAsync(entry).AnyContext();

            _logger.Trace("Abandon complete: {entryId}", entry.Id);
        }
        public override async Task CompleteAsync(IQueueEntry <T> entry)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug("Queue {Name} complete item: {EntryId}", _options.Name, entry.Id);
            }
            if (entry.IsAbandoned || entry.IsCompleted)
            {
                throw new InvalidOperationException("Queue entry has already been completed or abandoned.");
            }

            var azureQueueEntry = ToAzureEntryWithCheck(entry);
            await _queueReference.DeleteMessageAsync(azureQueueEntry.UnderlyingMessage).AnyContext();

            Interlocked.Increment(ref _completedCount);
            entry.MarkCompleted();
            await OnCompletedAsync(entry).AnyContext();

            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace("Complete done: {EntryId}", entry.Id);
            }
        }
Example #24
0
        protected virtual Activity StartProcessQueueEntryActivity(IQueueEntry <T> entry)
        {
            var activity = FoundatioDiagnostics.ActivitySource.StartActivity("ProcessQueueEntry", ActivityKind.Server, entry.CorrelationId);

            if (activity == null)
            {
                return(activity);
            }

            if (entry.Properties != null && entry.Properties.TryGetValue("TraceState", out var traceState))
            {
                activity.TraceStateString = traceState.ToString();
            }

            activity.DisplayName = $"Queue: {entry.EntryType.Name}";
            if (entry.GetValue() is WorkItemData workItem && !String.IsNullOrEmpty(workItem.SubMetricName))
            {
                activity.DisplayName = $"Queue Work Item: {workItem.SubMetricName}";
            }

            EnrichProcessQueueEntryActivity(activity, entry);

            return(activity);
        }
Example #25
0
        public override async Task RenewLockAsync(IQueueEntry <T> entry)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug("Queue {Name} renew lock item: {Id}", _options.Name, entry.Id);
            }

            if (entry is QueueEntry <T> val && val.Data["Pull-Strategy"].Equals(true))
            {
                var newLockedUntilUtc = await _messageReceiver.RenewLockAsync(entry.Id).AnyContext();

                if (_logger.IsEnabled(LogLevel.Trace))
                {
                    _logger.LogTrace("Renew lock done: {Id} - {newLockedUntilUtc}", entry.Id, newLockedUntilUtc);
                }
            }

            await OnLockRenewedAsync(entry).AnyContext();

            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace("Renew lock done: {Id}", entry.Id);
            }
        }
Example #26
0
        protected virtual void EnrichProcessQueueEntryActivity(Activity activity, IQueueEntry <T> entry)
        {
            if (!activity.IsAllDataRequested)
            {
                return;
            }

            activity.AddTag("EntryType", entry.EntryType.FullName);
            activity.AddTag("Id", entry.Id);
            activity.AddTag("CorrelationId", entry.CorrelationId);

            if (entry.Properties == null || entry.Properties.Count <= 0)
            {
                return;
            }

            foreach (var p in entry.Properties)
            {
                if (p.Key != "TraceState")
                {
                    activity.AddTag(p.Key, p.Value);
                }
            }
        }
Example #27
0
        public bool DispatchHandleQueueResponse(IQueueEntry entry)
        {
            switch (entry.Type)
            {
            case QueueEntryType.HOTEL:
                return(HandleHotelEntry(new Hotel(entry.Hotel)));

            case QueueEntryType.RESERVATION:
                return(HandleReservationEntry(new Reservation(entry.Reservation)));

            case QueueEntryType.ROOM:
                return(HandleRoomEntry(new Room(entry.Room)));

            case QueueEntryType.USER:
                return(HandleUserEntry(new User(entry.User)));

            case QueueEntryType.NONE:
                Console.Write("Got None type entry");
                return(false);

            default:
                return(false);
            }
        }
Example #28
0
        private async Task DoRecoveryStrategyAsync(
            QueueMessageRecoveryStrategy recoveryStrategy,
            IQueueEntry <TMessage> queueEntry)
        {
            switch (recoveryStrategy)
            {
            case QueueMessageRecoveryStrategy.Abandon:
                await DoAbandonMessageAsync(queueEntry)
                .ConfigureAwait(false);

                break;

            case QueueMessageRecoveryStrategy.Complete:
                await DoCompleteMessageAsync(queueEntry)
                .ConfigureAwait(false);

                break;

            case QueueMessageRecoveryStrategy.DeadLetter:
                await DoDeadLetterMessageAsync(queueEntry)
                .ConfigureAwait(false);

                break;

            case QueueMessageRecoveryStrategy.Requeue:
                await DoRequeueMessageAsync(queueEntry)
                .ConfigureAwait(false);

                break;

            default:
                throw new ArgumentOutOfRangeException(
                          nameof(recoveryStrategy),
                          $"Unexpected recovery strategy: {recoveryStrategy}");
            }
        }
Example #29
0
        protected async Task DoWorkAsync(IQueueEntry<SimpleWorkItem> w, AsyncCountdownEvent countdown, WorkInfo info) {
            _logger.Trace($"Starting: {w.Value.Id}");
            Assert.Equal("Hello", w.Value.Data);

            try {
                // randomly complete, abandon or blowup.
                if (RandomData.GetBool()) {
                    _logger.Trace($"Completing: {w.Value.Id}");
                    await w.CompleteAsync();
                    info.IncrementCompletedCount();
                } else if (RandomData.GetBool()) {
                    _logger.Trace($"Abandoning: {w.Value.Id}");
                    await w.AbandonAsync();
                    info.IncrementAbandonCount();
                } else {
                    _logger.Trace($"Erroring: {w.Value.Id}");
                    info.IncrementErrorCount();
                    throw new Exception();
                }
            } finally {
                _logger.Trace($"Signal {countdown.CurrentCount}");
                countdown.Signal();
            }
        }
Example #30
0
 public override Task AbandonAsync(IQueueEntry <T> entry)
 {
     // delay first abandon from maintenance (simulate timing issues which may occur to demonstrate the problem)
     return(base.AbandonAsync(new QueueEntry_Issue239 <T>(entry)));
 }
Example #31
0
 public QueueEntry_Issue239(IQueueEntry <T> queueEntry)
 {
     _queueEntry = queueEntry;
 }
Example #32
0
 protected async Task ReportProgress(IWorkItemHandler handler, IQueueEntry<WorkItemData> queueEntry, int progress = 0, string message = null) {
     try {
         await _messageBus.PublishAsync(new WorkItemStatus {
             WorkItemId = queueEntry.Value.WorkItemId,
             Type = queueEntry.Value.Type,
             Progress = progress,
             Message = message
         }).AnyContext();
     } catch (Exception ex) {
         handler.Log.Error(ex, "Error sending progress report: {0}", ex.Message);
     }
 }