Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document workflow.init for Python #3108

Merged
merged 7 commits into from
Oct 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions docs/develop/python/message-passing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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`.
Expand All @@ -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.

Expand Down Expand Up @@ -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
dandavison marked this conversation as resolved.
Show resolved Hide resolved

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).
fairlydurable marked this conversation as resolved.
Show resolved Hide resolved
(The Workflow input arguments are also passed to your `@workflow.run` method -- that always happens, whether or not you use the `@workflow.init` decorator.)
fairlydurable marked this conversation as resolved.
Show resolved Hide resolved
fairlydurable marked this conversation as resolved.
Show resolved Hide resolved
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
```

fairlydurable marked this conversation as resolved.
Show resolved Hide resolved
fairlydurable marked this conversation as resolved.
Show resolved Hide resolved


### Use `asyncio.Lock` to prevent concurrent handler execution {#control-handler-concurrency}

Concurrent processes can interact in unpredictable ways.
Expand Down