Skip to content

Commit 1e124f3

Browse files
committed
Document workflow.init for Python
1 parent 2dd9874 commit 1e124f3

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

docs/develop/python/message-passing.mdx

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ class GreetingWorkflow:
436436
return self.greetings[self.language]
437437
```
438438

439-
### Use wait conditions in handlers
439+
### Use wait conditions in handlers {#wait-in-message-handler}
440440

441441
It's common to use a Workflow wait condition to wait until a handler should start.
442442
You can also use wait conditions anywhere else in the handler to wait for a specific condition to become `True`.
@@ -453,8 +453,6 @@ The `workflow.wait_condition` method waits until your condition is met:
453453
)
454454
```
455455

456-
Remember: handlers can execute before the main Workflow method starts.
457-
458456
You can also use wait conditions anywhere else in the handler to wait for a specific condition to become true.
459457
This allows you to write handlers that pause at multiple points, each time waiting for a required condition to become true.
460458

@@ -486,6 +484,50 @@ You can silence these warnings on a per-handler basis by passing the `unfinished
486484

487485
See [Finishing handlers before the Workflow completes](/encyclopedia/workflow-message-passing#finishing-message-handlers) for more information.
488486

487+
488+
### Use `@workflow.init` to operate on Workflow input before any handler executes
489+
490+
Normally, your Workflow `__init__` method won't have any parameters.
491+
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.
492+
The SDK will then ensure that your `__init__` method receives the Workflow input arguments that the [Client sent](/develop/python/coretemporal-clients#start-workflow-execution).
493+
(The Workflow input arguments are also passed to your `@workflow.run` method -- that always happens, whether or not you use the `@workflow.init` decorator.)
494+
495+
To understand why `@workflow.init` is useful, suppose that you've written a Signal or Update handler that does something involving the Workflow input, but that you need to process the workflow input in some way before the handler should be allowed to access it.
496+
The problem is that it's possible for a Signal or Update handler to start executing _before_ your `@workflow.run` method!
497+
A solution is to use the `@workflow.init` decorator, and do the processing in your `__init__` method. (An alternative solution would be to [use `@workflow.wait_condition` in your handler](#wait-in-message-handler) to wait until the processing has been done by your `@workflow.run` method.
498+
That would work, but using `@workflow.init` is simpler.)
499+
500+
Here's an example.
501+
Notice that `__init__` and `get_greeting` have the same parameters, with the same type annotations:
502+
503+
```python
504+
@dataclass
505+
class MyWorkflowInput:
506+
name: str
507+
508+
509+
@workflow.defn
510+
class WorkflowRunSeesWorkflowInitWorkflow:
511+
@workflow.init
512+
def __init__(self, workflow_input: MyWorkflowInput) -> None:
513+
self.name_with_title = f"Sir {workflow_input.name}"
514+
515+
@workflow.run
516+
async def get_greeting(self, workflow_input: MyWorkflowInput):
517+
return f"Hello, {workflow_input.name}"
518+
519+
@workflow.update
520+
async def check_title_validity(self) -> bool:
521+
# 👈 The handler sees the workflow input after it has been processed by __init__.
522+
return await workflow.execute_activity(
523+
check_title_validity,
524+
self.name_with_title,
525+
schedule_to_close_timeout=timedelta(seconds=10),
526+
)
527+
```
528+
529+
530+
489531
### Use `asyncio.Lock` to prevent concurrent handler execution {#control-handler-concurrency}
490532

491533
Concurrent processes can interact in unpredictable ways.

0 commit comments

Comments
 (0)