diff --git a/references/dotnet/advanced-features.md b/references/dotnet/advanced-features.md index fd0f81e..dd844d0 100644 --- a/references/dotnet/advanced-features.md +++ b/references/dotnet/advanced-features.md @@ -96,9 +96,9 @@ var worker = new TemporalWorker( ## Workflow Init Attribute -Use `[WorkflowInit]` on a constructor to run initialization code when a workflow is first created. +You should always put state initialization logic in the constructor of your workflow class, so that it happens before signals/updates arrive. -**Purpose:** Execute some setup code before signal/update happens or run is invoked. +Normally, your constructor must have no arguments. However, if you add the `[WorkflowInit]` attribute, then your constructor instead receives the same workflow arguments that `[WorkflowRun]` receives: ```csharp [Workflow] @@ -122,7 +122,7 @@ public class MyWorkflow } ``` -Constructor and `[WorkflowRun]` method must have the same parameters with the same types. You cannot make blocking calls (activities, sleeps, etc.) from the constructor. +Constructor (with `[WorkflowInit]`) and `[WorkflowRun]` method must have the same parameters with the same types. You cannot make blocking calls (activities, sleeps, etc.) from the constructor. ## Workflow Failure Exception Types diff --git a/references/java/advanced-features.md b/references/java/advanced-features.md index e736da2..9db730c 100644 --- a/references/java/advanced-features.md +++ b/references/java/advanced-features.md @@ -116,6 +116,30 @@ worker.registerActivitiesImplementations(new MyActivitiesImpl()); factory.start(); ``` +## Workflow Init Annotation + +You should always put state initialization logic in the constructor of your workflow class, so that it happens before signals/updates arrive. + +Normally, your constructor must have no arguments. However, if you add the `@WorkflowInit` annotation, then your constructor instead receives the same workflow arguments that `run` receives: + +```java +public class MyWorkflowImpl implements MyWorkflow { + private final int foo; + + @WorkflowInit + public MyWorkflowImpl(MyInput input) { + foo = 1234; + } + + @Override + public ClusterManagerResult run(ClusterManagerInput input) { + // this.foo is already initialized + } +} +``` + +Constructor (with `@WorkflowInit`) and `run` method must have the same parameters with the same types. You cannot make blocking calls (activities, sleeps, etc.) from the constructor. + ## Workflow Failure Exception Types Control which exceptions cause workflow failures vs workflow task failures. diff --git a/references/python/advanced-features.md b/references/python/advanced-features.md index 3d86e9f..c5ec1b3 100644 --- a/references/python/advanced-features.md +++ b/references/python/advanced-features.md @@ -116,9 +116,9 @@ worker = Worker( ## Workflow Init Decorator -Use `@workflow.init` to run initialization code when a workflow is first created. +You should always put state initialization logic in the `__init__` of your workflow class, so that it happens before signals/updates arrive. -**Purpose:** Execute some setup code before signal/update happens or run is invoked. +Normally, your `__init__` must have no arguments. However, if you add the `@workflow.init` decorator, then your `__init__` instead receives the same workflow arguments that `@workflow.run` receives: ```python @workflow.defn @@ -130,11 +130,13 @@ class MyWorkflow: self._items: list[str] = [] @workflow.run - async def run(self) -> str: + async def run(self, initial_value: str) -> str: # self._value and self._items are already initialized return self._value ``` +`__init__` (with `@workflow.init`) and `@workflow.run` must have the same parameters with the same types. You cannot make blocking calls (activities, sleeps, etc.) from the `__init__`. + ## Workflow Failure Exception Types Control which exceptions cause workflow task failures vs workflow failures.