For those that haven't seen this, I wrote a post about a Smart Workflow. It was a workflow that utilized a State Machine and various states, to keep track of what it had done last. Then, if you happen to terminate the workflow and restart it, it would figure out roughly where it was, and then jump to the appropriate state so it wouldn't have to redo most of the stuff it had already done.
Today, I encountered a question about an already running workflow which they needed to update the design, terminate and restart it. But they didn't want it to start from the beginning.
I came up with the following idea.
I have a number of workflow that have been running and are waiting on a Request Approval. They have done a lot of work already, and for some business need, I need to update the workflow design, stop and start each of the workflow instances so it uses the latest business logic.
The problem is, I don't want it to redo all the stuff it has already done.
When you terminate a workflow, it gets a particular status. In this case "Cancelled".
You can make a call to the Nintex Workflow web service, specifically, the GetWorkflowHistoryForListItem web method. The method takes parameters like Item ID, List Name, Workflow Name, and the State of the workflow. So we can ask for the Cancelled state. In essence, this will tell us if we have had an instance of this workflow already run on this item and it has been terminated.
If there is workflow history, you will get a bunch of XML back. If there isn't, you'll get an empty text string back.
Then you simply need to jump to the appropriate part of the workflow. How do you do this? Use the state machine.
The scenario is, we have a simple item with a number and date field. The workflow runs and updates these (add 2 to the number field and 7 days to the date) and then send an approval request.
After the first run of the workflow, it updates the NextID and DateNextMeeting:
If you were to rerun this workflow, it would update the NextID and DateNextMeeting again, which is not something we want.
The workflow looks fairly simple:
When this workflow runs, it updates the fields quite quickly and then sits and waits on the Request Approval.
The business has asked that I modify the approval request and do something special or even add some more business logic after the approval. But they want this to happen to all running workflows also.
The solution I came up with, was to use something similar to my Smart Workflow idea, and that is utilize the State Machine.
Initial State - checks if a previous instance of the workflow ran and was cancelled
Beginning State - is the start of the workflow if it has never run before
Middle State - contains the Approval Request action
Firstly, we run the web service call:
Then we check the result and depending on whether we got data back or not, we jump to the appropriate state:
So we've gone from a fairly simple workflow of 5 actions, to a workflow of 13. But atleast we have somewhat of a solution.
When you terminate the workflow, the item then looks like this:
You can see now that we run the smarter workflow, it has kept the NextID and DateNextMeeting values as they were, since they've already been updated.
The graphical view of the workflow can be seen here:
You can see that it has gone to the Initial state, figured out that a previous instance ran, and so we don't need to go to the Beginning, and instead, it jumped straight to the Middle state which does the Request Approval.
Suggestions for Improvements
This is a solution, but it's really not perfect. Since most business workflows are more complicated than this.
Something I would leave for the reader, is that the amount of data that comes back from the workflow history (web service call) is quite large. It may be possible to interogate that information and cater for more situations in your workflow. It would definitely make you workflow larger though.