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
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints).
48
-
Therefore, each language is limited to the use of certain idiomatic techniques.
49
-
However, each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with external (to the Workflow) application code.
47
+
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints). Each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with application code outside the Workflow.
50
48
51
-
This means there are several things Workflows cannot do such as:
49
+
This means there are several things Workflows shouldn't do such as:
52
50
53
51
- Perform IO (network, disk, stdio, etc)
54
52
- Access/alter external mutable state
@@ -65,34 +63,28 @@ This is especially true with `Task`s.
65
63
Temporal requires that the deterministic `TaskScheduler.Current` is used, but many .NET async calls will use `TaskScheduler.Default` implicitly (and some analyzers even encourage this).
66
64
Here are some known gotchas to avoid with .NET tasks inside of Workflows:
67
65
68
-
- Do not use `Task.Run` - this uses the default scheduler and puts work on the thread pool.
69
-
- Use `Workflow.RunTaskAsync` instead.
70
-
- Can also use `Task.Factory.StartNew` with current scheduler or instantiate the `Task` and run `Task.Start` on it.
71
-
- Do not use `Task.ConfigureAwait(false)` - this will not use the current context.
72
-
- If you must use `Task.ConfigureAwait`, use `Task.ConfigureAwait(true)`.
73
-
- There is no significant performance benefit to `Task.ConfigureAwait` in workflows anyways due to how the scheduler works.
74
-
- Do not use anything that defaults to the default task scheduler.
75
-
- Do not use `Task.Delay`, `Task.Wait`, timeout-based `CancellationTokenSource`, or anything that uses .NET built-in timers.
76
-
-`Workflow.DelayAsync`, `Workflow.WaitConditionAsync`, or non-timeout-based cancellation token source is suggested.
77
-
- Do not use `Task.WhenAny`.
78
-
- Use `Workflow.WhenAnyAsync` instead.
66
+
- Use `Workflow.RunTaskAsync` instead of `Task.Run`. `Task.Run` uses the default scheduler and puts work on the thread pool.
67
+
- You can also use `Task.Factory.StartNew` with current scheduler or instantiate the `Task` and run `Task.Start` on it.
68
+
- If you need to use `Task.ConfigureAwait`, use `Task.ConfigureAwait(true)`. `Task.ConfigureAwait(false)` won't use the current context.
69
+
- There is no significant performance benefit to `Task.ConfigureAwait` in workflows because of how the scheduler works.
70
+
- Avoid anything that defaults to the default task scheduler.
71
+
- Use `Workflow.DelayAsync`, `Workflow.WaitConditionAsync`, or non-timeout-based cancellation token sources instead of `Task.Delay`, `Task.Wait`, timeout-based `CancellationTokenSource`, or anything that uses .NET built-in timers.
72
+
- Use `Workflow.WhenAnyAsync` instead of `Task.WhenAny`.
79
73
- Technically this only applies to an enumerable set of tasks with results or more than 2 tasks with results. Other
80
74
uses are safe. See [this issue](https://github.com/dotnet/runtime/issues/87481).
81
-
- Do not use `Task.WhenAll`
82
-
- Use `Workflow.WhenAllAsync` instead.
75
+
- Use `Workflow.WhenAllAsync` instead of `Task.WhenAll`.
83
76
- Technically `Task.WhenAll` is currently deterministic in .NET and safe, but it is better to use the wrapper to be
84
77
sure.
85
-
- Do not use `CancellationTokenSource.CancelAsync`.
86
-
- Use `CancellationTokenSource.Cancel` instead.
87
-
- Do not use `System.Threading.Semaphore` or `System.Threading.SemaphoreSlim` or `System.Threading.Mutex`.
88
-
- Use `Temporalio.Workflows.Semaphore` or `Temporalio.Workflows.Mutex` instead.
78
+
- Use `CancellationTokenSource.Cancel` instead of `CancellationTokenSource.CancelAsync`.
79
+
- Use `Temporalio.Workflows.Semaphore` or `Temporalio.Workflows.Mutex` instead of `System.Threading.Semaphore`, `System.Threading.SemaphoreSlim`, or `System.Threading.Mutex`.
89
80
-_Technically_`SemaphoreSlim` does work if only the async form of `WaitAsync` is used without no timeouts and
90
81
`Release` is used. But anything else can deadlock the workflow and its use is cumbersome since it must be disposed.
91
82
- Be wary of additional libraries' implicit use of the default scheduler.
92
83
- For example, while there are articles for `Dataflow` about [using a specific scheduler](https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-specify-a-task-scheduler-in-a-dataflow-block), there are hidden implicit uses of `TaskScheduler.Default`. For example, see [this bug](https://github.com/dotnet/runtime/issues/83159).
93
84
94
85
In order to help catch wrong scheduler use, by default the Temporal .NET SDK adds an event source listener for info-level task events.
95
86
While this technically receives events from all uses of tasks in the process, we make sure to ignore anything that is not running in a Workflow in a high performant way (basically one thread local check).
87
+
96
88
For code that does run in a Workflow and accidentally starts a task in another scheduler, an `InvalidWorkflowOperationException` will be thrown which "pauses" the Workflow (fails the Workflow Task which continually retries until the code is fixed).
97
89
This is unfortunately a runtime-only check, but can help catch mistakes early. If this needs to be turned off for any reason, set `DisableWorkflowTracingEventListener` to `true` in Worker options.
Copy file name to clipboardExpand all lines: docs/develop/dotnet/workflows/versioning.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,8 +31,8 @@ import { CaptionedImage } from '@site/src/components';
31
31
32
32
Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress.
33
33
34
-
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints).
35
-
If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows.
34
+
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. This only applies to Workflow orchestration logic. Non-deterministic work such as API calls, and database queries should be placed in Activities, which Temporal retries reliably.
35
+
36
36
With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version.
37
37
There are two primary Versioning methods that you can use:
Copy file name to clipboardExpand all lines: docs/develop/go/workflows/basics.mdx
+1-3Lines changed: 1 addition & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -183,9 +183,7 @@ func main() {
183
183
184
184
### How to develop Workflow logic {#workflow-logic-requirements}
185
185
186
-
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints).
187
-
Therefore, each language is limited to the use of certain idiomatic techniques.
188
-
However, each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with external (to the Workflow) application code.
186
+
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints). Each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with application code outside the Workflow.
189
187
190
188
In Go, Workflow Definition code cannot directly do the following:
Copy file name to clipboardExpand all lines: docs/develop/go/workflows/versioning.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,8 +20,8 @@ tags:
20
20
21
21
Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress.
22
22
23
-
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints).
24
-
If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows.
23
+
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. This only applies to Workflow orchestration logic. Non-deterministic work such as API calls, and database queries should be placed in Activities, which Temporal retries reliably.
24
+
25
25
With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version.
26
26
There are two primary Versioning methods that you can use:
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints).
215
-
Therefore, each language is limited to the use of certain idiomatic techniques.
216
-
However, each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with external (to the Workflow) application code.
214
+
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints). Each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with external (to the Workflow) application code.
217
215
218
216
When defining Workflows using the Temporal Java SDK, the Workflow code must be written to execute effectively once and to completion.
219
217
220
218
The following constraints apply when writing Workflow Definitions:
221
219
222
-
- Do not use mutable global variables in your Workflow implementations.
223
-
This will ensure that multiple Workflow instances are fully isolated.
224
-
- Your Workflow code must be deterministic.
225
-
Do not call non-deterministic functions (such as non-seeded random or `UUID.randomUUID()`) directly from the Workflow code.
226
-
The Temporal SDK provides specific API for calling non-deterministic code in your Workflows.
227
-
- Do not use programming language constructs that rely on system time.
228
-
For example, only use `Workflow.currentTimeMillis()` to get the current time inside a Workflow.
229
-
- Do not use native Java `Thread` or any other multi-threaded classes like `ThreadPoolExecutor`.
230
-
Use `Async.function` or `Async.procedure`, provided by the Temporal SDK, to execute code asynchronously.
231
-
- Do not use synchronization, locks, or other standard Java blocking concurrency-related classes besides those provided by the Workflow class.
232
-
There is no need for explicit synchronization because multi-threaded code inside a Workflow is executed one thread at a time and under a global lock.
220
+
- Do not use mutable global variables in your Workflow implementations. This will ensure that multiple Workflow instances are fully isolated.
221
+
- Workflow code must be deterministic. If you need to call non-deterministic functions (such as non-seeded random or `UUID.randomUUID()`) directly from the Workflow code, the Temporal SDK provides specific API for calling non-deterministic code in your Workflows.
222
+
- For operations like calling external APIs, invoking LLMs, querying databases, or performing I/O, use Activities. Activities run outside Workflow replay and are retried reliably.
223
+
- Use Temporal-provided functions instead of that rely on system time. For example, use only `Workflow.currentTimeMillis()` to get the current time inside a Workflow.
224
+
- Use `Async.function` or `Async.procedure`, provided by the Temporal SDK, to execute code asynchronously instead of native Java `Thread` or any other multi-threaded classes like `ThreadPoolExecutor`.
225
+
- Use only the concurrency features provided by the Workflow class. Multi-threaded code inside a Workflow is executed one thread at a time and under a global lock, so there is no need for explicit synchronization.
233
226
- Call `Workflow.sleep` instead of `Thread.sleep`.
234
227
- Use `Promise` and `CompletablePromise` instead of `Future` and `CompletableFuture`.
235
228
- Use `WorkflowQueue` instead of `BlockingQueue`.
236
-
- Use `Workflow.getVersion` when making any changes to the Workflow code.
237
-
Without this, any deployment of updated Workflow code might break already running Workflows.
238
-
- Do not access configuration APIs directly from a Workflow because changes in the configuration might affect a Workflow Execution path.
239
-
Pass it as an argument to a Workflow function or use an Activity to load it.
240
-
- Use `DynamicWorkflow` when you need a default Workflow that can handle all Workflow Types that are not registered with a Worker.
241
-
A single implementation can implement a Workflow Type which by definition is dynamically loaded from some external source.
242
-
All standard `WorkflowOptions` and determinism rules apply to Dynamic Workflow implementations.
229
+
- Use `Workflow.getVersion` when making any changes to the Workflow code to avoid deployment of updated Workflow code interfering with already-running Workflows.
230
+
- Do not access configuration APIs directly from a Workflow because changes in the configuration might affect a Workflow Execution path. Instead, pass it as an argument to a Workflow function or use an Activity to load it.
231
+
- Use `DynamicWorkflow` when you need a default Workflow that can handle all Workflow Types that are not registered with a Worker. A single implementation can implement a Workflow Type which by definition is dynamically loaded from some external source. All standard `WorkflowOptions` and determinism rules apply to Dynamic Workflow implementations.
Copy file name to clipboardExpand all lines: docs/develop/java/workflows/versioning.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,8 +21,8 @@ tags:
21
21
22
22
Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress.
23
23
24
-
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints).
25
-
If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows.
24
+
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. This only applies to Workflow orchestration logic. Non-deterministic work such as API calls, and database queries should be placed in Activities, which Temporal retries reliably.
25
+
26
26
With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version.
27
27
There are two primary Versioning methods that you can use:
### How to develop Workflow logic {#workflow-logic-requirements}
98
98
99
-
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints).
100
-
Therefore, each language is limited to the use of certain idiomatic techniques.
101
-
However, each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with external (to the Workflow) application code.
99
+
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints). Each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with application code outside the Workflow. used inside your Workflow to interact with external (to the Workflow) application code.
102
100
103
101
\*\*Temporal uses the [Microsoft Azure Event Sourcing pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing) to recover the state of a Workflow object including its local variable values.
Copy file name to clipboardExpand all lines: docs/develop/php/workflows/versioning.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,8 +29,8 @@ tags:
29
29
30
30
Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress.
31
31
32
-
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints).
33
-
If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows.
32
+
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. This only applies to Workflow orchestration logic. Non-deterministic work such as API calls, and database queries should be placed in Activities, which Temporal retries reliably.
33
+
34
34
With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version.
35
35
There are two primary Versioning methods that you can use:
Copy file name to clipboardExpand all lines: docs/develop/python/workflows/basics.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -163,7 +163,7 @@ class YourWorkflow:
163
163
**How to develop Workflow logic using the Temporal Python SDK.**
164
164
165
165
Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints).
166
-
Therefore, each language is limited to the use of certain idiomatic techniques. However, each Temporal SDK provides a
166
+
Each Temporal SDK provides a
167
167
set of APIs that can be used inside your Workflow to interact with external (to the Workflow) application code.
168
168
169
169
Workflow code must be deterministic because the Temporal Server may [replay](/develop/python/best-practices/testing-suite#replay) your Workflow to reconstruct its state. This means:
Copy file name to clipboardExpand all lines: docs/develop/python/workflows/versioning.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,8 +32,8 @@ import { CaptionedImage } from '@site/src/components';
32
32
33
33
Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress.
34
34
35
-
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints).
36
-
If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows.
35
+
The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. This only applies to Workflow orchestration logic. Non-deterministic work such as API calls, and database queries should be placed in Activities, which Temporal retries reliably.
36
+
37
37
With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version.
38
38
There are two primary Versioning methods that you can use:
0 commit comments