Hangfire seems to work well with .NET Core 2.0. There's one thing though.
ASP.NET Core 2.0 seems to have changed how services should be initiated. Previously Configure method of Startup.cs used to be the recommended place to do so. Now it seems to be the Main method of Program.cs. It's the recommended way of running database seed methods for example.
The problem is visible when using migrations in the project. Having Hangfire initialization in Configure causes Add-Migration command to execute the following:
PM> Add-Migration Lorem
Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using 'C:\Users\foo\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
infoinfo: Hangfire.SqlServer.SqlServerStorage[0]
Start installing Hangfire SQL objects...
: Hangfire.SqlServer.SqlServerStorage[0]
Start installing Hangfire SQL objects...
infoinfo: Hangfire.SqlServer.SqlServerStorage[0]
Hangfire SQL objects installed.
: Hangfire.SqlServer.SqlServerStorage[0]
Hangfire SQL objects installed.
Hangfire.BackgroundJobServer[0]
Starting Hangfire Server
Hangfire.BackgroundJobServer[0]
Starting Hangfire Server
Hangfire.BackgroundJobServer[0]
Using job storage: 'SQL Server: tcp:foo,1433@bar'
Hangfire.BackgroundJobServer[0]
Using job storage: 'SQL Server: tcp:foo,1433@bar'
Hangfire.BackgroundJobServer[0]
Using the following options for SQL Server job storage:
Hangfire.BackgroundJobServer[0]
Using the following options for SQL Server job storage:
Hangfire.BackgroundJobServer[0]
Queue poll interval: 00:00:15.
Hangfire.BackgroundJobServer[0]
Queue poll interval: 00:00:15.
Hangfire.BackgroundJobServer[0]
Using the following options for Hangfire Server:
Hangfire.BackgroundJobServer[0]
Using the following options for Hangfire Server:
Hangfire.BackgroundJobServer[0]
Worker count: 20
Hangfire.BackgroundJobServer[0]
Worker count: 20
Hangfire.BackgroundJobServer[0]
Listening queues: 'default'
Hangfire.BackgroundJobServer[0]
Listening queues: 'default'
Hangfire.BackgroundJobServer[0]
Shutdown timeout: 00:00:15
Hangfire.BackgroundJobServer[0]
Schedule polling interval: 00:00:15
Hangfire.BackgroundJobServer[0]
Shutdown timeout: 00:00:15
Hangfire.BackgroundJobServer[0]
Schedule polling interval: 00:00:15
dbug: Hangfire.Server.BackgroundProcessingServer[0]
Background process 'BackgroundProcessingServer' started.
dbug: Hangfire.Server.BackgroundProcessingServer[0]
Background process 'BackgroundProcessingServer' started.
dbug: Hangfire.Server.ServerHeartbeat[0]
Background process 'ServerHeartbeat' started.
dbug: Hangfire.Server.ServerHeartbeat[0]
Background process 'ServerHeartbeat' started.
dbug: Hangfire.Server.ServerWatchdog[0]
Background process 'ServerWatchdog' started.
dbug: Hangfire.Server.ServerWatchdog[0]
Background process 'ServerWatchdog' started.
Microsoft.EntityFrameworkCore.Infrastructure[100403]
Entity Framework Core 2.0.0-rtm-26452 initialized 'ApplicationDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
Microsoft.EntityFrameworkCore.Infrastructure[100403]
Entity Framework Core 2.0.0-rtm-26452 initialized 'ApplicationDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
dbug: Hangfire.SqlServer.ExpirationManager[0]
Background process 'Hangfire.SqlServer.ExpirationManager' started.
dbug: Hangfire.SqlServer.ExpirationManager[0]
Background process 'Hangfire.SqlServer.ExpirationManager' started.
dbug: Hangfire.SqlServer.ExpirationManager[0]
Removing outdated records from the 'AggregatedCounter' table...
dbug: Hangfire.SqlServer.ExpirationManager[0]
Removing outdated records from the 'AggregatedCounter' table...
dbug: Hangfire.SqlServer.CountersAggregator[0]
Background process 'Hangfire.SqlServer.CountersAggregator' started.
dbug: Hangfire.SqlServer.CountersAggregator[0]
Background process 'Hangfire.SqlServer.CountersAggregator' started.
dbugverbose: Background process 'Worker #1539d0f6' started.
dbug: Hangfire.SqlServer.CountersAggregator[0]
Aggregating records in 'Counter' table...
: Hangfire.SqlServer.CountersAggregator[0]
Aggregating records in 'Counter' table...
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #1539d0f6' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #1539d0f6' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #87fe3ef2' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #87fe3ef2' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #df81ffa2' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #df81ffa2' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #0b330fd5' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #0b330fd5' started.
dbugdbug: Hangfire.Server.Worker[0]
Background process 'Worker #e823ec90' started.
: Hangfire.Server.Worker[0]
Background process 'Worker #e823ec90' started.
dbugdbug: Hangfire.Server.Worker[0]
Background process 'Worker #ca628671' started.
: Hangfire.Server.Worker[0]
Background process 'Worker #ca628671' started.
dbugdbug: Hangfire.Server.Worker[0]
Background process 'Worker #2270f94b' started.
: Hangfire.Server.Worker[0]
Background process 'Worker #2270f94b' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #fccd8a70' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #fccd8a70' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #54d3e893' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #54d3e893' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #e0d82339' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #e0d82339' started.
dbugdbug: Hangfire.Server.Worker[0]
Background process 'Worker #4994ba1c' started.
: Hangfire.Server.Worker[0]
Background process 'Worker #4994ba1c' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #340890e5' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #340890e5' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #02ce354a' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #02ce354a' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #7e84e191' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #7e84e191' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #7bdb94d1' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #7bdb94d1' started.
dbugverbose: Background process 'Worker #28c56838' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #28c56838' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #b8e5394f' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #4630dd3a' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #6bb65a7c' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #9c87b85b' started.
dbug: Hangfire.Server.DelayedJobScheduler[0]
Background process 'DelayedJobScheduler' started.
dbug: Hangfire.Server.RecurringJobScheduler[0]
Background process 'RecurringJobScheduler' started.
: Hangfire.Server.Worker[0]
Background process 'Worker #28c56838' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #b8e5394f' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #4630dd3a' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #6bb65a7c' started.
dbug: Hangfire.Server.Worker[0]
Background process 'Worker #9c87b85b' started.
dbug: Hangfire.Server.DelayedJobScheduler[0]
Background process 'DelayedJobScheduler' started.
dbug: Hangfire.Server.RecurringJobScheduler[0]
Background process 'RecurringJobScheduler' started.
dbug: Hangfire.SqlServer.ExpirationManager[0]
Removing outdated records from the 'Job' table...
dbug: Hangfire.SqlServer.ExpirationManager[0]
Removing outdated records from the 'Job' table...
To undo this action, use Remove-Migration.
Maybe it's harmless, but still, running the pipeline with every Add-Migration is not optimal.
A quick workaround is not to initialize Hangfire in Development mode as that's when migration are generated. I'm wondering what the permanent solution may be.
if (!env.IsDevelopment())
{
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new[] { new HangfireAuthorizationFilter() }
});
app.UseHangfireServer();
}
Hangfire does in fact cause some issues with Add-Migration scenarios, have had similar issues.
The solution for my case was to split up the BuildWebHost code into a similar setup, but when running from Main instead of the Add-Migration I have setup a BuildMainWebHost which does exactly the same as the normal BuildWebHost, except I add an IStartupFilter into the service collection.
public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services => services.AddAutofac())
.UseStartup<Startup>()
.UseNLog()
.Build();
public static IWebHost BuildMainWebHost(string[] args) => WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services => {
services.AddAutofac();
services.AddTransient<IStartupFilter, HangfireStartupFilter>();
})
.UseStartup<Startup>()
.UseNLog()
.Build();
public static void Main(string[] args)
{
BuildMainWebHost(args).UseInitializer(typeof(IPimDbInitializer), typeof(IEtimDbInitializer), typeof(IIntranetDbInitializer))
.UseFileLoaders()
.Run();
}
The AddHangfire method can be called inside your normal ConfigureServices, however the UseHangfireDashboard and UseHangfireServer methods must not be called when trying to work with migrations. Therefor these can be placed inside an IStartupFilter implementation like so:
public class HangfireStartupFilter : IStartupFilter
{
#region Methods
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
builder.UseHangfireDashboard();
builder.UseHangfireServer();
next(builder);
};
}
#endregion Methods
}
Hope it helps!
Most helpful comment
Hangfire does in fact cause some issues with Add-Migration scenarios, have had similar issues.
The solution for my case was to split up the BuildWebHost code into a similar setup, but when running from Main instead of the Add-Migration I have setup a BuildMainWebHost which does exactly the same as the normal BuildWebHost, except I add an IStartupFilter into the service collection.
The AddHangfire method can be called inside your normal ConfigureServices, however the UseHangfireDashboard and UseHangfireServer methods must not be called when trying to work with migrations. Therefor these can be placed inside an IStartupFilter implementation like so:
Hope it helps!