Question

I set up a windows service with 2 consumers using AutoFac. In a happy path, this works really well. I was under the impresison that MassTransit handled exceptions for me. As the docs state: http://docs.masstransit-project.com/en/latest/overview/errors.html

The easiest thing is to just let the exception bubble out of your consumer method and MassTransit will automatically catch the exception for you

When an exception is thrown in the consumer, MassTransit indeed generates a fault but my service still crashes:

Application: WerkgeverService.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: AutoMapper.AutoMapperMappingException Stack: at System.Runtime.CompilerServices.AsyncMethodBuilderCore.b__5(System.Object) at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

The exception is logged because I log all uncaught exceptions:

Protected Overrides Sub OnStart(args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.
        Try
            Initialize()
            AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf HandleBubbledException
        Catch ex As Exception
            Me.EventLog.WriteEntry(ex.Message, EventLogEntryType.Error)
            Throw
        End Try
    End Sub


    Private Sub HandleBubbledException(sender As Object, args As UnhandledExceptionEventArgs)
        Dim exception = DirectCast(args.ExceptionObject, Exception)
        Me.EventLog.WriteEntry(String.Format("Message: {0} {2}Stacktrace:{2}{1}", exception.Message, exception.StackTrace, Environment.NewLine), EventLogEntryType.Error)
    End Sub

The exception itself is one from in AutoMapper and indeed gets logged in the eventlog (so it is not handled by MassTransit):

Message: Missing type map configuration or unsupported mapping.

Mapping types:
Int32 -> Int64
System.Int32 -> System.Int64

QUESTION: Is there any way in which I can prevent the service from crashing without adding try/catch to every consumer? AFAIK MassTransit should handle these...

Was it helpful?

Solution

This might be specific for my case, but I think I found the problem (thanks to the guys from MassTransit).

The problem was that my consumer starter a new thread.

Public Sub Consume(message As IConsumeContext(Of IMessage)) Implements Consumes(Of IConsumeContext(Of IMessage)).All.Consume
    HandleMessageAsync(message)
End Sub
Private Async Sub HandleMessageAsync(context As IConsumeContext(Of IMessage))
    Dim something = Await _controller.GetSomething(context.Message)
    Dim response As New MessageResponse
    response.something = something
    context.Respond(response)
End Sub

This thread lives out of the grasp of MassTransit so it can't catch any exception from that thread. The solution for me was to change it to:

Public Sub Consume(context As IConsumeContext(Of IMessage)) Implements Consumes(Of IConsumeContext(Of IMessage)).All.Consume
    Dim something = _controller.GetSomething(context.Message).Result
    Dim response As New MessageResponse
    response.something = something
    context.Respond(response)
End Sub

Just make sure the exception bubbles up before the Consume method exits. Otherwise you have to catch it yourself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top