Article Source: http://geekswithblogs.net/michaelstephenson
A few weeks back I got a comment to one of my blog posts by a guy who said he wished he had more control over persistence points in an orchestration. In his example he basically wanted to reduce the number of persistence points as he needed to improve performance in what sounded like a request response scenario.
Often in these kinds of scenarios if BizTalk has been well optimised and you still do not get the latency requirements you need then the likely hood is you are trying to solve a problem with BizTalk when a different solution would be most appropriate.
Anyway what did make me wonder was the opposite of what this guy wanted to do. My thoughts were:
- Is there a situation where I would actually want to persist the state of an orchestration myself?
- If I wanted to do this how could I do it?
- If I can actually do it where might I have used it?
- Would we benefit from an explicit "save" shape?
Anyway when you travel around a lot like myself you tend to get plenty of boring delays in the airport so on one such occasion I had a crack to see if you could do this.
How would I do it?
I wanted to do the simplest example which could demonstrate how I could persist the orchestration state from C# and then do something to show how if an error occurs and the orchestration suspends then I can resume it and it will complete as expected.
In the example orchestration I will receive a message which I won't really do anything with, it is simply to start the process. From here I will initialize a counter and then perform a loop from 1 to 20. Normally I will just trace out the current ordinal, but on the 10th iteration I will cause an error to be thrown (I simulate this by checking if a file exists on disk and if so throwing an error). When the orchestration suspends it can be resumed manually and it will not throw an error when it replays the 10th iteration.
After 20 iterations it will exit. The picture below shows the orchestration.
Now normally in the above orchestration, because there are no persistence points within the loop you would get an output in DebugView like in the below picture.
Here you can see after the error is thrown the process will restart from the beginning again. The next picture below shows what happens when I persisted the orchestration at each iteration in the loop. You can see how the process was resumed and started by replaying iteration 10 and continuing to the end.
Ok so for most people there is nothing new here, but that is just background information. The next thing is in this example is because I did not use any of the normal shapes that cause the state to be persisted how did I achieve this?
Within the Microsoft.BizTalk.XLANGs.BTXEngine namespace there is a BTXService class. With the below line of code I was able to persist the state of the current orchestration.
BTXService.RootService.Persist(false, BTXService.RootService.RootContext, false, false, false, false);
Ok so I have been able to do what I was wondering about, but as you can see to do it you have to use some of the "under the hood" BizTalk components so it isn't really a recommended way of doing this. This is another just because you can doesn't mean you should thing.
I was discussing this with some friends in the pub a while back and between us our thoughts were:
None of us could think of a specific example of where we would have used this technique, so that probably means we don't need a "Save" shape
- If we were doing something like this we would possibly have it within an atomic transaction scope anyway so it would create a persistence point before our work anyway. We kind of thought that this was one of the benefits of the XLANG engines approach to allowing you to develop orchestration workflow by protecting the developer from things such as this where if you can do too much you would be likely to get yourself into trouble.
I'd be interested to know if anyone has come across a situation where they felt this feature to explicitly persist the orchestration would have helped.
If you are interested in the example it can be downloaded below: