private async Task ProcessMessages(ReceiverContext receiverContext) { TimeSpan backoffAmount = _backoffTime; while (!_cts.IsCancellationRequested) { try { var messages = await receiverContext.Receiver.ReceiveBatchAsync( ReceiverContext.ReceiveBatchSize, receiverContext.ReceiveTimeout); receiverContext.OnMessage(messages); // Reset the receive timeout if it changed receiverContext.ReceiveTimeout = DefaultReadTimeout; continue; } catch (OperationCanceledException) { // This means the channel is closed _trace.TraceError("Receiving messages from the service bus threw an OperationCanceledException, most likely due to a closed channel."); return; } catch (MessagingEntityNotFoundException ex) { try { await receiverContext.Receiver.CloseAsync(); } catch { } receiverContext.OnError(ex); var ignored = TryCreateSubscription(receiverContext); return; } catch (ServerBusyException ex) { receiverContext.OnError(ex); } catch (Exception ex) { receiverContext.OnError(ex); // TODO: Exponential backoff backoffAmount = ErrorBackOffAmount; // After an error, we want to adjust the timeout so that we // can recover as quickly as possible even if there's no message receiverContext.ReceiveTimeout = ErrorReadTimeout; } // back off for ServerBusyException and other exceptions not handled is a specific way await Task.Delay(backoffAmount); } }
private bool ContinueReceiving(IAsyncResult asyncResult, ReceiverContext receiverContext) { bool shouldContinue = true; TimeSpan backoffAmount = BackoffAmount; try { IEnumerable <BrokeredMessage> messages = receiverContext.Receiver.EndReceiveBatch(asyncResult); receiverContext.OnMessage(messages); // Reset the receive timeout if it changed receiverContext.ReceiveTimeout = DefaultReadTimeout; } catch (ServerBusyException ex) { receiverContext.OnError(ex); // Too busy so back off shouldContinue = false; } catch (OperationCanceledException) { // This means the channel is closed _trace.TraceError("Receiving messages from the service bus threw an OperationCanceledException, most likely due to a closed channel."); return(false); } catch (Exception ex) { receiverContext.OnError(ex); shouldContinue = false; // TODO: Exponential backoff backoffAmount = ErrorBackOffAmount; // After an error, we want to adjust the timeout so that we // can recover as quickly as possible even if there's no message receiverContext.ReceiveTimeout = ErrorReadTimeout; } if (!shouldContinue) { TaskAsyncHelper.Delay(backoffAmount) .Then(ctx => ProcessMessages(ctx), receiverContext); return(false); } return(true); }
private void ProcessMessages(ReceiverContext receiverContext) { receive: try { IAsyncResult result = receiverContext.Receiver.BeginReceiveBatch(ReceiverContext.ReceiveBatchSize, receiverContext.ReceiveTimeout, ar => { if (ar.CompletedSynchronously) { return; } var ctx = (ReceiverContext)ar.AsyncState; if (ContinueReceiving(ar, ctx)) { ProcessMessages(ctx); } }, receiverContext); if (result.CompletedSynchronously) { if (ContinueReceiving(result, receiverContext)) { goto receive; } } } catch (OperationCanceledException) { // This means the channel is closed _trace.TraceError("OperationCanceledException was thrown in trying to receive the message from the service bus."); return; } catch (Exception ex) { _trace.TraceError(ex.Message); receiverContext.OnError(ex); Thread.Sleep(RetryDelay); goto receive; } }
private void ProcessMessages(ReceiverContext receiverContext) { receive: try { IAsyncResult result = receiverContext.Receiver.BeginReceiveBatch(receiverContext.ReceiveBatchSize, receiverContext.ReceiveTimeout, ar => { if (ar.CompletedSynchronously) { return; } var ctx = (ReceiverContext)ar.AsyncState; if (ContinueReceiving(ar, ctx)) { ProcessMessages(ctx); } }, receiverContext); if (result.CompletedSynchronously) { if (ContinueReceiving(result, receiverContext)) { goto receive; } } } catch (OperationCanceledException) { // This means the channel is closed return; } catch (Exception ex) { receiverContext.OnError(ex); // REVIEW: What should we do here? } }
private bool ContinueReceiving(IAsyncResult asyncResult, ReceiverContext receiverContext) { bool shouldContinue = true; TimeSpan backoffAmount = BackoffAmount; try { IEnumerable<BrokeredMessage> messages = receiverContext.Receiver.EndReceiveBatch(asyncResult); receiverContext.OnMessage(messages); // Reset the receive timeout if it changed receiverContext.ReceiveTimeout = DefaultReadTimeout; } catch (ServerBusyException ex) { receiverContext.OnError(ex); // Too busy so back off shouldContinue = false; } catch (OperationCanceledException) { // This means the channel is closed _trace.TraceError("Receiving messages from the service bus threw an OperationCanceledException, most likely due to a closed channel."); return false; } catch (MessagingEntityNotFoundException ex) { receiverContext.Receiver.CloseAsync().Catch(); receiverContext.OnError(ex); TaskAsyncHelper.Delay(RetryDelay) .Then(() => Retry(() => CreateSubscription(receiverContext.ConnectionContext, receiverContext.TopicIndex))); return false; } catch (Exception ex) { receiverContext.OnError(ex); shouldContinue = false; // TODO: Exponential backoff backoffAmount = ErrorBackOffAmount; // After an error, we want to adjust the timeout so that we // can recover as quickly as possible even if there's no message receiverContext.ReceiveTimeout = ErrorReadTimeout; } if (!shouldContinue) { TaskAsyncHelper.Delay(backoffAmount) .Then(ctx => ProcessMessages(ctx), receiverContext); return false; } return true; }
private bool ContinueReceiving(IAsyncResult asyncResult, ReceiverContext receiverContext) { bool shouldContinue = true; TimeSpan backoffAmount = BackoffAmount; try { IEnumerable<BrokeredMessage> messages = receiverContext.Receiver.EndReceiveBatch(asyncResult); receiverContext.OnMessage(messages); // Reset the receive timeout if it changed receiverContext.ReceiveTimeout = DefaultReadTimeout; } catch (ServerBusyException ex) { receiverContext.OnError(ex); // Too busy so back off shouldContinue = false; } catch (OperationCanceledException) { // This means the channel is closed return false; } catch (Exception ex) { receiverContext.OnError(ex); shouldContinue = false; // TODO: Exponential backoff backoffAmount = ErrorBackOffAmount; // After an error, we want to adjust the timeout so that we // can recover as quickly as possible even if there's no message receiverContext.ReceiveTimeout = ErrorReadTimeout; } if (!shouldContinue) { TaskAsyncHelper.Delay(backoffAmount) .Then(ctx => ProcessMessages(ctx), receiverContext); return false; } return true; }
private bool ContinueReceiving(IAsyncResult asyncResult, ReceiverContext receiverContext) { bool shouldContinue = true; TimeSpan backoffAmount = _backoffTime; try { IEnumerable <BrokeredMessage> messages = receiverContext.Receiver.EndReceiveBatch(asyncResult); receiverContext.OnMessage(messages); // Reset the receive timeout if it changed receiverContext.ReceiveTimeout = DefaultReadTimeout; } catch (ServerBusyException ex) { receiverContext.OnError(ex); // Too busy so back off shouldContinue = false; } catch (OperationCanceledException) { // This means the channel is closed _logger.LogError("Receiving messages from the service bus threw an OperationCanceledException, most likely due to a closed channel."); return(false); } catch (MessagingEntityNotFoundException ex) { receiverContext.Receiver.CloseAsync() .ContinueWith(t => _logger.LogInformation("{0}", t.Exception.ToString()), TaskContinuationOptions.OnlyOnFaulted); receiverContext.OnError(ex); Task.Run(async() => { await Task.Delay(RetryDelay); Retry(() => CreateSubscription(receiverContext.ConnectionContext, receiverContext.TopicIndex)); }); return(false); } catch (Exception ex) { receiverContext.OnError(ex); shouldContinue = false; // TODO: Exponential backoff backoffAmount = ErrorBackOffAmount; // After an error, we want to adjust the timeout so that we // can recover as quickly as possible even if there's no message receiverContext.ReceiveTimeout = ErrorReadTimeout; } if (!shouldContinue) { Task.Run(async() => { await Task.Delay(backoffAmount); ProcessMessages(receiverContext); }); return(false); } return(true); }