HangFire 0.8.1 released
17 May 2014 edit on githubNote. The following information may be outdated after 1.0 release. Please see the official documentation first.
Release notes
This release contains a bunch of new features, that complete the background job workflow (Deleted state), make it without additional latencies (MSMQ support) and inform you about failures in-time:
- Added - MSMQ queues support for SQL Server job storage.
- Added - “Deleted” state for jobs, when we don’t want to process them anymore.
- Added - “Requeue” and “Delete” buttons on a job page in HF Monitor.
- Added - Logging job failures: warning - there is a retry, error - no attempts left.
- Added -
BackgroundJob.Requeue
andBackgroundJob.Delete
methods. - Changed - Set
InvisibleTimeout
back from 5 to 30 minutes. - Changed -
RetryAttribute
is deprecated. UseAutomaticRetryAttribute
instead.
As always, the new version of HangFire can be installed via NuGet Gallery. Here is the package list.
Deleting jobs
There is a new state – DeletedState
, and some methods to perform the deletion – BackgroundJob.Delete
and IBackgroundJobClient.Delete
. When you are using these methods, a job is not being actually deleted, there is only state transition. Jobs in the deleted state expire after some delay (as succeeded jobs).
The operation does not provides guarantee that the job will not be performed. If you deleting a job that is performing right now, it will be performed anyway, despite of calls to delete methods.
Usage
If you want to delete job despite its current state, do the following:
var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Hello, world!"));
BackgroundJob.Delete(jobId);
// or
IBackgroundJobClient client = new BackgroundJobClient();
client.Delete(jobId);
If you want to be able to handle only deletion from exact state, for example, only from FailedState (because it may change after you click and before it will be deleted), you can specify it:
var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Hello, world!"));
BackgroundJob.Delete(jobId, FailedState.StateName);
// or
IBackgroundJobClient client = new BackgroundJobClient();
client.Delete(jobId, ScheduledState.StateName);
Manual deletion
Job details page now contains Requeue and Delete buttons (other pages also have these buttons). So, you can requeue and delete your jobs at any time:
MSMQ support for SQL Server storage
SQL Server job storage implementation does not require you to learn and install additional technologies, such as Redis, for projects to use HangFire. However, it uses polling to get new jobs that increases latency between the creation and invocation process (see also this feature request).
The MSMQ implementation, that was introduced in HangFire 0.8.1, replaces only the way HangFire enqueues and dequeues jobs. It uses transactional queues to delete jobs only upon successful completion, that allows to process jobs reliably inside ASP.NET applications. MSMQ queues contain only job identifiers, other information is still persisted in the SQL Server database.
Advantages of using MSMQ
- No additional latency. It uses blocking calls to fetch jobs – they will be processed as soon as possible.
- Immediate re-queueing of terminated jobs. If the processing was terminated in the middle, it will be started again immediately after application restart. SQL Server implementation uses InvisibleTimeout to distinguish between long-running and aborted jobs.
Installation
MSMQ support for SQL Server job storage implementation, like other HangFire extensions, is a NuGet package. So, you can install it using NuGet Package Manager Console window:
PM> Install-Package HangFire.SqlServer.MSMQ
Usage
To use MSMQ queues, you should do the following steps:
- Create them manually on each host. Don’t forget to grant appropriate permissions.
- Register all MSMQ queues in current
SqlServerStorage
instance.
var storage = new SqlServerStorage("<connection string>");
storage.UseMsmqQueues(@".\hangfire-{0}", "critical", "default");
// or storage.UseMsmqQueues(@".\hangfire-{0}") if you are using only "default" queue.
JobStorage.Current = storage;
To see the full list of supported paths and queues, check the MSDN article.
Limitations
- Only transactional MSMQ queues supported for reability reasons inside ASP.NET.
- You can not use both SQL Server Job Queue and MSMQ Job Queue implementations in the same server (see below). This limitation relates to HangFire.Server only. You can still enqueue jobs to whatever queues and watch them both in HangFire.Monitor.
The following case will not work: the critical
queue uses MSMQ, and the default
queue uses SQL Server to store job queue. In this case job fetcher can not make the right decision.
var storage = new SqlServerStorage("<connection string>");
storage.UseMsmqQueues(@".\hangfire-{0}", "critical");
JobStorage.Current = storage;
var options = new BackgroundJobServerOptions
{
Queues = new [] { "critical", "default" }
};
var server = new AspNetBackgroundJobServer(options);
server.Start();
Transition to MSMQ queues
If you have a fresh installation, just use the UseMsmqQueues
method. Otherwise, your system may contain unprocessed jobs in SQL Server. Since one HangFire.Server instance can not process job from different queues, you should deploy two instances of HangFire.Server, one listens only MSMQ queues, another – only SQL Server queues. When the latter finish its work (you can see this from HangFire.Monitor – your SQL Server queues will be removed), you can remove it safely.
If you are using default queue only, do this:
/* This server will process only SQL Server table queues, i.e. old jobs */
var oldStorage = new SqlServerStorage("<connection string>");
var oldOptions = new BackgroundJobServerOptions
{
ServerName = "OldQueueServer" // Pass this to differentiate this server from the next one
};
var oldQueueServer = new AspNetBackgroundJobServer(oldOptions, oldStorage);
oldQueueServer.Start();
/* This server will process only MSMQ queues, i.e. new jobs */
// Assign the storage globally, for client, server and monitor.
JobStorage.Current =
new SqlServerStorage("<connection string>").UseMsmqQueues(@".\hangfire-{0}");
var server = new AspNetBackgroundJobServer();
server.Start();
If you use multiple queues, do this:
/* This server will process only SQL Server table queues, i.e. old jobs */
var oldStorage = new SqlServerStorage("<connection string>");
var oldOptions = new BackgroundJobServerOptions
{
Queues = new [] { "critical", "default" }, // Include this line only if you have multiple queues
ServerName = "OldQueueServer" // Pass this to differentiate this server from the next one
};
var oldQueueServer = new AspNetBackgroundJobServer(oldOptions, oldStorage);
oldQueueServer.Start();
/* This server will process only MSMQ queues, i.e. new jobs */
// Assign the storage globally, for client, server and monitor.
JobStorage.Current =
new SqlServerStorage("<connection string>").UseMsmqQueues(@".\hangfire-{0}");
var options = new BackgroundJobServerOptions
{
Queues = new [] { "critical", "default" }
};
var server = new AspNetBackgroundJobServer(options);
server.Start();
Comments