elsa-core
elsa-core copied to clipboard
ParallelForEach: using variables
Description
When running steps in parallel, it is not possible to transfer data between activities of step. If use variables, the data is overwritten for all steps.
Steps to Reproduce
- Create a parallel loop.
- For each step, perform an operation that returns a result.
- Put this result in a variable.
public class TestWorkflow : WorkflowBase
{
protected override void Build(IWorkflowBuilder builder)
{
Variable<string> stepVariable = builder.WithVariable<string>().WithWorkflowStorage();
var sendHttpRequest = new SendHttpRequest
{
Url = new Input<Uri?>(new Uri("https://www.google.com/search?q=111111111")),
ParsedContent = new Output<object?>(stepVariable)
};
var stepWriteLine = new WriteLine(stepVariable);
var parallel = new ParallelForEach
{
Items = new Input<object>(new Expression("JavaScript", "[\"first\", \"second\"]")),
Body = new Flowchart
{
Activities =
{
sendHttpRequest,
stepWriteLine
},
Connections =
{
new Connection(sendHttpRequest, stepWriteLine)
}
}
};
var initWriteLine = new WriteLine("Line");
builder.Root = new Flowchart
{
Start = initWriteLine,
Activities =
{
initWriteLine,
parallel
},
Connections =
{
new Connection(initWriteLine, parallel)
}
};
}
}
The issue is that the Step variable lives in a shared scope (at the workflow-level) and so is continuously overwritten. What you need to do instead, is define the variable on the Flowchart activity in the Body of the ParallelForEach activity. This way, the variable becomes local to the current iteration, of which there can exist many in parallel.
Example (not tested ⚠ ):
public class TestWorkflow : WorkflowBase
{
protected override void Build(IWorkflowBuilder builder)
{
// Define a dangling workflow variable that is to be added to the Flowchart activity within the ParallelForEach activity.
var stepVariable = new Variable<string>();
var sendHttpRequest = new SendHttpRequest
{
Url = new Input<Uri?>(new Uri("https://www.google.com/search?q=111111111")),
ParsedContent = new Output<object?>(stepVariable)
};
var stepWriteLine = new WriteLine(stepVariable);
var parallel = new ParallelForEach
{
Items = new Input<object>(new Expression("JavaScript", "[\"first\", \"second\"]")),
Body = new Flowchart
{
Variables = { stepVariable }, // Add the stepVariable here to make it local to each iteration.
Activities =
{
sendHttpRequest,
stepWriteLine
},
Connections =
{
new Connection(sendHttpRequest, stepWriteLine)
}
}
};
var initWriteLine = new WriteLine("Line");
builder.Root = new Flowchart
{
Start = initWriteLine,
Activities =
{
initWriteLine,
parallel
},
Connections =
{
new Connection(initWriteLine, parallel)
}
};
}
}
Thank you very much for this information. This approach works correctly, but there are limitations.
- I do not understand if I can set a variable in the Flowchart action in the ParallelForEach action body via Studio. In the option you proposed, the variables are not displayed in Studio.
- For such an implementation, in the Workflow instances Journal, for each iteration, the same value from the first step is logged.