We have one scenario planning to receive kafka message and continuously signalWithStart a workflow with same workflow id, based on assumption that signalWithStart will start workflow execution with same workflow id but different run id when previous workflow terminates.
One doubt we have is that how will signal behave during the closing of the previous workflow, lets say the previous workflow is closing and now it receives a signal? Will the previous workflow throw an error and how should we do with this error, or will it handle the signal during closing as a compensation behavior? Or this last signal will be kept in server and launch the next new execution of workflow?
Temporal will detect the race condition, fail the last workflow task that was trying to close the workflow and let workflow process the newly arrived signal. You can see this as WorkflowTaskFailure with UnhandledCommand reason.
So signal is either processed by a workflow or workflow is closed before signal is delivered and a new workflow is started. So signals cannot be lost if the workflow code is written correctly.
“Temporal will detect the race condition, fail the last workflow task that was trying to close the workflow and let workflow process the newly arrived signal. You can see this as WorkflowTaskFailure with UnhandledCommand reason.”
Our code is like:
Queue q;
Signal method: {
add signal to the queue q
}
Workflow execution: {
While there are signals from the queue q {
pull one signal s from queue q
do action A based on that signal s
do action B based on that signal s
.....
}
...
}
So for the received signal during closing, the signal method will run and add signal to the queue,
but as it is already passed “While” block in “Workflow execution” during closing, i assume “action A” and “action B” will not apply onto this new signal. How can we reapply the execution code, “While” block with “action A” and “action B” as long as we receive new signal even during closing time?
Temporal will fail the last workflow task and roll back the workflow state to the previous one. Then, run the signal handler and, after that, unblock the workflow thread.
So, from the code point of view, it means that the code will re-execute the “While there are signals from the queue q” condition again and then process the signal inside the loop. This only works if the workflow code doesn’t block after checking the condition.
Does it means this “while” block needs to be the last workflow task to run so only that while block can be re-executed?
While block will re-execute if:
Workflow execution: {
while (the queue is not empt) {
Run activity A;
Run Activity B;
}
return output;
}
And while block will not re-execute if (there are activities after while block):
Workflow execution: {
while (the queue is not empt) {
Run activity A;
Run Activity B;
}
Run Activity C;
Run Activity D;
return output;
If it is received after “return output” code executed, but before the CompleteWorkflowExecution command is recorded by the service then the described above “rollback and reexecute the last task” logic will be executed. Note that if signals are sent at a high rate it is possible that a workflow never completes until it hits the max allowed signal limit. After that signals will be rejected until the workflow completion.
If it is received after the workflow completed at the service then the new workflow execution will be started.