Workflow persistence and bookmarks as workflow resiliency

I have a set of custom actions that are used in complex workflows.

I would like to make these (custom actions) persistent without having a workflow pending. It has to be a failover system, so whenever something happens during the execution of a workflow it can be:

  • paused by the user (at any time) and resumed later from a bookmark / point, it was paused (for example, the user noticed that the external system is offline and he wants to pause the workflow for a while).
  • in case of an unhandled exception, we can restart execution from the last bookmark / point in time
  • stopping the host WorkflowApplication can happen at any time and we can restart execution from the last bookmark / point in time

I've been working for a few days with the persistence of a workflow, but I'm not sure if I can achieve my goal. Why?

  • I can use blocking bookmarks in every custom activity, but blocking the workflow and restarting it just to save it doesn't look promising.
  • I could use non-blocking bookmarks, but I couldn't see them in the database and resume from there.

Can you please advise me what are the workflow factories?

I see some light in the unlocked bookmarks, but I can't move them and resume later. Could you please give me some advice on how to keep a non-blocking bookmark for later resumption?

Edit:

There was an attribute in wf3 PersistOnClose

that would be sufficient for my requirement. in wf4 it has been replaced with activity Persist

, which can also be useful, however I don't want to have additional activities in my already complex workflows.

Ideally it would be great to execute context.RequestPersist(callback)

from NativeActivityContext

, however this method is internal (and everything inside it is not visible outside of the original assembly.

+3


source to share


2 answers


This is what I came up with:

  • Non-blocking bookmarks are not an option. While a non-blocking bookmark does not prevent the creation activity from completing, it also does not cause the workflow instance to go dormant, which means it will not be saved. Non-blocking bookmarks are discarded after the operation (which created it) completes. This bookmark can only be resumed if activity creation has not yet been completed.
  • Usage is PersistOnCloseAttribute

    not an option because I am using WF4 and this attribute is .NET 3.x WF only.
  • Blocking bookmarks cannot be used because they block the execution of the workflow, which is undesirable.

The solution is to use an activity Persist

in every custom activity (needs to be extended NativeActivity

that can schedule child activities):

//class field
Activity childActivity = new Persist();

      

To make it work, it needs to be added to the metadata as ImplmentationChild:

protected override void CacheMetadata(NativeActivityMetadata metadata)
{
     base.CacheMetadata(metadata);
     metadata.AddImplementationChild(this.childActivity);
}

      

The last thing is to schedule the child activity from the Execute method (it doesn't matter where, persistence will only happen after the call operation is completed *).



protected override void Execute(NativeActivityContext context)
{
    //...
    context.ScheduleActivity((Activity)this.childActivity);
}

      

To save the workflow after an unhandled exception, this piece of code needs to be added to the WorkflowApplication:

 application.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
 {
      return UnhandledExceptionAction.Abort;
 };

      

* returning from the method Execute

does not necessarily mean that the activity is "complete" - that is, blocking bookmarks within the activity (see below).

There are several disadvantages to this solution:

  • The solution only supports one workflow state (last state).
  • Persistence can only occur when the activity is complete. This means persist / resume cannot be completed from the middle of the activity.
  • It does not work with parallel loops / sequences - actions from the parallel loop / sequence are saved after all parallel work has finished. It works correctly with regular loops / sequences.
  • Blocking bookmarks has a huge impact on this decision (if they are created when creating an activity or in other child activities of creating an activity). They cause this activity to not complete even though the Execute method returns. Eventually Persist will execute (either after the operation completes or before going into a wait state).
+3


source


If I understand your question correctly, you have below requirements.

  • Saving and restoring workflow.
  • User can pause and resume.
  • In case of any exceptions, the workflow is saved and resumed after the next action.

You can use the following steps.



  • You can use WF + WCF service to execute and host your workflow.
  • Add persistence and tracking with a database like Sql server if you are using oracle then you can use Devart.
  • Configure ControlEnpont to suspend and resume.
  • Use try / Catch and persistence to handle the exception.

in case of any problem and need for customization are discussed the same :) as I have developed a workflow similar to yours.

0


source







All Articles