I have simple job:
[DisallowConcurrentExecution]
public class OutgoingRegistriesJob : IJob {
private readonly ILogger<OutgoingRegistriesJob> _logger;
public OutgoingRegistriesJob(ILogger<OutgoingRegistriesJob> logger) {
_logger = logger;
}
public Task Execute(IJobExecutionContext context) {
_logger.LogInformation("{UtcNow}", DateTime.UtcNow);
return Task.CompletedTask;
}
}
This is how I register it to a service pipeline:
public static class QuartzExtensions {
public static IServiceCollection AddQuartzSetup(this IServiceCollection services) {
services.AddQuartz(opts => {
// => this is obsolete... what should I use instead?
// opts.UseMicrosoftDependencyInjectionJobFactory();
});
services.AddQuartzHostedService(options => { options.WaitForJobsToComplete = true; });
services.ConfigureOptions<UpdateS3BackgroundJobSetup>();
return services;
}
}
This is the configuration: If I remove the DbContext it's not failing so it's seems like a kinda of DI issue
public class UpdateS3BackgroundJobSetup : IConfigureOptions<QuartzOptions> {
private readonly IApplicationConfigurationDbContext _dbContext;
public UpdateS3BackgroundJobSetup(
IApplicationConfigurationDbContext dbContext
) {
_dbContext = dbContext;
}
public async void Configure(QuartzOptions options) {
var configuration =
await _dbContext.ApplicationConfigurations
.Where(cfg => cfg.Name == "metamorph-db")
.FirstOrDefaultAsync();
var jobKey = JobKey.Create(nameof(OutgoingRegistriesJob));
options
.AddJob<OutgoingRegistriesJob>(jobBuilder => jobBuilder.WithIdentity(jobKey))
.AddTrigger(trigger =>
trigger
.ForJob(jobKey)
.WithSimpleSchedule(schedule =>
schedule.WithIntervalInMinutes(5).RepeatForever()));
}
}
Error:
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Quartz.Spi.IJobFactory Lifetime: Singleton ImplementationType: Quartz.Simpl.MicrosoftDependencyInjectionJobFactory': Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.) (Error while validating the service descriptor 'ServiceType: Quartz.ContainerConfigurationProcessor Lifetime: Singleton ImplementationType: Quartz.ContainerConfigurationProcessor': Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.) (Error while validating the service descriptor 'ServiceType: Quartz.ISchedulerFactory Lifetime: Singleton ImplementationType: Quartz.ServiceCollectionSchedulerFactory': Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: Quartz.QuartzHostedService': Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.)
---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Quartz.Spi.IJobFactory Lifetime: Singleton ImplementationType: Quartz.Simpl.MicrosoftDependencyInjectionJobFactory': Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.
---> System.InvalidOperationException: Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateCallSite(ServiceCallSite callSite)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
at Program.<Main>$(String[] args) in /Users/genady/dev/ar-dotnet-workspace/MetamorphDB/Api/Program.cs:line 52
---> (Inner Exception #1) System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Quartz.ContainerConfigurationProcessor Lifetime: Singleton ImplementationType: Quartz.ContainerConfigurationProcessor': Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.
---> System.InvalidOperationException: Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateCallSite(ServiceCallSite callSite)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)<---
---> (Inner Exception #2) System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Quartz.ISchedulerFactory Lifetime: Singleton ImplementationType: Quartz.ServiceCollectionSchedulerFactory': Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.
---> System.InvalidOperationException: Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateCallSite(ServiceCallSite callSite)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)<---
---> (Inner Exception #3) System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: Quartz.QuartzHostedService': Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.
---> System.InvalidOperationException: Cannot consume scoped service 'Application.Common.Interfaces.IApplicationConfigurationDbContext' from singleton 'Microsoft.Extensions.Options.IOptions`1[Quartz.QuartzOptions]'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateCallSite(ServiceCallSite callSite)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)<---
Issue is indeed related to dependency injection. IConfigureOptions is Singleton thus you cannot inject a scoped service like IApplicationConfigurationDbContext. But you can create a scope and resolve manually.
public class UpdateS3BackgroundJobSetup : IConfigureOptions<QuartzOptions> {
private readonly IServiceProvider _provider;
public UpdateS3BackgroundJobSetup(
IServiceProvider provider
) {
_provider = provider;
}
public async void Configure(QuartzOptions options) {
// Create a new scope
using (var scope = _provider.CreateScope())
{
// Resolve the Scoped service
var dbContext = scope.ServiceProvider.GetService<IApplicationConfigurationDbContext>();
var configuration =
await dbContext.ApplicationConfigurations
.Where(cfg => cfg.Name == "metamorph-db")
.FirstOrDefaultAsync();
var jobKey = JobKey.Create(nameof(OutgoingRegistriesJob));
options
.AddJob<OutgoingRegistriesJob>(jobBuilder => jobBuilder.WithIdentity(jobKey))
.AddTrigger(trigger =>
trigger
.ForJob(jobKey)
.WithSimpleSchedule(schedule =>
schedule.WithIntervalInMinutes(5).RepeatForever()));
}
}
}