4

I am using MassTransit.Automatonymous (version 3.3.5 ) to manage a saga and I seem to be receiving unexpected events after a state has transitioned.

Here is my state set up:

        Initially(
            When(Requested)
                .ThenAsync(InitialiseSaga)
                .TransitionTo(Initialising)
            );

        During(Initialising,
            When(InitialisationCompleted)
                .ThenAsync(FetchTraceSetMetaData)
                .TransitionTo(FetchingTraceSetMetaData)
            );

        During(FetchingTraceSetMetaData,
            When(TraceSetMetaDataRetrieved)
                .ThenAsync(ExtractTiffFiles)
                .TransitionTo(ExtractingTiffFiles)
            );

        During(ExtractingTiffFiles,
            When(TiffFilesExtracted)
                .ThenAsync(DispatchTiffParseMessages)
                .TransitionTo(DispatchingTiffParseMessages)
            );

The error I sometimes receive is:

The TraceSetMetaDataRetrieved event is not handled during the ExtractingTiffFiles state for the ImportTraceSetDataStateMachine state machine

My understanding of how this should work at the point of the error is as follows:

During the FetchingTraceSetMetaData state, at some point I'll receive a TraceSetMetaDataRetrieved event. When this occurs, run the ExtractTiffFiles method, and transition to the ExtractingTiffFiles state.

Once in the ExtractingTiffFiles state, I wouldn't expect the TraceSetMetaDataRetrieved event since it's what got us into the ExtractingTiffFiles state.

The two FetchTraceSetMetaData and ExtractTiffFiles methods are as follows (truncated for brevity):

    public async Task FetchTraceSetMetaData(BehaviorContext<ImportTraceSetDataSagaState, InitialisationCompleteEvent> context)
    {
        var traceSetId = context.Instance.TraceSetId;
        _log.Information($"Getting pixel indicies for trace set with id {traceSetId}");

        // Snip...!

        await context.Publish(new TraceSetMetaDataRetrievedEvent { CorrelationId = context.Data.CorrelationId });
    }


    public async Task ExtractTiffFiles(BehaviorContext<ImportTraceSetDataSagaState, TraceSetMetaDataRetrievedEvent> context)
    {
        _log.Information($"Extracting tiffs for {context.Instance.TiffZipFileKey} and trace set with id {context.Instance.TraceSetId}");

        // Snip...!

        // Dispatch an event to put the saga in the next state where we dispatch the parse messages
        await context.Publish(new TiffFilesExtractedEvent { CorrelationId = context.Data.CorrelationId });
    }

Post posting pondering

It's just occurred to me that perhaps I should have my TransitionTo statements before my ThenAsync statements. e.g.

During(FetchingTraceSetMetaData,
        When(TraceSetMetaDataRetrieved)
            .TransitionTo(ExtractingTiffFiles)
            .ThenAsync(ExtractTiffFiles)
        );

Is that what I'm doing wrong?

Robert
  • 1,487
  • 1
  • 14
  • 26
  • What are you using for state storage, and what isolation level are you using for transactions? – Chris Patterson Nov 30 '16 at 18:48
  • I'm using the EntityFrameworkSaga repo (backed by Postgresql) and am using IsolationLevel.Serializable. FWIW, I'm also using ec.UseInMemoryOutbox(); on the endpoint. – Robert Nov 30 '16 at 21:35
  • And I forgot to ask which transport, and how long is it taking for the consumer to complete? – Chris Patterson Nov 30 '16 at 21:52
  • The ExtractTiffFiles method can take anywhere from 200ms up to ~10 seconds. The DispatchTiffParseMessages method would be anywhere from 20ms up to ~2 seconds. Transport is RabbitMQ running from this docker: https://hub.docker.com/_/rabbitmq/ on Amazon (Redhat) Linux. – Robert Nov 30 '16 at 22:01
  • @ChrisPatterson any idea what it might be? Do you need more information? – Robert Dec 09 '16 at 00:18

0 Answers0