Hangfire
Hangfire copied to clipboard
DisableConcurrentExecution doesn't work for RecurringJob
I am using Hangfire 1.7.3 and Hangfire.PostgreSql 1.6.0 on ASPNET Core 2.2.300. And I have a 24/7 RecurringJob running every minute with default 20 workers on server along with other jobs. This job can take more than 60 secunds sometimes and no concurrent execution should occur.
As a test project I used a job:
[AutomaticRetry(Attempts = 0)]
public class TestB {
[DisableConcurrentExecution(36000)]
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogWarning("Iniciando teste B");
try
{
System.Threading.Thread.Sleep(65000);
}
catch (Exception ex)
{
var message = "Fatal error in test B.";
_logger.LogCritical(ex, message);
throw;
}
_logger.LogWarning("Test B finished.");
return Task.CompletedTask;
}
And added on Startup as:
RecurringJob.AddOrUpdate<TestB>(nameof(TestB),
job => job.StartAsync(CancellationToken.None),
cronExpression: Configuration["CRON_JOB:TEST_B"],
TimeZoneInfo.Local);
During the 36000 seconds sometimes more than one job is triggered and also after that many at triggered in parallel. I wish this timeout should be infinite, but even during this time the annotation does not work.
Hi - I'm having the same problem.
Did this ever get resolved?
Thanks,
@Skeldave no, I just gave up on Hangfire. It is just not reliable/enough maintained. I have many production problems with it. It also have tons of bugs and unanswered issues like this one. I really suggest you go with other library or native batch jobs from .NET or other platform.
Whys isn't this still addressed?
@staticdev do you have any alternatives for what you switched to? I'm feeling the exact same about Hangfire. It's just not reliable and support/documentation is terrible. But I didn't see much better alternatives except Quartz.NET which is pretty rough as well.
Recurring job scheduler behaves the same way as System.Threading.Timers – it doesn't execute jobs in place, it enqueues a new background job when it's time to do so. There's a job filter that works as a client filter to prevent parallel execution of a recurring job, please see https://gist.github.com/odinserj/a6ad7ba6686076c9b9b2e03fcf6bf74e.
I'm sorry you had terrible experience, usually everything is fine when official storages are used. Regarding documentation, better storage support (and better documentation), better covering on what are the filters and how to write them correctly – I've spent enormous amount of time on these topics, it's just the topic of distributed processing is difficult. I working hard to make everything better and understand your pain.
I have zero problems with Hangfire for 5 years now. We use MS SQL for storage on latest NetCore (DotNet6) WebApp running on 4 servers. I have cca 60.000 Hangfire succeeded jobs (among normal jobs I have 15 recurring jobs) per/day.
I'm very happy with Hangfire and been using it for 7 years now. I use it with the official MS SQL storage and a storage provider i developed myself (https://www.nuget.org/packages/Hangfire.CompositeC1/) which have fullfilled my needs on countless of solutions throughout the years.
Recurring job scheduler behaves the same way as System.Threading.Timers – it doesn't execute jobs in place, it enqueues a new background job when it's time to do so. There's a job filter that works as a client filter to prevent parallel execution of a recurring job, please see https://gist.github.com/odinserj/a6ad7ba6686076c9b9b2e03fcf6bf74e.
I'm sorry you had terrible experience, usually everything is fine when official storages are used. Regarding documentation, better storage support (and better documentation), better covering on what are the filters and how to write them correctly – I've spent enormous amount of time on these topics, it's just the topic of distributed processing is difficult. I working hard to make everything better and understand your pain.
Hello there! I have a problem with this code. After some time (cannot really say what is some) some of my recurring jobs which are decorated with this attribute are stopping execution. I mean they are immediately canceled after new execution and when I placed logger there here is what it produces:
2023-11-28 16:05:33.7064|INFO|Namespace.Jobs.Hangfire.Attributes.SkipWhenPreviousJobIsRunningAttribute|running: yes
2023-11-28 16:05:33.7064|INFO|Namespace.Jobs.Hangfire.Attributes.SkipWhenPreviousJobIsRunningAttribute|Job will be canceled
and here is code in C#
var logger = new NLogFactory().Create(this);
string running = connection.GetValueFromHash($"recurring-job:{recurringJobId}", "Running");
logger.Info($"running: {running}");
if ("yes".Equals(running, StringComparison.OrdinalIgnoreCase))
{
logger.Info($"Job will be canceled");
context.Canceled = true;
}
I don't know why is it happening, but it won't trigger from this moment... I am using SQLite file as DB.