Persistence and long running workflows  
Author Message
reline_sprint





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

Hello all

I am developing a specialist content management system that uses state machine workflows to control the content throughout its lifecycle, which could last from a few days to a number of years.

I have implemented a custom persistence service that uses Activity.Save and Activity.Load to (de)serialize the workflow state into and out of my backing store.

This all works fine and I am very happy with it. However there is one major issue:

Whenever I make the smallest change to a workflow none of my saved workflows can be deserialized.

Instead it throws an IndexOurOfRangeException from ActivitySurrogate.ActivitySerializedRef.OnDeserialization

This part of the framework does not appear to be designed for user extensibility!

So how can i work around this Can I modify the Activity serialization (not a task I relish the thought of) or can I somehow manually store the state of my Activity when it is persisted and then manually recreate it when the runtime requests it

Obviously the easy work around of "stop changing your workflow" will not work as my customers requirements change from day to day, so they are highly unlikely to stay the same for years to come!

Many thanks in advance

Alex



Software Development for Windows Vista8  
 
 
Serge Luca





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

Alex, you are right, it's an issue, specially with xoml only workflows...

you can read this, however :

http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=170216&SiteID=1

Serge

 
 
reline_sprint





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

Thanks for the quick reply Serge

RonaldK seems to be having the some troubles as I am. However as he points out the changes made to a workflow after deployment are likely to be critical so simply loading the old one is not a viable solution.

Idealy I need enough control of the deserialization process to handle the errors.

Or the ability to construct Workflows and manually set their state based on saved data, if possible, or report the error and fail gracefully if not. Without messing about with serialization at all.

Any ideas

Alex


 
 
Matt Milner - Pluralsight





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

one option is to use the overload for the save method and supply your own formatter/serializer. You'll need to provide surrogate serializers much like the default implementation does, but you'll get total control over the binary formatter including adding your own custom SerializationBinder where you can determine what version of the classes to use to deserialize.

Matt



 
 
Jon Flanders





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

Matt - where would a SerializationBinder come into play    Since Activity doesn't (and can't) implement ISerializable - I don't think the SerializationBinder could come into play for Activities.

 

Do you have an example where this works

 

I think you could do the same thing by created an IObjectReference type that is version aware when using SerializatoinSurrogates



 
 
Matt Milner - Pluralsight





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

right you are, I was a little too quick on the keys; rattled off a feature of binary formatter that doesn't come into play here. It would really be adding your own surrogate selector that would allow you to control the serialization.

Matt



 
 
Jon Flanders





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

No worries - I was mostly interested if you found a way to get ISerializable to work with an Activity type :)

 
 
Tom Lake





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

It sounds to me like you are overwriting the old assembly after making changes. When the persisted workflow is deserialized the type still needs to be accessible to the workflow runtime. You can't just modify your workflow, compile it and have the runtime automatically update all instances when they are deserialized.

When you call CreateWorkflow passing in a Type, that type and its assembly have to be accessible to the workflow runtime for the life of that workflow. If you want to make changes to running instances you have to use dynamic update.



 
 
Alexey Lavnikov





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

You can't just modify your workflow, compile it and have the runtime automatically update all instances when they are deserialized. 

Yes, but imho that is a natural way of things...

After being using WF for one month I found several critical disadvantages in its current version:

First one is binary serialization. You are forced to have 1 WF assembly pro workflow class, having .net dll-hell again + "no go" to workflow upgrade. I don't expect my clients will ever accept this approach. I hope MS will address this issue in close future. I'd like to see WF instance data layed out in different columns in my table by my persistence service, rather than in fragile zipped blob field.

Second one is that WF runtime is non-transactional itself. If you start in your workflow several subworkflows - you cannot wrap them in TransactionScope using. So, no something like Debit/Credit workflows for you...

So lack of these obvious features is my reason to wait till next version...


 
 
Matt Milner - Pluralsight





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

Alexey,

How do you manage the state of your long running services/applications today

If you want the data stored differntly in the database, then you can write your own persistence service that does this. You can determine how you want to handle the serialization and saving of state and manage the process for retrieving that data to restore the state of your workflow.

In regards to your second item, transactions, I'd recommend that if you have reusable debit or credit logic, that you wrap it up in a composite activity rather than a separate workflow. Then you can use the composite activity in your workflow and have your activities participate in the work batch/transaction. If you need a workflow that just does a debit or credit, then create a workflow, drop in your composite activity and it is done.

You can wait for version 2.0 if you want, but I think you might be missing some fo the extensibility and encapsulation features available in the current version. My 2 cents.

Matt



 
 
Alexey Lavnikov





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

How do I manage the state of a workflow today It's it really simple. (I use only state machine workflow as a superset of all others)

For each type of workflow I have separate table in database, all private fields of workflow are stored as columns in table, plus I have 5 fixed columns - workflow id, current & previous state path, workflow status (terminated, suspended etc) and state entrance time string. Using this data I have more than enough information to restore workflow state. The problem with WF is that I cannot use it like this. Not this version... That was an answer from original WF guys.

Wanna know what I did I wrote my .NET classes having the same names... I do design in VS.NET, then I paste the designed code and replace using System.Workflow namespace with my one...

The plus is - everything works as I expect, everything is saved/loaded as I expect, everything is simple and fast almost ten fold... I don't care about multithreading, because my database does (using optimistic locking) while trying to save updated workflow...

I just have a bad feeling, that I cheated...


 
 
Alexey Lavnikov





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

No worries - I was mostly interested if you found a way to get ISerializable to work with an Activity type :)

There is nothing special - Activity.Save(Stream, IFormatter), you may pass your own formatter implementation and load/save what you want. The problem is that this approach is too complex for my simplicity-loving mind... What if I miss some important data Who will guaranty than workflow will work as expected I dunno, this approach is too unsteady... I would not risk.


 
 
Jon Flanders





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

Actually there is something special going on - see http://www.masteringbiztalk.com/blogs/jon/PermaLink,guid,5f4d8c41-73bf-4d7f-93b4-8934130a783b.aspx

Neither Activity nor any of the derived Activities implement ISerializable or have the serializable attribute on them.

So an ISerializable implemenation on an Activity is a no-op - it will never be called.



 
 
reline_sprint





PostPosted: Windows Workflow Foundation, Persistence and long running workflows Top

Ok, so it looks like serialization is not the way to go. There is no way that I can garantee that the workflow will not be changed while there are existing instances in the field.

Alexey, your implementation sounds ideal, as I have little instance data in my WF and all I really want to do is create a new instance of the latest version and set it to the state it was in when persisted (if such a state still exists.. if not then error).

I can happily create my new instance with reflection, but how did you set it to the appropriate state I can't see how this could be done without access to the StateMachineExecutionState object.

Any links or code snippets would be greatly appricated.

Cheers

Alex