private async Task ProcessMessagesAsync(Message message, CancellationToken token) { // Deserialize the message to get the original json sent to the producer api var simpleMessage = JsonConvert.DeserializeObject <SimpleMessage>(Encoding.UTF8.GetString(message.Body)); //await _processData.Process(simpleMessage); // decide what to communicate back to the service bus switch (simpleMessage.MessageType) { case SimpleMessageType.Complete: await subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); telemetryClient.TrackTrace($"Message with id {message.MessageId} successfully processed"); break; case SimpleMessageType.SendToDlq: await subscriptionClient.DeadLetterAsync(message.SystemProperties.LockToken); telemetryClient.TrackTrace($"Message with id {message.MessageId} sent to DLQ"); break; case SimpleMessageType.Error: // increments the delivery count throw new InvalidOperationException("Cannot process message"); default: // increments the delivery count await subscriptionClient.AbandonAsync(message.SystemProperties.LockToken); telemetryClient.TrackTrace($"Message with id {message.MessageId} abandoned. Retrying shortly..."); break; } }
private static async Task ReceiveMessages_FromTopicSubscriptionsAsync(SubscriptionClient client, CancellationToken token, Color color) { var doneReceiving = new TaskCompletionSource <bool>(); token.Register( async() => { await client.CloseAsync(); doneReceiving.SetResult(true); } ); client.RegisterMessageHandler( async(message, token1) => { try { if (ProcessMessages(message, color)) { await client.CompleteAsync(message.SystemProperties.LockToken); } else { await client.DeadLetterAsync(message.SystemProperties.LockToken, "Message is of the wrong type", "Cannot deserialize this message as the type in the Label prop is unknown."); } } catch (Exception ex) { Log.Error($"[{message.MessageId}] -- {ex.Message}"); } }, GetDefaultMessageHandlingOptions()); await doneReceiving.Task; }
private async Task MessageReceived(Microsoft.Azure.ServiceBus.Message message, CancellationToken cancelationToken) { try { using (var compressedStream = new MemoryStream(message.Body)) using (var decompressorStream = new DeflateStream(compressedStream, CompressionMode.Decompress)) { using (var decompressedStream = new MemoryStream()) { decompressorStream.CopyTo(decompressedStream); await ReceiveAsync(new Request(decompressedStream.ToArray())); await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); } } } catch (Exception ex) { Console.WriteLine($"{ex.GetType().Name}: {ex.Message}"); Console.WriteLine(ex.StackTrace); await _subscriptionClient.DeadLetterAsync(message.SystemProperties.LockToken, ex.GetType().FullName, ex.Message); throw; } }
private async Task OnMessageAsync(Message brokeredMessage, CancellationToken cancellationToken) { if (_subscribers.IsEmpty) { return; } if (_logger.IsEnabled(LogLevel.Trace)) { _logger.LogTrace("Received message: {MessageId} :{SequenceNumber}", brokeredMessage.MessageId, brokeredMessage.SystemProperties.SequenceNumber); } MessageBusData message; try { message = _serializer.Deserialize <MessageBusData>(brokeredMessage.Body); } catch (Exception ex) { if (_logger.IsEnabled(LogLevel.Warning)) { _logger.LogWarning(ex, "OnMessageAsync({MessageId}) Error deserializing messsage: {Message}", brokeredMessage.MessageId, ex.Message); } // A lock token can be found in LockToken, only when ReceiveMode is set to PeekLock await _subscriptionClient.DeadLetterAsync(brokeredMessage.SystemProperties.LockToken).AnyContext(); return; } if (_options.ReceiveMode == ReceiveMode.PeekLock && _options.AutoComplete == false) { await _subscriptionClient.CompleteAsync(brokeredMessage.SystemProperties.LockToken).AnyContext(); } await SendMessageToSubscribersAsync(message, _serializer).AnyContext(); }
private async Task ProcessMessagesAsync(Message message, CancellationToken cancellationToken) { try { var messageBody = Encoding.UTF8.GetString(message.Body); _logger.LogDebug($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber} Body: {messageBody}"); var user = System.Text.Json.JsonSerializer.Deserialize <AzureActiveDirectoryUser>(messageBody); await _messageProcessor.ProcessUser(user); if (!cancellationToken.IsCancellationRequested && !_subscriptionClient.IsClosedOrClosing && message.SystemProperties.IsLockTokenSet) { await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); } } catch (Exception ex) { var msg = $"Exception when processing message: {Encoding.UTF8.GetString(message.Body)}, sending message to DeadLetter. StackTrace: {ex.StackTrace}"; _logger.LogError(ex, msg); if (!_subscriptionClient.IsClosedOrClosing && message.SystemProperties.IsLockTokenSet) { await _subscriptionClient.DeadLetterAsync(message.SystemProperties.LockToken, msg); } } }
protected virtual async Task TryReceiveAsync( BrokeredMessage message, Action <IDeliveryContext> callback) { try { Log.Verbose($"Translating wire-specific message into channel message for channel {_identifier}."); CurrentMessage = _configuration.MessageAdapter.Build(message); Log.Info($"Routing message '{message.MessageId}' received through group '{_configuration.GroupName}' to configured receiver callback on channel {_identifier}."); callback(this); // Signal message processing as having completed. await _subscriptionClient .CompleteAsync(message.LockToken) .ConfigureAwait(false); } catch (ChannelConnectionException) { Log.Warn($"Channel {_identifier} has become unavailable, aborting."); throw; } catch (PoisonMessageException) { Log.Warn($"Wire message {message.MessageId} on channel {_identifier} could not be deserialized; forwarding to poison message exchange."); await _subscriptionClient .DeadLetterAsync(message.LockToken) .ConfigureAwait(false); } catch (DeadLetterException e) { var seconds = (SystemTime.UtcNow - e.Expiration).TotalSeconds; Log.Info($"Wire message {message.MessageId} on channel {_identifier} expired on the wire {seconds:n3} seconds ago; forwarding to dead letter exchange."); await _subscriptionClient .DeadLetterAsync(message.LockToken) .ConfigureAwait(false); } catch (Exception) { } }
private static async Task ReceiveMessages_FromTopicSessionStateSubscriptionsAsync(SubscriptionClient client, CancellationToken token, ConsoleColor color, int EndCount) { var doneReceiving = new TaskCompletionSource <bool>(); token.Register( async() => { await client.CloseAsync(); doneReceiving.SetResult(true); }); client.RegisterSessionHandler( async(session, message, token1) => { try { var stateData = await session.GetStateAsync(); var session_state = stateData != null ? Utils.Deserialize <SessionStateManager>(stateData) : new SessionStateManager(); if ((int)message.UserProperties["Count"] == session_state.LastProcessedCount + 1) //check if message is next in the sequence { if (ProcessMessages(message, Color.White)) { await session.CompleteAsync(message.SystemProperties.LockToken); if (((int)message.UserProperties["Count"]) == EndCount) { //end of the session await session.CloseAsync(); } } else { await client.DeadLetterAsync(message.SystemProperties.LockToken, "Message is of the wrong type", "Cannot deserialize this message as the type in the Labl prop is uknown."); } } else { session_state.DeferredList.Add((int)message.UserProperties["Count"], message.SystemProperties.SequenceNumber); await session.DeferAsync(message.SystemProperties.LockToken); await session.SetStateAsync(Utils.Serialize <SessionStateManager>(session_state)); } long last_processed = await ProcessNextMessagesWithSessionStateAsync(client, session, session_state, EndCount, color); } catch (Exception ex) { Log.Error("Unable to receive {0} from subscription: Exception {1}", message.MessageId, ex); } }, GetDefaultSessionHandlingOptions()); await doneReceiving.Task; }
/// <summary> /// Calls .DeadLetter explicitly /// </summary> public async Task DeadLetterAsync(QueueMessage message, string reason, string errorDescription) { if (!_peekLock) { return; } if (!_messageIdToBrokeredMessage.TryRemove(message.Id, out Message bm)) { return; } await _client.DeadLetterAsync(bm.MessageId); }
async Task ReceiveMessagesAsync(string connectionString, string topicName, string subscriptionName, CancellationToken cancellationToken, ConsoleColor color) { // var subscriptionPath = SubscriptionClient.FormatSubscriptionPath(topicName, subscriptionName); //var receiver = new MessageReceiver(connectionString,subscriptionPath, ReceiveMode.PeekLock); var receiver = new SubscriptionClient(connectionString, topicName, subscriptionName); System.Diagnostics.Debug.WriteLine("output1"); var doneReceiving = new TaskCompletionSource <bool>(); // close the receiver and factory when the CancellationToken fires cancellationToken.Register( async() => { await receiver.CloseAsync(); doneReceiving.SetResult(true); }); System.Diagnostics.Debug.WriteLine("output2"); // register the RegisterMessageHandler callback receiver.RegisterMessageHandler( async(message, cancellationToken) => { if (message.Label != null && message.ContentType != null && message.Label.Equals("Scientist", StringComparison.InvariantCultureIgnoreCase) && message.ContentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase)) { var body = message.Body; dynamic scientist = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(body)); string name = scientist.test; await receiver.CompleteAsync(message.SystemProperties.LockToken); } else { await receiver.DeadLetterAsync(message.SystemProperties.LockToken); //, "ProcessingError", "Don't know what to do with this message"); } }, new MessageHandlerOptions((e) => LogMessageHandlerException(e)) { AutoComplete = false, MaxConcurrentCalls = 1 }); await doneReceiving.Task; }
private static async Task OnMessageReceived(Message message, CancellationToken token) { string messageText = Encoding.UTF8.GetString(message.Body); if (messageText.Contains("deadletter")) { await _subscriptionClient.DeadLetterAsync(message.SystemProperties.LockToken, "Invalid message", "We cannot process the incoming message"); } else { Console.WriteLine($"[*] {messageText}"); await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); } }
private static async Task <long> ProcessNextMessagesWithSessionStateAsync(SubscriptionClient client, IMessageSession session, SessionStateManager session_state, ConsoleColor color) { int x = session_state.LastProcessedCount + 1; long seq2 = 0; while (true) { if (!session_state.DeferredList.TryGetValue(x, out seq2)) { break; } //------------------------------- var deferredMessage = await session.ReceiveDeferredMessageAsync(seq2); if (ProcessMessages(deferredMessage, color)) { await session.CompleteAsync(deferredMessage.SystemProperties.LockToken); if (deferredMessage.UserProperties["IsLast"].ToString().ToLower() == "true") { //end of the session await session.SetStateAsync(null); await session.CloseAsync(); } else { session_state.LastProcessedCount = ((int)deferredMessage.UserProperties["Order"]); session_state.DeferredList.Remove(x); await session.SetStateAsync(Serialize <SessionStateManager>(session_state)); } } else { await client.DeadLetterAsync(deferredMessage.SystemProperties.LockToken, "Message is of the wrong type or could not be processed", "Cannot deserialize this message as the type is unknown."); session_state.DeferredList.Remove(x); await session.SetStateAsync(Serialize <SessionStateManager>(session_state)); } //------------------------------ x++; } return(seq2); }
private static async Task <long> ProcessNextMessagesWithSessionStateAsync(SubscriptionClient client, IMessageSession session, SessionStateManager session_state, int EndOfSessionCount, ConsoleColor color) { int x = session_state.LastProcessedCount + 1; long seq2 = 0; if (session_state.DeferredList.TryGetValue(x, out long seq1)) { while (true) { if (!session_state.DeferredList.TryGetValue(x, out seq2)) { break; } //------------------------------- var deferredMessage = await session.ReceiveDeferredMessageAsync(seq2); if (ProcessMessages(deferredMessage, Color.White)) { await session.CompleteAsync(deferredMessage.SystemProperties.LockToken); session_state.LastProcessedCount = ((int)deferredMessage.UserProperties["Count"]); session_state.DeferredList.Remove(x); await session.SetStateAsync(Utils.Serialize <SessionStateManager>(session_state)); } else { await client.DeadLetterAsync(deferredMessage.SystemProperties.LockToken, "Message is of the wrong type", "Cannot deserialize this message as the type in the Label prop is unknown."); session_state.DeferredList.Remove(x); await session.SetStateAsync(Utils.Serialize <SessionStateManager>(session_state)); } //------------------------------ x++; } } return(seq2); }
private static async Task ReceiveMessages_FromTopicSessionSubscriptionsAsync(SubscriptionClient client, CancellationToken token, ConsoleColor color, int EndCount) { var doneReceiving = new TaskCompletionSource <bool>(); token.Register( async() => { await client.CloseAsync(); doneReceiving.SetResult(true); }); client.RegisterSessionHandler( async(session, message, token1) => { try { Utils.ConsoleWrite($"[{message.SessionId}]\n", ConsoleColor.Blue, ConsoleColor.Red); if (ProcessMessages(message, Color.White)) { await session.CompleteAsync(message.SystemProperties.LockToken); if (((int)message.UserProperties["Count"]) == EndCount) { //end of the session await session.CloseAsync(); } } else { await client.DeadLetterAsync(message.SystemProperties.LockToken, "Message is of the wrong type", "Cannot deserialize this message as the type in the Label prop is unknown."); } } catch (Exception ex) { Log.Error("Unable to receive {0} from subscription: Exception {1}", message.MessageId, ex); } }, GetDefaultSessionHandlingOptions()); await doneReceiving.Task; }
private Task OnMessageAsync(Message brokeredMessage, CancellationToken cancellationToken) { if (_subscribers.IsEmpty) { return(Task.CompletedTask); } _logger.LogTrace("OnMessageAsync({messageId})", brokeredMessage.MessageId); MessageBusData message; try { message = _serializer.Deserialize <MessageBusData>(brokeredMessage.Body); } catch (Exception ex) { _logger.LogWarning(ex, "OnMessageAsync({0}) Error deserializing messsage: {1}", brokeredMessage.MessageId, ex.Message); return(_subscriptionClient.DeadLetterAsync(brokeredMessage.SystemProperties.LockToken, "Deserialization error", ex.Message)); } SendMessageToSubscribers(message, _serializer); return(Task.CompletedTask); }
public async Task <ServedDrink> GetNextDrinkAsync(string customerName) { var client = new SubscriptionClient(BarTopicCnBuilder, customerName); string body = null; client.RegisterMessageHandler(async(msg, token) => { Message message = msg; if (message != null) { body = Encoding.UTF8.GetString(message.Body); if (body.Contains("spoiled", StringComparison.OrdinalIgnoreCase)) { await client.DeadLetterAsync(msg.SystemProperties.LockToken); } else { await client.CompleteAsync(msg.SystemProperties.LockToken); } } }, new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = 1, AutoComplete = false }); await client.UnregisterMessageHandlerAsync(TimeSpan.FromMilliseconds(2000)); await client.CloseAsync(); if (body != null) { return(JsonSerializer.Deserialize <ServedDrink>(body)); } return(default);
private async Task MessageReceived(Microsoft.Azure.ServiceBus.Message message, CancellationToken cancelationToken) { try { using (var compressedStream = new MemoryStream(message.Body)) using (var decompressorStream = new DeflateStream(compressedStream, CompressionMode.Decompress)) { using (var decompressedStream = new MemoryStream()) { decompressorStream.CopyTo(decompressedStream); /* * it is possible that this may not be the client that asked for the RPC request * but it could be the one that consumed the message. If this is the case the * asyn coupler will say, nope I didn't ask for this and will not processe it. * return it back to the pool to see if another client can handle it. */ if ((await ReceiveAsync(new Response(decompressedStream.ToArray()))).Successful) { await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); } else { await _subscriptionClient.AbandonAsync(message.SystemProperties.LockToken); } } } } catch (Exception ex) { message.Label = ex.Message; await _subscriptionClient.DeadLetterAsync(message.SystemProperties.LockToken, ex.GetType().FullName, ex.Message); throw; } }
/// <summary> /// Method created to connect and process the Topic/Subscription in the azure. /// </summary> /// <returns></returns> private void ProcessSubscription() { try { foreach (var topic in _topics) { MethodInfo method = GetMethod(topic); string topicName = topic.Value.TopicName; string subscriptName = topic.Value.Subscription; ReceiveMode receiveMode = ReceiveMode.PeekLock; if (topic.Value.DeleteAfterRead) { receiveMode = ReceiveMode.ReceiveAndDelete; } int takeQuantity = topic.Value.TakeQuantity; //Register Trace on the telemetry SubscriptionClient subscriptionClient = new SubscriptionClient(GetConnection(topic), topicName, subscriptName, receiveMode, null); //Register the method to process receive message //The RegisterMessageHandler is validate for all register exist on the queue, without need loop for items subscriptionClient.RegisterMessageHandler( async(message, cancellationToken) => { try { InvokeProcess(method, message.Body); await subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); } catch (Exception exRegister) { Exception moreInfo = new Exception($"Exception reading message from topic {topicName} and subscriptName {subscriptName}. See inner exception for details. Message={exRegister.Message}", exRegister); //Use the class instead of interface because tracking exceptions directly is not supposed to be done outside AMAW (i.e. by the business code) Workbench.Instance.Telemetry.TrackException(moreInfo); var exceptionDetails = $"{exRegister.Message}"; //If there is a business error or a invlida input, set DeadLetter on register if (subscriptionClient.ReceiveMode == ReceiveMode.PeekLock) { if (exRegister.InnerException != null) { exceptionDetails = $"{exceptionDetails} \n {exRegister.InnerException?.Message}"; if (exRegister.InnerException is InvalidInputException) { var inputErrors = (exRegister.InnerException as InvalidInputException).InputErrors; string jsonString = (new { critics = inputErrors }).ToStringCamelCase(); exceptionDetails = $"{exceptionDetails} \n {jsonString}"; //This operation is only allowed PeekLock await subscriptionClient.DeadLetterAsync(message.SystemProperties.LockToken, exceptionDetails, $"{exRegister.StackTrace}"); } if (exRegister.InnerException is BusinessValidationException) { var inputErrors = (exRegister.InnerException as BusinessValidationException).InputErrors; string jsonString = (new { critics = inputErrors }).ToStringCamelCase(); exceptionDetails = $"{exceptionDetails} \n {jsonString}"; //This operation is only allowed PeekLock await subscriptionClient.DeadLetterAsync(message.SystemProperties.LockToken, exceptionDetails, $"{exRegister.StackTrace}"); } } } } }, new MessageHandlerOptions((e) => ExceptionReceivedHandler(e)) { AutoComplete = false, MaxConcurrentCalls = takeQuantity }); } } catch (Exception exception) { Exception moreInfo = new Exception($"Error setting up subscription consumption from service bus. See inner exception for details. Message={exception.Message}", exception); //Use the class instead of interface because tracking exceptions directly is not supposed to be done outside AMAW (i.e. by the business code) Workbench.Instance.Telemetry.TrackException(moreInfo); } }
async Task ReceiveMessagesAsync(string connectionString, string topicName, string subscriptionName, CancellationToken cancellationToken, ConsoleColor color) { // var subscriptionPath = SubscriptionClient.FormatSubscriptionPath(topicName, subscriptionName); //var receiver = new MessageReceiver(connectionString,subscriptionPath, ReceiveMode.PeekLock); var receiver = new SubscriptionClient(connectionString, topicName, subscriptionName); var doneReceiving = new TaskCompletionSource <bool>(); // close the receiver and factory when the CancellationToken fires cancellationToken.Register( async() => { await receiver.CloseAsync(); doneReceiving.SetResult(true); }); // register the RegisterMessageHandler callback receiver.RegisterMessageHandler( async(message, cancellationToken1) => { if (message.Label != null && message.ContentType != null && message.Label.Equals("Scientist", StringComparison.InvariantCultureIgnoreCase) && message.ContentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase)) { var body = message.Body; dynamic scientist = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(body)); lock (Console.Out) { Console.ForegroundColor = color; Console.WriteLine( "\t\t\t\tMessage received: \n\t\t\t\t\t\tMessageId = {0}, \n\t\t\t\t\t\tSequenceNumber = {1}, \n\t\t\t\t\t\tEnqueuedTimeUtc = {2}," + "\n\t\t\t\t\t\tExpiresAtUtc = {5}, \n\t\t\t\t\t\tContentType = \"{3}\", \n\t\t\t\t\t\tSize = {4}, \n\t\t\t\t\t\tContent: [ firstName = {6}, name = {7} ]", message.MessageId, message.SystemProperties.SequenceNumber, message.SystemProperties.EnqueuedTimeUtc, message.ContentType, message.Size, message.ExpiresAtUtc, scientist.firstName, scientist.name); Console.ResetColor(); } await receiver.CompleteAsync(message.SystemProperties.LockToken); } else { await receiver.DeadLetterAsync(message.SystemProperties.LockToken); //, "ProcessingError", "Don't know what to do with this message"); } }, new MessageHandlerOptions((e) => LogMessageHandlerException(e)) { AutoComplete = false, MaxConcurrentCalls = 1 }); await doneReceiving.Task; }
public async Task FailedAckAsync(MessageReceived <string> message, CancellationToken token = default) { await subscriptionClient.DeadLetterAsync(message.PopReceipt); }
private async Task ReceiveMessages_FromTopicSessionStateSubscriptionsAsync(SubscriptionClient client, CancellationToken token, ConsoleColor color) { var doneReceiving = new TaskCompletionSource <bool>(); token.Register( async() => { await client.CloseAsync(); doneReceiving.SetResult(true); }); client.RegisterSessionHandler( async(session, message, token1) => { try { var stateData = await session.GetStateAsync(); var session_state = stateData != null ? Deserialize <SessionStateManager>(stateData) : new SessionStateManager(); if ((int)message.UserProperties["Order"] == session_state.LastProcessedCount + 1) //check if message is next in the sequence { if (ProcessMessages(message, color)) { await session.CompleteAsync(message.SystemProperties.LockToken); session_state.LastProcessedCount = ((int)message.UserProperties["Order"]); await session.SetStateAsync(Serialize <SessionStateManager>(session_state)); if (message.UserProperties["IsLast"].ToString().ToLower() == "true") { //end of the session await session.SetStateAsync(null); await session.CloseAsync(); } } else { await client.DeadLetterAsync(message.SystemProperties.LockToken, "Message is of the wrong type or could not be processed", "Cannot deserialize this message as the type is unknown."); } } else { session_state.DeferredList.Add((int)message.UserProperties["Order"], message.SystemProperties.SequenceNumber); await session.DeferAsync(message.SystemProperties.LockToken); await session.SetStateAsync(Serialize(session_state)); } long last_processed = await ProcessNextMessagesWithSessionStateAsync(client, session, session_state, color); } catch (Exception ex) { Console.WriteLine("-->> ERROR : Unable to receive {0} from subscription: Exception {1}", message.MessageId, ex); } }, new SessionHandlerOptions(e => LogMessageHandlerException(e)) { MessageWaitTimeout = TimeSpan.FromSeconds(5), MaxConcurrentSessions = 1, AutoComplete = false }); await doneReceiving.Task; }