Can the saga context be obtained when implementing the IHandleSagaNotFound

sagas

(Steven) #1

Hi,

When implementing a global handler for IHandleSagaNotFound, is it possible to obtain information on which saga was tried to load?
I have a design where one published message would have to resurrect 2 sagas.
If a saga cannot be found for a reason, I would throw an exception, so the message is retried and eventually sent to the error queue.
In the other case, I would not throw an exception and just “ignore” the message.

One solution could be to redesign those 2 sagas into one.
But that would be my last option.

I was thinking of implementing a behavior that hooks in before the SagaPersistenceBehavior, to store the saga information somewhere, and use that in the SagaNotFoundHandler.

Anyone already implemented such a behavior?
Some pointers are most welcome.

Regards,
Steven.


(Andreas Öhlund) #2

Hi Steven, you can get access to the list of saga involved by extending the receive pipeline. ( I’ve cobbled together some code that will get you going)

Add the following 2 behaviors


class SagaTypeRecorder : Behavior<IInvokeHandlerContext>
{
    public override Task Invoke(IInvokeHandlerContext context, Func<Task> next)
    {
        if(context.MessageHandler.Instance is Saga)
        {
            var sagas = context.Extensions.Get<SagaTypeHolder.SagasInvolved>();

            sagas.Sagas.Add(context.MessageHandler.HandlerType);
        }

        return next();
    }


}

class SagaTypeHolder : Behavior<IIncomingPhysicalMessageContext>
{
    public override Task Invoke(IIncomingPhysicalMessageContext context, Func<Task> next)
    {
        context.Extensions.Set(new SagasInvolved());

        return next();
    }

    public class SagasInvolved
    {
        public List<Type> Sagas = new List<Type>();
    }
}

and register them:

endpointConfiguration.Pipeline.Register(typeof(SagaTypeHolder), "Holds potential sagas for the incoming message");
endpointConfiguration.Pipeline.Register(typeof(SagaTypeRecorder), "Records potential sagas for the incoming message");
  

You can then use this in your saga not found handler

    public Task Handle(object message, IMessageProcessingContext context)
    {
        var involvedSagas = context.Extensions.Get<SagaTypeHolder.SagasInvolved>();

        foreach(var sagaType in involvedSagas.Sagas)
        {
            Console.Out.WriteLine(sagaType.FullName);
        }

        return Task.CompletedTask;
    }

That said, your design sounds a bit funky so perhaps refactoring this into a single saga might be the better long term solution?


(Avinash K C) #3

Hi Andreas Öhlund,
Do you have something that works with NserviceBus v4.4.2, Suggested interfaces are from higher versions I believe.


(Andreas Öhlund) #4

Hi, nothing comes to mind. Unfortunately we didn’t have those types of extension capabilities back then.

Any chance you could upgrade to at least v5?