views:

339

answers:

2

I have a workflow that will watch certain databases and kick off other workflows when it notices a trigger. I only want one instance of this "observer" workflow to be going at any point in time; otherwise, if two or more were running, they'd both notice the change and both fire off the same workflow, which wouldn't work well.

This "observer" workflow is persisted. So...how do I make it so that if the runtime doesn't have an instance of this workflow persisted already, it starts one, but if one is already there, just use the persisted one?

Almost sounds like I could create a small run-once console app that kicked off the workflow I wanted, and then the "real" runtime just pulled the persisted one and never tries to create a new one, but that doesn't sound very elegant.

+1  A: 

We had this problem in a project a while ago. The solution we came up with was to host two runtimes; one with persistence services and one without. In the runtime with no persistence service we were running a couple of this kind of "monitoring workflows" that were automatically started when the host was started.

This is how it was implemented:

First, we had a config file in which we set up the persistence service:

<configuration>
    <configSections>
     <section name="RuntimeWithPersistence" type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </configSections>
    <RuntimeWithPersistence>
     <CommonParameters/>
     <Services>
      <add type="System.Workflow.Runtime.Hosting.DefaultWorkflowSchedulerService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionString="[dbconnectionstring]" UnloadOnIdle="true"/>
     </Services>
    </RuntimeWithPersistence>
</configuration>

And in the workflow host application (cut and edited, but I think i communicates the idea):

public class WorkflowHost
{
    private WorkflowRuntime _runtime = null;
    private WorkflowRuntime _nonPersistingRuntime = null;

    private void SetupRuntime()
    {
     // create a new WorkflowRuntime that points out a config section
     // defining a persistence service
     _runtime = new WorkflowRuntime("RuntimeWithPersistence");
     // set up additional services to use
     _runtime.StartRuntime()

     // create a new WorkflowRuntime that does not point out a config section
     _nonPersistingRuntime = new WorkflowRuntime();
     // set up additional services to use
     _nonPersistingRuntime.StartRuntime()
     // start monitoring workflows in the non persisting runtime
     StartMonitoringWorkflows(_nonPersistingRuntime);
    }
}
Fredrik Mörk
Thanks for the feedback! I started to go down this approach as well, but I'm trying to find an elegant solution to another problem there: the monitoring one has to know which "triggers" it's fired before, so it doesn't do it again the next time it sees it. That's why I was thinking of using persistence with the monitoring one, so it can store a list of triggers to ignore that it's already acted upon. I like the idea though and will investigate it more thoroughly.
Chris
We were into the same kind of thinking, but found to simple and reliable way to determine whether the runtime already had a persisted instance of the workflow or not (it may be that there is; we were relative beginners in the workflow world, and I have not investigated it further since then...)
Fredrik Mörk
+2  A: 

I'm considering this problem as well for a project I'm currently working. However it seems to me that the function of monitoring the DB is not the responsibilty of the workflow.

We're going to create a Service to add to the runtime. This service will raise events that the workflow listens for in the HandleEventActivity. That way the workflow goes idle, is persisted and stays that way until a real work actually needs doing.

AnthonyWJones