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?
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.