stashbox: variable '' of type 'System.IServiceProvider' referenced from scope '', but it is not defined

Hi am using stashbox with aspnet core 2.2 and Hangfire.

It is a multi tenant solution, where I spawn one hangfire instance for each tenant, and I hand each hangfire instance their own child container with their own specific registrations.

However when the hangfire server tries to start a job, and resolve a service, I get the following exception.

System.InvalidOperationException: variable '' of type 'System.IServiceProvider' referenced from scope '', but it is not defined
   at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)
   at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
   at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
   at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
   at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda)
   at System.Linq.Expressions.ExpressionExtensions.CompileDelegate(Expression expression, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\Extensions\ExpressionExtensions.cs:line 42
   at Stashbox.Lifetime.SingletonLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\SingletonLifetime.cs:line 21
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Expressions.ConstructorSelector.TryBuildResolutionConstructor(ConstructorInformation constructor, ResolutionContext resolutionContext, IContainerContext containerContext, IServiceRegistration serviceRegistration, TypeInformation& failedParameter, Expression[]& parameterExpressions, Boolean skipUknownResolution) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 93
   at Stashbox.BuildUp.Expressions.ConstructorSelector.SelectConstructor(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, ConstructorInformation[] constructors) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 46
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateInitExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 138
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type serviceType) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 91
   at Stashbox.BuildUp.DefaultObjectBuilder.GetExpressionInternal(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\DefaultObjectBuilder.cs:line 32
   at Stashbox.BuildUp.ObjectBuilderBase.BuildDisposalTrackingAndFinalizerExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 52
   at Stashbox.BuildUp.ObjectBuilderBase.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 21
   at Stashbox.Lifetime.SingletonLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType)
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.ResolutionScope.Activate(ResolutionContext resolutionContext, Type type, Object name) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 272
   at Stashbox.ResolutionScope.Resolve(Type typeFrom, Boolean nullResultAllowed, Object[] dependencyOverrides) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 94
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.<>c.<AddDataProtectionServices>b__2_0(IServiceProvider s)
   at (DT1 , IResolutionScope )
   at Stashbox.ResolutionScope.GetOrAddScopedItem(Int32 key, Object sync, Func`2 factory) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 180
   at Stashbox.Lifetime.SingletonLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\SingletonLifetime.cs:line 21
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Expressions.ConstructorSelector.TryBuildResolutionConstructor(ConstructorInformation constructor, ResolutionContext resolutionContext, IContainerContext containerContext, IServiceRegistration serviceRegistration, TypeInformation& failedParameter, Expression[]& parameterExpressions, Boolean skipUknownResolution) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 93
   at Stashbox.BuildUp.Expressions.ConstructorSelector.SelectConstructor(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, ConstructorInformation[] constructors) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 46
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateInitExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 138
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type serviceType) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 91
   at Stashbox.BuildUp.DefaultObjectBuilder.GetExpressionInternal(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\DefaultObjectBuilder.cs:line 32
   at Stashbox.BuildUp.ObjectBuilderBase.BuildDisposalTrackingAndFinalizerExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 52
   at Stashbox.BuildUp.ObjectBuilderBase.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 21
   at Stashbox.Lifetime.SingletonLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType)
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Expressions.ConstructorSelector.TryBuildResolutionConstructor(ConstructorInformation constructor, ResolutionContext resolutionContext, IContainerContext containerContext, IServiceRegistration serviceRegistration, TypeInformation& failedParameter, Expression[]& parameterExpressions, Boolean skipUknownResolution) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 93
   at Stashbox.BuildUp.Expressions.ConstructorSelector.SelectConstructor(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, ConstructorInformation[] constructors) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 46
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateInitExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 138
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type serviceType) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 91
   at Stashbox.BuildUp.DefaultObjectBuilder.GetExpressionInternal(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\DefaultObjectBuilder.cs:line 32
   at Stashbox.BuildUp.ObjectBuilderBase.BuildDisposalTrackingAndFinalizerExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 52
   at Stashbox.BuildUp.ObjectBuilderBase.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 21
   at Stashbox.Lifetime.ScopedLifetimeBase.GetFactoryExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\ScopedLifetimeBase.cs:line 38
   at Stashbox.Lifetime.ScopedLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\ScopedLifetime.cs:line 27
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Expressions.ConstructorSelector.TryBuildResolutionConstructor(ConstructorInformation constructor, ResolutionContext resolutionContext, IContainerContext containerContext, IServiceRegistration serviceRegistration, TypeInformation& failedParameter, Expression[]& parameterExpressions, Boolean skipUknownResolution) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 93
   at Stashbox.BuildUp.Expressions.ConstructorSelector.SelectConstructor(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, ConstructorInformation[] constructors) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 46
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateInitExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 138
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type serviceType) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 91
   at Stashbox.BuildUp.DefaultObjectBuilder.GetExpressionInternal(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\DefaultObjectBuilder.cs:line 32
   at Stashbox.BuildUp.ObjectBuilderBase.BuildDisposalTrackingAndFinalizerExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 52
   at Stashbox.BuildUp.ObjectBuilderBase.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 21
   at Stashbox.Lifetime.ScopedLifetimeBase.GetFactoryExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\ScopedLifetimeBase.cs:line 38
   at Stashbox.Lifetime.ScopedLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\ScopedLifetime.cs:line 27
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.ResolutionScope.Activate(ResolutionContext resolutionContext, Type type, Object name) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 272
   at Stashbox.ResolutionScope.Resolve(Type typeFrom, Boolean nullResultAllowed, Object[] dependencyOverrides) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 94
   at Proplan.API.Common.Extensions.HangfireActivatorScope.Resolve(Type type) in C:\Users\furie\source\repos\PPBS\Proplan.API\Common\Extensions\ApplicationBuilderHangfireExtensions.cs:line 112
   --- End of inner exception stack trace ---
   at Proplan.API.Common.Extensions.HangfireActivatorScope.Resolve(Type type) in C:\Users\furie\source\repos\PPBS\Proplan.API\Common\Extensions\ApplicationBuilderHangfireExtensions.cs:line 116
   at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_0.<PerformJobWithFilters>b__0()
   at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
   at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
   at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

Here is my wiring

public static class ServiceCollectionHangfireExtensions
{
    public static IServiceCollection AddHangfire(this IServiceCollection services)
    {
        services.AddScoped<JobStorage>(_ => new SqlServerStorage(
            _.GetService<IHttpContextAccessor>().HttpContext?.RequestServices.GetRequiredService<Tenant>().ConnectionString ??
            _.GetRequiredService<Tenant>().ConnectionString,
            new SqlServerStorageOptions { PrepareSchemaIfNecessary = false }
        ));
        services.AddScoped<JobActivator>(_ => new HangfireActivator(_.GetRequiredService<IDependencyResolver>(), 
            $"RequestActivator:{_.GetService<IHttpContextAccessor>().HttpContext?.RequestServices.GetService<Tenant>()?.Name ?? _.GetService<Tenant>()?.Name}"));
        services.AddScoped<IBackgroundJobFactory>(x => new BackgroundJobFactory(x.GetRequiredService<IJobFilterProvider>()));
        services.AddScoped<IBackgroundJobStateChanger>(x => new BackgroundJobStateChanger(x.GetRequiredService<IJobFilterProvider>()));
        services.AddScoped<IBackgroundJobPerformer>(x => new BackgroundJobPerformer(x.GetRequiredService<IJobFilterProvider>(), x.GetRequiredService<JobActivator>()));
        services.AddScoped<IBackgroundJobClient>(x => new BackgroundJobClient(x.GetRequiredService<JobStorage>(), x.GetRequiredService<IBackgroundJobFactory>(), x.GetRequiredService<IBackgroundJobStateChanger>()));
        services.AddScoped<IRecurringJobManager>(x => new RecurringJobManager(x.GetRequiredService<JobStorage>(), x.GetRequiredService<IBackgroundJobFactory>()));

        return services.AddHangfire(configuration => { });
    }
}

public static class ApplicationBuilderHangfireExtensions
{
    public static IApplicationBuilder UseHangfire(this IApplicationBuilder appBuilder)
    {
        var lifetime = appBuilder.ApplicationServices.GetRequiredService<IApplicationLifetime>();
        var rootContainer = appBuilder.ApplicationServices.GetRequiredService<IStashboxContainer>();

        using (var serviceScope = appBuilder.ApplicationServices.CreateScope())
        {
            var catalogContext = serviceScope.ServiceProvider.GetRequiredService<ICatalogContext>();
        
            foreach (var tenant in catalogContext.Tenants.Where(x => x.AutomaticMigrationEnabled).AsNoTracking().ToList().Distinct(Tenant.ConnectionStringComparer))
            {
                var childContainer = InitializeChildContainer(rootContainer.CreateChildContainer(), tenant);

                CreateBackgroundJobServer(childContainer, lifetime);

                var recurringJobManager = childContainer.Resolve<IRecurringJobManager>();

                recurringJobManager.AddOrUpdate("TERRA", Job.FromExpression<ITerraService>(x => x.SyncTerrestrialDataAsync()), Cron.Weekly());
            }
        }

        return appBuilder;
    }

    private static IStashboxContainer InitializeChildContainer(IStashboxContainer container, Tenant tenant)
    {
        // Have tried both with and without this line of code, with no difference.
        container.RegisterInstance(container.Resolve<IServiceScopeFactory>().CreateScope().ServiceProvider);
        container.Register<BackgroundJobServer>(x => x.WithSingletonLifetime());
        container.Register<JobStorage>(x => x.WithFactory(y => new SqlServerStorage(tenant.ConnectionString)).WithSingletonLifetime());
        container.Register<JobActivator>(x => x.WithFactory(y => new HangfireActivator(y, tenant.Name)).WithSingletonLifetime());
        container.Register<BackgroundJobServerOptions>(x
            => x.WithFactory(y => new BackgroundJobServerOptions { ServerName = tenant.Name, WorkerCount = 1 }).WithSingletonLifetime()); // TODO: WorkerCount should probably be configurable
        container.Register<IProplanContext, ProplanContext>(x => x.WithInjectionParameters(
                new InjectionParameter { Name = "tenant", Value = tenant },
                new InjectionParameter { Name = "options", Value = new DbContextOptionsBuilder<ProplanContext>().UseSqlServer(tenant.ConnectionString).Options }
            ).WithScopedLifetime()
        );

        return container;
    }

    private static BackgroundJobServer CreateBackgroundJobServer(IDependencyResolver dependencyResolver, IApplicationLifetime lifetime)
    {
        var server = dependencyResolver.Resolve<BackgroundJobServer>();

        lifetime.ApplicationStopping.Register(() => server.SendStop());
        lifetime.ApplicationStopped.Register(() => server.Dispose());

        return server;
    }
}

public class HangfireActivator : JobActivator
{
    private readonly IDependencyResolver _dependencyResolver;
    private readonly string _scopeName;
    private int _scopeCount;

    public HangfireActivator(IDependencyResolver dependencyResolver, string scopeName = "")
    {
        _dependencyResolver = dependencyResolver;
        _scopeName = scopeName;
    }

    public override JobActivatorScope BeginScope(JobActivatorContext context)
    {
        var scopeName = $"{_scopeName}({_scopeCount++})";
        return new HangfireActivatorScope(_dependencyResolver.BeginScope(scopeName, true), context, scopeName);
    }
}

public class HangfireActivatorScope : JobActivatorScope
{
    private readonly IDependencyResolver _scope;
    private readonly JobActivatorContext _context;
    private readonly string _scopeName;

    public HangfireActivatorScope(IDependencyResolver dependencyResolver, JobActivatorContext context, string scopeName)
    {
        _scope = dependencyResolver;
        _context = context;
        _scopeName = scopeName;
    }

    public override object Resolve(Type type)
    {
        try
        {
            return _scope.Resolve(type, true);
        }
        catch (Exception ex)
        {
            throw new Exception($"[Scope: {_scopeName}][Job: {_context.BackgroundJob.Id}] failed to resolve dependency of type: {type.Name}.", ex);
        }
    }

    public override void DisposeScope() => _scope?.Dispose();
}

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (8 by maintainers)

Commits related to this issue

Most upvoted comments

Ah, I see, thanks for your effort anyway, without this issue, those problems would have stayed in the code for a long time I think. And thank you in advance for spending your own time recreating that exception!

Yes, what you described was the main goal of the child container feature, and also it should work now in that way if I remember correctly. To be honest, except the tests I never used this feature in real projects and never got issues about it until now, so I’m really glad because this is an opportunity to make it more usable! Please let me verify that it works as you explained and if not I’ll make the necessary changes!