public async Task StartPumpAsync()
        {
            IMessageSession initialSession = null;

            // Do a first receive of a Session on entity to flush any non-transient errors.
            // Timeout is a valid exception.
            try
            {
                initialSession = await this.client.AcceptMessageSessionAsync().ConfigureAwait(false);

                // MessagingEventSource.Log.SessionReceiverPumpInitialSessionReceived(this.client.ClientId, initialSession);
            }
            catch (TimeoutException)
            {
            }

            // Schedule Tasks for doing PendingAcceptSession calls
            for (int i = 0; i < this.sessionHandlerOptions.MaxConcurrentAcceptSessionCalls; i++)
            {
                if (i == 0)
                {
                    TaskExtensionHelper.Schedule(() => this.SessionPumpTaskAsync(initialSession));
                }
                else
                {
                    TaskExtensionHelper.Schedule(() => this.SessionPumpTaskAsync(null));
                }
            }
        }
Пример #2
0
        public async Task StartPumpAsync()
        {
            int             retryCount     = 0;
            BrokeredMessage initialMessage = null;

            while (true)
            {
                try
                {
                    initialMessage = await this.messageReceiver.ReceiveAsync().ConfigureAwait(false);

                    MessagingEventSource.Log.MessageReceiverPumpInitialMessageReceived(this.messageReceiver.ClientId, initialMessage);
                    break;
                }
                catch (Exception exception)
                {
                    retryCount++;
                    MessagingEventSource.Log.MessageReceiverPumpInitialMessageReceiveException(this.messageReceiver.ClientId, retryCount, exception);

                    if (retryCount == MaxInitialReceiveRetryCount ||
                        !this.ShouldRetry(exception))
                    {
                        throw;
                    }

                    TimeSpan backOffTime = this.GetBackOffTime(exception);
                    await Task.Delay(backOffTime, this.pumpCancellationToken).ConfigureAwait(false);
                }
            }

            TaskExtensionHelper.Schedule(() => this.MessagePumpTask(initialMessage));
        }
Пример #3
0
        async Task MessagePumpTaskAsync()
        {
            while (!this.pumpCancellationToken.IsCancellationRequested)
            {
                Message message = null;
                try
                {
                    await this.maxConcurrentCallsSemaphoreSlim.WaitAsync(this.pumpCancellationToken).ConfigureAwait(false);

                    message = await this.messageReceiver.ReceiveAsync(this.registerHandlerOptions.ReceiveTimeOut).ConfigureAwait(false);

                    if (message != null)
                    {
                        MessagingEventSource.Log.MessageReceiverPumpTaskStart(this.messageReceiver.ClientId, message, this.maxConcurrentCallsSemaphoreSlim.CurrentCount);
                        TaskExtensionHelper.Schedule(() => this.MessageDispatchTask(message));
                    }
                }
                catch (Exception exception)
                {
                    MessagingEventSource.Log.MessageReceivePumpTaskException(this.messageReceiver.ClientId, string.Empty, exception);
                    await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.Receive).ConfigureAwait(false);
                }
                finally
                {
                    // Either an exception or for some reason message was null, release semaphore and retry.
                    if (message == null)
                    {
                        this.maxConcurrentCallsSemaphoreSlim.Release();
                        MessagingEventSource.Log.MessageReceiverPumpTaskStop(this.messageReceiver.ClientId, this.maxConcurrentCallsSemaphoreSlim.CurrentCount);
                    }
                }
            }
        }
Пример #4
0
 public void StartPump()
 {
     // Schedule Tasks for doing PendingAcceptSession calls
     for (int i = 0; i < this.sessionHandlerOptions.MaxConcurrentAcceptSessionCalls; i++)
     {
         TaskExtensionHelper.Schedule(this.SessionPumpTaskAsync);
     }
 }
Пример #5
0
        async Task SessionPumpTaskAsync()
        {
            while (!this.pumpCancellationToken.IsCancellationRequested)
            {
                var concurrentSessionSemaphoreAcquired = false;
                try
                {
                    await this.maxConcurrentSessionsSemaphoreSlim.WaitAsync(this.pumpCancellationToken).ConfigureAwait(false);

                    concurrentSessionSemaphoreAcquired = true;

                    await this.maxPendingAcceptSessionsSemaphoreSlim.WaitAsync(this.pumpCancellationToken).ConfigureAwait(false);

                    var session = await this.client.AcceptMessageSessionAsync().ConfigureAwait(false);

                    if (session == null)
                    {
                        await Task.Delay(Constants.NoMessageBackoffTimeSpan, this.pumpCancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    // `session` needs to be copied to another local variable before passing to Schedule
                    // because of the way variables are captured. (Refer 'Captured variables')
                    var messageSession = session;
                    TaskExtensionHelper.Schedule(() => this.MessagePumpTaskAsync(messageSession));
                }
                catch (Exception exception)
                {
                    MessagingEventSource.Log.SessionReceivePumpSessionReceiveException(this.clientId, exception);

                    if (concurrentSessionSemaphoreAcquired)
                    {
                        this.maxConcurrentSessionsSemaphoreSlim.Release();
                    }

                    if (exception is ServiceBusTimeoutException)
                    {
                        await Task.Delay(Constants.NoMessageBackoffTimeSpan, this.pumpCancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        if (!(exception is ObjectDisposedException && this.pumpCancellationToken.IsCancellationRequested))
                        {
                            await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.AcceptMessageSession).ConfigureAwait(false);
                        }
                        if (!MessagingUtilities.ShouldRetry(exception))
                        {
                            await Task.Delay(Constants.NoMessageBackoffTimeSpan, this.pumpCancellationToken).ConfigureAwait(false);
                        }
                    }
                }
                finally
                {
                    this.maxPendingAcceptSessionsSemaphoreSlim.Release();
                }
            }
        }
Пример #6
0
            async Task MessagePumpTaskAsync()
            {
                while (!_pumpCancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        await _maxConcurrentCallsSemaphoreSlim.WaitAsync(_pumpCancellationToken).ConfigureAwait(false);

                        TaskExtensionHelper.Schedule(async() =>
                        {
                            Message message = null;
                            try
                            {
                                message = await _messageReceiver.ReceiveAsync(_registerHandlerOptions.ReceiveTimeOut).ConfigureAwait(false);
                                if (message != null)
                                {
                                    TaskExtensionHelper.Schedule(() =>
                                    {
                                        return(MessageDispatchTask(message));
                                    });
                                }
                            }
                            catch (OperationCanceledException) when(_pumpCancellationToken.IsCancellationRequested)
                            {
                                // Ignore as we are stopping the pump
                            }
                            catch (ObjectDisposedException) when(_pumpCancellationToken.IsCancellationRequested)
                            {
                                // Ignore as we are stopping the pump
                            }
                            catch (Exception exception)
                            {
                                await RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.Receive).ConfigureAwait(false);
                            }
                            finally
                            {
                                // Either an exception or for some reason message was null, release semaphore and retry.
                                if (message == null)
                                {
                                    _maxConcurrentCallsSemaphoreSlim.Release();
                                }
                            }
                        });
                    }
                    catch (OperationCanceledException) when(_pumpCancellationToken.IsCancellationRequested)
                    {
                        // Ignore as we are stopping the pump
                    }
                    catch (ObjectDisposedException) when(_pumpCancellationToken.IsCancellationRequested)
                    {
                        // Ignore as we are stopping the pump
                    }
                    catch (Exception exception)
                    {
                        await RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.Receive).ConfigureAwait(false);
                    }
                }
            }
        async Task MessageDispatchTask(Message message)
        {
            CancellationTokenSource renewLockCancellationTokenSource = null;
            Timer autoRenewLockCancellationTimer = null;

            MessagingEventSource.Log.MessageReceiverPumpDispatchTaskStart(this.messageReceiver.ClientId, message);

            if (this.ShouldRenewLock())
            {
                renewLockCancellationTokenSource = new CancellationTokenSource();
                TaskExtensionHelper.Schedule(() => this.RenewMessageLockTask(message, renewLockCancellationTokenSource.Token));

                // After a threshold time of renewal('AutoRenewTimeout'), create timer to cancel anymore renewals.
                autoRenewLockCancellationTimer = new Timer(this.CancelAutoRenewLock, renewLockCancellationTokenSource, this.registerHandlerOptions.MaxAutoRenewDuration, TimeSpan.FromMilliseconds(-1));
            }

            try
            {
                MessagingEventSource.Log.MessageReceiverPumpUserCallbackStart(this.messageReceiver.ClientId, message);
                await this.onMessageCallback(message, this.pumpCancellationToken).ConfigureAwait(false);

                MessagingEventSource.Log.MessageReceiverPumpUserCallbackStop(this.messageReceiver.ClientId, message);
            }
            catch (Exception exception)
            {
                MessagingEventSource.Log.MessageReceiverPumpUserCallbackException(this.messageReceiver.ClientId, message, exception);
                await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.UserCallback).ConfigureAwait(false);

                // Nothing much to do if UserCallback throws, Abandon message and Release semaphore.
                if (!(exception is MessageLockLostException))
                {
                    await this.AbandonMessageIfNeededAsync(message).ConfigureAwait(false);
                }

                if (ServiceBusDiagnosticSource.IsEnabled())
                {
                    this.diagnosticSource.ReportException(exception);
                }
                // AbandonMessageIfNeededAsync should take care of not throwing exception
                this.maxConcurrentCallsSemaphoreSlim.Release();

                return;
            }
            finally
            {
                renewLockCancellationTokenSource?.Cancel();
                renewLockCancellationTokenSource?.Dispose();
                autoRenewLockCancellationTimer?.Dispose();
            }

            // If we've made it this far, user callback completed fine. Complete message and Release semaphore.
            await this.CompleteMessageIfNeededAsync(message).ConfigureAwait(false);

            this.maxConcurrentCallsSemaphoreSlim.Release();

            MessagingEventSource.Log.MessageReceiverPumpDispatchTaskStop(this.messageReceiver.ClientId, message, this.maxConcurrentCallsSemaphoreSlim.CurrentCount);
        }
        public async Task StartPumpAsync()
        {
            Message initialMessage = null;

            initialMessage = await this.messageReceiver.ReceiveAsync().ConfigureAwait(false);

            if (initialMessage != null)
            {
                MessagingEventSource.Log.MessageReceiverPumpInitialMessageReceived(this.messageReceiver.ClientId, initialMessage);
            }

            TaskExtensionHelper.Schedule(() => this.MessagePumpTask(initialMessage));
        }
Пример #9
0
        async Task MessageDispatchTask(BrokeredMessage message)
        {
            CancellationTokenSource renewLockCancellationTokenSource = null;
            Timer autoRenewLockCancellationTimer = null;

            MessagingEventSource.Log.MessageReceiverPumpDispatchTaskStart(this.messageReceiver.ClientId, message);

            if (this.ShouldRenewLock())
            {
                renewLockCancellationTokenSource = new CancellationTokenSource();
                TaskExtensionHelper.Schedule(() => this.RenewMessageLockTask(message, renewLockCancellationTokenSource.Token));

                // After a threshold time of renewal('AutoRenewTimeout'), create timer to cancel anymore renewals.
                autoRenewLockCancellationTimer = new Timer(this.CancelAutoRenewlock, renewLockCancellationTokenSource, this.onMessageOptions.AutoRenewTimeout, TimeSpan.FromMilliseconds(-1));
            }

            try
            {
                MessagingEventSource.Log.MessageReceiverPumpUserCallbackStart(this.messageReceiver.ClientId, message);
                await this.onMessageCallback(message, this.pumpCancellationToken).ConfigureAwait(false);

                MessagingEventSource.Log.MessageReceiverPumpUserCallbackStop(this.messageReceiver.ClientId, message);
            }
            catch (Exception exception)
            {
                MessagingEventSource.Log.MessageReceiverPumpUserCallbackException(this.messageReceiver.ClientId, message, exception);
                this.onMessageOptions.RaiseExceptionReceived(new ExceptionReceivedEventArgs(exception, "UserCallback"));

                // Nothing much to do if UserCallback throws, Abandon message and Release semaphore.
                await this.AbandonMessageIfNeededAsync(message).ConfigureAwait(false);

                this.maxConcurrentCallsSemaphoreSlim.Release();
                return;
            }
            finally
            {
                renewLockCancellationTokenSource?.Cancel();
                renewLockCancellationTokenSource?.Dispose();
                autoRenewLockCancellationTimer?.Dispose();
            }

            // If we've made it this far, user callback completed fine. Complete message and Release semaphore.
            await this.CompleteMessageIfNeededAsync(message).ConfigureAwait(false);

            this.maxConcurrentCallsSemaphoreSlim.Release();

            MessagingEventSource.Log.MessageReceiverPumpDispatchTaskStop(this.messageReceiver.ClientId, message, this.maxConcurrentCallsSemaphoreSlim.CurrentCount);
        }
        async Task MessagePumpTaskAsync()
        {
            while (!this.pumpCancellationToken.IsCancellationRequested)
            {
                Message message = null;
                try
                {
                    await this.maxConcurrentCallsSemaphoreSlim.WaitAsync(this.pumpCancellationToken).ConfigureAwait(false);

                    message = await this.messageReceiver.ReceiveAsync(this.registerHandlerOptions.ReceiveTimeOut).ConfigureAwait(false);

                    if (message != null)
                    {
                        MessagingEventSource.Log.MessageReceiverPumpTaskStart(this.messageReceiver.ClientId, message, this.maxConcurrentCallsSemaphoreSlim.CurrentCount);

                        TaskExtensionHelper.Schedule(() =>
                        {
                            if (ServiceBusDiagnosticSource.IsEnabled())
                            {
                                return(this.MessageDispatchTaskInstrumented(message));
                            }
                            else
                            {
                                return(this.MessageDispatchTask(message));
                            }
                        });
                    }
                }
                catch (Exception exception)
                {
                    // Not reporting an ObjectDisposedException as we're stopping the pump
                    if (!(exception is ObjectDisposedException && this.pumpCancellationToken.IsCancellationRequested))
                    {
                        MessagingEventSource.Log.MessageReceivePumpTaskException(this.messageReceiver.ClientId, string.Empty, exception);
                        await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.Receive).ConfigureAwait(false);
                    }
                }
                finally
                {
                    // Either an exception or for some reason message was null, release semaphore and retry.
                    if (message == null)
                    {
                        this.maxConcurrentCallsSemaphoreSlim.Release();
                        MessagingEventSource.Log.MessageReceiverPumpTaskStop(this.messageReceiver.ClientId, this.maxConcurrentCallsSemaphoreSlim.CurrentCount);
                    }
                }
            }
        }
Пример #11
0
            async Task MessageDispatchTask(Message message)
            {
                CancellationTokenSource renewLockCancellationTokenSource = null;
                Timer autoRenewLockCancellationTimer = null;

                if (ShouldRenewLock())
                {
                    renewLockCancellationTokenSource = new CancellationTokenSource();
                    TaskExtensionHelper.Schedule(() => RenewMessageLockTask(message, renewLockCancellationTokenSource.Token));

                    // After a threshold time of renewal('AutoRenewTimeout'), create timer to cancel anymore renewals.
                    autoRenewLockCancellationTimer = new Timer(CancelAutoRenewLock, renewLockCancellationTokenSource, _registerHandlerOptions.MaxAutoRenewDuration, TimeSpan.FromMilliseconds(-1));
                }

                try
                {
                    await _onMessageCallback(message, _pumpCancellationToken).ConfigureAwait(false);
                }
                catch (Exception exception)
                {
                    await RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.UserCallback).ConfigureAwait(false);

                    // Nothing much to do if UserCallback throws, Abandon message and Release semaphore.
                    if (!(exception is MessageLockLostException))
                    {
                        await AbandonMessageIfNeededAsync(message).ConfigureAwait(false);
                    }

                    // AbandonMessageIfNeededAsync should take care of not throwing exception
                    _maxConcurrentCallsSemaphoreSlim.Release();

                    return;
                }
                finally
                {
                    renewLockCancellationTokenSource?.Cancel();
                    renewLockCancellationTokenSource?.Dispose();
                    autoRenewLockCancellationTimer?.Dispose();
                }

                // If we've made it this far, user callback completed fine. Complete message and Release semaphore.
                await CompleteMessageIfNeededAsync(message).ConfigureAwait(false);

                _maxConcurrentCallsSemaphoreSlim.Release();
            }
Пример #12
0
        async Task MessagePumpTask(BrokeredMessage initialMessage)
        {
            while (!this.pumpCancellationToken.IsCancellationRequested)
            {
                BrokeredMessage message = null;
                try
                {
                    await this.maxConcurrentCallsSemaphoreSlim.WaitAsync(this.pumpCancellationToken).ConfigureAwait(false);

                    if (initialMessage == null)
                    {
                        message = await this.messageReceiver.ReceiveAsync();
                    }
                    else
                    {
                        message        = initialMessage;
                        initialMessage = null;
                    }

                    if (message != null)
                    {
                        MessagingEventSource.Log.MessageReceiverPumpTaskStart(this.messageReceiver.ClientId, message, this.maxConcurrentCallsSemaphoreSlim.CurrentCount);
                        TaskExtensionHelper.Schedule(() => this.MessageDispatchTask(message));
                    }
                }
                catch (Exception exception)
                {
                    MessagingEventSource.Log.MessageReceivePumpTaskException(this.messageReceiver.ClientId, exception);
                    this.onMessageOptions.RaiseExceptionReceived(new ExceptionReceivedEventArgs(exception, "Receive"));
                    TimeSpan backOffTimeSpan = this.GetBackOffTime(exception);
                    await Task.Delay(backOffTimeSpan, this.pumpCancellationToken).ConfigureAwait(false);
                }
                finally
                {
                    // Either an exception or for some reason message was null, release semaphore and retry.
                    if (message == null)
                    {
                        this.maxConcurrentCallsSemaphoreSlim.Release();
                        MessagingEventSource.Log.MessageReceiverPumpTaskStop(this.messageReceiver.ClientId, this.maxConcurrentCallsSemaphoreSlim.CurrentCount);
                    }
                }
            }
        }
Пример #13
0
        internal void SetServerBusy(string exceptionMessage)
        {
            // multiple call to this method will not prolong the timer.
            if (this.encounteredServerBusy)
            {
                return;
            }

            lock (this.serverBusyLock)
            {
                if (!this.encounteredServerBusy)
                {
                    this.encounteredServerBusy      = true;
                    this.ServerBusyExceptionMessage = string.IsNullOrWhiteSpace(exceptionMessage) ?
                                                      Resources.DefaultServerBusyException : exceptionMessage;
                    this.IsServerBusy = true;
                    TaskExtensionHelper.Schedule(ScheduleResetServerBusy);
                }
            }
        }
        async Task SessionPumpTaskAsync(IMessageSession initialSession)
        {
            IMessageSession session;

            while (!this.pumpCancellationToken.IsCancellationRequested)
            {
                bool concurrentSessionSemaphoreAquired = false;
                try
                {
                    await this.maxConcurrentSessionsSemaphoreSlim.WaitAsync(this.pumpCancellationToken).ConfigureAwait(false);

                    concurrentSessionSemaphoreAquired = true;

                    if (initialSession != null)
                    {
                        session = initialSession;
                        TaskExtensionHelper.Schedule(() => this.MessagePumpTaskAsync(session));
                        initialSession = null;
                    }
                    else
                    {
                        await this.maxPendingAcceptSessionsSemaphoreSlim.WaitAsync(this.pumpCancellationToken).ConfigureAwait(false);

                        session = await this.client.AcceptMessageSessionAsync().ConfigureAwait(false);

                        if (session == null)
                        {
                            await Task.Delay(Constants.NoMessageBackoffTimeSpan, this.pumpCancellationToken).ConfigureAwait(false);

                            continue;
                        }
                        TaskExtensionHelper.Schedule(() => this.MessagePumpTaskAsync(session));
                    }
                }
                catch (Exception exception)
                {
                    MessagingEventSource.Log.SessionReceivePumpSessionReceiveException(this.clientId, exception);

                    if (concurrentSessionSemaphoreAquired)
                    {
                        this.maxConcurrentSessionsSemaphoreSlim.Release();
                    }

                    if (!(exception is TimeoutException))
                    {
                        this.RaiseExceptionRecieved(exception, "AcceptMessageSession");
                        if (!MessagingUtilities.ShouldRetry(exception))
                        {
                            break;
                        }
                    }
                    else
                    {
                        await Task.Delay(Constants.NoMessageBackoffTimeSpan, this.pumpCancellationToken).ConfigureAwait(false);
                    }
                }
                finally
                {
                    this.maxPendingAcceptSessionsSemaphoreSlim.Release();
                }
            }
        }
 public void StartPump()
 {
     TaskExtensionHelper.Schedule(() => this.MessagePumpTaskAsync());
 }
Пример #16
0
 public void StartPump()
 {
     TaskExtensionHelper.Schedule(MessagePumpTaskAsync);
 }
Пример #17
0
        async Task MessagePumpTaskAsync(IMessageSession session)
        {
            if (session == null)
            {
                return;
            }

            CancellationTokenSource renewLockCancellationTokenSource = new CancellationTokenSource();

            if (this.ShouldRenewSessionLock())
            {
                TaskExtensionHelper.Schedule(() => this.RenewSessionLockTaskAsync(session, renewLockCancellationTokenSource.Token));
            }

            Timer userCallbackTimer = new Timer(
                OnUserCallBackTimeout,
                renewLockCancellationTokenSource,
                Timeout.Infinite,
                Timeout.Infinite);

            try
            {
                while (!this.pumpCancellationToken.IsCancellationRequested && !session.IsClosedOrClosing)
                {
                    Message message;
                    try
                    {
                        message = await session.ReceiveAsync(this.sessionHandlerOptions.MessageWaitTimeout).ConfigureAwait(false);
                    }
                    catch (Exception exception)
                    {
                        MessagingEventSource.Log.MessageReceivePumpTaskException(this.clientId, session.SessionId, exception);
                        if (exception is ServiceBusTimeoutException)
                        {
                            // Timeout Exceptions are pretty common. Not alerting the User on this.
                            continue;
                        }

                        await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.Receive).ConfigureAwait(false);

                        break;
                    }

                    if (message == null)
                    {
                        MessagingEventSource.Log.SessionReceivePumpSessionEmpty(this.clientId, session.SessionId);
                        break;
                    }

                    // Set the timer
                    userCallbackTimer.Change(this.sessionHandlerOptions.MaxAutoRenewDuration, TimeSpan.FromMilliseconds(-1));
                    bool callbackExceptionOccured = false;
                    try
                    {
                        await this.userOnSessionCallback(session, message, this.pumpCancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception exception)
                    {
                        MessagingEventSource.Log.MessageReceivePumpTaskException(this.clientId, session.SessionId, exception);
                        await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.UserCallback).ConfigureAwait(false);

                        callbackExceptionOccured = true;
                        if (!(exception is MessageLockLostException || exception is SessionLockLostException))
                        {
                            await this.AbandonMessageIfNeededAsync(session, message).ConfigureAwait(false);
                        }
                    }
                    finally
                    {
                        userCallbackTimer.Change(Timeout.Infinite, Timeout.Infinite);
                    }

                    if (!callbackExceptionOccured)
                    {
                        await this.CompleteMessageIfNeededAsync(session, message).ConfigureAwait(false);
                    }
                    else if (session.IsClosedOrClosing)
                    {
                        // If User closed the session as part of the callback, break out of the loop
                        break;
                    }
                }
            }
            finally
            {
                userCallbackTimer.Dispose();
                await this.CloseSessionIfNeededAsync(session).ConfigureAwait(false);

                CancelAndDisposeCancellationTokenSource(renewLockCancellationTokenSource);
                this.maxConcurrentSessionsSemaphoreSlim.Release();
            }
        }
Пример #18
0
        async Task MessagePumpTaskAsync(IMessageSession session)
        {
            if (session == null)
            {
                return;
            }

            var renewLockCancellationTokenSource = new CancellationTokenSource();

            if (this.ShouldRenewSessionLock())
            {
                TaskExtensionHelper.Schedule(() => this.RenewSessionLockTaskAsync(session, renewLockCancellationTokenSource.Token));
            }

            var autoRenewLockCancellationTimer = new Timer(
                CancelAutoRenewLock,
                renewLockCancellationTokenSource,
                Timeout.Infinite,
                Timeout.Infinite);

            try
            {
                while (!this.pumpCancellationToken.IsCancellationRequested && !session.IsClosedOrClosing)
                {
                    Message message;
                    try
                    {
                        message = await session.ReceiveAsync(this.sessionHandlerOptions.MessageWaitTimeout).ConfigureAwait(false);
                    }
                    catch (Exception exception)
                    {
                        MessagingEventSource.Log.MessageReceivePumpTaskException(this.clientId, session.SessionId, exception);
                        if (exception is ServiceBusTimeoutException)
                        {
                            // Timeout Exceptions are pretty common. Not alerting the User on this.
                            continue;
                        }

                        if (!(exception is ObjectDisposedException && this.pumpCancellationToken.IsCancellationRequested))
                        {
                            await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.Receive).ConfigureAwait(false);
                        }
                        break;
                    }

                    if (message == null)
                    {
                        MessagingEventSource.Log.SessionReceivePumpSessionEmpty(this.clientId, session.SessionId);
                        break;
                    }

                    bool     isDiagnosticSourceEnabled = ServiceBusDiagnosticSource.IsEnabled();
                    Activity activity    = isDiagnosticSourceEnabled ? this.diagnosticSource.ProcessSessionStart(session, message) : null;
                    Task     processTask = null;

                    try
                    {
                        // Set the timer
                        autoRenewLockCancellationTimer.Change(this.sessionHandlerOptions.MaxAutoRenewDuration,
                                                              TimeSpan.FromMilliseconds(-1));
                        var callbackExceptionOccurred = false;
                        try
                        {
                            processTask = this.userOnSessionCallback(session, message, this.pumpCancellationToken);
                            await processTask.ConfigureAwait(false);
                        }
                        catch (Exception exception)
                        {
                            if (isDiagnosticSourceEnabled)
                            {
                                this.diagnosticSource.ReportException(exception);
                            }

                            MessagingEventSource.Log.MessageReceivePumpTaskException(this.clientId, session.SessionId, exception);
                            await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.UserCallback).ConfigureAwait(false);

                            callbackExceptionOccurred = true;
                            if (!(exception is MessageLockLostException || exception is SessionLockLostException))
                            {
                                await this.AbandonMessageIfNeededAsync(session, message).ConfigureAwait(false);
                            }
                        }
                        finally
                        {
                            autoRenewLockCancellationTimer.Change(Timeout.Infinite, Timeout.Infinite);
                        }

                        if (!callbackExceptionOccurred)
                        {
                            await this.CompleteMessageIfNeededAsync(session, message).ConfigureAwait(false);
                        }
                        else if (session.IsClosedOrClosing)
                        {
                            // If User closed the session as part of the callback, break out of the loop
                            break;
                        }
                    }
                    finally
                    {
                        this.diagnosticSource.ProcessSessionStop(activity, session, message, processTask?.Status);
                    }
                }
            }
            finally
            {
                renewLockCancellationTokenSource.Cancel();
                renewLockCancellationTokenSource.Dispose();
                autoRenewLockCancellationTimer.Dispose();

                await this.CloseSessionIfNeededAsync(session).ConfigureAwait(false);

                this.maxConcurrentSessionsSemaphoreSlim.Release();
            }
        }
Пример #19
0
 void IPromotableSinglePhaseNotification.SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)
 {
     this.transactionManager.RemoveEnlistment(this.transactionId);
     TaskExtensionHelper.Schedule(() => this.SinglePhaseCommitAsync(singlePhaseEnlistment));
 }
Пример #20
0
 void IPromotableSinglePhaseNotification.Rollback(SinglePhaseEnlistment singlePhaseEnlistment)
 {
     _transactionManager.RemoveEnlistment(_transactionId);
     TaskExtensionHelper.Schedule(() => RollbackAsync(singlePhaseEnlistment));
 }