.netmasstransitsaga

Masstransit Courier Activity problem to catch exception and trigger Compensate


i am trying to work with masstransit courier routing slip. i have fulfill consumer that activates are added as

public class FullFillHerdGroupEditConsumer : IConsumer<IFullFillHerdGroupEditMessage>
    {
        public async Task Consume(ConsumeContext<IFullFillHerdGroupEditMessage> context)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine(" start Fullfill consumer");

            var builder = new RoutingSlipBuilder(NewId.NextGuid());

            

            Console.WriteLine("1 - Global raw data Herd Group Edit Activity");

            builder.AddActivity("GlobalRawDataGroupEdit", new Uri("queue:GlobalGeneticsRawDataEditGroup_execute"), new
            {
                newGroupTitle = context.Message.GroupTitle,
                oldGroupTitle = context.Message.oldGroupTitle
            });




            Console.WriteLine("2 - Global Analytics Herd Group Edit Activity");

            builder.AddActivity("GlobalAnalyticsGroupEdit", new Uri("queue:GlobalAnalyticsEditGroup_execute"), new
            {
                GroupId = context.Message.GroupId,
                GroupTitle = context.Message.GroupTitle,
                oldGroupTitle = context.Message.oldGroupTitle
            });


            var routingSlip = builder.Build();

            await context.Execute(routingSlip);
        }
    } 

and as mentioned i have two activities.

First activity to execute in fullfill consumer

public class GlobalGeneticsRawDataEditGroupActivity : IActivity<IGlobalGeneticsRawDataEditGroupArgument, IGeneticsRawDataEditGroupLog>
{

    public async Task<CompensationResult> Compensate(CompensateContext<IGeneticsRawDataEditGroupLog> context)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"[ rawdata ] : Compensate rawdata Edit Group Activity roleback to ( {context.Log.oldGroupTitle} ) from ( {context.Log.newGroupTitle} )");
        return context.Compensated();
    }

    public async Task<ExecutionResult> Execute(ExecuteContext<IGlobalGeneticsRawDataEditGroupArgument> context)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"[ rawdata ] : Execute rawdata Edit Group Activity Edit to ( {context.Arguments.newGroupTitle} ) from ( {context.Arguments.oldGroupTitle} )");

        //do some logics

        return context.Completed();
    }
}

public interface IGeneticsRawDataEditGroupLog
{
    public string newGroupTitle { get; set; }
    public string oldGroupTitle { get; set; }
}

public interface IGlobalGeneticsRawDataEditGroupArgument
{
    public string newGroupTitle { get; set; }
    public string oldGroupTitle { get; set; }
}

and the second one which i want to reproduce exception to observe and test compensation.

public async Task<CompensationResult> Compensate(CompensateContext<IGlobalAnalyticsEditGroupLog> context)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"[ Global Analytics ] : Compensate Edit Group Activity roleback to ( {context.Log.oldGroupTitle} ) from ( {context.Log.GroupTitle} ) ");
            
            
            return context.Compensated();
        }

        public async Task<ExecutionResult> Execute(ExecuteContext<IGlobalAnalyticsEditGroupArgument> context)
        {

            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine($"[ Global Analytics ] : Execute Edit Group Activity Edit to ( {context.Arguments.GroupTitle} ) from  ( {context.Arguments.oldGroupTitle} )");

            if (true)
            {
                //throw new InvalidOperationException("This is a Test Exception....!");
                return context.FaultedWithVariables(new InvalidOperationException("This is a Test Exception....!"), new 
                {
                    GroupTitle = context.Arguments.GroupTitle,
                    oldGroupTitle = context.Arguments.oldGroupTitle
                });
            }

            //do some logics

            return context.Completed();
            

            
        }
    }

    public interface IGlobalAnalyticsEditGroupArgument
    {
        
        public string GroupTitle { get; set; }
        public string oldGroupTitle { get; set; }
        
    }

    public interface IGlobalAnalyticsEditGroupLog
    {
        public string GroupTitle { get; set; }
        public string oldGroupTitle { get; set; }
    }

the problem is throwing exception in activity does not trigger the compensate task that here it shows some message for test with different color.

Note: i also set retries to 2 in masstransit configuration.
and this is what i get
console


Solution

  • "If an activity does not store any compensation data, the Compensate method is never called."

    I believe you need to fault the activity with compensation data in order for the Compensate method to be called.

    From the documentation: https://masstransit-project.com/advanced/courier/activities.html#terminating-a-routing-slip

    Maybe something like this https://github.com/MassTransit/MassTransit/discussions/3943#:~:text=return%20context.FaultedWithVariables(new%20System.Exception(%22%E9%94%99%E8%AF%AF%22)%2C%20log