Reputation: 2365
I have a WebAPI project that uses an expensive backend resource - expensive in the time it takes to set up, memory usage etc. (in my implementation it's Azure Storage queues and table connections).
Obviously, multiple API calls can share the same connection by using a lock(and it would be good if they did), thus avoiding the startup costs each time.
My question is: what's the best pattern to architecture this?
I know that with WebAPI you can't really rely on any of the code running - as it reacts to incoming requests..and each call has its own instance of the controller. I've considered having a static class, possibly creating it in global.ascx - but is that guaranteed to stay there and not get collected? Or is there a better way of doing this?
Upvotes: 1
Views: 618
Reputation: 16413
The way I'd tackle it is to create a service which encapsulates this behaviour and expose it via an interface. You can perform any locking inside the service to ensure that it always happens (e.g.):
public class ExpensiveService : IExpensiveService
{
private object locker = new object();
public void SendMessage(Message message)
{
lock (this.locker)
{
...
}
}
}
Always lock on a private object which only the class which needs to do the locking can see - never lock on this
You then expose your service as a constructor arg to each controller which needs it:
public class SomeController
{
private IExpensiveService expensiveService;
public SomeController(IExpensiveService expensiveService)
{
this.expensiveService = expensiveService;
}
}
Lastly, you should use an IOC container (Ninject, Autofac, SimpleInjector etc) and register a single instance of ExpensiveService
as a singleton within the container. This means that every time a new controller is created, it will get the same instance of ExpensiveService
as every other controller.
The advantages to this approach are that it allows you to test your controller easily as you can mock the IExpensiveService
. The controller is not tightly coupled to some static object or singleton.
Upvotes: 2
Reputation: 63772
Static fields will not be collected (static classes are one of the managed memory roots), so unless you manually remove the reference, it's only going to die with a process (and maybe application domain) restart. Of course, that could happen quite often depending on your server configuration, but that's up to the configuration :)
Do make sure you don't use events on that static object, though - it's one of the great ways to get tons of memory leaks :)
Upvotes: 2