new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Temporal · Develop · all subjects

child-workflows

92 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

Set versioning intent on ChildWorkflowOptions and ContinueAsNewOptions

ChildWorkflowOptions and ContinueAsNewOptions also support the setVersioningIntent method to override default versioning behavior, similar to ActivityOptions.

Invoking Child Workflows in Java

You can invoke other Workflows as Child Workflows using Workflow.newChildWorkflowStub() or Workflow.newUntypedChildWorkflowStub() within a Workflow Definition.

Any Workflow can run as Child Workflow or standalone

Any Workflow can be run as a standalone Workflow or as a Child Workflow, so registering a Child Workflow in a SimplePlugin is the same as registering any Workflow.

When to add Child Workflows instead of Workflow libraries in plugins

Consider adding a Child Workflow in a plugin instead of a Workflow library when one or more of these conditions apply: the child should outlive the parent, the Workflow Event History would otherwise not scale in parent Workflows, or when you want a separate Workflow ID for the child so that it can be operated independently of the parent's state (canceled, terminated, paused).

Saga pattern key points

Add compensating actions to a list before executing each Activity. Use reversed(compensations) to undo operations in the correct order. Handle compensation failures gracefully as they might fail too. Temporal manages all state and retry logic, making Saga implementation straightforward.

Saga pattern implementation example in Python

from temporalio import workflow from temporalio.exceptions import ActivityError, ApplicationError from datetime import timedelta @workflow.defn class OrderWorkflow: @workflow.run async def run(self, order): compensations = [] try: # Reserve inventory compensations.append({ "activity": revert_inventory, "input": order }) await workflow.execute_activity( reserve_inventory, order, start_to_close_timeout=timedelta(seconds=10), ) # Charge payment compensations.append({ "activity": refund_payment, "input": order }) payment_id = await workflow.execute_activity( charge_payment, order, start_to_close_timeout=timedelta(seconds=10), ) # Create shipment compensations.append({ "activity": cancel_shipment, "input": payment_id }) shipment_id = await workflow.execute_activity( create_shipment, order, start_to_close_timeout=timedelta(seconds=10), ) return {"payment_id": payment_id, "shipment_id": shipment_id} except ActivityError as e: workflow.logger.error(f"Order failed: {e.cause}, rolling back...") # Execute compensations in reverse order for compensation in reversed(compensations): try: await workflow.execute_activity( compensation["activity"], compensation["input"], start_to_close_timeout=timedelta(seconds=10), ) except ActivityError as comp_err: # Log compensation failure but continue with others workflow.logger.error(f"Compensation failed: {comp_err.cause}") # Re-raise the original error raise ApplicationError( f"Order failed: {e.cause}", type="OrderFailed" )

Example: Function with child Workflow export

import { sleep } from '@temporalio/workflow'; import { someWorkflowToRunAsChild } from './some-workflow'; export { someWorkflowToRunAsChild }; export async function functionToTest(): Promise<number> { const result = await wf.executeChild(someWorkflowToRunAsChild); return result + 42; }

Export child Workflows from same file

If a function in Workflow context starts a Child Workflow, that Workflow must be exported from the same file so the Worker knows about it.

Parent Close Policy example

await Workflow.ExecuteChildWorkflowAsync( (MyChildWorkflow wf) => wf.RunAsync(), new() { ParentClosePolicy = ParentClosePolicy.Abandon });

ExecuteChildWorkflowAsync basic example

await Workflow.ExecuteChildWorkflowAsync((MyChildWorkflow wf) => wf.RunAsync());

Child Workflow Execution in .NET SDK

A Child Workflow Execution is a Workflow Execution that is scheduled from within another Workflow using a Child Workflow API. In .NET, use the ExecuteChildWorkflowAsync() method to start a Child Workflow and wait for completion, or use StartChildWorkflowAsync() to start a Child Workflow and return its handle. ExecuteChildWorkflowAsync() is a helper method that internally calls StartChildWorkflowAsync() plus await handle.GetResultAsync().

Child Workflow Event History in .NET

Child Workflow related Events (StartChildWorkflowExecutionInitiated, ChildWorkflowExecutionStarted, ChildWorkflowExecutionCompleted) are logged in the Workflow Execution Event History. The ChildWorkflowExecutionStarted Event must be logged to the Event History before the Parent Workflow completes to ensure the Child Workflow has started.

Child Workflow startup guarantee in .NET

In .NET, awaiting StartChildWorkflowAsync() or ExecuteChildWorkflowAsync() internally waits for the ChildWorkflowExecutionStarted Event before returning, so the Child Workflow is guaranteed to have started once the call resolves.

Set Parent Close Policy in .NET

Set the ParentClosePolicy property inside the ChildWorkflowOptions for ExecuteChildWorkflowAsync or StartChildWorkflowAsync to specify the behavior of the Child Workflow when the Parent Workflow closes.

Async Child Workflows require Abandon policy and ChildWorkflowExecutionStarted event

To asynchronously spawn a Child Workflow Execution, the Child Workflow must have an Abandon Parent Close Policy set in the Child Workflow Options. Additionally, the Parent Workflow Execution must wait for the ChildWorkflowExecutionStarted Event to appear in its Event History before it completes. If the Parent makes the ExecuteChildWorkflow call and then immediately completes, the Child Workflow Execution does not spawn.

ExecuteChildWorkflow API in Go

To spawn a Child Workflow Execution in Go, use the ExecuteChildWorkflow API from the go.temporal.io/sdk/workflow package. The call requires an instance of workflow.Context with workflow.ChildWorkflowOptions applied to it, the Workflow Type, and any parameters to pass to the Child Workflow. ExecuteChildWorkflow returns a ChildWorkflowFuture instance.

Child Workflow Options inheritance in Go

In Go, workflow.ChildWorkflowOptions contain the same fields as client.StartWorkflowOptions. Workflow Option fields automatically inherit their values from the Parent Workflow Options if they are not explicitly set. If a custom WorkflowID is not set, one is generated when the Child Workflow Execution is spawned.

Apply Child Workflow Options with WithChildOptions

In Go, use the WithChildOptions API to apply Child Workflow Options to an instance of workflow.Context. This context is then passed to the ExecuteChildWorkflow call.

Wait for Child Workflow result with Get method

Call the .Get() method on the ChildWorkflowFuture instance to wait for the Child Workflow result.

Basic Child Workflow execution example in Go

func YourWorkflowDefinition(ctx workflow.Context, params ParentParams) (ParentResp, error) { childWorkflowOptions := workflow.ChildWorkflowOptions{} ctx = workflow.WithChildOptions(ctx, childWorkflowOptions) var result ChildResp err := workflow.ExecuteChildWorkflow(ctx, YourOtherWorkflowDefinition, ChildParams{}).Get(ctx, &result) if err != nil { // ... } return resp, nil } func YourOtherWorkflowDefinition(ctx workflow.Context, params ChildParams) (ChildResp, error) { return resp, nil }

Wait for Child Workflow spawn with GetChildWorkflowExecution

To ensure that a Child Workflow Execution has started, call the GetChildWorkflowExecution method on the ChildWorkflowFuture instance, which returns a different Future. Then call the Get() method on that Future to wait until the Child Workflow Execution has spawned.

Async Child Workflow example in Go

import ( "go.temporal.io/api/enums/v1" ) func YourWorkflowDefinition(ctx workflow.Context, params ParentParams) (ParentResp, error) { childWorkflowOptions := workflow.ChildWorkflowOptions{ ParentClosePolicy: enums.PARENT_CLOSE_POLICY_ABANDON, } ctx = workflow.WithChildOptions(ctx, childWorkflowOptions) childWorkflowFuture := workflow.ExecuteChildWorkflow(ctx, YourOtherWorkflowDefinition, ChildParams{}) var childWE workflow.Execution if err := childWorkflowFuture.GetChildWorkflowExecution().Get(ctx, &childWE); err != nil { return err } return resp, nil } func YourOtherWorkflowDefinition(ctx workflow.Context, params ChildParams) (ChildResp, error) { return resp, nil }

Parent Close Policy in Go

A Parent Close Policy determines what happens to a Child Workflow Execution if its Parent changes to a Closed status (Completed, Failed, or Timed Out). The default Parent Close Policy is PARENT_CLOSE_POLICY_TERMINATE. In Go, set the Parent Close Policy on the ParentClosePolicy field of workflow.ChildWorkflowOptions using values from the go.temporal.io/api/enums/v1 package.

Parent Close Policy values in Go

The possible Parent Close Policy values in Go are: PARENT_CLOSE_POLICY_ABANDON, PARENT_CLOSE_POLICY_TERMINATE, and PARENT_CLOSE_POLICY_REQUEST_CANCEL. The type is ParentClosePolicy from go.temporal.io/api/enums/v1. Default value is PARENT_CLOSE_POLICY_TERMINATE.

Parent Close Policy example in Go

import ( "go.temporal.io/api/enums/v1" ) func YourWorkflowDefinition(ctx workflow.Context, params ParentParams) (ParentResp, error) { childWorkflowOptions := workflow.ChildWorkflowOptions{ ParentClosePolicy: enums.PARENT_CLOSE_POLICY_ABANDON, } ctx = workflow.WithChildOptions(ctx, childWorkflowOptions) childWorkflowFuture := workflow.ExecuteChildWorkflow(ctx, YourOtherWorkflowDefinition, ChildParams{}) return resp, nil } func YourOtherWorkflowDefinition(ctx workflow.Context, params ChildParams) (ChildResp, error) { return resp, nil }

Explicit GetChildWorkflowExecution required in Go for event logging

In Go, you must explicitly call GetChildWorkflowExecution() on the ChildWorkflowFuture and then call Get() on the returned Future to wait for the ChildWorkflowExecutionStarted Event to be logged to the Event History.

Execute untyped Child Workflow asynchronously in Java

ChildWorkflowStub childUntyped = Workflow.newUntypedChildWorkflowStub( "GreetingChild", // your workflow type ChildWorkflowOptions.newBuilder().setWorkflowId("childWorkflow").build()); Promise<String> greeting = childUntyped.executeAsync(String.class, String.class, "Hello", name); String result = greeting.get();

ChildWorkflowExecutionStarted event must log before parent completes in Java

In Java, the ChildWorkflowExecutionStarted Event must be logged to the Event History before the Parent Workflow completes to ensure the Child Workflow has started. You must explicitly call Workflow.getWorkflowExecution(child) to get a Promise, then call .get() on that Promise to wait for this Event.

Async Child Workflow invocation in Java

The first call to the Child Workflow stub must always be its Workflow method (method annotated with @WorkflowMethod). Child Workflow methods can be invoked synchronously or asynchronously using Async#function or Async#procedure. The synchronous call blocks until a Child Workflow method completes. The asynchronous call returns a Promise which can be used to wait for the completion of the Child Workflow method.

Spawn typed Child Workflow asynchronously example

GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class); Promise<String> greeting = Async.function(child::composeGreeting, "Hello", name); // ... greeting.get()

Spawn single Child Workflow from parent example

@WorkflowInterface public interface GreetingChild { @WorkflowMethod String composeGreeting(String greeting, String name); } public class GreetingWorkflowImpl implements GreetingWorkflow { @Override public String getGreeting(String name) { GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class); return child.composeGreeting("Hello", name); } }

Spawn two Child Workflows in parallel in Java

public class GreetingWorkflowImpl implements GreetingWorkflow { @Override public String getGreeting(String name) { GreetingChild child1 = Workflow.newChildWorkflowStub(GreetingChild.class); Promise<String> greeting1 = Async.function(child1::composeGreeting, "Hello", name); GreetingChild child2 = Workflow.newChildWorkflowStub(GreetingChild.class); Promise<String> greeting2 = Async.function(child2::composeGreeting, "Bye", name); return "First: " + greeting1.get() + ", second: " + greeting2.get(); } }

New stub required for each child workflow

Workflows are stateful, so a new stub must be created for each new child workflow when spawning multiple Child Workflows.

Query to Child Workflows not supported from parent workflow code

Sending a Query to Child Workflows from within the parent Workflow code is not supported. However, you can send a Query to Child Workflows from Activities using WorkflowClient.

Default Parent Close Policy in Java

The default Parent Close Policy option is set to PARENT_CLOSE_POLICY_TERMINATE, which terminates the Child Workflow Execution.

Set Parent Close Policy in Java

Set Parent Close Policy on an instance of ChildWorkflowOptions using ChildWorkflowOptions.newBuilder().setParentClosePolicy(). The type is ChildWorkflowOptions.Builder and the default is PARENT_CLOSE_POLICY_TERMINATE.

Parent Close Policy with ABANDON example

public void parentWorkflow() { ChildWorkflowOptions options = ChildWorkflowOptions.newBuilder() .setParentClosePolicy(ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON) .build(); MyChildWorkflow child = Workflow.newChildWorkflowStub(MyChildWorkflow.class, options); Async.procedure(child::<workflowMethod>, <args>...); Promise<WorkflowExecution> childExecution = Workflow.getWorkflowExecution(child); // Wait for child to start childExecution.get() }

Ensure Child Workflow starts before parent closes

Steps 3 and 4 in the Parent Close Policy pattern are needed to ensure that a Child Workflow Execution starts before the parent closes. If the parent initiates a Child Workflow Execution and then completes immediately after, the Child Workflow will never execute. The pattern involves calling Workflow.getWorkflowExecution() on the child stub and waiting for the returned Promise to complete.

PHP Parent Close Policy example with POLICY_ABANDON

Example setting Parent Close Policy to POLICY_ABANDON: $child = Workflow::newUntypedChildWorkflowStub( 'child-workflow', ChildWorkflowOptions::new() ->withParentClosePolicy(ParentClosePolicy::POLICY_ABANDON) ); yield $child->start();

Child Workflow Execution definition in PHP

A Child Workflow Execution is a Workflow Execution that is scheduled from within another Workflow using a Child Workflow API. Child Workflow related Events (StartChildWorkflowExecutionInitiated, ChildWorkflowExecutionStarted, ChildWorkflowExecutionCompleted) are logged in the Workflow Execution Event History.

ChildWorkflowExecutionStarted Event must be logged before parent completes

The ChildWorkflowExecutionStarted Event must be logged to the Event History before the Parent Workflow completes to ensure the Child Workflow has started. In PHP, yielding $child->start() or Workflow::executeChildWorkflow() internally waits for this Event before returning, so the Child Workflow is guaranteed to have started once the yield resolves.

PHP Child Workflow stub creation with newChildWorkflowStub

Create a child workflow stub using Workflow::newChildWorkflowStub(ChildWorkflowInterface::class, ChildWorkflowOptions::new()). Configure options like withWorkflowId() and withExecutionStartToCloseTimeout(). Use one stub per child workflow run.

Child Workflow method call returns Promise immediately

When you call $child->workflowMethod(args), the method call returns immediately and returns a Promise. This allows you to execute more code without having to wait for the scheduled Workflow to complete.

PHP Child Workflow async/sync execution patterns

To call a child workflow asynchronously, call $child->workflowMethod() which returns immediately with a Promise. To call synchronously, use yield $child->workflowMethod() which waits for the result.

PHP Child Workflow example with Promise and error handling

Example code: $child = Workflow::newChildWorkflowStub( ChildWorkflowInterface::class, ChildWorkflowOptions::new() ->withWorkflowId('BID-SIMPLE-CHILD-WORKFLOW') ->withExecutionStartToCloseTimeout(DateInterval::createFromDateString('30 minutes')) ); $promise = $child->workflowMethod('value'); try{ $value = yield $promise; } catch(TemporalException $e) { $logger->error('child workflow failed'); throw $e; }

PHP executeChildWorkflow direct API

Alternative to stub creation is using Workflow::executeChildWorkflow() directly: $childResult = yield Workflow::executeChildWorkflow('ChildWorkflowName', ['args'], ChildWorkflowOptions::new()->withWorkflowId('BID-SIMPLE-CHILD-WORKFLOW'), Type::TYPE_STRING);

PHP Parent Close Policy values

In PHP, Parent Close Policy is set via ChildWorkflowOptions::withParentClosePolicy() method. The possible values from the ParentClosePolicy class are: POLICY_TERMINATE, POLICY_ABANDON, POLICY_REQUEST_CANCEL.

PHP untyped Child Workflow stub creation

Create an untyped child workflow stub using Workflow::newUntypedChildWorkflowStub('workflow-name', ChildWorkflowOptions). This allows starting child workflows without a specific interface type.

PHP yield required for child workflow start before parent close

When starting a child workflow with yield $child->start(), the yield ensures that a Child Workflow Execution starts before the parent closes. This is necessary to guarantee the child workflow has been initiated.

Setting parent close policy in Python

Set the parent_close_policy parameter inside the start_child_workflow() function or the execute_child_workflow() function to specify the behavior of the Child Workflow when the Parent Workflow closes. Use ParentClosePolicy enum values such as ABANDON.

Child workflow execution in Python

In Python SDK, start a Child Workflow Execution using either the execute_child_workflow() function which starts the Child Workflow and waits for completion, or the start_child_workflow() function which starts a Child Workflow and returns its handle. The execute_child_workflow() function is a helper for start_child_workflow() plus await handle.

Python child workflow execution example

from temporalio import workflow from dataobject import ComposeGreetingInput from temporalio.workflow import ParentClosePolicy @workflow.defn class ComposeGreetingWorkflow: @workflow.run async def run(self, input: ComposeGreetingInput) -> str: return f"{input.greeting}, {input.name}!" @workflow.defn class GreetingWorkflow: @workflow.run async def run(self, name: str) -> str: return await workflow.execute_child_workflow( ComposeGreetingWorkflow.run, ComposeGreetingInput("Hello", name), id="hello-child-workflow-workflow-child-id", parent_close_policy=ParentClosePolicy.ABANDON, )

Awaiting child workflow ensures start event completion

In Python, awaiting start_child_workflow() or execute_child_workflow() internally waits for the ChildWorkflowExecutionStarted event before returning, so the Child Workflow is guaranteed to have started once the call resolves.

start_child_workflow method in Ruby

In Ruby, the start_child_workflow method starts a Child Workflow and returns its handle without waiting for completion. This method is useful if you want to do something after the Child Workflow has only started, or to get the Workflow/Run ID, or to signal it while running. Like execute_child_workflow, it internally waits for the ChildWorkflowExecutionStarted event before returning.

Parent Close Policy default in Ruby

The default Parent Close Policy option in Ruby is set to terminate the Child Workflow Execution when the Parent Workflow changes to a Closed status.

How to set child workflow fairness in Ruby SDK

Set the parent_close_policy parameter for execute_child_workflow or start_child_workflow to specify the behavior of the Child Workflow when the Parent Workflow closes. For example, use parent_close_policy: Temporalio::Workflow::ParentClosePolicy::ABANDON to abandon the Child Workflow when the Parent closes.

execute_child_workflow example in Ruby

Temporalio::Workflow.execute_child_workflow(MyChildWorkflow, 'my-workflow-arg')

execute_child_workflow with parent_close_policy example in Ruby

Temporalio::Workflow.execute_child_workflow( MyChildWorkflow, 'my-workflow-arg', parent_close_policy: Temporalio::Workflow::ParentClosePolicy::ABANDON )

ChildWorkflowExecutionStarted event timing requirement

The ChildWorkflowExecutionStarted Event must be logged to the Event History before the Parent Workflow completes to ensure the Child Workflow has started. In Ruby, calling start_child_workflow or execute_child_workflow internally waits for this event before returning.

Start a Child Workflow in Rust using ctx.child_workflow()

In Rust, use ctx.child_workflow() to start a Child Workflow Execution. Pass the workflow function, input parameters, and ChildWorkflowOptions. Awaiting ctx.child_workflow() internally waits for the ChildWorkflowExecutionStarted event before returning, guaranteeing the Child Workflow has started once the call resolves.

Give your agent this brain