Race condition with content-based correlation (or How to implement a Duplex Contract) RRS feed

  • Question

  • I just spent a while trying to see why I had inconsistent behavior in my workflow which would work the first time, but not the second or third. I have found that it's a problem with the way I'm using content-based correlation as there is a race between the correlation initialization and receiving the message from the other service.

    If everything worked properly, I would have something like:
    1. WF1 calls WF2 which returns a job id
    2. WF1 waits on a Receive looking for that job id in a message
    3. WF2 calls WF1 with the job's result (has the job id in that message)
    4. WF1 receives the message and does further processing

    My workflows look like this:
    Workflow 1 = new Sequence
      new Send(),
      new ReceiveReply() // CorrelationInitializer = new QueryCorrelationInitializer (on job id in body)
      new Receive // CorrelatesOn = new MessageQuerySet (on job id in body)

    Workflow 2 = new Sequence
      new Receive(),
      new SendReply() // returns a job id in the message body
    ... // processing
      new Send() // calls the original caller with job id in the message body

    The problem I'm seeing is that when WF2's processing is really fast, the message from it's last Send is not recognized by WF1's service host (UnknownMessageReceived). I believe this is because the correlation on WF1 has not yet initialized/registered. Because the SendReply in WF2 is a one-way, the second Send is actually being sent to WF1 while WF1 is still processing the initial reply from WF2. If I put a 1 second delay in WF2 after SendReply, everything works fine.

    If this were pure WCF, my services could be described with contracts like:

    [ServiceContract(... CallbackContract = typeof(IWF2Client))]
    interface IWF2
      Guid Run(...);

    interface IWF2Client // implemented by WF1's last Receive
      OnComplete(Guid id, ...);

    I'm wondering how I should be doing this because obviously my current solution is not working. 

    Has anyone else tried this sort of callback pattern with workflow services? Could I get some guidance from the WF team? I guess when you boil it down, I'm basically looking to implement a Duplex contract in WF

    Many thanks!
    Tuesday, March 9, 2010 4:49 AM

All replies