JobActivatorScope.Current throws NRE in Filters

job-filters
Tags: #<Tag:0x00007f499a5d3820>

#1

I started working with Hangfire last week and so far I like what it has to offer. However, there is one area where I keep running into problems. Job scope within filters. I’m assumed Job Scopes follow the same pattern as WebAPI/OwinContexts however that does not appear to be the case.

Anytime I reference JobActivatorScope.Current within a filter, be it a singleton or a transient, Current is always null. I pulled the source down and, if I’m following the code path correct, A scope does not begin until after a the Filters are resolved, but before the Job executes.

Our system leverages StructureMap and nested containers quite a bit and we were hoping to continue that pattern with Hangfire since there is support of nested scopes.

Two examples of how we are using nest containers:

  1. unit of work pattern and database transactions
  2. pushing the current user into the scope.

Is it possible to access/share the active job scope that will be used to resolve and exeucte the job? Are there any code examples covering this behavior?

Thank you


#2

Job scope is created after all filters’ OnPerforming and destroyed before OnPerformed, so there’s no way to access it from the filters.

I’m not sure which ‘current user’ you want to push into scope, because the job is executed by the background thread and at random time, so things like OwinContext etc. no longer exist. If you need to save the user which caused the job to be started, you should store it as a job parameter when the job is created. Then you can either access it from the job method, or put it into scope by a custom job activator.


#3

Thank you @pieceofsummer. If we cannot access the scope in OnPerforming or On Performed are there any filter events that we can hook into where the JobScope does exist? Is there any documentation on JobFilters that explains the order of events?

What we are trying to do is configure our nested containers for cross cutting concerns with contextual information. Since we do not have access to the Owin Context we want to place the current user’s ID into the job’s parameter dictionary. Then pull the ID out, find the user, and place the user in the Scope (nested container).

We though filters would be the ideal candidate since this is a cross cutting concern for any background job and we don’t want to add the user ID and loading logic to every background method.


#4

thinking of other options here…

Would a pull request be accepted if the logic was changed to create the scope prior to filter creation and dispose after the filters have completed? Basically encapsulating the filter execution into the job scope?


#5

I believe there already was a similar PR some time ago, but it wasn’t merged yet.

Currently you might go with a client filter + job activator pair. It will put current user id into job parameters in IClientFilter.OnCreating, and then a custom job activator will pick that parameter and pre-fill scope after it is created in JobActivator.BeginScope.


#6

I already have a StructureMap Job Activator. The problem is a nested container isn’t available within a filter and the activator creates the scope, but the timing of the creation is done elsewhere.

I’m spiking a console app to log filter and job events so I can figure out what objects are available when. Then I can create a solution accordingly.


#7

@JasonMeckley Did you ever find a method for using NestedContainers?


#8

i didn’t. I refactored the filter to not use DI. Not ideal, but it solved my problem