I’ve been trying to use the AsyncCompletionClient to finish one of my activities. I tried copying the example from the Typescript documentation and it doesn’t seem to work:
import { CompleteAsyncError, Context } from '@temporalio/activity';
import { AsyncCompletionClient } from '@temporalio/client';
export async function doSomethingAsync(): Promise<string> {
const taskToken = Context.current().info.taskToken;
setTimeout(() => doSomeWork(taskToken), 1000);
throw new CompleteAsyncError();
}
// this work could be done in a different process or on a different machine
async function doSomeWork(taskToken: Uint8Array): Promise<void> {
const client = new AsyncCompletionClient();
// does some work...
await client.complete(taskToken, 'Job\'s done!');
}
This is what my workflow looks like:
const result = await doSomethingAsync();
return result;
We don’t recommend using async activities for long running operations. The reason is that you’ll have to wait for long even if the activity is lost before enqueued in the external system.
The recommended pattern is to use an activity to send the request to an external system. Then use a signal to notify workflow about the operation completion.
Thanks for the suggestion. I guess I might use a signal instead but can you explain what you mean by “activity is lost”?
I assumed that once the activity is invoked, it is written to the log, so it wouldn’t matter how long it takes to complete it.
For example, the activity worker crashes after receiving the activity task but before invoking the activity function. There are other edge cases that cause activity tasks to never execute. To deal with such scenarios Temporal relies on StartToClose timeout and Heartbeat timeout for long running activities. But in your case you have to set StartToClose timeout to a large value. So it will be retried with a large delay.
In the case of “activity for request then signal for reply,” the activity timeout can be short, causing fast retries in the case of intermittent failures.