50

Is there a way to disable re-queueing of a failed Hangfire BackgroundJob?

We do not want the failed jobs to be executed again as this might cause issues.

Owen Pauling
  • 11,349
  • 20
  • 53
  • 64
user2992766
  • 1,156
  • 1
  • 8
  • 14

5 Answers5

42

Solved, using [AutomaticRetry(Attempts = 0)]

CodeZombie
  • 5,367
  • 3
  • 30
  • 37
user2992766
  • 1,156
  • 1
  • 8
  • 14
  • 4
    You may also add `OnAttemptsExceeded = AttemptsExceededAction.Delete` to ignore them and do not blow up the "failed jobs" page. – odinserj Mar 04 '15 at 15:46
  • 1
    This solution is what that docs say to do, but in practice, I don't see a difference in the running system. My failed jobs retry themselves even when this attribute is on the method that I'm calling from my recurring Job. Others seem to have the [same problem](http://discuss.hangfire.io/t/automaticretry-attempts-0-onattemptsexceeded-attemptsexceededaction-fail-is-not-working/648) too. – Nate Jackson Mar 31 '15 at 16:30
  • 8
    if using DI container you must put the attribute on the interface definition and not on the implementation. eg. `interface IMyService { [AutomaticRetry(Attempts = 0)void MyMethod(); }` – Simon_Weaver May 08 '18 at 01:14
29

You can either annotate the method to run in the background with the following attribute:

[AutomaticRetry(Attempts = 0)]

Or set it globally:

GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
Owen Pauling
  • 11,349
  • 20
  • 53
  • 64
  • But how do you do this on a job-by-job basis? Say you want retries by defualy, but a job failed in an unrecoverable way and you don't want it to retry that specific job. – Douglas Gaskell Feb 06 '22 at 18:47
19

Important if using DI container with an interface, you must put the attribute on the interface definition

public interface IDataUpdater
{
    [Hangfire.AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
    void UpdateData();
}

Queue the job like this

Hangfire.RecurringJob.AddOrUpdate<IDataUpdater>(updater => updater.UpdateData(), Cron.Hourly);

Test it by just throwing any old exception within your implementation. If you've done it right you'll see this in the job history under 'deleted'.

enter image description here

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
9

Ran into this today but wanted to set the Retry Filter globally in a .NET API application.

The following worked...

services.AddHangfire(configuration => {
            // Disable retry for failed jobs
            // https://docs.hangfire.io/en/latest/background-processing/dealing-with-exceptions.html?highlight=retry
            configuration.UseFilter(new AutomaticRetryAttribute { Attempts = 0 });
        });
Marty
  • 321
  • 3
  • 5
7

I ran into a similar issue and I was able to find a solution. Using a global filter was not an option for me. I'm using asp.net core and I have a simple fire and forget background job. For some reason the AutomaticRetryAttribute was being ignored. It turned out the way I was adding the job was the key to my solution. I had a similar code in my app that was causing the issue:

BackgroundJob.Enqueue<IMyJobService>(js => js.DoWork());

In my IMyJobService implementation I had the following code:

[AutomaticRetry(Attempts = 0)]
public void DoWork()
{
    // I'm working hard here
}

The solution that I came up with was:

public MyTestController
{
    private readonly IMyJobService _myJobService;

    public MyTestClass(IMyJobService myJobService)
    {
        _myJobService = myJobService;
    }

    public ActionResult Work()
    {
        BackgroundJob.Enqueue(() => _myJobService.DoWork());
        return Ok();
    }
}

Instead of relying on BackgroundJob.Enqueue<T> to inject my IMyJobService implementation I do it myself. That's basically it. I hope this will help someone.

Stef
  • 203
  • 3
  • 4
  • 3
    I solved the same issue putting the AutomaticRetryAttribute on the method definition of the interface, not on the implemented one. – gjspaho Oct 03 '17 at 18:28