Handling race condition signal and termination of workflow

We are confused and worried about how signals are handled wrt awaits and if there is a guarantee that a signal is handled.

From the documentation it is said that a promise when sending a signal resolves when the signal is received by the server. What happens if this signal is received at the moment of completion of the workflow?

We have for example following code:

export async function restartFnOnItemUpdate(
  fn: () => Promise<void>
): Promise<void> {
  let updateScope = new CancellationScope({cancellable: true});

  setHandler(updateItemUrnSignal, () => {
    updateScope.cancel();
    updateScope = new CancellationScope({cancellable: true}); 
  });

  let notCompleted = true;
  while (notCompleted) {
    try {
      await updateScope.run(async () => {
        return fn();
      });
      notCompleted = false;
    } catch(error) {
      if(!isCancellation(error)) throw error;
    }
  }
}

The workflow calls this restartFnOnItemUpdate with the fn which consists of multiple activities. e.g.

export async function workflow() {
  await restartFnOnItemUpdate( () => {
    await activity1();
    await activity2();
  }):
};

How can we ensure the signal is always handled?

1 Like

What happens if this signal is received at the moment of completion of the workflow?

Temporal detects this condition and roll backs workflow state to allow signal handling.

How can we ensure the signal is always handled?

Temporal guarantees that the signal handler is always called for a signal. You need to make sure that the signal is handled before completing the workflow.

1 Like

The question is then how can we ensure that the signal is handled?
If I understand correctly the setHandler function could be called after the last await i.e. await restartFnOnItemUpdate meaning that the signal will have no influence.

Should we override the handler then with one which restarts the workflow? (continueAsNew)

setHandler function is guaranteed to be called before the main workflow function is unblocked.

In following screenshot we have a completion of a childWorkflow and at the same time the workflow got started to handle this completion a signal was received, this resulted in a start event to handle this signal.

Would in this situation the handler be called before the childWorkflow is handled (if we would map this to the example code above, the childWorkflow could be replaced by activity2)?

The WorkflowTaskFailed happened exactly because workflow completion was requested and there was a signal that wasn’t handled. A workflow task retry was used to handle the signal.

Would in this situation the handler be called before the childWorkflow is handled

Yes.