public void ReceiveMessages(Func <IssueCreatedEventArgs, CancellationToken, Task> issueCreatedHandler = null, Func <NewIssueCreatedEventArgs, CancellationToken, Task> newissueCreatedHandler = null, MessageHandlerOptions options = null) { var messageHandlerOptions = options ?? new MessageHandlerOptions(OnDefaultError); _messageReceiver.RegisterMessageHandler(async(msg, token) => { _logger.Information("Received service bus message {MessageId}: {Label}", msg.Id.ToString(), msg.Label); switch (msg.Label) { case IssueMessageSender.ISSUE_CREATED: { if (issueCreatedHandler != null) { _logger.Information("ISSUE_CREATED"); await ReceiveIssueCreated(msg, token, issueCreatedHandler); } else { await _messageReceiver.CompleteAsync(msg.LockToken); } break; } default: { await _messageReceiver.DeadLetterAsync(msg.LockToken, $"Unknown message type: { msg.Label }"); break; } } }, messageHandlerOptions); }
internal async Task OnMessageAsyncUnregisterHandlerShortTimeoutTestCase( IMessageSender messageSender, IMessageReceiver messageReceiver, int maxConcurrentCalls, bool autoComplete, int messageCount) { var count = 0; await TestUtility.SendMessagesAsync(messageSender, messageCount); messageReceiver.RegisterMessageHandler( async(message, token) => { TestUtility.Log($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber}"); await Task.Delay(TimeSpan.FromSeconds(8)); if (messageReceiver.ReceiveMode == ReceiveMode.PeekLock && !autoComplete) { await messageReceiver.CompleteAsync(message.SystemProperties.LockToken); } Interlocked.Increment(ref count); }, new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = maxConcurrentCalls, AutoComplete = autoComplete }); await Task.Delay(TimeSpan.FromSeconds(2)); await messageReceiver.UnregisterMessageHandlerAsync(TimeSpan.FromSeconds(2)); Assert.True(count == 0); }
static async Task ReceiveMessagesAsync(int numberOfMessagesToReceive, ILogger tw) { // Receive the message IList <Message> receiveList = await messageReceiver.ReceiveAsync(numberOfMessagesToReceive); foreach (Message msg in receiveList) { tw.LogInformation($"Received message: SequenceNumber:{msg.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(msg.Body)}"); await messageReceiver.CompleteAsync(msg.SystemProperties.LockToken); } }
static async Task ProcessMessagesAsyncDead(Message receivedMessage, CancellationToken token) { try { ProcessMessage(receivedMessage, "dead-letter"); await subscriptionDeadLetter.CompleteAsync(receivedMessage.SystemProperties.LockToken); } catch (Exception) { await subscriptionDeadLetter.AbandonAsync(receivedMessage.SystemProperties.LockToken); } }
protected override void ReceiveEvent(IMessageReceiver client, BrokeredMessage message) #endif { try { Logger.LogDebug(string.Format("An event message arrived with the id '{0}'.", message.MessageId)); string messageBody = message.GetBodyAsString(); IEvent <TAuthenticationToken> @event = MessageSerialiser.DeserialiseEvent(messageBody); CorrelationIdHelper.SetCorrelationId(@event.CorrelationId); Logger.LogInfo(string.Format("An event message arrived with the id '{0}' was of type {1}.", message.MessageId, @event.GetType().FullName)); Type eventType = @event.GetType(); string targetQueueName = eventType.FullName; try { object rsn = eventType.GetProperty("Rsn").GetValue(@event, null); targetQueueName = string.Format("{0}.{1}", targetQueueName, rsn); } catch { Logger.LogDebug(string.Format("An event message arrived with the id '{0}' was of type {1} but with no Rsn property.", message.MessageId, eventType)); // Do nothing if there is no rsn. Just use @event type name } CreateQueueAndAttachListenerIfNotExist(targetQueueName); EnqueueEvent(targetQueueName, @event); // remove the original message from the incoming queue #if NET452 message.Complete(); #endif #if NETSTANDARD2_0 client.CompleteAsync(message.SystemProperties.LockToken).Wait(1500); #endif Logger.LogDebug(string.Format("An event message arrived and was processed with the id '{0}'.", message.MessageId)); } catch (Exception exception) { // Indicates a problem, unlock message in queue Logger.LogError(string.Format("An event message arrived with the id '{0}' but failed to be process.", message.MessageId), exception: exception); #if NET452 message.Abandon(); #endif #if NETSTANDARD2_0 client.AbandonAsync(message.SystemProperties.LockToken).Wait(1500); #endif } }
static async Task ReceiveMessagesAsync(int numberOfMessagesToReceive) { while (numberOfMessagesToReceive-- > 0) { // Receive the message Message message = await messageReceiver.ReceiveAsync(); // Process the message Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}"); // Complete the message so that it is not received again. // This can be done only if the MessageReceiver is created in ReceiveMode.PeekLock mode (which is default). await messageReceiver.CompleteAsync(message.SystemProperties.LockToken); } }
async Task CompleteMessageIfNeededAsync(Message message) { try { if (_messageReceiver.ReceiveMode == ReceiveMode.PeekLock && _registerHandlerOptions.AutoComplete) { await _messageReceiver.CompleteAsync(new[] { message.SystemProperties.LockToken }).ConfigureAwait(false); } } catch (Exception exception) { await RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.Complete).ConfigureAwait(false); } }
private static async Task HandleMessage(Message message, CancellationToken token) { try { bool isDeadLetterMessage = message.UserProperties.Keys.FirstOrDefault(k => k.Equals("DeadLetterReason")) != null; bool hasSessionId = !string.IsNullOrEmpty(message.SessionId); Console.WriteLine("Message Received!"); var smsMessage = JsonConvert.DeserializeObject <SmsMessage>(Encoding.UTF8.GetString(message.Body)); Console.WriteLine("Content: " + smsMessage.Content); Console.WriteLine("Destination: " + smsMessage.Destination); Console.WriteLine("Is DLQ: " + isDeadLetterMessage); // Writing messages with not null sessionId's to session disabled queues is not forbidden. // In fact, if you write messages with sessionId to a queue where sessions are disabled, // you will still get messages FIFO. Console.WriteLine("Has session ID: " + hasSessionId); if (hasSessionId) { Console.WriteLine("Session ID: " + message.SessionId); } // Complete the message so that it is not received again. // This can be done only if the queue Client is created in ReceiveMode.PeekLock mode (which is the default). if (isDeadLetterMessage) { await _dlqReceiver.CompleteAsync(message.SystemProperties.LockToken); } else { await _queueClient.CompleteAsync(message.SystemProperties.LockToken); } Console.WriteLine("***********************\n"); } catch { Console.WriteLine("Received exception while handling the message, abandoning..."); await _queueClient.AbandonAsync(message.SystemProperties.LockToken); } }
private async Task ProcessMessagesAsync(Message message, CancellationToken token) { T payload = null; if (message.Body[0] == charAt) { payload = OneSolution.ServiceBus.XmlMessageExtention.ParseXmlMessage <T>(message); } else { payload = JsonSerializer.Deserialize <T>(Encoding.UTF8.GetString(message.Body)); } var lockToken = message.SystemProperties.LockToken; await processor.ProcessMessagesAsync(payload, lockToken, token).ConfigureAwait(false); await receiver.CompleteAsync(lockToken).ConfigureAwait(false); }
internal static async Task <Message> GetDeferredMessageAsync(this IMessageReceiver messageReceiver, Message message) { if (!message.TryGetDeferredSequenceNumber(out var sequenceNumber)) { return(message); } using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { await messageReceiver.CompleteAsync(message.SystemProperties.LockToken).ConfigureAwait(false); message = await messageReceiver.ReceiveDeferredMessageAsync(sequenceNumber) .ConfigureAwait(false); scope.Complete(); } return(message); }
/// <summary> /// Processes an incoming message. /// </summary> /// <param name="receiver"></param> /// <param name="message"></param> /// <returns></returns> private async Task ProcessMessageForClient(IMessageReceiver receiver, Message message) { SampleMessage messageData = null; try { messageData = DeserializeMessage(message); } catch (Exception ex) { //this is an issue, we received data that cannot be interpreted as MessageData. await MessageProcessingFailed(message, ex).ConfigureAwait(false); //move to dlc if (message.SystemProperties.IsReceived) { await receiver.DeadLetterAsync(message.SystemProperties.LockToken, "Message cannot be deserialized into MessageData.").ConfigureAwait(false); } } try { //if messageData is null, this means message is not supposed to be handled if (messageData != null) { await ProcessMessage(receiver, message, messageData) .ConfigureAwait(false); } else { //unable to process, and not interested await receiver.CompleteAsync(message.SystemProperties.LockToken).ConfigureAwait(false); } } catch (MessageLockLostException ex) { _logger?.LogWarning(ex, "Message lock was lost for message {MessageId}", message.MessageId); } catch (Exception ex) { await MessageProcessingFailed(message, ex).ConfigureAwait(false); } }
private async Task HandleMessage(Message message, CancellationToken cancellationToken) { //Console.WriteLine($"Handled message id {message.MessageId}, diagnostic id {message.UserProperties["Diagnostic-Id"]}, enclosed type {message.UserProperties["EnclosedType"]}"); try { await messageHandler.HandleMessage(message, cancellationToken); await messageReceiver.CompleteAsync(message.SystemProperties.LockToken); } catch (Exception ex) { Dictionary <string, object> abandonReasons = new Dictionary <string, object> { { "Exception.Message", ex.Message }, { "Exception.StackTrace", ex.ToString() } }; await messageReceiver.AbandonAsync(message.SystemProperties.LockToken, abandonReasons); } }
private async Task _handleMessage(RecoverabilityContext context, CancellationToken cancellationToken) { bool isHandled = false; try { context = await _recoverability.OnPreHandle(context); if (context.SkipMessage) { return; } await _handleMessageFunc( new TransportMessage(context.Message.Label, context.Message.Body, _metaDataMapper.ExtractMetaData(context.Message)), _endpoint ); isHandled = true; } catch (NonTransientException nte) { _logger.LogError(nte, "AzureServiceBusMessagePump encountered a NonTransient Exception handling a message. Sending to DLQ. Endpoint: {EndpointName}", context.Endpoint.Name); await _receiver.DeadLetterAsync(context.Message.SystemProperties.LockToken); } catch (Exception exc) { //backoff retry _logger.LogError(exc, "AzureServiceBusMessagePump encountered an exception handling a message. Attempting to recover. Endpoint: {EndpointName}. Label: {messageLabel}", context.Endpoint.Name, context.Message?.Label); await _recoverability.Recover(context); } //if an exception occurs completing the message then it will stay on the queue and be handled again //we don't want to trigger recoverability/retry if (isHandled) { await _completeImmediateRetryPolicy.ExecuteAsync(() => _receiver.CompleteAsync(context.Message.SystemProperties.LockToken) ); await _recoverability.OnPostHandle(context); } }
internal async Task OnMessageAsyncTestCase( IMessageSender messageSender, IMessageReceiver messageReceiver, int maxConcurrentCalls, bool autoComplete, int messageCount) { int count = 0; await TestUtility.SendMessagesAsync(messageSender, messageCount); messageReceiver.RegisterMessageHandler( async(message, token) => { TestUtility.Log($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber}"); count++; if (messageReceiver.ReceiveMode == ReceiveMode.PeekLock && !autoComplete) { await messageReceiver.CompleteAsync(message.SystemProperties.LockToken); } }, new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = maxConcurrentCalls, AutoComplete = autoComplete }); // Wait for the OnMessage Tasks to finish Stopwatch stopwatch = Stopwatch.StartNew(); while (stopwatch.Elapsed.TotalSeconds <= 60) { if (count == messageCount) { TestUtility.Log($"All '{messageCount}' messages Received."); break; } else { await Task.Delay(TimeSpan.FromSeconds(5)); } } Assert.True(count == messageCount); }
public async Task <bool> ResubmitDeadLetterMessageAsync(string messageId, string serviceBusQueue, long sequenceNumber) { bool IsSuccess = false; IMessageReceiver messageReceiver = _messageReceiverFactory.Create(serviceBusQueue, ReceiveMode.PeekLock, true); Message deadLetter = await messageReceiver.PeekBySequenceNumberAsync(sequenceNumber); if (deadLetter != null) { var newMessage = _messageReader.ReadMessage(Encoding.UTF8.GetString(deadLetter.Body)); //Check that the messageId matches the one that we want to re-enqueue if (newMessage.MessageId.Equals(messageId)) { try { //Attempt to send the message back onto the queue // never re-queue a message with a duplicate id - it will fail to save to message archive newMessage.MessageId = Guid.NewGuid().ToString(); await _messageSender.SendMessage(newMessage); } catch (Exception ex) { _log.LogError(ex, "ResubmitDeadLetterMessageAsync Exception"); throw new ServiceBusReaderException("ResubmitDeadLetterMessageAsync", ex); } finally { //Delete message after resubmitting var msg = await messageReceiver.ReceiveAsync(); await messageReceiver.CompleteAsync(msg.SystemProperties.LockToken); IsSuccess = true; } } } await messageReceiver.CloseAsync(); return(IsSuccess); }
public async Task ReceiveMessageAsync(IMessageReceiver receiver, Message message, CancellationToken cancellationToken) { Exception receiveEx = null; try { cancellationToken.ThrowIfCancellationRequested(); Console.WriteLine("Received MessageId=[{0}] MessageBody=[{1}]", message.MessageId, Encoding.UTF8.GetString(message.Body)); await receiver.CompleteAsync(message.SystemProperties.LockToken); } catch (Exception ex) { receiveEx = ex; Console.WriteLine("Exception ocurred during ReceiveMessageAsync() Message=[{0}]", ex.Message); } if (receiveEx != null) { await receiver.AbandonAsync(message.SystemProperties.LockToken); } }
protected async Task <bool> HandleMessageOutcome( Message message, MessageHandlingResult result) { var isSuccessful = result.Result == MessageHandlingResult.HandlingResult.Completed; var shouldAutoComplete = _endpointHandlingConfig.AutoComplete || _receiver.IsClosedOrClosing; if (shouldAutoComplete) { return(isSuccessful); } try { switch (result.Result) { case MessageHandlingResult.HandlingResult.Completed: await _receiver.CompleteAsync(message.SystemProperties.LockToken).ConfigureAwait(false); break; case MessageHandlingResult.HandlingResult.DeadLettered: case MessageHandlingResult.HandlingResult.UnrecognisedMessageType: await _receiver.DeadLetterAsync(message.SystemProperties.LockToken, result.AdditionalProperties).ConfigureAwait(false); break; case MessageHandlingResult.HandlingResult.Abandoned: await _receiver.AbandonAsync(message.SystemProperties.LockToken, result.AdditionalProperties).ConfigureAwait(false); break; } } catch (MessageLockLostException ex) { _logger.LogError(LogEventIds.ListenerException, ex, $"MessageLockLostException in {_name}>"); } return(isSuccessful); }
static async Task ProcessDeadLetterQueueMessagesAsync(Message message, CancellationToken token) { // Process the message // This could include retries or logging for further troubleshooting Console.WriteLine($"Received DLQ message: SequenceNumber:{message.SystemProperties} Body:{Encoding.UTF8.GetString(message.Body)}"); if (message.UserProperties.ContainsKey("DeadLetterReason")) { Console.WriteLine("\t DeadLetterReason: {0}", message.UserProperties["DeadLetterReason"]); } if (message.UserProperties.ContainsKey("DeadLetterErrorDescription")) { Console.WriteLine("\t DeadLetterErrorDescription: {0}", message.UserProperties["DeadLetterErrorDescription"]); } // Complete the message so that it is not received again. // This can be done only if the deadLetterReceiver is created in ReceiveMode.PeekLock mode (which is default). await deadLetterReceiver.CompleteAsync(message.SystemProperties.LockToken); // Note: Use the cancellationToken passed as necessary to determine if the deadLetterReceiver has already been closed. // If deadLetterReceiver has already been Closed, you may chose to not call CompleteAsync() or AbandonAsync() etc. calls // to avoid unnecessary exceptions. }
/// <summary> /// Handles one message. /// </summary> /// <param name="receiver"></param> /// <param name="serviceBusMessage"></param> /// <param name="messageData"></param> /// <returns></returns> private async Task ProcessMessage(IMessageReceiver receiver, Message serviceBusMessage, SampleMessage messageData) { //TODO: de-duplicate messages ImmutableList <SampleMessage> value; if (_cache.TryGetValue("CacheKey", out var val)) { value = (ImmutableList <SampleMessage>)val; } else { value = ImmutableList <SampleMessage> .Empty; } messageData.Receiver = receiver == _primaryMessageReceiver ? "PrimaryReceiver" : "SecondaryReceiver"; value = value.Add(messageData); _cache.Set("CacheKey", value); _logger.LogInformation("Received message with body: {MessageData}", messageData); await receiver.CompleteAsync(serviceBusMessage.SystemProperties.LockToken).ConfigureAwait(false); }
private async Task <IList <QueueMessage> > ProcessMessagesInTransaction(string queueName, int quantity) { IEnumerable <QueueMessage> formattedMessages = new List <QueueMessage>(); var messages = await _messageReceiver.ReceiveAsync(quantity, TimeSpan.FromSeconds(60)); try { if (messages == null) { return(null); } formattedMessages = messages.Select(message => message.Convert(_userService.GetUserId(), queueName)); await AddMessagesToDatabase(formattedMessages); await _messageReceiver.CompleteAsync(messages.Select(message => message.GetLockToken())); } catch (CosmosBatchInsertException ex) { await HandleBatchCreationFailure(formattedMessages, ex.StatusCode); _logger.LogError("Failed to create messages with error: {0}, exception: {1}", ex.StatusCode.ToString(), ex.ToString()); } catch (Exception ex) { _logger.LogError("Failed to receive messages: {0}", ex.ToString()); foreach (var message in formattedMessages) { await _messageReceiver.AbandonAsync(message.OriginalMessage.GetLockToken()); } } return(formattedMessages.ToList()); }
static async Task ReceiveMessagesAsync(int numberOfMessagesToReceive, TraceWriter tw) { //while (numberOfMessagesToReceive-- > 0) //{ // Receive the message IList <Message> receiveList = await messageReceiver.ReceiveAsync(numberOfMessagesToReceive); foreach (Message msg in receiveList) { MemoryStream stream = new MemoryStream(msg.Body); DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(TheMsgBody)); var body = (TheMsgBody)ser.ReadObject(stream); Message NewMessage = new Message(); NewMessage.Body = msg.Body; NewMessage.MessageId = msg.MessageId; // Process the message if (body.SalesValue > 9999) { tw.Info("AWESOME - Big sales incoming!"); } else { tw.Info($"Regular sales incoming..."); } NewMessage.UserProperties.Add("SalesValue", body.SalesValue); await messageSender.SendAsync(NewMessage); await messageReceiver.CompleteAsync(msg.SystemProperties.LockToken); } // Complete the message so that it is not received again. // This can be done only if the MessageReceiver is created in ReceiveMode.PeekLock mode (which is default). //} }
public async Task Complete(string lockToken) { await _messageReceiver.CompleteAsync(lockToken).ConfigureAwait(false); }
/// <summary> /// dispatch message by its label /// </summary> /// <param name="message"></param> /// <param name="receiver"></param> /// <returns></returns> private async Task DispatchMessage(Message message, IMessageReceiver receiver) { if (message.Label == null || !setting.messageHandlers.ContainsKey(message.Label)) { // don't have to wait the call /*await*/ receiver.AbandonAsync(message.SystemProperties.LockToken); return; } var handlers = setting.messageHandlers[message.Label]; if (handlers.Count == 0) { // don't have to wait the call /*await*/ receiver.CompleteAsync(message.SystemProperties.LockToken); return; } try { var hId = -1; var pack = new HandlerPack(); pack.stationId = stationId; pack.receiver = receiver; pack.message = message; pack.terminate = () => { hId = handlers.Count; }; pack.next = async() => { hId++; if (hId < handlers.Count) { var handler = handlers[hId]; await handler.Invoke(pack); } }; // start handler function chain while (hId < handlers.Count) { try { await pack.next(); } catch (System.Exception e) { Console.WriteLine("============"); Console.WriteLine(e.ToString()); receiver.DeadLetterAsync(message.SystemProperties.LockToken); break; } } return; } catch (System.Exception e) { Console.WriteLine(e.ToString()); } // for any uncatched exception try { receiver.AbandonAsync(message.SystemProperties.LockToken); } catch (System.Exception e) { throw; } }
internal void StartMessageBatchReceiver(CancellationToken cancellationToken) { SessionClient sessionClient = null; IMessageReceiver receiver = null; if (_isSessionsEnabled) { sessionClient = _sessionClient.Value; } else { receiver = Receiver; } Task.Run(async() => { while (true) { try { if (!_started || cancellationToken.IsCancellationRequested) { _logger.LogInformation("Message processing has been stopped or cancelled"); return; } if (_isSessionsEnabled && (receiver == null || receiver.IsClosedOrClosing)) { try { receiver = await sessionClient.AcceptMessageSessionAsync(); receiver.PrefetchCount = _serviceBusOptions.PrefetchCount; } catch (ServiceBusTimeoutException) { // it's expected if the entity is empty, try next time continue; } } IList <Message> messages = await receiver.ReceiveAsync(_serviceBusOptions.BatchOptions.MaxMessageCount, _serviceBusOptions.BatchOptions.OperationTimeout); if (messages != null) { Message[] messagesArray = messages.ToArray(); ServiceBusTriggerInput input = ServiceBusTriggerInput.CreateBatch(messagesArray); input.MessageReceiver = receiver; FunctionResult result = await _triggerExecutor.TryExecuteAsync(input.GetTriggerFunctionData(), cancellationToken); if (cancellationToken.IsCancellationRequested) { return; } // Complete batch of messages only if the execution was successful if (_serviceBusOptions.BatchOptions.AutoComplete && _started) { if (result.Succeeded) { await receiver.CompleteAsync(messagesArray.Select(x => x.SystemProperties.LockToken)); } else { List <Task> abandonTasks = new List <Task>(); foreach (var lockTocken in messagesArray.Select(x => x.SystemProperties.LockToken)) { abandonTasks.Add(receiver.AbandonAsync(lockTocken)); } await Task.WhenAll(abandonTasks); } } } else { // Close the session and release the session lock after draining all messages for the accepted session. if (_isSessionsEnabled) { await receiver.CloseAsync(); } } } catch (ObjectDisposedException) { // Ignore as we are stopping the host } catch (Exception ex) { // Log another exception _logger.LogError($"An unhandled exception occurred in the message batch receive loop", ex); if (_isSessionsEnabled && receiver != null) { // Attempt to close the session and release session lock to accept a new session on the next loop iteration try { await receiver.CloseAsync(); } catch { // Best effort receiver = null; } } } } }, cancellationToken); }
internal void StartMessageBatchReceiver(CancellationToken cancellationToken) { SessionClient sessionClient = null; IMessageReceiver receiver = null; if (_isSessionsEnabled) { sessionClient = _messagingProvider.CreateSessionClient(_entityPath, _serviceBusAccount.ConnectionString); } else { receiver = Receiver; } Task.Run(async() => { while (true) { try { if (!_started || cancellationToken.IsCancellationRequested) { return; } if (_isSessionsEnabled) { try { receiver = await sessionClient.AcceptMessageSessionAsync(); } catch (ServiceBusTimeoutException) { // it's expected if the entity is empty, try next time continue; } } IList <Message> messages = await receiver.ReceiveAsync(_serviceBusOptions.BatchOptions.MaxMessageCount, _serviceBusOptions.BatchOptions.OperationTimeout); if (messages != null) { Message[] messagesArray = messages.ToArray(); ServiceBusTriggerInput input = ServiceBusTriggerInput.CreateBatch(messagesArray); input.MessageReceiver = receiver; FunctionResult result = await _triggerExecutor.TryExecuteAsync(input.GetTriggerFunctionData(), cancellationToken); if (cancellationToken.IsCancellationRequested) { return; } // Complete batch of messages only if the execution was successful if (_serviceBusOptions.BatchOptions.AutoComplete && _started) { if (result.Succeeded) { await receiver.CompleteAsync(messagesArray.Select(x => x.SystemProperties.LockToken)); } else { // Delivery count is not incremented if // Session is accepted, the messages within the session are not completed (even if they are locked), and the session is closed // https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-sessions#impact-of-delivery-count if (_isSessionsEnabled) { List <Task> abandonTasks = new List <Task>(); foreach (var lockTocken in messagesArray.Select(x => x.SystemProperties.LockToken)) { abandonTasks.Add(receiver.AbandonAsync(lockTocken)); } await Task.WhenAll(abandonTasks); } } } // Close the session and release the session lock if (_isSessionsEnabled) { await receiver.CloseAsync(); } } } catch (ObjectDisposedException) { // Ignore as we are stopping the host } catch (Exception ex) { // Log another exception _logger.LogError($"An unhandled exception occurred in the message batch receive loop: {ex.ToString()}"); } } }, cancellationToken); }
public void Start(QueueReaderSettings config, ActiveQueueContext context) { _receiver = new MessageReceiver( new ServiceBusConnection(config.ConnectionString), config.QueueName, prefetchCount: PrefetchCount ); _receiverTokenSource = new CancellationTokenSource(); var completeTime = DateTime.UtcNow; _receiverTask = Task.Run(async() => { while (!_receiverTokenSource.IsCancellationRequested) { var receiveTime = DateTime.UtcNow; context.OnMeasure("AzureCTime", (receiveTime - completeTime).TotalMilliseconds); IList <Message> messages; try { messages = await _receiver.ReceiveAsync(MaxMessageCount); if (messages == null || messages.Count == 0) { continue; } } catch (Exception ex) { context.OnError($"AzureActiveQueue - exception received: {ex}"); try { await Task.Delay(TimeoutOnException, _receiverTokenSource.Token); } catch (OperationCanceledException) { // ignore } continue; } var processTime = DateTime.UtcNow; context.OnMeasure("AzureRTime", (processTime - receiveTime).TotalMilliseconds); context.OnMeasure("AzureBSize", messages.Count); var lockTokens = messages.Select(x => x.SystemProperties.LockToken); var completeMessagesTask = _receiver.CompleteAsync(lockTokens); foreach (var message in messages) { Event msg = null; try { msg = Event.Parser.ParseFrom(message.Body); } catch (Exception) { // ToDo: remove temporal fallback try { var buf = message.GetBody <byte[]>(); msg = Event.Parser.ParseFrom(buf); } catch (Exception ex) { context.OnError($"AzureActiveQueue - not able to handle message: {ex}"); } if (msg != null) { var curDate = DateTime.UtcNow; var name = $"{msg.Source}::{msg.Instance}"; if (!_fallbacks.TryGetValue(name, out var date) || (curDate - date).TotalMinutes > 30) { context.OnVerbose($"[AzureActiveQueue] {name} used obsolete xml serialized Event"); _fallbacks[name] = curDate; } } } if (msg != null) { context.OnReceivedMessage(msg); } } completeTime = DateTime.UtcNow; context.OnMeasure("AzurePTime", (completeTime - processTime).TotalMilliseconds); try { await completeMessagesTask; } catch (Exception ex) { context.OnError($"Failed to complete messages: {ex}"); } } }); }
internal async Task OnMessageAsyncUnregisterHandlerShortTimeoutTestCase( IMessageSender messageSender, IMessageReceiver messageReceiver, int maxConcurrentCalls, bool autoComplete, int messageCount) { var count = 0; await TestUtility.SendMessagesAsync(messageSender, messageCount); messageReceiver.RegisterMessageHandler( async(message, token) => { TestUtility.Log($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber}"); await Task.Delay(TimeSpan.FromSeconds(8)); if (messageReceiver.ReceiveMode == ReceiveMode.PeekLock && !autoComplete) { await messageReceiver.CompleteAsync(message.SystemProperties.LockToken); } Interlocked.Increment(ref count); }, new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = maxConcurrentCalls, AutoComplete = autoComplete }); await messageReceiver.UnregisterMessageHandlerAsync(TimeSpan.FromSeconds(2)); Assert.True(count == 0); // Reregister won't have any problems count = 0; var remainingMessageCount = messageCount - maxConcurrentCalls; messageReceiver.RegisterMessageHandler( async(message, token) => { TestUtility.Log($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber}"); if (messageReceiver.ReceiveMode == ReceiveMode.PeekLock && !autoComplete) { await messageReceiver.CompleteAsync(message.SystemProperties.LockToken); } Interlocked.Increment(ref count); }, new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = maxConcurrentCalls, AutoComplete = autoComplete }); var stopwatch = Stopwatch.StartNew(); while (stopwatch.Elapsed.TotalSeconds <= 60) { if (count == remainingMessageCount) { TestUtility.Log($"All '{remainingMessageCount}' messages Received."); break; } await Task.Delay(TimeSpan.FromSeconds(5)); } Assert.True(count == remainingMessageCount); }
public void Complete(string lockToken) { _messageReceiver.CompleteAsync(lockToken).Wait(); }
internal static async Task CompleteMessagesAsync(IMessageReceiver messageReceiver, IList <Message> messages) { await messageReceiver.CompleteAsync(messages.Select(message => message.SystemProperties.LockToken)); Log($"Completed {messages.Count} messages"); }
public override Task CompleteAsync( IQueueMessage message, CancellationToken cancellationToken = default(CancellationToken)) { return(_messageReceiver.CompleteAsync(message.LeaseId)); }