Wednesday, 09 May 2007

One very hot issue in workflow foundation is the problems you get when you want to handle some external event in your workflow multiple times, having the correct activity invoked based on some arbitrary piece of data. This can be very helpful if you want to use just one event, for instance: 'procesCommand', and issue different commands to your workflow. So, based on the eventargs of the procesCommandEvent, a different activity will be executed. Having such a system, very rapid development is possible and I like the idea of issuing my workflow 'commands'.

With the standard 'handle external event activity' [HEEA], this is entirely possible. However, it's usage is seriously hampered by the need to setup correlation before-hand. Let's say you have a statemachine, and in some state we will have a few eventdriven activities. The first child-activity of these eventdriven activities is always a HEEA. Since we just want to raise one event, the HEEA is configured with the same event on your external data service. To let the system know which HEEA should react when you raise your 'procesCommand' event, you have to setup a correlation token.
You will thus set up one correlation token for each HEEA that should react in your state. This can be done during the state-initialization. So the defining of the token is done some place other then the configuring of your HEEA itself. The whole proces is very cumbersome with more then a few HEEA to configure. Especially because when you configure the HEEA to use a correlation token, visual studio will present you with a dropdown list of all tokens it knows about, including the ones from other states.

I do not like this mechanism. It's very error-prone, counter intuitive and basically a load of crap.

A great solution would be to build your own version of HEEA, which will just be configured with a string that identifies the command it will react to. Seems easy enough. You will have to implement IEventActivity and possibly IActivityListener<QueueEventArgs> and your done! There is a great example in the SDK that does this for the filesystem. However, while doing this I found out that when the queuename is not unique, only the first IEventActivity will get the Subscribe call. This means that setting up multiple eventactivities with the same queuename (for instance 'procesCommandQueue') is very hard.

Enter the correlationservice: The WF-team created an elaborate service that works by registering 'followers' (the HEEA activities that will not get the subscribe call) and delegating to the first HEEA (the one that did get the subscribe call) the responsibility of notifying it's followers when a message was picked up from the queue.
(In case you haven't read Essential Workflow Foundation by Dharma Shukla and Bob Schmidt: you should, it has an essential introduction into queue's which is the foundation of workflow, which, coincidentally, is the title of their book ;-) ).

That correlationservice is not something to be proud of, and also not something that one would want to build themselves. But without it, only your first procesCommand activity will be able to react to your event, and it might not be the one that should react!

This explains the cowardly piece in the title of this post: by making each queueName unique, all your problems will go away. Therefor, when you setup your queue in the initialize of your activity, name it 'procesCommandQueue' + this.CommandToReactTo. That will give it a unique name.
Then, instead of raising an event, just set your eventargs on the queue of your workflowinstance like this: instance.EnqueueItem('procesCommandQueue' + CommandYouWantToIssue, yourEventargs, null, null).

Since all your procesCommandHandlers were subscribed to different queue's, the correct one will pickup the eventargs + execute, and all is fine. Thus, the cowardly, but perfectly acceptable way to go about this problem, is to tackle it from the outside, instead of the inside.

Wednesday, 09 May 2007 21:08:00 (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback