Skip to content

Commit 33a022a

Browse files
committed
Grammar update on Workflows doc
Signed-off-by: Greg Haskins <[email protected]>
1 parent 429764b commit 33a022a

File tree

1 file changed

+28
-28
lines changed

1 file changed

+28
-28
lines changed

doc/workflows.md

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
## What is a Workflow?
44

5-
Workflows are resilient programs, meaning that they will continue execution even in the presence of different failure conditions.
5+
Workflows are resilient programs that will continue execution even under different failure conditions.
66

7-
Workflows encapsulate execution/orchestration of Tasks which include Activities and child Workflows. They also need to react to external events, deal with Timeouts, etc.
7+
Workflows encapsulate the execution/orchestration of Tasks, including Activities and child Workflows. They must also react to external events, deal with Timeouts, etc.
88

99
In this Clojure SDK programming model, a Temporal Workflow is a function declared with ([defworkflow](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.workflow#defworkflow))
1010

@@ -16,7 +16,7 @@ In this Clojure SDK programming model, a Temporal Workflow is a function declare
1616

1717
## Implementing Workflows
1818

19-
A Workflow implementation consists of defining a (defworkflow) function. This function is invoked by the platform each time a new Workflow execution is started or retried. As soon as this method returns, the Workflow execution is considered as completed and the result is available to the caller via ([get-result](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#get-result)).
19+
A Workflow implementation consists of defining a (defworkflow) function. The platform invokes this function each time a new Workflow execution is started or retried. Returning from the method signals that the Workflow execution is considered complete. The result is available to the caller via ([get-result](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#get-result)).
2020

2121
### Example
2222

@@ -30,36 +30,36 @@ A Workflow implementation consists of defining a (defworkflow) function. This fu
3030

3131
### Workflow Implementation Constraints
3232

33-
Temporal uses the [Event Sourcing pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing) to recover the state of a Workflow object including its threads and local variable values. In essence, every time a Workflow state has to be restored, its code is re-executed from the beginning. Note that during replay, successfully executed Activities are not re-executed as their results are already recorded in the Workflow event history.
33+
Temporal uses the [Event Sourcing pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing) to recover the state of a Workflow object, including its threads and local variable values. In essence, the Workflow code is re-executed from the beginning whenever a Workflow state requires restoration. During replay, successfully executed Activities are not re-executed but return the result previously recorded in the Workflow event history.
3434

35-
Even though Temporal has the replay capability, which brings resilience to your Workflows, you should never think about this capability when writing your Workflows. Instead, you should focus on implementing your business logic/requirements and write your Workflows as they would execute only once.
35+
Even though Temporal has the replay capability, which brings resilience to your Workflows, you should never think about this capability when writing your Workflows. Instead, you should focus on implementing your business logic/requirements and write your Workflows as they would execute only once.
3636

37-
There are some things however to think about when writing your Workflows, namely determinism and isolation. We summarize these constraints here:
37+
There are some things, however, to think about when writing your Workflows, namely determinism and isolation. We summarize these constraints here:
3838

39-
- Do not use any mutable global variables such as atoms in your Workflow implementations. This will assure that multiple Workflow instances are fully isolated.
39+
- Do not use any mutable global variables such as atoms in your Workflow implementations. This will ensure that multiple Workflow instances are fully isolated.
4040
- Do not call any non-deterministic functions like non-seeded random or uuid-generators directly from the Workflow code. (Coming soon: SideEffect API)
41-
- Perform all IO operations and calls to third-party services on Activities and not Workflows, as they are usually non-deterministic in nature.
42-
- Do not use any programming language constructs that rely on system time. (Coming soon: API methods for time)
43-
- Do not use threading primitives such as clojure.core.async/go or clojure.core.async/thread. (Coming soon: API methods for async function execution)
41+
- Perform all IO operations and calls to third-party services on Activities and not Workflows, as they are usually non-deterministic.
42+
- Do not use any programming language constructs that rely on system time. (Coming soon: API methods for time)
43+
- Do not use threading primitives such as clojure.core.async/go or clojure.core.async/thread. (Coming soon: API methods for async function execution)
4444
- Do not perform any operations that may block the underlying thread, such as clojure.core.async/<!!.
45-
- There is no general need in explicit synchronization because multi-threaded code inside a Workflow is executed one thread at a time and under a global lock.
46-
- This Clojure SDK provides integration with [promesa](https://github.com/funcool/promesa) with a few limitations (See [Promises](#promises)), for asynchronous integration with safe blocking operations, such as waiting on an Activity.
47-
- (Coming soon) Use versioning-support when making any changes to the Workflow code. Without this, any deployment of updated Workflow code might break already running Workflows.
48-
- Don’t access configuration APIs directly from a Workflow because changes in the configuration might affect a Workflow execution path. Pass it as an argument to a Workflow function or use an Activity to load it.
45+
- There is no general need for explicit synchronization because multi-threaded code inside a Workflow is executed one thread at a time and under a global lock.
46+
- This Clojure SDK provides integration with [promesa](https://github.com/funcool/promesa) with a few limitations (See [Promises](#promises)) for asynchronous integration with safe blocking operations, such as waiting on an Activity.
47+
- (Coming soon) Use versioning-support when making changes to the Workflow code. Without this, any deployment of updated Workflow code might break already running Workflows.
48+
- Don’t access configuration APIs directly from a Workflow because changes in the configuration might affect a Workflow execution path. Pass it as an argument to a Workflow function or use an Activity to load it.
4949

5050
## Registering Workflows
5151

52-
By default, Workflows are automatically registered simply by declaring a (defworkflow). You may optionally manually declare specific Workflows to register when creating Workers (see [worker-options](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.worker#worker-options)).
52+
By default, Workflows are automatically registered simply by declaring a (defworkflow). You may optionally manually specify Workflows to register when creating Workers (see [worker-options](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.worker#worker-options)).
5353

54-
*It should be noted that the name of the workflow, the arguments and signals that the workflow accepts, and the data that the workflow returns are all part of a contract that you need to maintain across potentially long-lived instances. Therefore, the Workflow definition must be treated with care whenever code is refactored.*
54+
*It should be noted that the name of the Workflow, the arguments and signals that the Workflow accepts, and the data that the workflow returns are all part of a contract that you need to maintain across potentially long-lived instances. Therefore, refactoring code involving Workflow logic should be treated with care to avoid inadvertently breaking your contract.*
5555

5656
## Starting Workflow Executions
5757

58-
In this Clojure SDK, Workflows are always started with the following flow:
58+
In this Clojure SDK, developers manage Workflows with the following flow:
5959

6060
1. Invoke [create-workflow](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#create-workflow)
61-
2. Invoke [start](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#start) or [signal-with-start](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#signal-with-start). The `params` passed to these functions will be forwarded to the workflow and available as `args` in the request map of the Workflow.
62-
3. Gather the asynchronous results with [get-result](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#get-result) which returns a promise and needs to be dereferenced.
61+
2. Invoke [start](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#start) or [signal-with-start](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#signal-with-start). The `params` passed to these functions will be forwarded to the Workflow and available as `args` in the request map of the Workflow.
62+
3. Gather the asynchronous results with [get-result](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.client.core#get-result), which returns a promise and requires dereferencing before the result value is realized.
6363

6464
### Example
6565

@@ -75,13 +75,13 @@ In this Clojure SDK, Workflows are always started with the following flow:
7575

7676
## Safe blocking within Workflows
7777

78-
The Temporal Workflow instance behaves like a [Lightweight Process](https://en.wikipedia.org/wiki/Light-weight_process) or [Fiber](https://en.wikipedia.org/wiki/Fiber_(computer_science)). This means the system can generally support a high ratio of Workflow instances to CPUs often in the range of 1000:1 or greater. Achieving this feat requires controlling the IO in and out of the instance in a way that maximizes resource sharing. Therefore, any LWP/Fiber implementation will generally provide its own IO constructions (e.g. mailboxes, channels, promises, etc.), and Temporal is no exception.
78+
A Temporal Workflow instance behaves like a [Lightweight Process](https://en.wikipedia.org/wiki/Light-weight_process) or [Fiber](https://en.wikipedia.org/wiki/Fiber_(computer_science)). These types of designs support a high ratio of Workflow instances to CPUs, often in the range of 1000:1 or greater. Achieving this feat requires controlling the IO in and out of the instance to maximize resource sharing. Therefore, any LWP/Fiber implementation will generally provide its own IO constructs (e.g., mailboxes, channels, promises, etc.), and Temporal is no exception.
7979

8080
In this Clojure SDK, this support comes in a few different flavors:
8181

8282
### Promises
8383

84-
Certain methods naturally return Workflow-safe Promises, such as invoking an Activity from a Workflow. These Workflow-safe Promises have been integrated with the [promesa](https://github.com/funcool/promesa) library. This section serves to document their use and limitations.
84+
Specific methods naturally return Workflow-safe Promises, such as invoking an Activity from a Workflow. The Clojure SDK integrates these Workflow-safe Promises with the [promesa](https://github.com/funcool/promesa) library. This section serves to document their use and limitations.
8585

8686
#### Safe to use
8787

@@ -111,7 +111,7 @@ Placing (p/resolved) (or anything else that ultimately creates a promesa promise
111111

112112
##### Good example
113113

114-
The proper method is to ensure that a Temporal native operation starts the chain
114+
The proper method is to ensure that a Temporal native operation starts the chain.
115115

116116
```clojure
117117
...
@@ -123,15 +123,15 @@ The proper method is to ensure that a Temporal native operation starts the chain
123123

124124
##### Watch out for implicit conversion
125125

126-
The following situation can lead to a failure
126+
The following situation can lead to a failure:
127127

128128
```clojure
129129
(-> (when some-condition
130130
(a/invoke some-activity {:some "args"}))
131131
(p/then (fn [x] ...)))
132132
```
133133

134-
for situations where some-condition is `false` because promesa will cast the scalar `nil` to (p/resolved nil), thus violating the origination rule. Instead, do this:
134+
For situations where `some-condition` is `false` because promesa will cast the scalar `nil` to (p/resolved nil), thus violating the origination rule. Instead, do this:
135135

136136
```clojure
137137
...
@@ -143,19 +143,19 @@ for situations where some-condition is `false` because promesa will cast the sca
143143
(p/then (fn [x] ...)))
144144
```
145145

146-
Thus ensuring that the origination rules are met regardless of the outcome of the conditional.
146+
Doing so ensures that the origination rules are met regardless of the outcome of the conditional.
147147

148148
### Await
149149

150-
You may use [await](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.core#await) to efficiently park the Workflow until a provided predicate evaluates to true. The predicate is evaluated at each major state transition of the Workflow.
150+
You may use [await](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.core#await) to efficiently park the Workflow until a provided predicate evaluates to true. The Temporal platform will re-evaluate the predicate at each major state transition of the Workflow.
151151

152152
### Temporal Signals
153153

154154
Your Workflow may send or receive [signals](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.signals).
155155

156156
#### Receiving Signals
157157

158-
Your Workflow may either block waiting with signals with [<!](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.signals#%3C!) or use the non-blocking [poll](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.signals#poll). In either case, your Workflow needs to obtain the `signals` context provided in the Worklow request map.
158+
Your Workflow may either block waiting with signals with [<!](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.signals#%3C!) or use the non-blocking [poll](https://cljdoc.org/d/io.github.manetu/temporal-sdk/CURRENT/api/temporal.signals#poll). Either way, your Workflow needs to obtain the `signals` context provided in the Workflow request map.
159159

160160
##### Example
161161

@@ -164,4 +164,4 @@ Your Workflow may either block waiting with signals with [<!](https://cljdoc.org
164164
[ctx {:keys [signals]}]
165165
(let [message (<! signals "MySignal")]
166166
...))
167-
```
167+
```

0 commit comments

Comments
 (0)