When a Workflow is cancelled, how is the ongoing execution handled?

Cancellation request returns OK as soon as it is accepted by the service. It is delivered and handled by a workflow asynchronously as potentially the cleanup code can take long time.

The way cancellation is handled by the workflow code is SDK specific.

Go

Go it uses Context.Done channel to notify workflow code that cancellation request was received. Most Temporal Go SDK APIs will immediately fail with CanceledError when called with already canceled context.

An activity that is already executing the behavior depends on the value of WaitForCancellation property of ActivityOptions. If this property is set to true the activity Future is going to become ready only after the activity completes or reports the cancellation. For an activity to get canceled it must heartbeat as heartbiting is the only way at this point to send information to an already executing activity. If the WaitForCancellation is set to false the cancellation is still sent to an activity, but the activity result Future becomes ready with CanceledError immediately.

The same applies to a child workflow. ChildWorkflowOptions.WaitForCancellation property is used. And the cancellation of a child workflow follows the same approach as of any other workflow. As it is not possible to use a context that spawned from a root workflow context to call any SDK functions a disconnected context has to be used for cleanup. Use workflow.NewDisconnectedContext to create one.

Java

Java doesn’t have a commonly used way to cancel computation besides a very unfriendly Thread.interrupt. So the Temporal framework uses its own CancellationScope abstraction. The code inside a CancellationScope is canceled when cancel is called on the surrounding scope. The main workflow method is always invoked in the context of a root cancellation scope. And this root scope is canceled when a workflow is canceled.

The behavior of an activity invocation is controlled through ActivityOptions.cancellationType property. It can have three values: WAIT_CANCELLATION_COMPLETED, TRY_CANCEL, ABANDON. The WAIT_CANCELLATION_COMPLETED blocks the activity invocation until the activity is canceled or completed, TRY_CANCEL sends cancellation to the activity, but immediately fails its invocation in the workflow code and ABANDON doesn’t send cancellation and immediately fails it in the workflow code. For an activity to get canceled it must heartbeat as heartbiting is the only way at this point to send information to an already executing activity.

The child workflow has similar ChildWorkflowOptions.cancellationType property with the similar behavior.