Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Julien Chable

He blogs, you blog, I blog ...

Archives

Workflow Foundation : Custom persistence points

A workflow is commonly used for executing long running business processes, some of them could be business critical for companies. As you may think, you can handle most of the inherent issues by using the WF Transaction capability and the TransactionScopeActivity activity. However this is not the point here, it's about how to use the persistence activity capability which is very quick and easy way to create custom persistence point in your critical workflow.

In WF, you have several ways to ensure the reliability of your workflow in case of sudden crash or power outage, indeed none are really 100% secure. Imagine, you build a similar workflow that receive an order from a web service call, add it into a table and then send back the result:

clip_image002

We are in a compensable sequence, so if an exception is thrown you can act accordingly and rollback your actions in the database without any problem.

If the machine crashes before the AddOrderInDB activity execution, you haven't added the row in the table so that's fine it won't break your data model integrity nor your business. The distant system won't receive any response from the web service call, but that's not our matter to handle that now. If the machine crashes after the AddOrderInDB activity execution, we added the order in the database and the distant system won't receive any response from the web service. Like the previous scenario, the distant system will have to handle that case and it might call the web service method again. So what about our application reliability in this case, will we send the order twice and ask the customer for money twice as well or don't take the order in acccount at all?

Ok, we can think that using a transaction in our code to commit changes in the database is enough. That if the crash occurred just before the commit instruction, a second web service call will not hurt our process so much, and if not, lost an order is not so important for our business. But we have to tell our boss that our application is not 100% reliable !

Let's assume that we want to use a transaction scope to secure the process (and this one is very short). In this case there is only two ways to do that:

  • By surrounding the whole compensable sequence: it's impossible to use any fault, cancellation, suspension, termination and compensation handlers in a TransactionScopeActivity. The point of transaction is that its work either succeeds or fails. Using a CompensatableTransactionScopeActivity may be another option but that will not be a big advantage here in case of a power outage.
  • By surrounding only the CodeActivity containing the "insert order in db" code activity.

The last solution here is the best in this case and if you're only using a TransactionScopeActivity activity. Why ? Because once a TransactionScopeActivity successfully completes its execution, the ambient transaction is committed and then persisted (not passivated which would include disposal of the activity objects in memory). As a consequence, if the machine crash the workflow will resume its execution, maybe on another machine (in another AppDomain and in a different WF runtime), just after the transaction. Hence, the use of TransactionScopeActivity requires a WF runtime that is configured with a persistence service. So you don't have to ask a second call and you won't lose your order.

However, what about a crash before the transaction ? Maybe the distant system will time out and resend the order to the web service. In this case, this is fine for you. But if it doesn't call the web service again, we simply lost an order and another opportunity to make our company profitable but we don't have corrupted our data model.

Here the use of a transaction is justify because we use in the AddOrderInDB activity only types defined in the System.Data.SqlClient namespace that know how to enlist in the ambient transaction.

What if Mr. Boss asks us to make some enhancements in the workflow? If we add some extra critical steps in the transaction, the workflow will not be persisted until the TransactionScopeActivity succeed and if the machine crash, you will call the already executed activities twice. Moreover, the extra activities inside the TransactionScopeActivity execute nontransactionnal work. Nested each critical activity, even which that contain nontransactional work, will persist the work after each critical steps. However you will not use the transaction advantage here, just the side effect of the TransactionScopeActivity that persist the workflow instance after a successful execution.

image

The key point will be to create some kind of restore point that persist the workflow when encounter. You can create such activity by decorating your custom activity class with the PersistOnCloseAttribut. Here is an example of a basic restore point activity that persist the workflow when the activity move to the Closed state.

using System;
using System.ComponentModel;
using System.Workflow.ComponentModel;
using System.Workflow.Activities;

namespace WorkflowConsoleApplication1
{
[PersistOnClose]
public partial class RestorePointActivity : System.Workflow.ComponentModel.Activity
{
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
return ActivityExecutionStatus.Closed;
}
}
}

Our new workflow using the above activity:

clip_image004

By using this kind of activity (or any other custom activity decorated with the PersistOnClose attribute), you are able to face more crashes or power outages as usual. Nevertheless, this workflow sample is very straightforward and the more complex your workflow is, the more attention you need to have to handle the extreme situations in long running workflows in critical environment.

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: mardi 22 avril 2008 23:00 par neodante

Commentaires

Pas de commentaires

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01