In my last post I talked about unit testing your OWIN pipeline and briefly mentioned that you shouldn't do any heavy lifting from inside your UseWhatever method. Examples of that include starting background tasks or connecting to other services (through that HttpMessageHandler). If you're lucky, those tasks can be initiated in a laziness fashion. For instance, your component could use the first incoming request as a trigger to start that thread. However, some components might want to start processing some data as early as possible just to make sure that data is ready when the first request comes in. So how do you initiate those things instead?
Ingredient 5: Postpone the heavily lifting using startable components
Well, there's no real best practice, but what worked well for us is to return an object from the UseXXX extension method that implements IStartable and exposes a single asynchronous Start method.
public class Startable : IStartable
{
private readonly Func<Task> starterFunc;
public Startable(Func<Task> starterFunc)
{
this.starterFunc = starterFunc;
}
public Task Start()
{
return starterFunc();
}
}
Within your middleware extension method you can use it like this:
public static IStartable UseMyComponent(this IAppBuilder appBuilder)
{
// Add whatever nested middleware or WebAPI stuff you need to the appBuilder
return new Startable(() => async {
// Do the heavy lifting such as creating threads, etc.
await …
})
}
Leave a Comment