public static class HangfireConfig { public static void AddHangfire(this IServiceCollection services, IConfiguration configuration) { Log.Information("Configuring hangfire..."); services.AddScoped(); services.AddHangfire(config => config .SetDataCompatibilityLevel(CompatibilityLevel.Version_170) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UseSqlServerStorage(configuration["ConnectionStrings:Default"], new SqlServerStorageOptions { CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), QueuePollInterval = TimeSpan.Zero, UseRecommendedIsolationLevel = true, DisableGlobalLocks = true }) .UseFilter(new HangfireProlongJobExpirationAttribute()) .UseFilter(new HangfireLogFailureAttribute()) .UseConsole()); services.AddHangfireServer(options => { options.ServerName = $"{Environment.MachineName}:AdminServer"; options.WorkerCount = Math.Min(Environment.ProcessorCount * 5, 20); options.Queues = new[] { Environment.MachineName.ToLower(), "default" }; options.SchedulePollingInterval = TimeSpan.FromMinutes(1); options.CancellationCheckInterval = TimeSpan.FromMinutes(1); }); } public static void UseHangfireDashboard(this IApplicationBuilder app) { app.UseHangfireDashboard("/admin/hangfire", new DashboardOptions { AppPath = "/admin/home", Authorization = new[] { new HangfireAuthorizationFilter() }, StatsPollingInterval = 15000 }, JobStorage.Current); InitializeRecurringJobs(); } public static void InitializeRecurringJobs() { using (var connection = JobStorage.Current.GetConnection()) { foreach (var recurringJob in connection.GetRecurringJobs()) { RecurringJob.RemoveIfExists(recurringJob.Id); } } RecurringJob.AddOrUpdate("Keep_Alive", h => h.KeepAlive(1, null), "*/20 * * * *"); } }