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)); } } }
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)); }
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); } } } }
public void StartPump() { // Schedule Tasks for doing PendingAcceptSession calls for (int i = 0; i < this.sessionHandlerOptions.MaxConcurrentAcceptSessionCalls; i++) { TaskExtensionHelper.Schedule(this.SessionPumpTaskAsync); } }
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(); } } }
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)); }
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); } } } }
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(); }
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); } } } }
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()); }
public void StartPump() { TaskExtensionHelper.Schedule(MessagePumpTaskAsync); }
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(); } }
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(); } }
void IPromotableSinglePhaseNotification.SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment) { this.transactionManager.RemoveEnlistment(this.transactionId); TaskExtensionHelper.Schedule(() => this.SinglePhaseCommitAsync(singlePhaseEnlistment)); }
void IPromotableSinglePhaseNotification.Rollback(SinglePhaseEnlistment singlePhaseEnlistment) { _transactionManager.RemoveEnlistment(_transactionId); TaskExtensionHelper.Schedule(() => RollbackAsync(singlePhaseEnlistment)); }