private void TryHandleMessageInner(SqlTransaction transaction, ServiceBrokerMessage message) { // Only handle transport messages if (message.MessageTypeName != ServiceBrokerMessageType && !message.IsDialogTimerMessage()) { logger.Debug("Ignoring message of type {0} from queue {1}", message.MessageTypeName, ServiceBrokerQueue); return; // ignore } IncomingTransportMessage transportMessage = null; try { if (message.IsDialogTimerMessage()) { //transportMessage = TryLoadDialogTimerTimeoutMessage(transaction, message); throw new NotImplementedException(); } else { transportMessage = TryDeserializeTransportMessage(message); } if (!transportMessage.Headers.ContainsKey(StandardHeaders.OriginatingAddress)) { transportMessage.Headers[StandardHeaders.OriginatingAddress] = ServiceBrokerWrapper.TryGetConversationFarService(transaction, message.ConversationHandle); } Exception lastException = null; if (faultManager.HasMaxRetriesExceeded(transportMessage, out lastException)) { logger.Debug("MaxRetriesExceeded: Moving message {0} from queue {1} to poison message table.", message.ConversationHandle.ToString(), ServiceBrokerQueue); MoveToPoisonMessage(transaction, message, transportMessage, lastException, "MaxRetriesExceeded", MaxRetries); return; // return without error to commit transaction } logger.Debug("Notifying observers of new TransportMessage for message {0} from queue {1}.", message.ConversationHandle, ServiceBrokerQueue); this.MessageAvailable?.Invoke(this, new MessageAvailableEventArgs(transportMessage)); } catch (CannotDeserializeMessageException e) { // If we can't deserialize the transport message or inner message, there is no reason to retry. // note: error is already logged so we don't need to log here logger.Debug("DeserializeError: Moving message {0} from queue {1} to poison message table.", message.ConversationHandle.ToString(), ServiceBrokerQueue); MoveToPoisonMessage(transaction, message, transportMessage, e, "DeserializeError", 0); return; // return without error to commit transaction } }
private void TryHandleMessage(object message) { var messageID = MessageId(message).ToString(); logger.Debug("Received message {0} from queue {1}", messageID, QueueName); // NOTE this method _should not_ throw an exception! try { var transportMessage = new IncomingTransportMessage(messageID, new Dictionary <string, string>(), message); Exception lastException = null; if (faultManager.HasMaxRetriesExceeded(transportMessage, out lastException)) { logger.Debug("MaxRetriesExceeded. Will not re-enque.", messageID.ToString(), QueueName); OnPoisonMessageDetected(new PoisonMessageDetectedEventArgs() { QueueName = QueueName, Retries = MaxRetries, Exception = lastException, MessageId = messageID, ErrorCode = "MaxRetriesExceeded", }); return; // return without error to commit transaction } logger.Debug("Notifying observers of new TransportMessage for message {0} from queue {1}.", messageID.ToString(), QueueName); OnMessageAvailable(transportMessage); faultManager.ClearFailuresForMessage(messageID); logger.Debug("Committed message {0} from queue {1}", messageID.ToString(), QueueName); } catch (Exception e) { faultManager.IncrementFailuresForMessage(messageID.ToString(), e); logger.Error(e, "Exception caught handling message {0} from queue {1}. Re-enqueing.", messageID, QueueName); Thread.Sleep(1000); // TODO possibly implement a backoff with the fault manager based on number of retries? queue.Enqueue(message); queueNotifier.Set(); } }
private void TryHandleMessage(ReceiverLink receiverLink, Message amqpMessage) { // NOTE this method _should not_ throw an exception! var threadName = receiverLink.Name; var messageID = amqpMessage.Properties?.MessageId ?? "?"; try { logger.Debug("{0}: Received Message with MessageId={1}", threadName, messageID); var headers = new Dictionary <string, string>(); if (amqpMessage.ApplicationProperties != null) { foreach (var key in amqpMessage.ApplicationProperties.Map.Keys) { headers[key.ToString()] = amqpMessage.ApplicationProperties.Map[key].ToString(); } } object message = null; try { message = DecodeMessage(amqpMessage); } catch (Exception e) { logger.Error(e, "{0}: Cannot Decode Message. Will not re-enqueue.", threadName); OnPoisonMessageDetected(new PoisonMessageDetectedEventArgs() { QueueName = ReceiverLinkAddress, Retries = MaxRetries, Exception = e, MessageId = messageID, ErrorCode = "DecodeException", }); } if (message != null) { var transportMessage = new IncomingTransportMessage(messageID, headers, message); Exception lastException = null; if (faultManager.HasMaxRetriesExceeded(transportMessage, out lastException)) { logger.Error(lastException, "{0}: MaxRetriesExceeded for MessageId={1}. Will not re-enqueue.", threadName, messageID.ToString()); OnPoisonMessageDetected(new PoisonMessageDetectedEventArgs() { QueueName = ReceiverLinkAddress, Retries = MaxRetries, Exception = lastException, MessageId = messageID, ErrorCode = "MaxRetriesExceeded", }); } else { logger.Debug("{0}: Notifying observers of new TransportMessage for MessageId={1}.", threadName, messageID.ToString()); OnMessageAvailable(transportMessage); faultManager.ClearFailuresForMessage(messageID); } } receiverLink.Accept(amqpMessage); logger.Debug("{0}: Accepting MessageId={1}", threadName, messageID.ToString()); } catch (Exception e) { faultManager.IncrementFailuresForMessage(messageID.ToString(), e); receiverLink.Reject(amqpMessage); logger.Error(e, "{0}: Exception caught handling MessageId={1}. Rejecting.", threadName, messageID.ToString()); Thread.Sleep(1000); // TODO possibly implement a backoff with the fault manager based on number of retries? } }