I couldn't get this to work. I considered using an interceptor, but I would still have the problem of a rollback not sending the message because an exception was thrown. as a result i went with a try/catch in each consumer. log the error and send a failure message.
On Oct 2, 1:00 pm, Mike Nichols <[email protected]> wrote: > Thanks I'll look at that > > On Fri, Oct 2, 2009 at 9:44 AM, Ayende Rahien <[email protected]> wrote: > > Mike, you have a memory leak in your implementation. > > Even message that fails completely is never cleaned up. > > > On Fri, Oct 2, 2009 at 5:43 PM, Mike Nichols > > <[email protected]>wrote: > > >> Jason > >> Here is my module that works as you are trying to (I believe). Note I am > >> doing the send in the MessageCompleted handler,not in the messageFailure. > >> Ignore the lame method of configuration for the NumberOfRetries value...:) > >> public class ExceptionHandlingMessageModule : IMessageModule, > >> IBusConfigurationAware > >> { > >> public static int? NumberOfRetries; > >> private readonly Hashtable<string, ErrorCounter> failureCounts = > >> new Hashtable<string, ErrorCounter>(); > >> private ITransport transport; > > >> public void Configure(AbstractRhinoServiceBusFacility facility, > >> IConfiguration configuration) > >> { > >> if (!NumberOfRetries.HasValue) > >> NumberOfRetries = facility.NumberOfRetries; > >> } > > >> public void Init(ITransport transport) > >> { > >> this.transport = transport; > >> transport.MessageProcessingFailure += > >> TransportOnMessageProcessingFailure; > >> transport.MessageProcessingCompleted += > >> TransportOnMessageProcessingCompleted; > >> } > > >> public void Stop(ITransport transport) > >> { > >> transport.MessageProcessingFailure -= > >> TransportOnMessageProcessingFailure; > >> transport.MessageProcessingCompleted -= > >> TransportOnMessageProcessingCompleted; > >> } > > >> private void > >> TransportOnMessageProcessingCompleted(CurrentMessageInformation > >> information, > >> Exception e) > >> { > >> ErrorCounter val = null; > >> failureCounts.Read(reader => > >> reader.TryGetValue(information.TransportMessageId, out val)); > >> if (val == null) > >> return; > >> if (val.FailureCount == NumberOfRetries) > >> { > >> var messageType = (information.Message ?? "no > >> message").ToString(); > >> // Log.For(this).Info("Sending error message for exception > >> '{0}'",e); > >> transport.Send(new Endpoint {Uri = information.Source}, > >> new[] > > >> { > > >> new ExceptionMessage > > >> { > > >> ErrorText = val.Exception.Message, > > >> ExceptionToString = val.Exception.ToString(), > > >> Timestamp = DateTime.Now, > > >> MessageType = messageType, > > >> MessageId = information.MessageId, > > >> Source = information.Source, > > >> Message = information.Message > > >> } > > >> }); > >> } > >> if (e == null) > >> { > >> failureCounts.Write(writer => > >> writer.Remove(information.TransportMessageId)); > >> } > >> } > > >> private void > >> TransportOnMessageProcessingFailure(CurrentMessageInformation information, > >> Exception exception) > >> { > >> failureCounts.Write(writer => > >> { > >> ErrorCounter errorCounter; > >> if > >> (writer.TryGetValue(information.TransportMessageId, out errorCounter) == > >> false) > >> { > >> errorCounter = new > >> ErrorCounter > >> { > > >> FailureCount = 0, > > >> Exception = exception > >> }; > > >> writer.Add(information.TransportMessageId, errorCounter); > >> } > >> errorCounter.FailureCount += 1; > >> }); > >> } > > >> private class ErrorCounter > >> { > >> public Exception Exception; > >> public int FailureCount; > > >> } > >> } > > >> On Fri, Oct 2, 2009 at 7:20 AM, Jason Meckley > >> <[email protected]>wrote: > > >>> I use RQ for all my projects, but I'm not seeing any exceptions. in > >>> the code i provided originally I'm replying on the transport within > >>> the MessageProcessingFailure event after the maximum number of > >>> failures occurs. should I move this to MessageProcessingCompleted, > >>> checking the number of failed attempts to determine if a reply should > >>> be sent? > > >>> On Oct 2, 10:09 am, Ayende Rahien <[email protected]> wrote: > >>> > And if this after the rollback, it also explains it. > >>> > Depending on what kind of queue you use. If you are using MSMQ, it will > >>> be > >>> > silently ignored. If you are using RQ, it will throw. > > >>> > On Fri, Oct 2, 2009 at 4:04 PM, Jason Meckley <[email protected] > >>> >wrote: > > >>> > > I originally got the idea from the LoadBalancerMessageModule. I will > >>> > > log some stats on Transaction.Current to see what's happening there. > > >>> > > if this is before rollback, then that would explain why the message > >>> is > >>> > > not sent, correct? > > >>> > > On Oct 2, 9:17 am, Ayende Rahien <[email protected]> wrote: > >>> > > > Jason, > >>> > > > I don't think that you can send messages from message modules. > >>> > > > The idea never occurred to me, to tell you the truth. > >>> > > > In this particular case, I can't recall off hand what the > >>> transaction > >>> > > state > >>> > > > if for this case, but I think it is just before we roll it back, or > >>> maybe > >>> > > > even without a transaction. > >>> > > > Both of those scenarios will explain why you aren't seeing the > >>> message > >>> > > being > >>> > > > sent. > > >>> > > > On Thu, Oct 1, 2009 at 8:37 PM, Jason Meckley < > >>> [email protected] > >>> > > >wrote: > > >>> > > > > I have ~2 dozen consumers that all handle the happy days scenario > >>> (no > >>> > > > > exceptions). I then have a message module which will handle the > >>> > > > > exceptions. the code my be easier to understand > > >>> > > > > public class OutOfRetriesMessageModule : IMessageModule > >>> > > > > { > >>> > > > > private readonly IReflection reflection; > >>> > > > > private readonly int numberOfRetries; > >>> > > > > private readonly Hashtable<Guid, int> failures; > > >>> > > > > private ITransport theTransport; > > >>> > > > > public OutOfRetriesMessageModule(int numberOfRetries, > >>> > > > > Hashtable<Guid, int> failures, IReflection reflection) > >>> > > > > { > >>> > > > > this.numberOfRetries = numberOfRetries; > >>> > > > > this.failures = failures; > >>> > > > > this.reflection = reflection; > >>> > > > > } > > >>> > > > > public void Init(ITransport transport) > >>> > > > > { > >>> > > > > theTransport = transport; > >>> > > > > transport.MessageProcessingFailure += > >>> > > > > message_processing_failure_send_failure_notice_if_necessary; > >>> > > > > transport.MessageProcessingCompleted += > >>> > > > > message_processing_completed_clear_failures_if_necessary; > >>> > > > > } > > >>> > > > > public void Stop(ITransport transport) > >>> > > > > { > >>> > > > > transport.MessageProcessingFailure -= > >>> > > > > message_processing_failure_send_failure_notice_if_necessary; > >>> > > > > transport.MessageProcessingCompleted -= > >>> > > > > message_processing_completed_clear_failures_if_necessary; > >>> > > > > } > > >>> > > > > private void > >>> > > > > message_processing_failure_send_failure_notice_if_necessary > >>> > > > > (CurrentMessageInformation information, Exception exception) > >>> > > > > { > >>> > > > > var messageId = information.MessageId; > >>> > > > > if (exception == null) return; > >>> > > > > if(!typeof > >>> > > > > (RequestToGenerateReportMessage).IsAssignableFrom > >>> > > > > (information.Message.GetType())) return; > > >>> > > > > increment_failed_attempts(messageId); > >>> > > > > if (!has_exceeded_number_of_retries(messageId)) > >>> return; > > >>> > > > > send_failure_notice(information); > >>> > > > > } > > >>> > > > > private void > >>> > > > > message_processing_completed_clear_failures_if_necessary > >>> > > > > (CurrentMessageInformation information, Exception exception) > >>> > > > > { > >>> > > > > if (exception != null) return; > >>> > > > > failures.Write(writer => writer.Remove > >>> > > > > (information.MessageId)); > >>> > > > > } > > >>> > > > > private void increment_failed_attempts(Guid messageId) > >>> > > > > { > >>> > > > > failures.Write(writer => > >>> > > > > { > >>> > > > > int attempts; > >>> > > > > writer.TryGetValue(messageId, > >>> out > >>> > > > > attempts); > >>> > > > > writer.Add(messageId, > >>> ++attempts); > >>> > > > > }); > >>> > > > > } > > >>> > > > > private bool has_exceeded_number_of_retries(Guid id) > >>> > > > > { > >>> > > > > var attempts = 0; > >>> > > > > failures.Read(reader => reader.TryGetValue(id, out > >>> > > > > attempts)); > >>> > > > > return attempts >= numberOfRetries; > >>> > > > > } > > >>> > > > > private void send_failure_notice(CurrentMessageInformation > >>> > > > > information) > >>> > > > > { > > ... > > read more » --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Rhino Tools Dev" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/rhino-tools-dev?hl=en -~----------~----~----~----~------~----~------~--~---
