My SharePoint State Machine workflow has come a long way since my last post, and I’m going to record my discoveries and tips over the coming weeks. The first discovery is the importance of procrastination.
Procrastination you ask? Well, actually the use of a Delay event within a SharePoint workflow. It’s a long story, but worth telling. To provide some background, the characteristics of our workflow are:
- It is a reasonably complex state machine workflow with around 15 states
- It is a long running workflow with about half of the states requiring operator intervention, prompted by the creation of custom tasks
- We wanted to update a “status” type column (and other columns) on the item upon which the workflow was running, and it was this that caused the original “save conflict” exception to be raised
- The workflow was initiated either when a new item was created in the list, or could be initiated manually
- We are developing in Visual Studio 2008, with SharePoint Extensions 1.2 installed
After a bit of further investigation, I had discovered that what I said in my last post wasn’t 100% true all of the time. Our contention from the previous post was that you simply had to catch the exception thrown when updating the item, ensure it was a save conflict exception and throw it away. It appears that we were being fooled by the defaults on our particular status column. The update was NOT in fact succeeding when we simply caught and discarded the exception, it was just that the column was correctly being set to its initial default value.
After doing some reading about workflow dehydration and rehydration, we decided to introduce a delay activity in the very first state of our workflow. And this did the trick! A workflow in SharePoint is “deyhdrated”, or persisted back to the underlying database, whenever it is awaiting an external event and cannot continue. These external events include:
- A Delay activity
- A Task is created
- etc, etc
What we have observed was that the problem arose because the workflow was being fired synchronously with the creation of the new item, and thus any changes made during this initial invocation of the workflow conflict with the creation of the item.
The solution to this problem? Ensure the item creation has “completed”, before we try to do any updates to the item. How to achieve this? Easy, cause the workflow to be dehydrated, which is most easily achieved by the use of the Delay activity. So my state machine workflow now starts with an initial state whose sole activity is invoke the Delay activity, and sets the next state to the one where the real work starts.
A word of warning about the Delay activity. Some of the very early pre-RTM versions of SharePoint workflow apparently had some bugs with the Delay activity, so ensure you’ve got the latest patches and service packs installed.
Additionally, you might be surprised by the way the workflow executes after the Delay activity returns.
Firstly, if you invoked the workflow interactively from the SharePoint user interface, the workflow execution will have been initiated by the SharePoint web site, and if you were debugging for example, you would be attached to the IIS Application Pool process w3wp.exe.
Once the Delay activity has been invoked, user control will be returned to the web page. When the workflow resumes after the Delay activity timeout, the workflow will be running under the Windows SharePoint Timer Service, OWSTIMER.exe. This is because the rehydration and continuing execution of the workflow is carried out by this process. The web site, naturally enough, has nothing further to do with it.
Secondly, you’ll quickly become frustrated by the inordinately long time you have to wait for a workflow to continue after a Delay activity. This is because, even if you set the Delay to 1 second, this only means the workflow becomes a candidate for rehydration and continuing execution when the Windows SharePoint Timer Service checks next. By default, this is set to every 10 minutes from memory, so you’ll get very frustrated waiting this to happen! Fortunately there’s a way you can minimise the delay. By using the STSADM command, you can force the check every minute. The command is:
stsadm -o setproperty -pn job-workflow -pv "Every 1 minutes between 0 and 59" -url http://sitename
So these series of findings were a huge breakthrough for us in developing our state machine workflow. In summary:
- Don’t even try to update an item against which a workflow is running, if you are in the initial state (and I assume as the initial activity of a sequential workflow) after item creation or presumably editing, whichever are flagged to initiate a workflow at the time of association. Use the Delay activity to ensure any modifications that invoked the workflow are actually complete, and then your updates should succeed.
- Be aware of the way your workflow will execute once you do introduce a Delay activity. After the Delay activity timeout has completed, the workflow execution will continue under the Windows SharePoint Timer Service (OWSTIMER.exe).
- You can use the STSADM command to ensure the Windows SharePoint Timer Service checks on workflows needing to progress more frequently than it would by default.
In my next post I’ll document some findings about custom Workflow Statuses, and how you can use them to improve the readability of the workflow status column in your lists.