Base solution for your next web application
Open Closed

Unable to run Hangfire with multiple queues #5495


User avatar
0
jefftindall created

We currently have an application utilizing Hangfire with all jobs going to the "default" queue. We are attempting to utilize multiple queues now and are having no luck at this point.

The class that we want to defer to a different queue is decorated with the new queue name and we've added the following code to our App_Start\Startup.cs file:

app.UseHangfireServer(new BackgroundJobServerOptions
{
    Queues = new string[] { "default", "secondary" }
});

We are configuring our JobStorage in the PreInitialize function of the Abp startup module.

When we launch the application with this configuration, we receive the following errors in the log:

DEBUG 2018-08-09 14:31:51,751 [c94ad] Hangfire.Server.Worker - Background process 'Worker #5f7c94ad' started. DEBUG 2018-08-09 14:31:51,777 [28638] Hangfire.Server.Worker - Background process 'Worker #0f928638' started. DEBUG 2018-08-09 14:31:51,796 [c94ad] Hangfire.Server.Worker - Error occurred during execution of 'Worker #5f7c94ad' process. Execution will be retried (attempt #1) in 00:00:00 seconds. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Transactions.TransactionException: The operation is not valid for the state of the transaction. ---> System.Transactions.TransactionPromotionException: Failure while attempting to promote transaction. ---> System.Data.SqlClient.SqlException: There is already an open DataReader associated with this Command which must be closed first. ---> System.ComponentModel.Win32Exception: The wait operation timed out --- End of inner exception stack trace ---

Additionally we are unable to see the new queue in the Hangfire dashboard, so it's obviously not working.

We had a thought that moving the JobStorage initilization into the Startup class, but when we do that I get: 'JobStorage.Current property value has not been initialized. You must set it before using Hangfire Client or Server API.'

Commenting out the UseHangfireServer configuration above will allow all default queue processing to work as expected.

Has anyone had any success getting multiple queues working with ASP.NET Zero/ASP.NET Boilerplate/Hangfire?


3 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    We are configuring our JobStorage in the PreInitialize function of the Abp startup module.

    What is the specific code? I want to reproduce this problem.

  • User Avatar
    0
    jefftindall created

    Here is the code we are using to setup the SqlServerStorage:

    var optServiceBusQueue = ConfigurationManager.AppSettings[AppSettings.Hangfire.ServiceBusQueue];
    var optServiceBusQueuePrefix = ConfigurationManager.AppSettings[AppSettings.Hangfire.ServiceBusQueuePrefix];
    var sqlStorage = new SqlServerStorage("Default");
    var connectionString = ConfigurationManager.ConnectionStrings["Microsoft.ServiceBus.ConnectionString"];
    int timeToLiveDays = 14;
    Action<QueueDescription> configureAction = qd =>
    {
        qd.MaxSizeInMegabytes = 5120;
        qd.DefaultMessageTimeToLive = new TimeSpan(timeToLiveDays, 0, 0, 0);
    };
    
    sqlStorage.UseServiceBusQueues(new ServiceBusQueueOptions
    {
        ConnectionString = connectionString.ConnectionString,
    
        Configure = configureAction,
    
        // The actual queues used in Azure will have this prefix if specified
        // (e.g. the "default" queue will be created as "my-prefix-default")
        //
        // This can be useful in development environments particularly where the machine
        // name could be used to separate individual developers machines automatically
        // (i.e. "my-prefix-{machine-name}".Replace("{machine-name}", Environment.MachineName))
        QueuePrefix = optServiceBusQueuePrefix,
    
        // The queues to monitor. This *must* be specified, even to set just
        // the default queue as done here
        Queues = new[] { EnqueuedState.DefaultQueue, optServiceBusQueue },
    
        // By default queues will be checked and created on startup. This option
        // can be disabled if the application will only be sending / listening to 
        // the queue and you want to remove the 'Manage' permission from the shared
        // access policy.
        //
        // Note that the dashboard *must* have the 'Manage' permission otherwise the
        // queue length cannot be read
        CheckAndCreateQueues = true
    });
    Configuration.BackgroundJobs.UseHangfire(configuration =>
    {
        configuration.GlobalConfiguration.UseStorage(sqlStorage);
        var autoRetry = new AutomaticRetryAttribute
        {
            Attempts = retryCount,
            OnAttemptsExceeded = attemptsExceededAction
        };
        configuration.GlobalConfiguration.UseFilter(autoRetry);
    });
    
  • User Avatar
    0
    maliming created
    Support Team

    Can you download a Zero MVC Test Project(<a class="postlink" href="https://aspnetzero.com/Download">https://aspnetzero.com/Download</a>) and reproduce it and share it?

    I can specify queue in abp.

    <a class="postlink" href="http://docs.hangfire.io/en/latest/background-processing/configuring-queues.html">http://docs.hangfire.io/en/latest/backg ... ueues.html</a>

    public static class Test
    {
    	[Queue("secondary")]
    	public static void SomeMethod()
    	{
    
    	}
    
    	[Queue("default")]
    	public static void SomeMethod2()
    	{
    
    	}
    }
    
    BackgroundJob.Enqueue(() => Test.SomeMethod());
    BackgroundJob.Enqueue(() => Test.SomeMethod2());