Пример #1
0
        private async Task ProcessOneMessage(
            ServiceBusReceivedMessage triggerMessage,
            CancellationToken cancellationToken)
        {
            ServiceBusErrorSource errorSource = ServiceBusErrorSource.Receive;
            EventArgs             args        = null;

            try
            {
                errorSource = ServiceBusErrorSource.ProcessMessageCallback;
                try
                {
                    ServiceBusEventSource.Log.ProcessorMessageHandlerStart(Processor.Identifier, triggerMessage.SequenceNumber,
                                                                           triggerMessage.LockTokenGuid);
                    args = await OnMessageHandler(triggerMessage, cancellationToken).ConfigureAwait(false);

                    ServiceBusEventSource.Log.ProcessorMessageHandlerComplete(Processor.Identifier, triggerMessage.SequenceNumber,
                                                                              triggerMessage.LockTokenGuid);
                }
                catch (Exception ex)
                {
                    ServiceBusEventSource.Log.ProcessorMessageHandlerException(Processor.Identifier, triggerMessage.SequenceNumber,
                                                                               ex.ToString(), triggerMessage.LockTokenGuid);
                    throw;
                }

                if (Receiver.ReceiveMode == ServiceBusReceiveMode.PeekLock && ProcessorOptions.AutoCompleteMessages)
                {
                    var messages = (args is ProcessMessageEventArgs processMessageEventArgs)
                        ? processMessageEventArgs.Messages.Keys
                        : ((ProcessSessionMessageEventArgs)args).Messages.Keys;
                    foreach (ServiceBusReceivedMessage message in messages)
                    {
                        if (!message.IsSettled)
                        {
                            errorSource = ServiceBusErrorSource.Complete;
                            // don't pass the processor cancellation token
                            // as we want in flight auto-completion to be able
                            // to finish
                            await Receiver.CompleteMessageAsync(
                                message,
                                CancellationToken.None)
                            .ConfigureAwait(false);

                            message.IsSettled = true;
                        }
                    }
                }
            }
            catch (Exception ex)
                // This prevents exceptions relating to processing a message from bubbling up all
                // the way to the main thread when calling StopProcessingAsync, which we don't want
                // as it isn't actionable.
                when(!(ex is TaskCanceledException) || !cancellationToken.IsCancellationRequested)
                {
                    ThrowIfSessionLockLost(ex, errorSource);
                    await RaiseExceptionReceived(
                        new ProcessErrorEventArgs(
                            ex,
                            errorSource,
                            Processor.FullyQualifiedNamespace,
                            Processor.EntityPath,
                            cancellationToken))
                    .ConfigureAwait(false);

                    // if the user settled the message, or if the message or session lock was lost,
                    // do not attempt to abandon the message
                    ServiceBusFailureReason?failureReason = (ex as ServiceBusException)?.Reason;

                    if (!triggerMessage.IsSettled &&
                        _receiverOptions.ReceiveMode == ServiceBusReceiveMode.PeekLock &&
                        failureReason != ServiceBusFailureReason.SessionLockLost &&
                        failureReason != ServiceBusFailureReason.MessageLockLost)
                    {
                        try
                        {
                            // don't pass the processor cancellation token
                            // as we want in flight abandon to be able
                            // to finish even if user stopped processing
                            await Receiver.AbandonMessageAsync(
                                triggerMessage.LockTokenGuid,
                                cancellationToken : CancellationToken.None)
                            .ConfigureAwait(false);
                        }
                        catch (Exception exception)
                        {
                            ThrowIfSessionLockLost(exception, ServiceBusErrorSource.Abandon);
                            await RaiseExceptionReceived(
                                new ProcessErrorEventArgs(
                                    exception,
                                    ServiceBusErrorSource.Abandon,
                                    Processor.FullyQualifiedNamespace,
                                    Processor.EntityPath,
                                    cancellationToken))
                            .ConfigureAwait(false);
                        }
                    }
                }
            finally
            {
                if (args is ProcessMessageEventArgs processMessageEventArgs)
                {
                    await processMessageEventArgs.CancelMessageLockRenewalAsync().ConfigureAwait(false);
                }
            }
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="message"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task ProcessOneMessage(
            ServiceBusReceivedMessage message,
            CancellationToken cancellationToken)
        {
            ServiceBusErrorSource   errorSource = ServiceBusErrorSource.Receive;
            CancellationTokenSource renewLockCancellationTokenSource = null;
            Task renewLock = null;

            try
            {
                if (!Receiver.IsSessionReceiver &&
                    Receiver.ReceiveMode == ReceiveMode.PeekLock &&
                    AutoRenewLock)
                {
                    renewLockCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                    renewLock = RenewMessageLock(
                        message,
                        renewLockCancellationTokenSource);
                }

                errorSource = ServiceBusErrorSource.UserCallback;

                try
                {
                    ServiceBusEventSource.Log.ProcessorMessageHandlerStart(_identifier, message.SequenceNumber);
                    await OnMessageHandler(message, cancellationToken).ConfigureAwait(false);

                    ServiceBusEventSource.Log.ProcessorMessageHandlerComplete(_identifier, message.SequenceNumber);
                }
                catch (Exception ex)
                {
                    ServiceBusEventSource.Log.ProcessorMessageHandlerException(_identifier, message.SequenceNumber, ex.ToString());
                    throw;
                }

                if (Receiver.ReceiveMode == ReceiveMode.PeekLock &&
                    _processorOptions.AutoComplete &&
                    !message.IsSettled)
                {
                    errorSource = ServiceBusErrorSource.Complete;
                    // don't pass the processor cancellation token
                    // as we want in flight auto-completion to be able
                    // to finish
                    await Receiver.CompleteMessageAsync(
                        message.LockToken,
                        CancellationToken.None)
                    .ConfigureAwait(false);
                }

                await CancelTask(renewLockCancellationTokenSource, renewLock).ConfigureAwait(false);
            }
            catch (Exception ex)
                // This prevents exceptions relating to processing a message from bubbling up all
                // the way to the main thread when calling StopProcessingAsync, which we don't want
                // as it isn't actionable.
                when(!(ex is TaskCanceledException) || !cancellationToken.IsCancellationRequested)
                {
                    ThrowIfSessionLockLost(ex, errorSource);
                    await RaiseExceptionReceived(
                        new ProcessErrorEventArgs(
                            ex,
                            errorSource,
                            _fullyQualifiedNamespace,
                            _entityPath))
                    .ConfigureAwait(false);

                    // if the user settled the message, or if the message or session lock was lost,
                    // do not attempt to abandon the message
                    ServiceBusFailureReason?failureReason = (ex as ServiceBusException)?.Reason;

                    if (!message.IsSettled &&
                        _receiverOptions.ReceiveMode == ReceiveMode.PeekLock &&
                        failureReason != ServiceBusFailureReason.SessionLockLost &&
                        failureReason != ServiceBusFailureReason.MessageLockLost)
                    {
                        try
                        {
                            // don't pass the processor cancellation token
                            // as we want in flight abandon to be able
                            // to finish even if user stopped processing
                            await Receiver.AbandonMessageAsync(
                                message.LockToken,
                                cancellationToken : CancellationToken.None)
                            .ConfigureAwait(false);
                        }
                        catch (Exception exception)
                        {
                            ThrowIfSessionLockLost(exception, ServiceBusErrorSource.Abandon);
                            await RaiseExceptionReceived(
                                new ProcessErrorEventArgs(
                                    exception,
                                    ServiceBusErrorSource.Abandon,
                                    _fullyQualifiedNamespace,
                                    _entityPath))
                            .ConfigureAwait(false);
                        }
                    }
                }
            finally
            {
                renewLockCancellationTokenSource?.Cancel();
                renewLockCancellationTokenSource?.Dispose();
            }
        }