Search code examples
postgresql.net-corehangfire

Hangfire Recurring jobs not working - throw exception: "Unable to find a constructor"


I have .net core 2.1 web APP with Hangfire library (1.7.9) working on postgres (12).

I tried to add recurring job, but each time where Hangfire tried to fire it, it throws exception:

"Hangfire.Common.JobLoadException: Could not load the job. See inner exception for the details. ---> Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Microsoft.Extensions.FileProviders.PhysicalFileProvider. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'Providers[0].Source.FileProvider.Root', line 1, position 490."

My startup file (Hangfire's section):

 private void ConfigureHangfire(IServiceCollection services)
        {
            var settings = Configuration.GetSettings<HangfireSettings>();

            GlobalConfiguration.Configuration
                .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                .UseSimpleAssemblyNameTypeSerializer()
                .UseRecommendedSerializerSettings()
                .UsePostgreSqlStorage(Configuration.GetConnectionString("service_user"), new PostgreSqlStorageOptions
                {
                    SchemaName = "hangfire",
                    QueuePollInterval = TimeSpan.FromSeconds(15),
                    UseNativeDatabaseTransactions = true,
                    PrepareSchemaIfNecessary = true,
                    TransactionSynchronisationTimeout = TimeSpan.FromMinutes(15)
                });

            var options = new PostgreSqlStorageOptions
            {
                PrepareSchemaIfNecessary = settings.CreateDatabaseAutomatically
            };

            services.AddHangfire(config => config.UsePostgreSqlStorage(Configuration.GetConnectionString("service_user"), options));

            DailyDatabaseUpdate.TurnOnDailyUpdateScheduleWorker(9, 51, Configuration);
        }

After my test I realized that my method DailyDatabaseUpdate.TurnOnDailyUpdateScheduleWorker(9, 51, Configuration); contains parametr IConfiguration configuration . When I removed it everything works. But this interace is crucial to get my connection string.

How it can be solved?


Solution

  • A good solution is to have connectionstring set up part as IOption or something similar like binding configuration to some object and then contructor-injecting this object to a class which contains method acting as recurring job.

    Example:

    public StatusJobs(DbOptions dbOptions)
    {
        _dbOptions= dbOptions
    }
    
    [DisableConcurrentExecution(timeoutInSeconds: 20)]
    [AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
    public void DoSmth()
    {
        //dbOptions avalaible here
    }
    

    Also, it would be better to inject some connectionfactory instead of connectiostring.