Version 1.5.0 will open many types that were internal in previous versions of Hangfire, like Worker or IBackgroundFactory, to enable you to have completely custom background processing. This release simplifies the usage of these types, of course only to decrease the amount of questions on forums :smiley:.

1.5.0-beta3 comes with refactored Hangfire.States namespace – I was ashamed to make the IStateMachineFactoryFactory interface public (I believe FactoryFactory is an absolute evil). Worker identifiers are now auto-generated and based on GUIDs to prevent us from id collisions. Please read the GitHub release notes for some more details.

Filters for Processing state

Perhaps, this is the most important change in this release, apart from refactoring. Thanks to Andrew Young (@yngndrw on GitHub) for addressing the problem and fixing the original silly behavior, now Worker background process does not process a background job when it was unable to move it to the processing state.

This change allows us to intercept the moment when a worker fetches a background job to process it, and move it to other state than processing depending on some conditions.

  • Deleted to consider it cancelled (timeout elapsed, for example).
  • Enqueued to move it to the end of the queue (other jobs need to be processed, for example).
  • Scheduled to postpone its execution (can’t come up with an example, it’s your turn).

For example, here is the simplest implementation of a timeout filter, where you specify the timeout in hours, and the job is moved to the deleted state instead of processing.

public sealed class TimeoutAttribute : JobFilterAttribute, IElectStateFilter
{
    private readonly int _hours;

    public TimeoutAttribute(int hours)
    {
        _hours = hours;
    }

    public void OnStateElection(ElectStateContext context)
    {
        if (context.CandidateState is ProcessingState)
        {
            if (context.BackgroundJob.CreatedAt.AddHours(_hours) < DateTime.UtcNow)
            {
                context.CandidateState = new DeletedState();
            }
        }
    }
}   

Cancellation Tokens

It is possible now to use CancellationToken type in your job method parameters. Before calling a method, Hangfire will replace it with its own token that will fire on BackgroundJobServer instance shutdown.

public void AbortOnShutdownOnly(CancellationToken cancellationToken)
{
    for (var i = 0; i < 100000; i++)
    {
        Thread.Sleep(1000);
        cancellationToken.ThrowIfCancellationRequested();
    }
}

// Use CancellationToken.None or any other value
BackgroundJob.Enqueue(() => AbortOnShutdownOnly(CancellationToken.None));  

If you want your methods to be aborted during a state change (for example, after clicking the Delete or Requeue button in the dashboard), use the IJobCancellationToken interface, that fires in both cases: server shutdown and state change.

public void AbortOnShutdownAndStateChange(IJobCancellationToken cancellationToken)
{
    for (var i = 0; i < 100000; i++)
    {
        Thread.Sleep(1000);
        cancellationToken.ThrowIfCancellationRequested();
    }
}

BackgroundJob.Enqueue(() => AbortOnShutdownAndStateChange(JobCancellationToken.Null));

Subscribe to monthly updates

Subscribe to receive monthly blog updates. Very low traffic, you are able to unsubscribe at any time.

Comments