Get autofac ILifetimeScope from context in observer

99 views
Skip to first unread message

Tim Cools

unread,
Apr 6, 2018, 7:13:59 AM4/6/18
to masstransit-discuss
Hi,

I'm trying to get the autofac ILifetimeScope from a ConsumeContext in and IConsumeObserver or Filter. Based on other posts I hoped I could do somthing like this:

if (context.TryGetPayload<ILifetimeScope>(out var lifetimeScope))
    ... do something with the lifetimescope ...
}

But the context never contains the ILifetimeScope even though it was added to the payload of the ConsumeContext in the AutofacConsumerScopeProvider.

1) Can someone explain what's happening? Is this expected behavior? 
2) I might have wrong assumptions about how the context is passed in the pipeline. Is their any doc/post/... available which explains the usage of the contexts?


Feedback highly appreciated!

Tim

Tim Cools

unread,
Apr 11, 2018, 10:29:27 AM4/11/18
to masstransit-discuss
I made the test pass by adding the ILifetimeScope to the ConsumeContext passing in the AutofacConsumerScopeProvider.GetScope<T> method. But I'm not sure I fully understand the the lifecycle of the ConsumeContext. Is this an acceptable approach? 

Tim Cools

unread,
Apr 12, 2018, 9:23:31 AM4/12/18
to masstransit-discuss
Ok, I had some more time to dive deeper into the issue and it was not the way to go. I got already disposed exception when I tried to get anything from the container in the observer...

I ended up with creating a custom ConsumerFactory which is responsible for both the scope of the LifeTimeScope as notifying my profiler that a message is complete.

Chris, any concerns with this approach? 

    public class ProfileConsumerFactory<TConsumer> :
        IConsumerFactory<TConsumer>
        where TConsumer : class
    {
        private readonly string _name = "masstrasit-consumer-" + typeof(TConsumer).Name;
        private readonly ILifetimeScope _scope;
        public ProfileConsumerFactory(ILifetimeScope scope)
        {
            _scope = scope;
        }
        public async Task Send<TMessage>(ConsumeContext<TMessage> context, IPipe<ConsumerConsumeContext<TConsumer, TMessage>> next)
            where TMessage : class
        {
            using (var scope = _scope.BeginLifetimeScope(_name, builder => builder.ConfigureScope(context)))
            {
                var profilerContext = scope.Resolve<IProfilerContext>();
                try
                {
                    var consumerContext = scope.GetConsumer<TConsumer, TMessage>(context);
                    await next.Send(consumerContext).ConfigureAwait(false);
                    profilerContext.Complete();
                }
                catch (Exception exception)
                {
                    profilerContext.Failed(exception);
                    throw;
                }
            }
        }
        void IProbeSite.Probe(ProbeContext context)
        {
            context.Add("provider", "autofac");
            context.Add("scopeTag", _name);
        }
    }
Reply all
Reply to author
Forward
0 new messages