Michel
Michel

Reputation: 23615

Right architecture for using HangFire

I'm about to start using hangfire in C# in a asp.net mvc web application, and wonder how to create the right architecture.

As we are going to use HangFire, we are using it as a messagequeue, so we can process(store in the database) the user data directly and then for instance notify other systems and send email later in a separate process. So our code now looks like this

function Xy(Client newClient)
{
_repository.save(newClient);
_crmConnector.notify(newClient);
mailer.Send(repository.GetMailInfo(), newClient)
}

And now we want to put the last two lines 'on the queue'

So following the example on the hangfire site we could do this

var client = new BackgroundJobClient();
client.Enqueue(() => _crmConnector.notify(newClient));
client.Enqueue(() => mailer.Send(repository.GetMailInfo(), newClient));

but I was wondering whether that is the right solution.

I once read about putting items on a queue and those were called 'commands', and they were classes especially created to wrap a task/command/thing-to-do and put it on a queue.

So for the notify the crm connector this would then be

client.Enqueue(() => new CrmNotifyCommand(newClient).Execute();

The CrmNotifyCommand would then receive the new client and have the knowledge to execute _crmConnector.notify(newClient).

In this case all items that are put on the queue (executed by HangFire) would be wrapped in a 'command'. Such a command would then be a self containing class which knows how to execute a kind of business functionality. When the command itself uses more than 1 other class it could also be known as a facade I guess.

What do you think about such an architecture?

Upvotes: 4

Views: 3041

Answers (1)

Jim G.
Jim G.

Reputation: 15363

I once read about putting items on a queue and those were called 'commands', and they were classes especially created to wrap a task/command/thing-to-do and put it on a queue.

Yes, your intuition is correct.

You should encapsulate all dependencies and explicit functionality in a separate class, and tell Hangfire to simply execute a single method (or command).

Here is my example, that I derived from Blake Connally's Hangfire demo.

namespace HangfireDemo.Core.Demo
{
    public interface IDemoService
    {
        void RunDemoTask(PerformContext context);
    }

    public class DemoService : IDemoService
    {
        [DisplayName("Data Gathering Task <a href=\"jira.contoso.com\">Confluence Page</a>")]
        public void RunDemoTask(PerformContext context)
        {
            Console.WriteLine("This is a task that ran from the demo service.");
            BackgroundJob.ContinueJobWith(context.BackgroundJob.Id, () => NextJob());
        }

        public void NextJob()
        {
            Console.WriteLine("This is my next task.");
        }
    }
}

And then separately, to schedule that command, you'd write something like the following:

BackgroundJob.Enqueue("demo-job", () => this._demoService.RunDemoTask(null));

If you need further clarification, I encourage you to watch Blake Connally's Hangfire demo.

Upvotes: 3

Related Questions