Handle Signal while Activity InProgress or wf Failed?

Hi there!

I have a workflow that’s calling an activity which is calling an api. When the api fails the retry will kick in. Once retry has reached the maximumAttempts, it shows a wf execution status as “Failed”.

There is a possibility of a cancel signal to arrive at any point which should mark the workflow as successfully completed or cancelled, ideally, regardless of whether it’s working on an activity or is in a failed state.

When the workflow hasn’t reached the activity call, I can simply return when the signal has arrived but once the activity call is reached, I believe the signal does not get executed until the event loop is done with retrying the activity (possibly for a long time, depending on the retry policy). I also believe that once the workflow is in a Failed status, it won’t be able to process the signal anymore.

Again, a cancel signal should cause the workflow to be marked as successfully complete or cancelled.

What’s the best way to achieve that? Is there a good pattern?

Assuming that a signal can’t be processed if a wf is in a Failed state or until the activity returns a result to the workflow, I’m thinking that I’d have to catch the exceptions of the api in the activity and return a result to the wf that I can interpret via workflow code. Unfortunately for this solution, I’d have to wait and retry via code vs. using temporal retry mechanisms.

let isCancel = false;

export async function setupHandlers(): Promise<void> {
  setHandler(signals.cancel, (signal) => {
    isCancel = true;
  });
}

export async function myWorkflow({myId}: MyWorkflowInput): Promise<unknown> {

  await setupHandlers();
  let isSuccess = false;

  while (!isSuccess && !isCancel) {
    const result = await executeMyActivity();
    isSuccess = result.isSuccess;

    if (isCancel) {
      return 'need for activity got cancelled';
    }
    if (!isSuccess) {
      log.info(`activity failed`);
      // waiting before making next attempt
      await wf.sleep(1000 * 60); // sleep for 60 seconds

      // probably throw an ApplicationError at some point to avoid retrying indefinitely. 
    }
  }  
  return; // successful completion
}

Is there a better way?
Thank you for your thoughts!

To cancel running activities, use the cancellation scope or workflow cancellation instead of a signal. See this sample that uses workflow cancellation.