locked
WorkflowApplication.Run, SqlWorkflowInstanceStore and Delay Activity not resumed(?) RRS feed

  • Question

  • Hi all, 

    I am trying to leverage the persistence on our own BPM application built upon BETA 2 of WF. We have a WCF service that accepts external "RunWorkflow" requests, that, in turn (on the WCF method implementation) create the WorkflowApplication, loads designed XAML, and runs the workflow itself.

    I added a Delay activity and added SqlWorkflowInstanceStore instance. Basically on my logs, I see that the Workflows runs fine until Delay activity is reached. The Workflow gets Unloaded correctly but is never resumed.

    Obviously I installed and configured the  Workflow Management Service correctly (I suppose) by making it point my instance database, where the appropriate scripts have been executed.

    Looking at the  SQL Profiler, I see activity of the Management Service. 

    I tried to look into the [System.Activities.DurableInstancing].CommandQueueExecutionLogTable and  [System.Activities.DurableInstancing].CommandQueueTable are empty.

    The table 
    [System.Activities.DurableInstancing].InstancesTable

    Contains some rows (at each new worfklow appends a new instance and this is fine)... however wiht the "ExecutionStatus" set as "Idle".

    Any clue? Looks like I am missing something...

    Could MSFT please shed some light on this stuff?

    Thank you very much,
    Cheers


    Adriano
    Tuesday, December 1, 2009 3:17 PM

Answers

  • Ok so I think I know what's happening now....

    WMS only works with WorkflowServiceHost for instance recovery and durable timers. It uses the InstanceControlEndpoint to re-start an instance when the timer has expired, and as you're using WorkflowApplication WMS has no way to do this.

    The good news is that this has been changed and your scenario will be a lot easier to implement in the release version.

    The bad news is for beta 2 if you're using WorkflowApplication you will essentially need to handle durable timer functionality yourself.

    Regards
    --Stuart
    Tuesday, December 1, 2009 9:51 PM

All replies

  • The first place to look is the pending timer column in the InstancesTable - do you see values in there for the instances that you believe are waiting on a durable delay?
    Tuesday, December 1, 2009 4:34 PM
  • Hi Stuart, 

    yes it appears to be correctly... however the instance does not resume. Am I missing something? Should I need to set some other property -or- is there anything I can look at?

    Thank you.

    Adriano
    Tuesday, December 1, 2009 4:37 PM
  • Perhaps an obvious question :) - The instances with data in the PendingTimer column, has the time expired (ie is it in the past)?

    Also, look into the event log to see if WMS has recorded any errors.

    Tuesday, December 1, 2009 4:51 PM
  • Yes, I have a "PendingTimer" but NOT the "PendingCommandId" ... which is NULL... maybe this one is correct.

    However, strange thing... and this can explain the problem... the "PendingTimer" is set "10 seconds" before teh CreationTime. And 10 seconds is the Delay duration I set up on my workflow.

    Looks like this is not normal(?)... 

    Any idea?



    Adriano
    Tuesday, December 1, 2009 5:05 PM
  • OK I've re-read the thread - are you using WorkflowApplication to run the WF instance, or WorkflowServiceHost? It's not entirely clear.
    Tuesday, December 1, 2009 5:24 PM
  • Hi Stuart, sorry for the delay but I was out of office.

    Basically I have a WCF service that is used as "external interface" to our applications. Basically our applications invoke methods on this WCF service to start a Workflow by specifying the definition to use and pass a context. 

    This is done by creating a WorkflowApplication inside the  WCF method service implementation. So I am not using the WorkflowServiceHost. 

    I've set up the WorkflowApplication.InstanceStore, and I am sure that the first phase is wokring correctly: I mean, the WF runs correctly if I wait for its completion, but as soon as I mark it to persist (the definition contains a delay activity), then I see that the WOrkflow is correctly executed till the "Unload" event that is fired when delay activity started and placed its own "bookmark" (or sort of it... I suppose) through the Instance store. 

    However, it never resumes.

    Please let me know if you need further information. I can send you a piece of code of what I am doing tomorrow (I am at home now)

    THANK YOU!!


    Adriano
    Tuesday, December 1, 2009 9:15 PM
  • Ok so I think I know what's happening now....

    WMS only works with WorkflowServiceHost for instance recovery and durable timers. It uses the InstanceControlEndpoint to re-start an instance when the timer has expired, and as you're using WorkflowApplication WMS has no way to do this.

    The good news is that this has been changed and your scenario will be a lot easier to implement in the release version.

    The bad news is for beta 2 if you're using WorkflowApplication you will essentially need to handle durable timer functionality yourself.

    Regards
    --Stuart
    Tuesday, December 1, 2009 9:51 PM
  • Thank you Stuart for your answer!

    Now all is much clear. However, do you think that I could somehow expose this InstanceControlEndPoint manually as an additional endpoint for my WCF service and let the WMS use it as "callback" to notify my service in order to resume the instances and so on?

    Again, thank you very much!


    Adriano
    Tuesday, December 1, 2009 10:06 PM
  • I don't think it is possible - the way this gets enabled needs workflow service host. You'd need to scan the DB looking for expired timers yourself and issue a load command for the instance.

    Wednesday, December 2, 2009 4:18 AM
  • OK thank you Stuart,
    I'll try to create my own Delay activity for now. 

    You told me that in the release version this behavior is changed. What are going to be the major differences? I mean, should I plan to change the WorkflowApplication usage in order to accomodate the changes somehow, -or- are you going to provide a mechanism to accomplish what I was asking for?

    Thank you again,
    Cheers

    Adriano
    Wednesday, December 2, 2009 8:13 AM
  • Not major differeneces - but you scenario will be much easier. Most likely you'll be able to achieve all of this just using WorkflowApplication.
    Wednesday, December 2, 2009 4:58 PM
  • Excellent. Thank you very much Stuart, 
    Cheers

    Adriano
    Wednesday, December 2, 2009 11:13 PM
  • Sorry to hijack this post, but on a related note. Will or does WMS support a plugable data provider interface that can be implemented. For example I need to persist my workflow instances in an Oracle DB will I need to essentially implement a custom WMS?
    http://taylorza.blogspot.com
    Saturday, December 5, 2009 10:32 AM
  • Yes it will in the final release, but it does not in the beta 2 release.

    Saturday, December 5, 2009 4:40 PM
  • Dear Stuart, 

    when you tell about "issue a load command for the instance"... are you referring to the "WorkflowApplication.Load(GUID)" method, or something else should be done? 

    Could I point you on this thread in order to give some feedbacks? 

    I didn't try to make the change as you suggested right now, but I saw that others are trying the same...

    THANK YOU in advance,
    Kind Regards,

    Adriano
    Monday, December 7, 2009 9:26 AM
  • For anyone that likes to solve this issue, please look at this post explaining the way to solve it:

    http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/thread/a11eb75d-65de-4787-9745-2fd634d0eee9

    For anyone hosting workflows on a own process (like I am doing - for example on a Windows Service) you should create your own Thread and at given intervals perform the check like this:

     void ResumePendingFlows()
        {
          MInstanceStore store = new MyInstanceStore(); 
          InstanceHandle handle = store.CreateInstanceHandle(null); 
          InstanceOwner owner = store.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.MaxValue).InstanceOwner; 
          store.DefaultInstanceOwner = owner; 
          
          bool hasRunnableWorkflows = false; 
          
          foreach (InstancePersistenceEvent currentEvent in store.WaitForEvents(handle, TimeSpan.Zero)) 
          { 
            if (currentEvent == HasRunnableWorkflowEvent.Value) 
            { 
              hasRunnableWorkflows = true; 
              break; 
            } 
          } 
          
          if (hasRunnableWorkflows) 
          { 
            Console.WriteLine("Found runnable workflows");
            WorkflowApplication app = new WorkflowApplication( .... ); 
            app.InstanceStore = store; 
            app.LoadRunnableInstance(); 
            app.Run(); 
          } 
          else 
          { 
            Console.WriteLine("Did not find runnable workflows"); 
          }
        }
    
    

    Thank you Stuart for this useful hint!

    Cheers

     


    Adriano
    Thursday, November 4, 2010 12:04 PM