Creating custom timer jobs within SharePoint enables a SharePoint developer to add a scheduled component to a SharePoint application. (Looking to get started with timer jobs? Andrew Connell has a good write-up on MSDN.)
On a recent project, I created a couple of custom timer jobs and ran into some interesting behavior related to the job locking that I don’t think is documented very well at the moment.
When you create a custom timer job, you inherit from SPJobDefinition. A couple of the constructors for the job allows you to specify a value for the lock type used by the job. This value is set as an enum of type SPJobLockType.
The MSDN documentation details the available values for the SPJobLockType enum as follows:
ContentDatabase | Locks the content database before processing. |
Job | Locks the job to prevent it from running on more than one machine. |
None | No locks. |
These values work about as you’d expect (if you can tell what to expect from the descriptions) for single WFE farms.
However, for farms with multiple WFEs, I think this information is sketchy at best and inaccurate at worst. Here’s how I’d modify the documentation based on my own experience:
ContentDatabase | Locks the content database before processing. If more than one WFE is part of the farm, only schedules the job to be executed on a single WFE. If that WFE is removed from the farm, the job is not scheduled on any other WFE automatically, so the job will no longer be executed until 1) the WFE is added back to the farm or 2) the feature that registered the job is deactivated and reactivated. |
Job | Locks the job to prevent multiple instances from running on the same machine. Job will be scheduled on every WFE in the farm and execute on all of them. (Note that this is quite different from the MSDN description; Andrew Connell’s article alludes to this same definition I’ve given.) |
None | No locks. Job will be scheduled on every WFE in the farm and execute on all of them without checking for running instances. |
I think you’ll find it a challenge if your desire is to have design in which the job is managed by the farm in such a way that it executes from only one machine and will be fault-tolerant such that if one WFE is not in the farm, it will simply execute on another WFE. It appears to me that the only option for accomplishing this scenario is to use the “Job” or “None” lock types. This schedules the timer job to execute on each WFE server. You can then implement custom communication between WFEs (via the database, remoting, or some other method) to have the WFEs determine that only one of them will execute at any one time. It’s not a great solution – and it’s one that feels like it should have been done already as part of the SharePoint farm infrastructure – but it’s functional.