Handle activity failure exceptions in workflows

Hi Team,
I have a workflow with 100s of activities,some sequential and some parallel.
How to I catch exception in such a scenario?
Do I need to put try/catch in each sequential activity?
can you please tell me if there is any better way to handle it?

Also, in case of parallel activites, I want to continue my workflow if some activities fail.How do I handle exception in parallel activity case?
Thanks in advance.

1 Like

Workflow code handles exceptions exactly the same way as any other Java code. You handle exceptions according to your business logic and can use various programming techniques to avoid code duplication.

In the majority of cases intermittent activity errors are handled by automatic retries according to a retry options passed to the activity. So workflow code doesn’t need to handle them at all.

If you want to continue workflow execution on non intermittent activity failure then try-catch is the right approach.

If you need to surround a lot of activities with try-catch use the standard Java programming techniques to reduce the code duplication. For example:

  public static <T> T ignoreException(Supplier<T> function, T defaultValue) {
    try {
      return function.get();
    } catch (Exception e) {
      return defaultValue;
    }
  }

Can be used as

String result = ignoreException(() -> activities.activity1(arg), "Whatever");

If you want to get really fancy then you can create your own dynamic interceptor which uses your custom annotations to mark activities that have to ignore their exceptions.

3 Likes

Ok, this is clear but there is something I don’t understand: in Java you always have to catch exceptions at some level or declare that they are thrown.

So, suppose I have a workflow method that calls an activity method where an exception can be thrown (e.g., my code tries to connect to a service to retrieve some info or do something but fails).

I cannot avoid catching the exception, otherwise I would need to declare the activity method “throws Exception” and catch it in the workflow method. So in the end it seems to me I have to manage the retries myself, which is not what I would expect. Is there any way to make the activity fail so that it is temporal itself that handles retries?

Maybe I’m completely misunderstanding temporal’s concepts…

OK, maybe it’s done by rethrowing the exception wrapped by Activity.wrap. Is this correct?

try{
...
}catch(Exception e)
{
    throw Activity.wrap(e);
}

I am feeling so lame, sorry guys…

Activity methods should not use throw checked exceptions. As you correctly pointed out if there is a need to propagate a checked exception use throw Activity.wrap(e).

3 Likes

Hi @maxim
I have a DSL implementation for executing dynamic workflows.
I am invoking activityStub.execute() to execute a dynamic activity using Temporal.

I want to achieve the following:
In case of application errors, I want to control the retry behavior of the dynamic activity as follows :

  1. On the activity side, If the application throws ExceptionA , I want Temporal to retry the activity.
  2. On the activity side, If the application throws Exception B, I want Temporal to fail the activity.

I plan to achieve this by performing the following:
On the Activity worker I will catch all application exceptions around the executor method.
a. If the activity-worker throws ExceptionA , I will catch it and throw activity.wrap(ExceptionA) ,
b. If the activity-worker throws ExceptionB , then I catch it and throw ApplicationFailure.newNonRetryableFailureWithCause(
ExceptionB.getMessage(), ExceptionB.getType(), ExceptionB /** cause **/ );
Expected behavior:

  1. When Temporal gets the wrapped exception from the Activity-Worker :
  • For a. : When Temporal gets (a.) it will retry according to the RetryOptions configured on the Workflow - up until max-retries. After max-retries if the application still throws this exception then Temporal will throw a non-retryable exception with ExceptionA as the cause.
  • For b. : When Temporal gets (b.) it will fail the activity and route the exception to the Temporal client side (Dynamic Workflow executor) .
  1. On the Workflow Executor side - activityStub.execute()
  • The workflow-executor will only get ApplicationFailure with ExceptionA iff retry-logic for ExceptionA has failed max retry times.
  • The workflow-executor will get ApplicationFailure with ExceptionB whenever ExceptionB is thrown by the Activity-worker.

On the worker side, I will catch both these exceptions and handle a graceful shutdown of the Workflow and then throw a non-retryable exception.

Question: Will the above behavior work as expected ?

I don’t think you need all this complexity. Just add Exception B to the list of non retryable errors in the activity retry options.

3 Likes