Hangfire.AspnetCore with Autofac Multitenant - Example of Implementing Tenant Identification Strategy?

Hi, is there an example somewhere of a custom tenant identification strategy that works with with Hangfire? My approach so far is as follows:

  1. Implement a custom job filter attribute implementing IServerFilter. This looks at the job/arguments and attempts to set the current tenant identifier (used by the tenant identification strategy) using AsyncLocal API.

  2. From the tenant identification strategy, look for setting of current tenant id with AsyncLocal

The problem I’m facing (at least I think I’m facing) is that the tenant identification strategy never seems to be called after my filter has run and is able to setup the tenant id. If I add logging calls to both, I never see the filter and strategy firing on the same Thread.Current.ManagedThreadId which is worrisome.

Is there an example somewhere that shows this? Similar code used to work in .NET 4.6 but I’m blocked trying to migrate to .NET Core API with this presently. Any help/suggestions are appreciated.

Thanks!

If the job method is asynchronous, it will run on a thread pool thread, so it is natural it has different ManagedThreadId from the one the filter runs on. The main difference between AsyncLocal and ThreadLocal is the former is bound to a logical call (which can span across multiple threads), while the latter is bound to a particular thread.

Why don’t you just use job parameter to store tenant id? It would be displayed in Dashboard, and be easier to debug.

Use filterContext.SetJobParameter("TenantId", tenantId) in your filter to set parameter value. You may even do it once in IClientFilter when the job is enqueued since the arguments won’t change even if the job fails and being requeued, no need to do it every time in IServerFilter.

Then add PerformContext as a job argument and use context.GetJobParameter<string>("TenantId") to get parameter value.

Hi, thank you for responding. I don’t believe the tenant id is not the issue. Using the filter context as you suggested might be a good way to simplify/improve the performance, however, even with this I’m still faced with the problem of needing to set the tenant id before my custom id strategy has been called so that autofac will inject the appropriate dependencies (or their tenant specific overrides) to the job during execution.

I’m trying to get a simple POC to illustrate what I’m seeing at the moment here:

Thanks again

I’ve noticed a few things:

  1. You probably want to declare CountService as SingleInstance instead of InstancePerLifetimeScope, otherwise it would be instantiated every time the job is performed.

  2. You didn’t instruct Hangfire to use MultitenantContainer to resolve services. Add UseAutofacActivator(Startup.ApplicationContainer) after UseRedisStorage inside AddHangfire callback.

Then it should work as expected.

Hi, pieceofsummer. Thanks for the help! #2 was what I was missing… in reading the docs I didn’t realize that was necessary in light of Program.cs calling UseAutofacMultitenantRequestServices(() => Startup.ApplicationContainer). With that change I’m now seeing it resolve as expected. Thank you again for your help!