WorkflowQueueNames

As I wrote in my last post, I’m doing a bunch of WF related work. I’m close to releasing some WF related stuff I started building last week in Jon’s class. But I discovered something cool about the way WF’s queuing system works, and wanted to blog about it.

Side note - Speaking of Jon, he’s joined the “WF is not a toy” conversation. He had an interesting point about the persistence service that I hadn’t thought of. If you use the SQL persistence service and you have TransactionScope in your workflow, you end up with a distributed transaction, even if these are all writing against the same SQL instance. That’s a good enough reason to write your own persistence service right there.

In the WF stuff I’m building, I need a way for the WF runtime to notify a given workflow instance when something happens. WF has a low level queuing system as well as the higher abstraction data exchange system. I’m more interested in low level knowledge of WF, so I decided to use the queuing system.

In my implementation, the workflow instances only need to be notified when specific events happen. That is, I’m not passing in any real data on the queue – the arrival of the data is what’s important, not the data itself. Queues are identified by name and I started by using a simple string as my queue name. However, the queue name isn’t limited to be a string, it supports any IComparable class. This turned out to be a huge advantage for me.

Things worked fine when I was building a simple sequence, but when I moved to a parallel activity things went south. Since I was using a simple string, I ended up creating two queues with the same name, which didn’t work out well. Furthermore, I have two different notification situations. So I needed a way to have a unique queue name for the same activity type in parallel branches of the workflow as well as supporting two different notification situations.

Because queue name is IComparable instead of a string, I was able to create two queue name types – one for each notification situation. Each of these queue name types includes a string that I initialize to the activity’s qualified name, which as per the docs is “always unique in a workflow instance”. So I was able to kill two birds with one stone – supporting multiple parallel activities as well as multiple notification scenarios. That’s pretty cool. If they had used simple strings, I would have had to have a naming system like “notificationscenario:notificationdata:activityname” and then have to parse out the queue name string. In fact, I started down this path before I remembered that queue name is IComparable. Using IComparable is much much cleaner.

WF Clarifications and Corrections

Last week, after I posting my WF learnings, I got a call from Paul Andrew, Technical Product Manager for WF. Seems calling the built-in persistence service and the built-in web service support “toys” created some extra work for Paul. He blogged a response and I wanted to follow up on a few things here.

  1. The “toy” SQL Persistence Service – My understanding about how the built-in persistence service works was incorrect. As per Paul’s blog, “The WF runtime doesn’t load all idle instances on startup, that would be crazy.” Of course, we’re talking about the SQL Persistence Service, not the WF runtime, but it’s still crazy. It’s so crazy that when I thought that’s what the SQL Persistence Service did, I called it a toy! So I’m flat out wrong on this one. Sorry about that Paul (and the rest of the WF team).

  2. The “toy” Web Service Integration – Apparently, I was also mistaken about the use of ASP.NET sessions. But I was right about WF’s use of ASMX, the use of the tempuri.org namespace, and that web service support is limited to WS-I basic profile request/response style services. So while “toy” is a bit harsh, the web service integration is still pretty light weight. Where’s the WCF integration? I understand the need to support ASMX, but no WCF means no support for duplex conversations, either as service provider or consumer, and no support for reliable sessions. That makes WF’s web service integration a non-starter in my project. Of course, the good news is that you can build your own WF activities, so I can toss the built-in web  service activites and still get to keep the rest of WF.

  3. Is WF itself a “toy”? Paul has a list of reasons why WF isn’t a toy, including some silly ones (it wasn’t in Toy Story). In case there’s any confusion about my opinon of WF, let me be clear: I think WF rocks, full stop. My negative comments about WF were isolated to the two areas listed above and not intended to apply to WF as a whole. The other seven points were all about cool things that I didn’t realize WF does.

I’m not just trying to kiss up to Paul here – WF is one of two foundation technologies that my project absolutely depends on. (Any guesses on the other?) With the class out of the way and a better understaning as to what’s possible with WF, I will be diving much deeper on WF in the future. Watch this space for more WF related posts.