Skip to content

Commit 423e182

Browse files
committed
async handlers example
1 parent 1b39f58 commit 423e182

File tree

1 file changed

+42
-8
lines changed

1 file changed

+42
-8
lines changed

Diff for: message_passing/introduction/workflow_with_async_handlers.py

+42-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import asyncio
12
from dataclasses import dataclass
3+
from datetime import timedelta
24
from enum import IntEnum
35
from typing import Optional
46

5-
from temporalio import workflow
7+
from docutils import ApplicationError
8+
from temporalio import activity, workflow
69

710

811
class Language(IntEnum):
@@ -11,6 +14,23 @@ class Language(IntEnum):
1114
FRENCH = 3
1215
SPANISH = 4
1316
PORTUGUESE = 5
17+
ARABIC = 6
18+
HINDI = 7
19+
20+
21+
@activity.defn
22+
async def call_greeting_service(to_language: Language) -> Optional[str]:
23+
greetings = {
24+
Language.CHINESE: "你好,世界",
25+
Language.ENGLISH: "Hello, world",
26+
Language.FRENCH: "Bonjour, monde",
27+
Language.SPANISH: "¡Hola mundo",
28+
Language.PORTUGUESE: "Olá mundo",
29+
Language.ARABIC: "مرحبا بالعالم",
30+
Language.HINDI: "नमस्ते दुनिया",
31+
}
32+
await asyncio.sleep(0.2) # Pretend to do a network call
33+
return greetings.get(to_language)
1434

1535

1636
@dataclass
@@ -33,10 +53,12 @@ def __init__(self) -> None:
3353
Language.ENGLISH: "Hello, world",
3454
Language.CHINESE: "你好,世界",
3555
}
56+
self.lock = asyncio.Lock()
3657

3758
@workflow.run
3859
async def run(self) -> str:
3960
await workflow.wait_condition(lambda: self.approved_for_release)
61+
await workflow.wait_condition(workflow.all_handlers_finished)
4062
return self.greetings[self.language]
4163

4264
@workflow.query
@@ -54,17 +76,29 @@ def approve(self, input: ApproveInput) -> None:
5476
self.approver_name = input.name
5577

5678
@workflow.update
57-
def set_language(self, language: Language) -> Language:
79+
async def set_language(self, language: Language) -> Language:
5880
# 👉 An Update handler can mutate the Workflow state and return a value.
81+
# 👉 Since this update handler is async, it can execute an activity.
82+
if language not in self.greetings:
83+
# 👉 Use a lock here to ensure that multiple calls to set_language are processed in order.
84+
async with self.lock:
85+
greeting = await workflow.execute_activity(
86+
call_greeting_service,
87+
language,
88+
start_to_close_timeout=timedelta(seconds=10),
89+
)
90+
if greeting is None:
91+
# 👉 An update validator cannot be async, so cannot be used to check that the remote
92+
# call_greeting_service supports the requested language. Raising ApplicationError
93+
# will fail the Update, but the WorkflowExecutionUpdateAccepted event will still be
94+
# added to history.
95+
raise ApplicationError(
96+
f"Greeting service does not support {language.name}"
97+
)
98+
self.greetings[language] = greeting
5999
previous_language, self.language = self.language, language
60100
return previous_language
61101

62-
@set_language.validator
63-
def validate_language(self, language: Language) -> None:
64-
if language not in self.greetings:
65-
# 👉 In an Update validator you raise any exception to reject the Update.
66-
raise ValueError(f"{language.name} is not supported")
67-
68102
@workflow.query
69103
def get_language(self) -> Language:
70104
return self.language

0 commit comments

Comments
 (0)