0

I have an Azure WebJob containing few different functions.

These functions need to be injected with some services by Ninject (using constructor injection). Since the standard JobActivator - the class which is responsible to instantiate jobs' classes - creates them by invoking a parameterless costructor, I cannot use that.

In order to do this, I've created a class implementing the IJobActivator interface - provided by the WebJobs SDK, following something similar to this walkthrough.

Since I need this injected services to be alive until the function completes (and it seems that there is no way for the container to know when a function completes), I followed this workaround: https://blog.tech-fellow.net/2017/04/12/disposable-dependency-for-azure-webjob/

That article refers to a different container (StructureMap), but the concept is the same:

  • inside the JobActivator a nested container is created
  • that nested container is passed to the class that contains the function
  • the class that contains the function implements IDisposable interface
  • inside the Dispose() method that child container is disposed

Ninject, as far as I know, doesn't support nested containers, even if I found this extension that seems to do something similar.

So what I would do is:

  1. create a main kernel inside the WebJob, which I pass to the JobActivator
  2. inside the CreateInstance of the JobActivator, I create a new Child Kernel, from the original one
  3. I set that child kernel into the job's class instance
  4. inside the Disposemethod, I will dispose the child kernel

Questions:

  • what do you think about this approach of creating child kernels? Is something that you would avoid?
  • by checking the source code of the Child Kernel extension, it seems to me that, there is no particular change on the Dispose method of the child kernel. Am I correct if I say that by calling Dispose() on the child kernel, wont' dispose the main one?
  • can you please confirm that as soon as a Ninject kernel il disposed (by calling its Dispose() method), then all the created instances - even those that are InTransientScope - will be disposed?
Marconline
  • 1,108
  • 12
  • 30

1 Answers1

0

It turns out that creating a ChildKernel inside the JobActivator Activate() function is a very slow process.

My analysis shows that, if the concurrency on the JobActivator is high, the process of spinning up a new ChildKernel and activate the job will take a considerable amount of time. In my case it was a magnitude of order greater that the real job execution time, so it was totally unceptable.

What I did is serialize the process of job creation inside the JobActivator, by scoping to a particular ExecutionContext (a class that I created) the services that I needed to be scoped to a particular function execution.

All of my jobs implements the IDisposable interface. In the corresponding Dispose() method, I will dispose that particular ExecutionContext, letting Ninject Kernel (the only one instantiated inside the Program.cs) finally release services scoped to that object.

Marconline
  • 1,108
  • 12
  • 30