Parent and child workflow close policy

The docs state:

When a parent workflow is cancelled by the user, the child workflow can be cancelled or abandoned based on a configurable child policy.

If the policy is to cancel child workflows; what happens if the parent workflow returns an error? Do the children also terminate?

I believe ChildWorkflowClose policy was never implemented and is not even available at least in Temporal. Instead ParentClosePolicy was introduced. It defines child behavior in case of parent completion. This allows specifying different policies for different children.

The behavior of the child doesn’t depend on the reason the parent completed. So it doesn’t matter if the parent completed successfully, failed, or timed out. The child will be affected according to the policy:

  • PARENT_CLOSE_POLICY_TERMINATE: child workflow is terminated
  • PARENT_CLOSE_POLICY_ABANDON: the child is not notified about parent completion
  • PARENT_CLOSE_POLICY_REQUEST_CANCEL: the child gets the cancellation request

There is one more concept that applies to the parent-child relationship. A parent can request a child cancellation by canceling context passed to the ExecuteChildWorkflow call. The WaitFoCancellation parameter defines if the future returned from the ExecuteChildWorkflow becomes ready immediately or only after the child completes its execution.

1 Like

Hi Maxim. I’d like to ask about a parent canceling/terminating its child workflow execution.

There is parent workflow A executes a child workflow A with a timer. If the timer is triggered (timeout), the child wf is cancelled/terminated. Workflow A uses below versions:
- go.temporal.io/api v1.11.1-0.20220907050538-6de5285cf463
- go.temporal.io/sdk v1.17.0

Then, there is another parent workflow B, it executes a child workflow B with a timer. If the timer is triggered (timeout), the child wf should be cancelled/terminated. When I test it, the cwf is not cancelled although workflow B has the same code as workflow A. Workflow B uses below versions:
- go.temporal.io/api v1.13.0
- go.temporal.io/sdk v1.18.1

Below is the code snippet:

> childOptions := workflow.ChildWorkflowOptions{
> 	WorkflowID:            childWorkflowId,
> 	RetryPolicy:           retryPolicy,
> 	SearchAttributes:      searchAttributes,
> 	TaskQueue:             wf.TaskQueue,
> 	WorkflowIDReusePolicy: enums.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE,
> }
> ctx = workflow.WithChildOptions(ctx, childOptions)
> 
> childFuture := workflow.ExecuteChildWorkflow(ctx, utility.ChildWorkflowName, childWfReq)
> 
> loopCtx := workflow.WithActivityOptions(ctx, activityOptions)
> 	timerCtx, timerCancel := workflow.WithCancel(loopCtx)
> 	timer := workflow.NewTimer(timerCtx, dynamicConfig.Timer)
> 	selector := workflow.NewSelector(timerCtx)
> 	selector.AddFuture(timer, func(f workflow.Future) {
> 		err1 := f.Get(timerCtx, nil)
> 		if loopCtx.Err() != nil {
> 			logger.Error("Error occurred.", "error", loopCtx.Err())
> 		}
> 	}).AddFuture(childFuture, func(f workflow.Future) {
> 		err := childFuture.Get(ctx, &request)
> 		if err != nil {
> 			logger.Error("Error occurred getting child workflow result.", "error", err)
> 		}
> 		timerCancel()
> 	}).Select(loopCtx)
> }
  1. Could the different behaviors caused by different sdk/api versions?

I tried to modify workflow B to manually cancel the child workflow:

  • I added WaitForCancellation.
childOptions := workflow.ChildWorkflowOptions{
	...
	WaitForCancellation:   true,
}
  • I defined a cancel handler:
childCtx, cancelHandler := workflow.WithCancel(ctx)
  • Then I called the handler when the timer is triggered:
cancelHandler()

However, the child workflow is still running. I also tried to use childCtx.Done() but it does not work.

Bryan,
Next time open a separate topic for a new issue, please.

Look at the workflow execution histories of both workflows in both cases and see if they are different.

Hi Maxim,
Alright, let me move my question to a new topic then.