One queue for the whole farm, and one queue by server

I’ve had the same ‘problem’ and came up with the following solution:

  1. when configuring the server add a seperate queue per scheduler instance:
 var serverOptions = new BackgroundJobServerOptions()
                    {
                        ServerName = GetSchedulerInstanceServerName(),
                        Queues = new[] { InstanceName, "Default" } //<==instance name is some static property
                    };

where InstanceName is something unique to the server (e.g. the hostname + port)

  1. Add a jobfilter which extracts the queue from a job parameter:
  internal class UseQueueFromParameterAttribute: JobFilterAttribute, IElectStateFilter
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="QueueAttribute"/> class
        /// using the specified queue name.
        /// </summary>
        /// <param name="queue">Queue name.</param>
        public UseQueueFromParameterAttribute(int parameterIndex)
        {
            this.ParameterIndex = parameterIndex;
        }

        public int ParameterIndex { get; private set; }

        public void OnStateElection(ElectStateContext context)
        {
            var enqueuedState = context.CandidateState as EnqueuedState;
            if (enqueuedState != null)
            {
                enqueuedState.Queue = context.Job.Arguments[ParameterIndex].Replace("\"",string.Empty);
            }
        }
    }

Example usage:

  internal class MaintenanceJob
    {
        [UseQueueFromParameter(0)] //extracts the queuename from parameter with index 0
        public void Execute(string queuename)
        {
            //do some maintenance on the server
        }
    }

//now enqueue the job using the statically configured instance name
 BackgroundJob.Enqueue<MaintenanceJob(x=>x.Execute(InstanceName));

EDIT:
please keep in mind that a queue name may only contain lowercase characters, numbers or underscores and has a maximum length of 20 characters…

3 Likes