I’ve just uploaded a new release (v1.1) of my MSMQ Activities for Windows Workflow Foundation. This release does a few general fixes and polishes a few things here and there, but the largest change is a modification of the MsmqListenerService runtime service used by the MsmqReceiveActivity to listen to the MSMQ queues. This change is aimed at improving the situation I talked about on this past entry. Basically, this is something that will be very handy to ensure the activities work even when the hosting process dies unexpectedly and is restarted.

As part of this release, a new interface is introduced in the component: IMsmqSubscriptionPersistenceService (sorry for the long name). This interface is used by the MsmqListenerService to handle persistence of all subscriptions created at runtime to a given MSMQ Queue. This interface has three methods that are consumed by the listener service:

  • Persist(string host, MsmqSubscription subscription):
    This method should take the specified subscription and save it to a persistent storage, and is called when an MsmqReceiveActivity subscribes to a given MSMQ Queue.
    This method is called inside a System.Transactions.TransactionScope so that the listener service can abort the persistence if anything happens after that.
  • IEnumerable LoadAll(string host):
    This method is called when the listener service is started (right after the WorkflowEngine is started on the process, in fact) to get a list of all subscriptions stored for the given host. For each subscription that is loaded, the listener service configures again a listener on the queue the subscription relates to.
  • Remove(MsmqSubscription subscription):
    This method is called when a MsmqReceiveActivity removes a subscription to a queue. It should delete any record kept about the specified subscription in the persistent storage.

The host argument to Persist() and LoadAll() is a very basic mechanism to allow you to keep a single persistent storage for subscriptions coming from multiple applications (i.e. multiple processes/machines hosting the WorkflowRuntime). The host name to use is specified when you create the MsmqListenerService instance either through an argument in a new constructor overload, or through the configuration file through the “hostname” attribute. If you do not specify a hostname, the value “default” will be used instead. Be careful to always set the hostname explicitly if you’re going to be sharing the persistence storage.

Out of the box, I provide two implementations of the IMsmqSubscriptionPersistenceService interface:

  • NullMsmqSusbcriptionPersistenceService: This is an empty implementation that doesn’t do anything. It can be used if you simply don’t want or need to support subscription persistence.
  • SqlMsmqSubscriptionPersistenceService: This implementation stores all subscriptions as records in a table in a SQL Server database called “MsmqSubscriptions”.

You can select which implementation to use by simply adding it to the WorkflowRuntime’s runtime services collection (either through code or through the configuration file). In the case of the SQL implementation, you’ll need to provide the connection string to the database to use either through the constructor or through the “ConnectionString” attribute in the configuration XML.

Notice that you because of this, you could easily plug in your own custom persistence implementation to support other databases or repositories. One cool thing is that the WorkflowRuntime in essence acts here as an Inversion of Control (IoC) implementation for anything running on the Windows Workflow Foundation platform!

Tomas Restrepo

Software developer located in Colombia. Sr. PFE at Microsoft.