How to configure AddHangfireServer options.Queues if I need other services from within ConfigureServices()?

In aspnet core (or .net5), if I want a server to only process specific queues then within ConfigureServices() I should do something like this:

string[] queues = new[] { "one", "two" };
services.AddHangfireServer(options => { options.Queues = queues; });

But if I need to use some other .net objects to get my array of queue names (e.g. in my case, connect to a database to look them up) it’s quite hard to do this within ConfigureServices() since no serviceProvider is available and you shouldn’t build one as it’ll create an additional copy of singletons. Does anyone have a good pattern for solving this? The answers here don’t appear straightforward since the AddHangfireServer() method isn’t a trivial AddSingleton() call.

Currently I’m thinking it’ll be easiest to directly instantiate the objects I need within ConfigureServices, before using them to call AddHangfireServer(), but that’s not super simple in my case so I’d love to hear how anyone else has solved this.

thanks for any tips.

Rory

You could make your queue names constants.

If constants aren’t a good options for you, you could pass your queue names inside the configuration of your application.

Thanks for the reply. My queue names depend on the current system configuration, which can change from time to time, so can’t be constants. Specifically the queues represent which tenants that server is responsible for, and that’s stored in a database. I’ve considered making an IOptions to represent that configuration, and define it’s source from a database. But it feels quite difficult to do all that inside ConfigureServices and ensure it’s available before the call to AddHangfireServer.

I don’t see another way than doing what you said if you don’t want to instantiate a ServiceProvider inside the ConfigureService method.

Here’s a link that could help you : https://andrewlock.net/access-services-inside-options-and-startup-using-configureoptions/

1 Like

Hi guys,
I use this code to implement this:

private List<string> GetQueuesHangFire(IApplicationBuilder app)
    {
        using var serviceScope = app.ApplicationServices
        .GetRequiredService<IServiceScopeFactory>()
        .CreateScope();

        using var context = serviceScope.ServiceProvider.GetService<Models.DB.MyCustomContext>();
        var res = context.Queues.Select(x => x.Code).ToList();
        res.Add("default");
        return res;
    }

I hope that this help you.
Regards
Gon

Hi Gon, thanks for that. So you call that from Configure, not ConfigureServices? How are you starting the Hangfire server? The sample for asp.net puts it in ConfigureServices: services.AddHangfireServer() from which the ServiceProvider isn’t available yet.

Hi Roryk,
I call this method on Configure method using this:

var options = new BackgroundJobServerOptions
        {
            Queues = GetQueuesHangFire(app).ToArray()
        };
        app.UseHangfireServer(options, additionalProcesses: new[] { new ProcessMonitor(checkInterval: TimeSpan.FromSeconds(1)) });

The example is using net core 5 and net core 3.1 sincerely I didn’t test on asp.net classic.

Please could you test and give us your feedback?
Best regards
Gon

Hi Rory,

Did you ever work out how to resolve this? Running into the same problem and can’t find any examples on solving it.

Particularly as app.UseHangfireServer is now marked as Obsolete and will be removed in version 2.0.0

Thanks,
John

Hi there, since Hangfire 1.7.26 it’s now possible to use IServiceProvider type in the callback that’s passed to the AddHangfireServer.

services.AddHangfireServer((provider, options) =>
    options.Queues = provider.GetRequiredService<MyDatabase>().Queues);
1 Like

Thanks for the quick response Sergey. That should do the trick.