// Handle poison message exception by moving the poison message out of the way for regular processing to continue. public bool HandleError(Exception error) { MsmqPoisonMessageException poisonException = error as MsmqPoisonMessageException; if (null != poisonException) { long lookupId = poisonException.MessageLookupId; Console.WriteLine(" Poisoned message -message look up id = {0}", lookupId); // Get MSMQ queue name from app settings in configuration. System.Messaging.MessageQueue orderQueue = new System.Messaging.MessageQueue(OrderProcessorService.QueueName); System.Messaging.MessageQueue poisonMessageQueue = new System.Messaging.MessageQueue(OrderProcessorService.PoisonQueueName); System.Messaging.Message message = null; // Use a new transaction scope to remove the message from the main app queue and add it to the poison queue // the poison message service processes messages from the poison queue. using (TransactionScope txScope = new TransactionScope(TransactionScopeOption.RequiresNew)) { int retryCount = 0; while (retryCount < 3) { retryCount++; try { // Look up the poison message using the look up id. message = orderQueue.ReceiveByLookupId(lookupId); if (message != null) { // send the message to the poison message queue. poisonMessageQueue.Send(message, System.Messaging.MessageQueueTransactionType.Automatic); // complete transaction scope txScope.Complete(); Console.WriteLine("Moved poisoned message with look up id: {0} to poison queue: {1} ", lookupId, OrderProcessorService.PoisonQueueName); break; } } catch (InvalidOperationException) { //Code for the case when the message may still not be available in the queue because of a race condition in the transaction or //another node in the farm may actually have taken the message. if (retryCount < 3) { Console.WriteLine("Trying to move poison message but message is not available, sleeping for 10 seconds before retrying"); Thread.Sleep(TimeSpan.FromSeconds(10)); } else { Console.WriteLine("Giving up on trying to move the message"); } } } } // restart service host Console.WriteLine(); Console.WriteLine("Restarting the service to process rest of the messages in the queue"); Console.WriteLine("Press <ENTER> to stop the service"); ThreadPool.QueueUserWorkItem(orderProcessingCallback); return(true); } return(false); }
// Handle poison message exception by moving the offending message out of the way for regular processing to go on. public bool HandleError(Exception error) { MsmqPoisonMessageException poisonException = error as MsmqPoisonMessageException; if (null != poisonException) { long lookupId = poisonException.MessageLookupId; Console.WriteLine(" Poisoned message -message look up id = {0}", lookupId); // Get MSMQ queue name from app settings in configuration. System.Messaging.MessageQueue orderQueue = new System.Messaging.MessageQueue(Poisoned.WcfService.Properties.Settings.Default.QueueName); System.Messaging.MessageQueue poisonMessageQueue = new System.Messaging.MessageQueue(Poisoned.WcfService.Properties.Settings.Default.PoisonQueueName); System.Messaging.Message message = null; // Use a new transaction scope to remove the message from the main application queue and add it to the poison queue. // The poison message service processes messages from the poison queue. using (TransactionScope txScope = new TransactionScope(TransactionScopeOption.RequiresNew)) { int retryCount = 0; while (retryCount < 3) { retryCount++; try { // Look up the poison message using the look up id. message = orderQueue.ReceiveByLookupId(lookupId); if (message != null) { // Send the message to the poison message queue. poisonMessageQueue.Send(message, System.Messaging.MessageQueueTransactionType.Automatic); // complete transaction scope txScope.Complete(); Console.WriteLine("Moved poisoned message with look up id: {0} to poison queue: {1} ", lookupId, Poisoned.WcfService.Properties.Settings.Default.PoisonQueueName); break; } } catch (InvalidOperationException) { //Code for the case when the message may still not be available in the queue because of a race condition in transaction or //another node in the farm may actually have taken the message. if (retryCount < 3) { Console.WriteLine("Trying to move poison message but message is not available, sleeping for 10 seconds before retrying"); Thread.Sleep(TimeSpan.FromSeconds(10)); } else { Console.WriteLine("Giving up on trying to move the message"); } } } } // Restart the service host. Console.WriteLine(); Console.WriteLine("Restarting the service to process rest of the messages in the queue"); Console.WriteLine("Press <ENTER> to stop the service"); //ThreadPool.QueueUserWorkItem(orderProcessingCallback); return true; } return false; }
// Handle poison message exception by moving the offending message out of the way for regular processing to go on. public bool HandleError(Exception error) { MsmqPoisonMessageException poisonException = error as MsmqPoisonMessageException; //Note--we only want to handle poison messages coming from a durable/transacted MSMQ here. //So if this is not the exception type, don't do anything. Note that errors on //TCP, HTTP and non-transacted (volatile) MSMQ bindings for the Trade Service will attempt, //on their own, to send an order to the poison queue if an exception occurs. However, a poison //message in a durable queue is a special, important case that is handled here such that the //order message is never lost, yet is removed from the main processing queue so processing //is not interrupted and the queue is kept "clean." if (null != poisonException) { // Use a new transaction scope to remove the message from the main application queue and add it to the poison queue. // The poison message service processes messages from the poison queue. using (TransactionScope txScope = new TransactionScope(TransactionScopeOption.RequiresNew)) { long lookupId = poisonException.MessageLookupId; ConfigUtility.writeErrorConsoleMessage(" Poisoned message: message look up id = " + lookupId + "\n",EventLogEntryType.Information,true,new Settings()); // Get MSMQ queue name from app settings in configuration. if (!System.Messaging.MessageQueue.Exists(Settings.QUENAMEPOISON)) { ConfigUtility.writeErrorConsoleMessage("Creating Poison Message Queue: \n", EventLogEntryType.Information, true, new Settings()); ConfigUtility.writeErrorConsoleMessage(Settings.QUENAMEPOISON + "\n\n", EventLogEntryType.Information, true, new Settings()); System.Messaging.MessageQueue.Create(Settings.QUENAMEPOISON, true); } HostedServices opsService = Settings.hostedServices.Find(delegate(HostedServices hs) { return (hs.BindingType.Equals(ConfigUtility.NET_MSMQ_BINDING)); }); string tempqueuenametx = @".\private$\" + opsService.VirtualPath; System.Messaging.MessageQueue orderQueue = new System.Messaging.MessageQueue(tempqueuenametx); System.Messaging.MessageQueue poisonMessageQueue = new System.Messaging.MessageQueue(Settings.QUENAMEPOISON); System.Messaging.Message message = null; int retryCount = 0; while (retryCount < 4) { retryCount++; try { // Look up the poison message using the look up id. message = orderQueue.ReceiveByLookupId(lookupId); if (message != null) { // Send the message to the poison message queue. if (Settings.NOPOISONQUEUE) { ConfigUtility.writeErrorConsoleMessage("Running in /nopoisonq mode: message is being removed and discarded!\n", EventLogEntryType.Warning, true, new Settings()); txScope.Complete(); break; } else { poisonMessageQueue.Send(message, System.Messaging.MessageQueueTransactionType.Automatic); // complete transaction scope txScope.Complete(); string writemessage = string.Format("Moved poisoned message with look up id: {0} to poison queue: {1} ", lookupId, Settings.QUENAMEPOISON); ConfigUtility.writeErrorConsoleMessage(writemessage + "\n\n", EventLogEntryType.Information, true, new Settings()); break; } } } catch (InvalidOperationException) { //Code for the case when the message may still not be available in the queue because of a race in transaction or //another node in the farm may actually have taken the message. if (retryCount < 2) { ConfigUtility.writeErrorConsoleMessage("Trying to move poison message but message is not available. Will retry in 500 ms. \n", EventLogEntryType.Warning, true, new Settings()); Thread.Sleep(1000); } else { //The message will remain in the main queue in this condition. ConfigUtility.writeErrorConsoleMessage("Giving up on trying to move the message: May have been automatically moved already to the local retry queue on Vista/Win Server 2008 depending on binding setting!\n", EventLogEntryType.Warning, true, new Settings()); } } } } return true; } return false; }