Hangfire Discussion

IJobCancellationToken and CancellationToken clarification


#1

I’m using Hangfire to handle a longrunning SQL task. I’m a little confused about Hangfire’s support of CancellationTokens, though, and was hoping for some clarification.

According to https://www.hangfire.io/blog/2016/07/16/hangfire-1.6.0.html

If your async methods support CancellationToken parameters, don’t forget to add them to allow background processing server to stop gracefully during the application shutdown. With this release Hangfire is able to pass CancellationToken instance to your methods.

So do these tokens work similar to the JobCancellationToken.ShutdownToken in that it is only fired when Hangfire is exited? I guess I’m wondering what the point of that blog post is in regards to CancelTokens. They don’t seem to work any differently. Am I right that they’re not supposed to fire when a job is deleted through the MonitoringAPI or dashboard?

This is currently how I’m handling cancelling the SQL command:

try
{
    var mergeTask = cmd.ExecuteNonQueryAsync(cancelToken.ShutdownToken);
    while (!mergeTask.IsCompleted)
        cancelToken.ThrowIfCancellationRequested();
}
catch (JobAbortedException)
{
    cmd.Cancel();
}

This works but seems a bit inefficient having to constantly poll ThrowIfcancellationRequested(). Am I understanding this all correctly?

Thanks.


#2

I think he added that to the blog post to clarify that even in an async function you can accept a cancellation token as a parameter to be injected at runtime. The cancellation token definitely isn’t firing when the task is deleted from the dashboard. In fact, if the job has already been picked up and has begun processing back a background server, deleting from the dashboard doesn’t really do anything because the task will continue to execute to conclusion (or at least in our experience).

In terms of how to properly handle it, I don’t think you should have to actually query to get cancellation. What happens when a background server shuts down normally (ie: not due to an application crash) is it stops handling new request and fires the cancellation token to all tasks currently executing. It waits a short period of time for completion or token handling and then dies. So, if your background method were a loop that executes many times, but each time is relatively quick, you would just call the token.ThrowIfCancellationRequested(); as the first line inside the loop and you should be covered. It should all be automatic from there with no need to query.


#3

Thanks, that was mostly my understanding as well but was needing a sanity check to make sure I wasn’t missing anything.

There’s an open PR to use the regular CancellationToken for job deletes so hopefully it gets merged in. https://github.com/HangfireIO/Hangfire/pull/976

The polling I’m using is only for handling cancels through deletion on the dashboard/monitoringAPI. Passing just the ShutdownToken works perfectly for handling Hangfire being shutdown but I need to allow users to delete the jobs and stop their processing as well.