internal async Task ProcessMessageAsync(IStorageQueueMessage message, TimeSpan visibilityTimeout, CancellationToken cancellationToken)
        {
            try
            {
                if (!await _queueProcessor.BeginProcessingMessageAsync(message.SdkObject, cancellationToken))
                {
                    return;
                }

                FunctionResult result = null;
                using (ITaskSeriesTimer timer = CreateUpdateMessageVisibilityTimer(_queue, message, visibilityTimeout, _backgroundExceptionDispatcher))
                {
                    timer.Start();

                    result = await _triggerExecutor.ExecuteAsync(message, cancellationToken);

                    await timer.StopAsync(cancellationToken);
                }

                await _queueProcessor.CompleteProcessingMessageAsync(message.SdkObject, result, cancellationToken);
            }
            catch (OperationCanceledException)
            {
                // Don't fail the top-level task when an inner task cancels.
            }
            catch (Exception exception)
            {
                // Immediately report any unhandled exception from this background task.
                // (Don't capture the exception as a fault of this Task; that would delay any exception reporting until
                // Stop is called, which might never happen.)
                _backgroundExceptionDispatcher.Throw(ExceptionDispatchInfo.Capture(exception));
            }
        }
Пример #2
0
        private async Task ProcessMessageAsync(IStorageQueueMessage message, TimeSpan visibilityTimeout,
                                               CancellationToken cancellationToken)
        {
            try
            {
                bool succeeded;

                using (ITaskSeriesTimer timer = CreateUpdateMessageVisibilityTimer(_queue, message, visibilityTimeout,
                                                                                   _backgroundExceptionDispatcher))
                {
                    timer.Start();

                    succeeded = await _triggerExecutor.ExecuteAsync(message, cancellationToken);

                    await timer.StopAsync(cancellationToken);
                }

                // Need to call Delete message only if function succeeded.
                if (succeeded)
                {
                    await DeleteMessageAsync(message, cancellationToken);
                }
                else if (_poisonQueue != null)
                {
                    if (message.DequeueCount >= _maxDequeueCount)
                    {
                        _log.WriteLine("Message has reached MaxDequeueCount of {0}. Moving message to queue '{1}'.",
                                       _maxDequeueCount,
                                       _poisonQueue.Name);
                        await CopyToPoisonQueueAsync(message, cancellationToken);
                        await DeleteMessageAsync(message, cancellationToken);
                    }
                    else
                    {
                        await ReleaseMessageAsync(message, cancellationToken);
                    }
                }
                else
                {
                    // For queues without a corresponding poison queue, leave the message invisible when processing
                    // fails to prevent a fast infinite loop.
                    // Specifically, don't call ReleaseMessage(message)
                }
            }
            catch (OperationCanceledException)
            {
                // Don't fail the top-level task when an inner task cancels.
            }
            catch (Exception exception)
            {
                // Immediately report any unhandled exception from this background task.
                // (Don't capture the exception as a fault of this Task; that would delay any exception reporting until
                // Stop is called, which might never happen.)
                _backgroundExceptionDispatcher.Throw(ExceptionDispatchInfo.Capture(exception));
            }
        }
Пример #3
0
        private async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                // Allow Start to return immediately without waiting for any initial iteration work to start.
                await Task.Yield();

                Task wait = _initialWait;

                // Execute tasks one at a time (in a series) until stopped.
                while (!cancellationToken.IsCancellationRequested)
                {
                    TaskCompletionSource <object> cancellationTaskSource = new TaskCompletionSource <object>();

                    using (cancellationToken.Register(() => cancellationTaskSource.SetCanceled()))
                    {
                        try
                        {
                            await Task.WhenAny(wait, cancellationTaskSource.Task);
                        }
                        catch (OperationCanceledException)
                        {
                            // When Stop fires, don't make it wait for wait before it can return.
                        }
                    }

                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    try
                    {
                        TaskSeriesCommandResult result = await _command.ExecuteAsync(cancellationToken);

                        wait = result.Wait;
                    }
                    catch (OperationCanceledException)
                    {
                        // Don't fail the task, throw a background exception, or stop looping when a task cancels.
                    }
                }
            }
            catch (Exception exception)
            {
                // Immediately report any unhandled exception from this background task.
                // (Don't capture the exception as a fault of this Task; that would delay any exception reporting until
                // Stop is called, which might never happen.)
                _backgroundExceptionDispatcher.Throw(ExceptionDispatchInfo.Capture(exception));
            }
        }