Register a Separate DI Pipeline for Hangfire Jobs with Custom Activator

For those that don’t know, Hangfire is a powerful tool for setting up background jobs for .NET projects. It gives you the ability to leverage your existing backend code for schedules and recurring background jobs.

Save time and reduce duplication.

By leveraging the existing backend code, you can get jobs up and running much faster than if you were to set them up as a standalone service. You also save yourself the hassle of duplicating backend logic or setting up calls to your API.

Hangfire also provides an easy-to-use UI that gives you the ability to monitor, debug, and trigger jobs that are running within the tool. It is nothing over the top, but more than enough to get you off the ground.

Reuse your DI pipeline.

Another benefit of Hangfire is that you can re-use your existing DI pipeline. This mean that any services that you are injecting into you project will also be made available to the Hangfire jobs. This is where the strength of Hangfire comes from.

This does, however, come with one possible disadvantage. By default, you can’t separate functionality you want for backend jobs that is different from your other services.

Using a custom job activator.

This is where the custom job activator comes into play.This powerful Hangfire class give you the ability to pass in a separate service provider from what would be used through the traditional Hangfire flow.

To make it work, you will need to create a class that implements jobActivator.


private class CustomJobActivator : JobActivator {
    private readonly IServiceProvider _serviceProvider;

    public CustomJobActivator(IServiceProvider serviceProvider) =>
        _serviceProvider = serviceProvider;

    public override object ActivateJob(Type type) =>
        _serviceProvider.GetRequiredService(type);
}

Then you will need to tell the hangfire config to us the custom activator:


services.AddHangfire(hangfireConfig => hangfireConfig
    // other hangfire config methods
    .UseActivator(new CustomJobActivator(jobServices
        .BuildServiceProvider())));

There’s no need to replace everything.

Usually there are only a few things you want to replace in the default service provider. If this is the case then there is one more step you are going to need.

At the end of the day, a service provider is just a list of interfaces and their concrete implementations so the easiest way to replicate that is to copy them over. Here we can take advantage of the fact that .NET will use whatever the last mapping added was and override the implementation of any services we want to change.


var jobServices = new ServiceCollection();

foreach (var service in services) {
    jobServices.Add(service);
}

// Replace the application specific implementation with the job specific one
jobServices.AddSingleton<ISharedInterface, JobSpecificImplenation>();

// These need to be added when you override the standard hangfire activator
jobServices.AddSingleton(provider =>
    new BackgroundJobClient());
jobServices.AddSingleton(provider =>
    new RecurringJobManager());

It’s also important to note that, when you use a custom activator, you must also add two providers that Hangfire needs to function properly.

Conversation

Join the conversation

Your email address will not be published. Required fields are marked *