Parallel branching and scoping Generally, parallel branching is used when you need to execute different un-related activities simultaneously. Example 1: In your business process, if you need to call a web service and perform a transform. Since these two activities are un-related, they can be executed in parallel using a "Parallel" shape:
What is a scope? A "scope" is a unit or a block which is executed as a context and is associated with a transaction type. In order words, a scope defines a context which maintains the state for a defined unit-of-orchestration code. If you were to open the *.ODX files in Notepad, you would notice that the scope shape placed in an orchestration would create the following: scope { task { // Can be a transform or an expression shape. } }
Each scope shape in the orchestration maps to a "scoped" segment of code. A segment defines the boundaries where the control is passed back to the BizTalk engine to persist data in the MessageBox store, thus enabling consistency and durability. The scope shape in orchestration has two important properties:
•
Synchronized: This is a boolean flag which can either be "true" or "false". When two scopes in a parallel branch are set to Synchronized="true", then they would be executed independent of each other in such a way that each branch assumes that it is the only one being executed in the system. When an orchestration variable needs to be shared across several parallel branches, in that case, the scope's synchronization flag must be set to "true" or the 'Transaction Type' must be set to "Atomic".
•
Transaction Type: The 'Transaction Type' property can have the following values: 1. Atomic 2. Long Running and 3. None
Note: An orchestration (*.odx) file also has a 'Transaction Type' property.
Transaction types The classical definition of a transaction is - an atomic unit of work which results in moving the system from one consistent state to a new consistent and durable state. A transaction can either be "committed" or "rolled back" depending on various conditions. Note that a transaction which cannot be rolled back needs to be "compensated". This means that if an operation 'f(x)' has been performed on some data, in order to revert it back we need to perform an operation 'f(y)', which essentially performs an undo operation, this is known as "compensation" in simple terms.
Orchestration 'Transaction Type' • • • •
A non-transactional orchestration cannot have 'scope' shapes set to either "Atomic" or "Long Running". If an orchestration's transaction type is set to "Atomic", then the orchestration cannot have any other transactions within its 'scope' shapes. Atomic transactions cannot contain nested transactions or catch exception blocks. However, they can have compensation blocks. Long running transactions cannot be isolated from other transactions. However they can contain other atomic transactions and can have catch exception and compensation blocks.
The image above highlights the various key properties to be set for an orchestration. Note: These properties are applicable only when the 'Transaction Type' is set to 'Atomic'. •
•
•
•
Batch: A boolean value that determines if this transaction can be batched with other transactions across multiple instances of the orchestration. The default value is "true". It may improve performance with the possibility of losing isolation data. Isolation level: This property defines the degree of isolation between the state changes performed by different atomic transactions. This is not applicable for Long-Running transactions. BizTalk supports three isolation levels. These are 'Read Committed', 'Repeatable Read' and 'Serializable'. The last one being the default value. Retry: A boolean value which specifies that the atomic transaction can be retried in the event of a failure. Perform the following for Retry-"throw an instance of Microsoft.XLANGs.BaseTypes.RetryTransactionException" within the transaction boundary. Transaction type: Can be either "Atomic" or "Long Running" or "None".
Parallel branches - an example
The above image shows two parallel branches whose "synchronized" property is set to "true". The reason being, both the branches set the "CityCode" value, hence the use of shared data. The message assignment shape "Assigning 10" has the following lines of code: OutputXMLMessage = InputXMLMessage; OutputXMLMessage.CityCode = 10;
The message assignment shape "Assigning 20" has the following lines of code: OutputXMLMessage = InputXMLMessage; OutputXMLMessage.CityCode = 20;
Code walkthrough Line 1: The InputXMLMessage is assigned to OutputXMLMessage. Line 2: The property CityCode is set to "10" and "20" respectively. An error message appears, if the synchronized property is not set: 'OutputXMLMessage': if shared data is updated in a parallel then all references in every task must be in a synchronized or atomic scope
Timeouts 1. If the orchestration's transaction type is set to 'Atomic', then the default timeout value is 60 seconds. In this case, the time out value is an Int64 value.
2. If in the scope shape the transaction is 'Long Running', then the TimeoutException is thrown when the set timeout expires. In this case, the timeout value needs to set using: new System.Timespan(1,0,0,0);
3. If in the scope shape the transaction is 'Atomic' and timeout occurs, it is considered as an attempt failed.
Quick orchestration takeaways 1. A parallel branch need not have a scope if the orchestration 'Transaction Type' = "none" and if no variable is being shared across the branches.