Introduction

Long running processes are a very useful tool in BizTalk app development.  They can help us cover many cases where synchronous events cannot exist or the length of the process is determined by uncontrolled external factors, think people.

For a process, an Orchestration really, to be considered long running, it must rely on correlation in one or more operations.  At these correlated operations, the Orchestration will wait at the Receive Shape until the matching correlated message comes in.  Sometimes though, an undetermined wait time is not a desirable state and a need to influence the waiting processes comes up, as was the inspiration for this article.

Recently, I worked on a app that had a credible case for a long running process where a single Orchestration instance would handle all events for a specific entity, a Sequential Convoy.  Due to the nature of the business, this process could last hours or days.  But, we wanted a way to control the running instances in a managed way rather than rely only on Completing naturally or forcing a Terminate.

The BizTalk pattern we modeled after is the built in EDI Batch Control where the user can send several different ‘commands’ to an Orchestration instance while it’s performing its primary function.

The sample project can be found in the MSDN Code Gallery at: https://code.msdn.microsoft.com/BizTalk-Server-Sending-16f4e78e

Setup Control Messages

Enabling a Orchestration to receive control messages is simply a matter of activating another Correlation Set to subscribe to the control messages.  For this article, we’re implementing a single blanket Control Message, meaning a Control Message would affect all running Instances.  But as with EDI Batching, it’s very easy to add instance specific keys to manage a single instance if needed.

In addition to the expected Business Message Correlation Type and Set, we need a Control Message Correlation Type and Set:

 

To Initialize the Control Correlation Set, we use a Message of Type String with a meaningful, but otherwise irrelevant value.  We also give a value to the built-in Context Property, BTS.BizTalkControl, which is used as the correlation value for the actual Control Message.

To Initialize the Correlation Set, a Message must be sent.

A side effect is that this message by subscribed by something.  For that, we have an Orchestration that consists of a single Receive Shape.

The Receive Shape has a filter to receive messages where BTS.Operation is SendControlInit.

Now that our Control and Business Process Correlation Sets are Initialized, the Orchestration can begin is regular work cycle.

Receive Control Messages

At the end of business processing, a Sequential Convoy will typically wait for either a following business message or a Delay Shape.  To receive the Control Messages, we just add another Receive Shape which follows the Control Correlation Set.  Any of these will fire the Listen Shape.

Logic wise, the result of receiving a Control Message is the same as the Delay Shape firing.  We set the Loop Shape flag to false, then end our process gracefully.

The Control Message

The Control Message itself is very basic, consisting of a single Field with the Control Action.

<ns0:ControlMessage xmlns:ns0="http://SignalARunningOrchestration.CancelMessage">
  <BizTalkControl>CONTROLMSG</BizTalkControl>
  <Action>CANCEL</Action>
</ns0:ControlMessage>

To work with the Correlation Set, the value of the Control Action is Promoted to a built-it BizTalk Property, BTS.BizTalkControl.  (Note, I checked several system and found no evidence of this property being used for any purpose.  However, if you do find a conflict, the simple solution is to deploy a custom Context Property for this purpose.)

When passing through the XmlDisassembler, BTS.BizTalkControl is Promoted and ready for Correlation to any running Orchestration.  Additionally, the value of the Action is set to CANCEL.  This value is checked in the Orchestration which give the opportunity so send different commands to the Orchestrations.

Running the Sample

The sample app includes folders, sample files and Bindings for local Deployment.  MSDN Code Gallery Sample

  1. Build and Deploy the Solution.
  2. Copy the SignalARunningOrchestration subfolder from ReceiveLocationFoldersAndFiles to C:\
  3. Import the Binging file and Start the Application.
  4. Copy one or more BusinessMessage files to the ReceiveBusinessMessages folder.
  5. Check the Group Hub for the running instance.
  6. Copy the ControlMessage to the ReceiveControlMessages folder.
  7. Check the Group Hub.  The running instance has Completed and now appears in the Completed list.

Beware Zombies

One other potential side-effect is Zombies.  Since the order of Listen Shape branches is apparently not deterministic, you can very easily cut your business process off in the middle, while legitimate business messages are queued for the other Receive Shape.  One easy strategy to mitigate this is to stop all Receive operations, then wait for all running instances to go into a Dehydrated state.

Conclusion

As with any sample pattern, you can customize this process and technique to suit any number of scenarios, such as pausing processing, updating config, or retrieving the ‘status/state’ of the process.

Happy BizTalking!