Skip to main content

Asynchronous Activity Completion

View Markdown

Asynchronous Activity Completion enables the Activity Function to return without the Activity Execution completing.

There are three steps to follow:

  1. The Activity provides the external system with identifying information needed to complete the Activity Execution. Identifying information can be a Task Token, or a combination of Namespace, Workflow ID, and Activity ID.
  2. The Activity Function completes in a way that identifies it as waiting to be completed by an external system.
  3. The Temporal Client is used to Heartbeat and complete the Activity.

To complete an Activity asynchronously, give the Activity implementation an ActivityCompletionClient. Create one with client.newActivityCompletionClient() when you register the Activity with the Worker. When the work finishes, call the client's complete() method with the Task Token. In this example, composeGreetingAsync() runs on another thread and completes the Activity.

java-sandbox/activities/asynchronous-activity/src/main/java/io/temporal/docs/activities/asynchronousactivity/HelloAsyncActivityCompletion.java

/*
* ActivityCompletionClient is used to asynchronously complete activities. In this example we
* will use this client alongside with {@link
* io.temporal.activity.ActivityExecutionContext#doNotCompleteOnReturn()} which means our
* activity method will not complete when it returns, however is expected to be completed
* asynchronously using the client.
*/
private final ActivityCompletionClient completionClient;

GreetingActivitiesImpl(ActivityCompletionClient completionClient) {
this.completionClient = completionClient;
}

// Method that will complete action execution using the defined ActivityCompletionClient
private void composeGreetingAsync(byte[] taskToken, String greeting, String name) {
String result = greeting + " " + name + "!";

// Complete our workflow activity using ActivityCompletionClient
completionClient.complete(taskToken, result);
}

In the Activity method, get the Task Token from the Activity Execution context, hand the work off, and call doNotCompleteOnReturn() before the method returns.

java-sandbox/activities/asynchronous-activity/src/main/java/io/temporal/docs/activities/asynchronousactivity/HelloAsyncActivityCompletion.java

@Override
public String composeGreeting(String greeting, String name) {

// Get the activity execution context
ActivityExecutionContext context = Activity.getExecutionContext();

// Set a correlation token that can be used to complete the activity asynchronously
byte[] taskToken = context.getTaskToken();

/*
* For the example we will use a {@link java.util.concurrent.ForkJoinPool} to execute our
* activity. In real-life applications this could be any service. The composeGreetingAsync
* method is the one that will actually complete workflow action execution.
*/
ForkJoinPool.commonPool().execute(() -> composeGreetingAsync(taskToken, greeting, name));
context.doNotCompleteOnReturn();

// Since we have set doNotCompleteOnReturn(), the workflow action method return value is
// ignored.
return "ignored";
}

When doNotCompleteOnReturn() is called during an Activity Execution, the Activity Execution does not complete when its method returns. The method's return value is ignored, and the Activity Execution stays open until the ActivityCompletionClient completes it.