diff --git a/docs/develop/python/message-passing.mdx b/docs/develop/python/message-passing.mdx index 8522eb5875..d4f6558769 100644 --- a/docs/develop/python/message-passing.mdx +++ b/docs/develop/python/message-passing.mdx @@ -416,8 +416,6 @@ Here are three important use cases for `workflow.wait_condition`: - Wait in a handler until it's appropriate to continue. - Wait in the main Workflow until all active handlers have finished. -#### Use wait conditions in handlers - #### Wait for a Signal or Update to arrive It's common to use `workflow.condition` to wait for a particular Signal or Update to be sent by a Client: @@ -440,7 +438,7 @@ class GreetingWorkflow: return self.greetings[self.language] ``` -### Use wait conditions in handlers +#### Use wait conditions in handlers {#wait-in-message-handler} It's common to use a Workflow wait condition to wait until a handler should start. You can also use wait conditions anywhere else in the handler to wait for a specific condition to become `True`. @@ -457,8 +455,6 @@ The `workflow.wait_condition` method waits until your condition is met: ) ``` -Remember: handlers can execute before the main Workflow method starts. - You can also use wait conditions anywhere else in the handler to wait for a specific condition to become true. This allows you to write handlers that pause at multiple points, each time waiting for a required condition to become true. @@ -490,6 +486,51 @@ You can silence these warnings on a per-handler basis by passing the `unfinished See [Finishing handlers before the Workflow completes](/encyclopedia/workflow-message-passing#finishing-message-handlers) for more information. + +### Use `@workflow.init` to operate on Workflow input before any handler executes + +Normally, your Workflow `__init__` method won't have any parameters. +However, if you use the `@workflow.init` decorator on your `__init__` method, you can give it the same [Workflow parameters](/develop/python/core-application#workflow-parameters) as your `@workflow.run` method. +The SDK will then ensure that your `__init__` method receives the Workflow input arguments that the [Client sent](/develop/python/temporal-clients#start-workflow-execution). +(The Workflow input arguments are also passed to your `@workflow.run` method -- that always happens, whether or not you use the `@workflow.init` decorator.) +This is useful if you have message handlers that need access to workflow input: see [Initializing the Workflow first](/encyclopedia/workflow-message-passing#workflow-initializers). + +Here's an example. +Notice that `__init__` and `get_greeting` must have the same parameters, with the same type annotations: + +```python +@dataclass +class MyWorkflowInput: + name: str + + +@workflow.defn +class WorkflowRunSeesWorkflowInitWorkflow: + @workflow.init + def __init__(self, workflow_input: MyWorkflowInput) -> None: + self.name_with_title = f"Sir {workflow_input.name}" + self.title_has_been_checked = False + + @workflow.run + async def get_greeting(self, workflow_input: MyWorkflowInput) -> str: + await workflow.wait_condition(lambda: self.title_has_been_checked) + return f"Hello, {self.name_with_title}" + + @workflow.update + async def check_title_validity(self) -> bool: + # 👉 The handler is now guaranteed to see the workflow input + # after it has been processed by __init__. + is_valid = await workflow.execute_activity( + check_title_validity, + self.name_with_title, + schedule_to_close_timeout=timedelta(seconds=10), + ) + self.title_has_been_checked = True + return is_valid +``` + + + ### Use `asyncio.Lock` to prevent concurrent handler execution {#control-handler-concurrency} Concurrent processes can interact in unpredictable ways.