Checking for a job state

On my background process initiator page, users are able to select between running a job immediately (Enqueue) or at a later time (Schedule). After user has selected the action and fire the job, how do I check if the job has already been scheduled/queued so that I can present the appopriate UI when the page is visited again or accessed by other users?

Looks like you want to add background jobs to application’s domain model. You can create an entity for this case and assign a background job identifier.

var userJob = new UserJob
{
    UserId = userId,
    JobId = BackgroundJob.Enqueue(() => SomeMethod());
};

_db.Save(userJob); // Pseudo-code

And later you can query that job was created.

var userJob = _db.UserJobs.SingleOrDefault(x => x.UserId == userId);
if (userJob == null)
{
    // There is no associated job
}
else
{
    // Job was created
}

Thanks for your reply. I thought this could be done without having to keep track of the job outside of HF, but instead by querying the existing HF storage via the monitoring API or something.

E.g:
For a background job to send reminder emails in batch, a job (whether thru Enqueue, Scheduled, or AddOrUpdate) can be fired and has the ability to identify the job name, say ‘SendReminderEmails’.

And we can check the current status of the job, if any, just by specifying the job name ‘SendReminderEmails’.

@ajakblackgoat, sorry for the delay. As for now, you can query jobs only by their ID. Later I’m planning to add the filtering feature, but it will require table or index scan and is not affordable for applications (except for monitoring). If you want to track your jobs, integrate background job ids with your domain model and query jobs based on their Ids.

But it is better to add another attribute to your entities, such as IsCompleted, or PercentsCompleted, because:

  • succeeded or deleted background jobs expire after some time (one day by default), and it is hard to determine whether it was succeeded or deleted;
  • it is hard to predict the state consequence of a single job. The simplest path is: EnqueuedProcessingSucceeded, but it can be EnqueuedProcessingSucceededDeleted by adminEnqueued by other adminProcessingFailedDeleted – state workflow can be very complex, do not rely on them.

@odinserj - How exactly do I query the jobs on their ID to find their status?

I couldn’t find an example in the documentation?

@tom, sorry for the delay. Check the JobStorage.Current.GetMonitoringApi() method and the IMonitoringApi interface. This interface is being used by Hangfire Dashboard web ui, so you’ll find there all information available in the dashboard.

Hi
I am working on the same issue.
I have checked the interface of monitorAPI, it seem functions are categorized by state. And there is no parameter for jobId. Do I need to call all of these method DeletedJob(), SuccessedJob() … and etc to check if my jobid is in the list for this purpose? Or any method specific method able to return full list of jobs with its state, fetched, en-queued and etc?

Please advice. tq

You can also use the IStorageConnection interface’s (by obtaining it with JobStorage.GetConnection) GetJobData and GetStateData methods. They will return what you need. However, be aware that job states are very volatile in Hangfire and they should not be used by an application logic.

We subscribe to messages from NServicebus and when a specific message is received then we need to run a job. Sometimes many of the same message arrives within a short time period and we want to Throttle the inflow to not create too many jobs for the same thing. The job itself is idempotent.

It would be nice with a parameter to Schedule that checks if there is already a job for this task.

string jobKey = GetHashValue(command);
backgroundJobClient.ScheduleIfNew<UpdateSalesRevenueJob>(job => job.Execute(command), TimeSpan.FromSeconds(10), jobKey);

Then if jobKey is already scheduled, but not processed, then this new schedule will be ignored.

1 Like

Please check the following gist. With some modifications, you can achieve what you want. If you have questions regarding to it, don’t hesitate to ask them!

@odinserj
Thanks for that example. Can you give an example usage of the DisableMultipleQueuedItemsFilter? I do not understand how to utilize that to solve the problem @di97mni described in his last post.