What’s the recommended way to retry groups of related activities?

For example, suppose in the middle of a workflow I have two activities ActivityA and ActivityB . ActivityA modifies the state of some external system, and ActivityB can only run while this external system is in a compatible state. If ActivityB fails and retries, it’s possible that the external system state is no longer compatible, and we need to retry both ActivityA and ActivityB . What’s the recommended way to express this? I can see a few approaches:

  1. Merge the logic for ActivityA and ActivityB into a new ActivityC , which can be retried as a whole.
  2. Create a child workflow containing ActivityA and ActivityB and invoke this child from the original workflow.
  3. Some other approach? Maybe some custom “precondition failed” error from ActivityB that the workflow can use to retry starting at ActivityA ?

The simplest approach is to retry both activities from the workflow code. Java SDK even provides Workflow.retry method which makes it trivial. You have to code the retry code path yourself in other SDKs. See fileprocessing sample (Java, Go) that uses these techniques.

In some cases modeling the sequence as a child workflow and specifying a retry policy for it is also a reasonable approach.

I’m working in Go, so unfortunately Workflow.retry isn’t available to me. Are there any plans to bring similar functionality to Go?

The linked Go example wraps the sequence of activities inside a loop. By my understanding, Temporal would still retry each activity individually, and only when an activity has exhausted its retry attempt count (or activity/session timeout) would the next iteration of the loop trigger.

We could define some custom non-retryable error to circumvent pointless retries by Temporal, but our explicit retry code path still can’t take advantage of things like Temporal’s retry backoff, etc.

It seems that modeling as a child workflow (or combining the activities, as in option 1 from the original question) might be the way to go.

We could define some custom non-retryable error to circumvent pointless retries by Temporal, but our explicit retry code path still can’t take advantage of things like Temporal’s retry backoff, etc.

You can disable individual activity retries by setting retryOptions.maxAttempts to 1.

I’m working in Go, so unfortunately Workflow.retry isn’t available to me. Are there any plans to bring similar functionality to Go?

You can implement an utility class/function that does it yourself trivially.