You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/develop/python/python-sdk-sync-vs-async.mdx
+32-32Lines changed: 32 additions & 32 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -56,7 +56,7 @@ into a synchronous program that executes serially, defeating the entire purpose
56
56
of using `asyncio`. This can also lead to potential deadlock, and unpredictable behavior
57
57
that causes tasks to be unable to execute. Debugging these issues can be difficult
58
58
and time consuming, as locating the source of the blocking call might not always
59
-
be immediately obvious.
59
+
be immediately evident.
60
60
61
61
Due to this, Python developers must be extra careful to not make blocking calls
62
62
from within an asynchronous Activity, or use an async safe library to perform
@@ -71,33 +71,33 @@ such as `aiohttp` or `httpx`. Otherwise, use a synchronous Activity.
71
71
72
72
Python workers have following components for executing code:
73
73
74
-
- Your event loop, which runs tasks from async activities**plus the rest of the Temporal Worker, such as communicating with the server**.
75
-
- An executor for executing activity tasks from synchronous activities. A thread pool executor is recommended.
76
-
- A thread pool executor for executing workflow tasks.
74
+
- Your event loop, which runs Tasks from async Activities**plus the rest of the Temporal Worker, such as communicating with the server**.
75
+
- An executor for executing Activity Tasks from synchronous Activities. A thread pool executor is recommended.
76
+
- A thread pool executor for executing Workflow Tasks.
77
77
78
78
> See Also: [docs for](https://python.temporal.io/temporalio.worker.Worker.html#__init__)`worker.__init__()`
79
79
80
80
### Activities
81
81
82
-
- The activities and the temporal worker SDK code both run the default asyncio event loop or whatever event loop you give the Worker.
82
+
- The Activities and the temporal worker SDK code both run the default asyncio event loop or whatever event loop you give the Worker.
83
83
- Synchronous Activities run in the `activity_executor`.
84
84
85
85
### Workflows
86
86
87
-
Since workflow tasks (1) are CPU bound, (2) need to be timed out for deadlock detection, and (3) need to not block other workflow tasks, they are run in threads. The `workflow_task_executor` is the thread pool these tasks are run on.
87
+
Since Workflow Tasks (1) are CPU bound, (2) need to be timed out for deadlock detection, and (3) need to not block other Workflow Tasks, they are run in threads. The `workflow_task_executor` is the thread pool these Tasks are run on.
88
88
89
89
The fact that Workflow Tasks run in a thread pool can be confusing at first because Workflow Definitions are `async`.
90
-
The key differentiator is that the `async` in Workflow Definitions is not referring to the standard event loop -- it is referring to the workflow's own event loop.
91
-
Each workflow gets its own “workflow event loop”, which is deterministic, and described in [the Python SDK blog](https://temporal.io/blog/durable-distributed-asyncio-event-loop#temporal-workflows-are-asyncio-event-loops).
92
-
The workflow event loop doesn't constantly loop -- it just gets cycled through during a workflow task to make as much progress as possible on all of its futures.
90
+
The key differentiator is that the `async` in Workflow Definitions isn't referring to the standard event loop -- it's referring to the Workflow's own event loop.
91
+
Each Workflow gets its own “Workflow event loop,” which is deterministic, and described in [the Python SDK blog](https://temporal.io/blog/durable-distributed-asyncio-event-loop#temporal-workflows-are-asyncio-event-loops).
92
+
The Workflow event loop doesn't constantly loop -- it just gets cycled through during a Workflow Task to make as much progress as possible on all of its futures.
93
93
When it can no longer make progress on any of its futures, then the Workflow Task is complete.
94
94
95
95
### Number of CPU cores
96
96
97
97
The only ways to use more than one core in a python worker (considering Python's GIL) are:
98
98
99
99
- Run more than one worker process.
100
-
- Run the sync activities in a process pool executor, but a thread pool executor is recommended.
100
+
- Run the synchronous Activities in a process pool executor, but a thread pool executor is recommended.
101
101
102
102
### Separating Activity and Workflow Workers
103
103
@@ -106,30 +106,30 @@ some users choose to deploy separate Workers for Workflow Tasks and Activity Tas
106
106
107
107
## Activity Definition
108
108
109
-
**By default, activities should be synchronous rather than asynchronous**.
110
-
You should only make an activity asynchronous if you are _very_
109
+
**By default, Activities should be synchronous rather than asynchronous**.
110
+
You should only make an Activity asynchronous if you are _very_
111
111
sure that it does not block the event loop.
112
112
113
113
This is because if you have blocking code in an `async def` function,
114
114
it blocks your event loop and the rest of Temporal, which can cause bugs that are
115
-
very hard to diagnose, including freezing your worker and blocking workflow progress
116
-
(because Temporal can't tell the server that workflow tasks are completing).
117
-
The reason synchronous activities help is because they
115
+
hard to diagnose, including freezing your worker and blocking Workflow progress
116
+
(because Temporal can't tell the server that Workflow Tasks are completing).
117
+
The reason synchronous Activities help is because they
118
118
run in the `activity_executor` ([docs for](https://python.temporal.io/temporalio.worker.Worker.html#__init__)`worker.__init__()`)
119
119
rather than in the global event loop,
120
120
which helps because:
121
121
122
122
- There's no risk of accidentally blocking the global event loop.
123
123
- If you have multiple
124
-
activity tasks running in a thread pool rather than an event loop, one bad
125
-
activity task can't slow down the others; this is because the OS scheduler preemptively
124
+
Activity Tasks running in a thread pool rather than an event loop, one bad
125
+
Activity Task can't slow down the others; this is because the OS scheduler preemptively
126
126
switches between threads, which the event loop coordinator does not do.
127
127
128
128
> See Also:
129
129
> ["Types of Activities" section of Python SDK README](https://github.com/temporalio/sdk-python#types-of-activities)
130
130
> and [Sync vs Async activity implementations](https://docs.temporal.io/develop/python/python-sdk-sync-vs-async)
131
131
132
-
## Implementing Synchronous Activities
132
+
## How to implement Synchronous Activities
133
133
134
134
The following code is a synchronous Activity Definition.
135
135
It takes a name (`str`) as input and returns a
@@ -160,11 +160,11 @@ class TranslateActivities:
160
160
return response.text
161
161
```
162
162
163
-
In the above example we chose not to share a session across the Activity, so
163
+
The preceeding example doesn't share a session across the Activity, so
164
164
`__init__` was removed. While `requests` does have the ability to create sessions,
165
-
it is currently unknown if they are thread safe. Due to no longer having or needing
165
+
it's currently unknown if they are thread safe. Due to no longer having or needing
166
166
`__init__`, the case could be made here to not implement the Activities as a class,
0 commit comments