What are exactly "fetched jobs" returned by IMonitoringApi?

Hello, I’m pretty new to Hangfire, and have to customize the dashboard in order to get more infos about jobs and the queues they’re in (quite the same thing that has been asked here : Queue name in job list ).
In order to do so, I’m trying to understand exactly what is returned by IMonitoringApi various methods. So far I’m quite ok, except for the FetchedJobs() method. I don’t really understand what fetched jobs are ; according to references I’ve found on this forum, a job is “fetched” when a worker grabs it from a queue in order to process it, is that correct ?
If so, are the fetched jobs returned by the FetchedJobs() method the jobs that are currently fetched, or the jobs that have been fetched, whether they’ve already been processed or not ?
Additionnaly, why is there no FetchedState class in the Hangfire.State ? It’s the only State class I haven’t found.
Thanks in advance !

Generally, yes, fetched jobs are those picked up by the workers. But result of FetchedJobs() is rather storage implementation-specific, for example, SQL Server storage always returns zero :slight_smile:

When the worker is free, It tries to pick next pending job from the queue. When the job is found, the worker needs to secure it somehow for itself, so other workers won’t start processing it too. There are a few ways of doing so.

For example, SQL Server storage immediately deletes the job from queue, but keeps transaction uncommitted until the worker has finished processing. And in case it failed to finish (exception, server reboot etc.), transaction is automatically rolled back and the job returned to the queue, to be picked up by other workers. So technically the jobs are really not fetched from the queue, but struggle on the verge of life and death like Schrödinger’s cat :slight_smile:

But many other storages can’t do so, so they use another approach: the moment they pick a job, they brand it with a timestamp (FetchedAt), so other workers won’t touch it for the time being (de-facto 24h for many Hangfire storage implementations). During this time, job is not removed from the queue (its Queue field remains intact), but neither is picked by other workers. That’s what is fetched.

After it finished processing, the worker will finally remove the job from queue (by erasing both Queue and FetchedAt fields). And even if it failed, the job would eventually be picked by another worker after timeout. Obviously, the latency in this case would be much greater, compared to a transaction, but it is still the only choice for many storages.

1 Like

Understood. Thanks a lot :slight_smile: