There are some database operations I need to execute before the end of the final attempt of my Hangfire background job (I need to delete the database record related to the job)
My current job is set with the following attribute:
[AutomaticRetry(Attempts = 5, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
With that in mind, I need to determine what the current attempt number is, but am struggling to find any documentation in that regard from a Google search or Hangfire.io documentation.
Simply add
PerformContext
to your job method; you'll also be able to access yourJobId
from this object. For attempt number, this still relies on magic strings, but it's a little less flaky than the current/only answer:You can use
OnPerforming
orOnPerformed
method ofIServerFilter
if you want to check the attempts or if you want you can just wait onOnStateElection
ofIElectStateFilter
. I don't know exactly what requirement you have so it's up to you. Here's the code you want :)How to add your filter
Sample output :
(NB! This is a solution to the OP's problem. It does not answer the question "How to get the current attempt number")
Use a job filter and the
OnStateApplied
callback:Add the filter directly to the job function:
or add it globally:
or like this:
Or see http://docs.hangfire.io/en/latest/extensibility/using-job-filters.html for more information about job filters.
NOTE: This is based on the accepted answer: https://stackoverflow.com/a/38387512/2279059
The difference is that
OnStateApplied
is used instead ofOnStateElection
, so the filter callback is invoked only after the maximum number of retries. A downside to this method is that the state transition to "failed" cannot be interrupted, but this is not needed in this case and in most scenarios where you just want to do some cleanup after a job has failed.NOTE: Empty
catch
handlers are bad, because they can hide bugs and make them hard to debug in production. It is necessary here, so the callback doesn't get called repeatedly forever. You may want to log exceptions for debugging purposes. It is also advisable to reduce the risk of exceptions in a job filter. One possibility is, instead of doing the cleanup work in-place, to schedule a new background job which runs if the original job failed. Be careful to not apply the filterCleanupAfterFailureFilter
to it, though. Don't register it globally, or add some extra logic to it...