Help with resolver reuse inside IMessageService

I’m trying to put together some code to show this better, but in the meantime, hopefully I can explain my issue in bits.

I use an DataRepository around ORMLite that is per-request so it can easily commit/rollback a transaction if the request throws an error.

container.RegisterAutoWiredAs<DataRepository, IDataRepository>().ReusedWithin(Funq.ReuseScope.Request);
container.Register<IDataRepositoryCache>(new DataRepositoryCacheClientCache());

The DataRepository has an DI reference to the database (obviously) and the cache (a wrapper around ICacheClient)

public DataRepository(IDbConnectionFactory dbFactory, IDataRepositoryCache cache)
{
	DbFactory = dbFactory;
	Cache = cache;
}

I use the MessageService, which on my development machine just processes messages using InMemoryTransientMessageService.

IMessageService mq = new InMemoryTransientMessageService();
container.Register<IMessageService>(mq);
container.Register(mq.MessageFactory);

mq.RegisterHandler<MyMessage>(m => { return appHost.ServiceController.ExecuteMessage(m); });

Now, the problem occurs inside a normal request, where I call the MessageService.

e.g.

public IDataRepository Data {get; set;}
public object Post(MyRequest request)
{
  :
  // Data is pointing to the request's DataRepository instance
  :
  using (var producer = AppHostBase.Instance.TryResolve<IMessageFactory>().CreateMessageProducer())
  {
    producer.Publish<MyMessage>(new MyMessage {});
  }
  :
  // Data is pointing to same DataRepository instance, but it has been disposed
  :
}

When that Publish() returns, the DataRepository in the current request has been disposed. I just assumed that producer.Publisher() would create a new request and therefore its own DataRepository, but that doesn’t seem to be the case - it reuses the existing one. However, it disposes it before returning - which in my case also cleans up resources.

First, is this correct behaviour?

Is there a way around it, or am I doing something fundamentally wrong?

Thanks.

The Request Scope only applies to the context of a HTTP Request, register it as a transient dependency instead with:

container.RegisterAutoWiredAs<DataRepository, IDataRepository>()
    .ReusedWithin(Funq.ReuseScope.None);

Thanks, thought there might be something simple.

However, I’m stilling getting some odd behaviour.

I’ve changed it to Reuse.None, so I’m getting a new DataRepository each service call.

However, if I put some watches and step through, when the MessageService call happens

mq.RegisterHandler<MyMessage>(m => { return appHost.ServiceController.ExecuteMessage(m); });

at the end of that ExecuteMessage, I can see it going through disposing the DataRepository of the caller, leaving me in the same position.

Could it be that if appHost.ServiceController is the same instance (as would happen when all running locally), then it’s disposing things it created even though it’s nested?

i.e.

AppHost->ServiceController
  Create new DataRepository (DR1)
  Process Request using DR1
    Call MessageService
      Call AppHost->ServiceController->ExecuteMessage
        Create new DataRepository (DR2)
        Process message Request using DR2
        Clean up ServiceController instance, (which is DR1)
    DR1 is now disposed

I’m not quite following the issue but ServiceController is a singleton, yes. Are you saying that DR2 is never disposed?

Also you can publish a message with base.MessageProducer.Publish(new MyMessage()) instead of accessing the AppHost instance directly.

Both DR1 and DR2 are disposed.

Sorry if this is just a misunderstanding, but what I think is happening is that when I call

MessageProducer.Publish(new MyMessage())

inside an existing Request, it disposes all resources attached to the singleton ServiceController (or AppHost), not just the ones created for that ServiceController.Execute.

In my App I have a ServiceRunner overriding Execute, so:

public override object Execute (..) // processing my original HTTP request)
{
  DR1 = requestContext.TryResolve<IDataRepository>();
  base.Execute(..);
}

The execute calls my service, which calls the MessageService

public object Post(MyRequest req)
{
  :
  base.MessageProducer.Publish(new MyMessage());
  :
}

While running locally, that just calls my ServiceRunner to process the MyMessage request. So calling Execute() creates a new DataRepository (call it DR2) and executes.

public override object Execute (..) // processing the MyMessage request)
{
  DR2 = requestContext.TryResolve<IDataRepository>();
  base.Execute(..);
} // when this exits, it disposes DR1 and DR2

However, when Execute ends, it goes through and disposes all objects, DR2 and DR1. So when control comes back out of the Publish, the original DataRepository (DR1) has also been disposed.

Sorry if this is plainly obvious, and I’m just doing something wrong.

I’ve moved things around and probably need to restructure it to correct this problem. I guess what I was original expecting was that Reuse.Request was any request not just HTTPRequest and that it would track which items were created within the scope, rather than clearing them all.

Yeah the InMemoryTransientMessageService isn’t a proper IMessageService like the others, it effectively executes the request synchronously and after each time a Service is executed it’s disposed including all transient dependencies resolved up to that point. You can delay publishing messages until the end of your Service so you don’t need to use them after messages are published.

Ok, thanks.

I’ve moved the message service to use AWS. I was using the InMemoryTransientMessageService one for local development, but this way it becomes asynchronous and everything works as expected.

I guess the other option would be an InMemoryAsyncTransientMessageService which queues up messages and processes them at the end of the request, which I might have to do if I find I’m working offline.

Cheers.