Thursday, May 13, 2004
Well, this was a little gem that was pointed out to me by a buddy from Microsoft UK who said that surely this little snippet of information was worth a drive in my new car!
Well, I'm not so sure, but it's useful nonetheless ;-)
So, onto the topic in hand. A documented feature of Send Ports in Orchestrations is that it is possible for an acknowledgement to be returned to the running orchestration when a message has been transmitted to its destination. It's often been the case (in previous versions) that it would be useful to know when a message has been transmitted, and if there is a transmission failure and the message goes into the suspend queue, then to be able to take corrective action in the orchestration. With Delivery Notifications it is possible to do that!
How does it work?
Well, when this option has been switched on, a context property called BTS.AckRequired is set that informs the adapter that a transmission acknowledgement is required. Once the message has been transmitted successfully an 'ack' is returned that the engine uses to progress the orchestration. If the message fails to be transmitted (after the retry count has been exhausted), then a 'nack' is returned instead. If a nack is received by the orchestration engine, then a DeliveryFailureException is thrown that can be caught in the orchestration using an Exception Block Handler in an enclosing non-atomic scope. The non-atomic enclosing scope is not exited until a ack/nack is received - which makes this very useful as the orchestration won't continue and will just block. The documentation states that an atomic scope is required for the send shape although I have found that it also seems to work in a non-atomic scope as well.
How do I do it?
In orchestration, perform the following steps to delivery notification heaven:
- Set up a port that is used to send messages.
- Look at the port properties, and set the Delivery Notification property to Transmitted.
- Create a non-atomic scope shape with the transaction type set to Long Running.
- Add an exception handler block to the scope to catch exceptions of type DeliveryFailureException.
- Add a send shape inside the scope and hook it up to the port.
Don't forget that the non-atomic scope (or the orchestration if no scope is specified) will not complete until either an ack or a nack is received. Very useful for running some sort of corrective action in case of transmission failure. Also, I've not tried, but I wonder if, rather than putting the corrective logic in the exception block, whether the succeeded() XLANG/s expression could be used to test if the scope had failed, and then perform corrective action but in the main flow of the orchestration. Sounds feasible I guess...