Custom IBackgroundJobStateChanger Not Being Called

Environment

  • Hangfire Version: 1.8.7
  • Hosting Environment: (e.g., Linux, .NET Core 8)

Issue

I am attempting to implement a custom IBackgroundJobStateChanger to intercept and log every state change in my Hangfire jobs. My goal is to execute specific logic every time a job’s state changes (e.g., from Enqueued to Processing, or from Processing to Succeeded, same with failed).

Despite following the standard procedure for replacing the default IBackgroundJobStateChanger with a custom implementation, I’m observing that my custom state changer is not being invoked consistently for every state change.

Current Implementation

I’ve configured my custom IBackgroundJobStateChanger as follows in my Program.cs:

public void ConfigureServices(IServiceCollection services)
{
    builder.Services
    .AddTransient<IBackgroundJobStateChanger, BackgroundJobStateChanger>()
    .AddTransient<IBackgroundJobFactory, BackgroundJobFactory>()     
    .AddTransient<IBackgroundJobStateChanger>(x
    => new CustomBackgroundJobStateChanger(
        x.GetRequiredService<ILogger<CustomBackgroundJobStateChanger>>(),
        new BackgroundJobStateChanger(
            x.GetRequiredService<IJobFilterProvider>())));
}

CustomBackgroundJobStateChanger Implementation

public class CustomBackgroundJobStateChanger(
    ILogger<CustomBackgroundJobStateChanger> iLogger,
    [NotNull] IBackgroundJobStateChanger inner) : IBackgroundJobStateChanger
{
    private readonly IBackgroundJobStateChanger _inner = inner ?? throw new ArgumentNullException(nameof(inner));

    public IState ChangeState(StateChangeContext context)
    {
        iLogger.LogInformation("Entering ChangeState in CustomBackgroundJobStateChanger");
        iLogger.LogError("ChangeState {ContextBackgroundJobId} to {ContextNewState}", context.BackgroundJobId, context.NewState);
        var result = _inner.ChangeState(context);
        iLogger.LogInformation("Exiting ChangeState in CustomBackgroundJobStateChanger");
        return result;
    }
}

Questions

  1. Are there known issues or limitations with IBackgroundJobStateChanger in Hangfire 1.8.7 that could prevent a custom implementation from being invoked as expected?
  2. Is there a recommended approach or alternative method to ensure that custom logic can be executed reliably on every state change in Hangfire jobs?

Thank you for your assistance and any guidance you can provide on this issue.