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
The `all()`and `parallel()` functions check the total number of leaf operations in a single fan-out group against `command_batch_size`. This is checked before any individual activities or children are scheduled, so the run fails cleanly rather than partially scheduling a batch.
119
+
The `all()`function checks the total number of leaf operations in a single fan-out group against `command_batch_size`. This is checked before any individual activities or children are scheduled, so the run fails cleanly rather than partially scheduling a batch.
120
120
121
121
### Payload size
122
122
@@ -156,7 +156,7 @@ This catches runaway loops that create unbounded events in a single task without
Copy file name to clipboardExpand all lines: docs/features/child-workflows.md
+14-14Lines changed: 14 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,28 +44,28 @@ final class ParentWorkflow extends Workflow
44
44
- Parent workflows can signal the current child through that handle with `signal()`, `signalWithArguments()`, or method-call sugar such as `$this->child()?->approvedBy('Taylor')`.
45
45
- Query replay keeps those handles read-only, while inline update application can still use the handle to emit a real child signal exactly once.
46
46
- Waterline exposes that relationship in detail views through lineage (`parents` / `continuedWorkflows`), child wait rows in `waits`, and typed child entries in `timeline`.
47
-
-`Workflow\V2\all()` can group child workflows by themselves or alongside `activity(...)` calls from the same parent step when you build the barrier with `startChild()` and `startActivity()`.
48
-
- Child-only `all([...startChild(...)])` barriers, nested `parallel([...])`child groups, and mixed `startChild(...)` plus `startActivity(...)` barriers return results in the original nested array shape once every member of the group completes successfully.
47
+
-`Workflow\V2\all()` can group child workflows by themselves or alongside `activity(...)` calls from the same parent step when you build the barrier with closures such as `fn () => child(...)` and `fn () => activity(...)`.
48
+
- Child-only `all([fn () => child(...)])` barriers, nested child groups, and mixed `fn () => child(...)` plus `fn () => activity(...)` barriers return results in the original nested array shape once every member of the group completes successfully.
49
49
- In any barrier that includes children, the parent wakes immediately on the first failed, cancelled, or terminated child, but successful child closures do not wake the parent until the last successful member in every enclosing group closes.
50
50
- If several barrier members have already closed unsuccessfully by the time the parent replays, the parent-visible failure is selected by earliest recorded close time and then by the lower barrier leaf index for exact timestamp ties.
51
51
- Once that selected child close has already been thrown into the parent step, later sibling closures stay sibling history only; they do not replace the chosen throwable or reopen the parent run.
52
52
53
53
## Parallel Child Barrier
54
54
55
-
Import the helpers with `use function Workflow\V2\all;` and `use function Workflow\V2\startChild;` when you want one parent step to wait on several child workflows together.
55
+
Import the helpers with `use function Workflow\V2\all;` and `use function Workflow\V2\child;` when you want one parent step to wait on several child workflows together.
56
56
57
57
```php
58
58
use function Workflow\V2\all;
59
-
use function Workflow\V2\startChild;
59
+
use function Workflow\V2\child;
60
60
use Workflow\V2\Workflow;
61
61
62
62
final class ParentWorkflow extends Workflow
63
63
{
64
64
public function handle(): array
65
65
{
66
66
$children = all([
67
-
startChild(FirstChildWorkflow::class),
68
-
startChild(SecondChildWorkflow::class),
67
+
fn () => child(FirstChildWorkflow::class),
68
+
fn () => child(SecondChildWorkflow::class),
69
69
]);
70
70
71
71
return $children;
@@ -113,7 +113,7 @@ final class ParentWorkflow extends Workflow
113
113
114
114
-`$this->child()` returns the latest visible child handle or `null`.
115
115
-`$this->children()` returns every visible handle in workflow-step order.
116
-
- During `all([...startChild(...)])` barriers, those handles appear in the same step order as the child calls inside the barrier, and `$this->child()` returns the last visible one.
116
+
- During `all([fn () => child(...)])` barriers, those handles appear in the same step order as the child calls inside the barrier, and `$this->child()` returns the last visible one.
117
117
- A handle's `runId()` follows the newest parent-recorded `ChildRunStarted` in that child invocation chain, so a parent waiting on a child that used `continueAsNew()` still sees the latest child run id without losing the original `callId()`.
118
118
119
119
## Handle Availability
@@ -153,7 +153,7 @@ When a parent workflow closes — whether by completing, failing, timing out, be
153
153
154
154
### Setting the policy
155
155
156
-
Pass a `ChildWorkflowOptions` as the first argument to `child()` or `startChild()`:
156
+
Pass a `ChildWorkflowOptions` as the first argument to `child()`:
157
157
158
158
```php
159
159
use function Workflow\V2\child;
@@ -174,11 +174,11 @@ final class ParentWorkflow extends Workflow
174
174
}
175
175
```
176
176
177
-
The same pattern works with `startChild()` for parallel barriers:
177
+
The same pattern works with closures inside `all()` for parallel barriers:
178
178
179
179
```php
180
180
use function Workflow\V2\all;
181
-
use function Workflow\V2\startChild;
181
+
use function Workflow\V2\child;
182
182
use Workflow\V2\Enums\ParentClosePolicy;
183
183
use Workflow\V2\Support\ChildWorkflowOptions;
184
184
@@ -187,8 +187,8 @@ $cancelOptions = new ChildWorkflowOptions(
@@ -220,6 +220,6 @@ Waterline shows the `parent_close_policy` in:
220
220
221
221
The current surface does not include:
222
222
223
-
- built-in bounded-concurrency helpers beyond the current `all([...startChild(...)])`, `all([...startActivity(...)])`, and mixed `all([...startChild(...), startActivity(...)])` barriers
223
+
- built-in bounded-concurrency helpers beyond the current `all([fn () => child(...)])`, `all([fn () => activity(...)])`, and mixed `all([fn () => child(...), fn () => activity(...)])` barriers
224
224
225
-
In other words, durable child handles are supported for already-reached child steps, but it does not yet include higher-level launch-handle or bounded-concurrency APIs beyond today's `child(...)`, `startChild()`, and `all([...])` surface.
225
+
In other words, durable child handles are supported for already-reached child steps, but it does not yet include higher-level launch-handle or bounded-concurrency APIs beyond today's `child(...)` and `all([...])` surface.
Copy file name to clipboardExpand all lines: docs/features/concurrency.md
+23-23Lines changed: 23 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,9 +6,9 @@ import ConcurrencySimulator from '@site/src/components/ConcurrencySimulator';
6
6
7
7
# Concurrency
8
8
9
-
In `Workflow\V2`, named workflows use straight-line helpers inside an ordinary `handle()` method: `activity()`, `awaitSignal()`, `timer()`, `sideEffect()`, `getVersion()`, and the other single-step helpers suspend directly under the hood instead of forcing `yield` into every workflow body. Named v2 workflows are straight-line only, so do not `yield` from the workflow body.
9
+
In `Workflow\V2`, named workflows use straight-line helpers inside an ordinary `handle()` method: `activity()`, `signal()`, `timer()`, `sideEffect()`, `getVersion()`, and the other single-step helpers suspend directly under the hood instead of forcing `yield` into every workflow body. Named v2 workflows are straight-line only, so do not `yield` from the workflow body.
10
10
11
-
Parallel barriers still suspend as one durable workflow step through `all([...])`. In straight-line workflows, build those barriers with explicit launch helpers such as `startActivity()`, `startChild()`, and `parallel([...])` so the runtime can see the full barrier tree before the workflow suspends. Results still come back in the original nested array shape, while Waterline keeps each durable leaf wait visible and uses `parallel_group_path` to show which outer and inner barriers that leaf belongs to.
11
+
Parallel barriers still suspend as one durable workflow step through `all([...])`. In straight-line workflows, build those barriers with closures such as `fn () => activity(...)` and `fn () => child(...)` so the runtime can see the full barrier tree before the workflow suspends. Results still come back in the original nested array shape, while Waterline keeps each durable leaf wait visible and uses `parallel_group_path` to show which outer and inner barriers that leaf belongs to.
12
12
13
13
## Series
14
14
@@ -46,17 +46,17 @@ class MyWorkflow extends Workflow
46
46
This example will execute 3 activities in parallel, waiting for the completion of all activities and collecting the results.
47
47
48
48
```php
49
-
use function Workflow\V2\{all, startActivity};
49
+
use function Workflow\V2\{all, activity};
50
50
use Workflow\V2\Workflow;
51
51
52
52
class MyWorkflow extends Workflow
53
53
{
54
54
public function handle()
55
55
{
56
56
return all([
57
-
startActivity(MyActivity1::class),
58
-
startActivity(MyActivity2::class),
59
-
startActivity(MyActivity3::class),
57
+
fn () => activity(MyActivity1::class),
58
+
fn () => activity(MyActivity2::class),
59
+
fn () => activity(MyActivity3::class),
60
60
]);
61
61
}
62
62
}
@@ -72,25 +72,25 @@ class MyWorkflow extends Workflow
72
72
title="Parallel Execution Simulator"
73
73
/>
74
74
75
-
The main difference between the serial example and the parallel execution example is where suspension happens. In the serial example, each `activity()` call suspends and resumes the workflow directly. In the parallel example, the `startActivity()` builders describe the whole barrier first and `all()` suspends once for the whole group, so every member can run in parallel before the workflow resumes.
75
+
The main difference between the serial example and the parallel execution example is where suspension happens. In the serial example, each `activity()` call suspends and resumes the workflow directly. In the parallel example, the closures describe the whole barrier first and `all()` suspends once for the whole group, so every member can run in parallel before the workflow resumes.
76
76
77
77
## Nested Barriers
78
78
79
79
Nested `all([...])` groups let one workflow step express a tree of durable fan-out and fan-in work. The runtime schedules every activity or child workflow as a durable leaf sequence, records the leaf's full `parallel_group_path`, waits until every enclosing barrier can make progress, and then rebuilds the original nested result shape before resuming the workflow body. During replay, an activity or child leaf from an `all([...])` step must still match that recorded group path; typed leaf history that has no group metadata is treated as incompatible older preview history instead of being guessed into the current barrier.
80
80
81
81
```php
82
-
use function Workflow\V2\{all, parallel, startActivity};
82
+
use function Workflow\V2\{all, activity};
83
83
use Workflow\V2\Workflow;
84
84
85
85
final class NestedWorkflow extends Workflow
86
86
{
87
87
public function handle(): array
88
88
{
89
89
return all([
90
-
startActivity(BuildSummary::class),
91
-
parallel([
92
-
startActivity(BuildInvoice::class),
93
-
startActivity(BuildShipment::class),
90
+
fn () => activity(BuildSummary::class),
91
+
fn () => all([
92
+
fn () => activity(BuildInvoice::class),
93
+
fn () => activity(BuildShipment::class),
94
94
]),
95
95
]);
96
96
}
@@ -101,7 +101,7 @@ In that example, Waterline exposes three open leaf waits, not one synthetic "nes
101
101
102
102
## Async Callback
103
103
104
-
`async(...)` runs a serializable callback as a durable child workflow with the system type `durable-workflow.async`. Async callbacks use the same straight-line-only helper contract as named v2 workflows, so `activity()`, `awaitSignal()`, `timer()`, `sideEffect()`, and the other single-step helpers suspend directly inside the callback body without forcing `yield`.
104
+
`async(...)` runs a serializable callback as a durable child workflow with the system type `durable-workflow.async`. Async callbacks use the same straight-line-only helper contract as named v2 workflows, so `activity()`, `signal()`, `timer()`, `sideEffect()`, and the other single-step helpers suspend directly inside the callback body without forcing `yield`.
105
105
106
106
```php
107
107
use function Workflow\V2\{activity, async};
@@ -125,7 +125,7 @@ final class CustomerWorkflow extends Workflow
125
125
}
126
126
```
127
127
128
-
The parent run sees the callback as a child wait, so command history, lineage, and Waterline detail use the same `child_call_id`, child run id, and child outcome history as an explicit `child(...)` call. The callback is serialized with Laravel's serializable-closure support, so keep it app-local and deployment-local. Use a named `child(SomeWorkflow::class, ...)` call when the work needs a stable public workflow type for cross-service routing or long-lived code evolution. `async(...)` callbacks are now straight-line only in v2, so call helpers like `activity()`, `child()`, `awaitSignal()`, `timer()`, and `all([...])` directly without `yield`.
128
+
The parent run sees the callback as a child wait, so command history, lineage, and Waterline detail use the same `child_call_id`, child run id, and child outcome history as an explicit `child(...)` call. The callback is serialized with Laravel's serializable-closure support, so keep it app-local and deployment-local. Use a named `child(SomeWorkflow::class, ...)` call when the work needs a stable public workflow type for cross-service routing or long-lived code evolution. `async(...)` callbacks are now straight-line only in v2, so call helpers like `activity()`, `child()`, `signal()`, `timer()`, and `all([...])` directly without `yield`.
129
129
130
130
## Mixed Activity + Child Barriers
131
131
@@ -134,16 +134,16 @@ The same `all()` helper can also fan in a mixed group of activities and child wo
134
134
When more than one barrier member has already closed unsuccessfully by the time the parent replays, the parent receives the failure with the earliest recorded close time. If two failures have the same recorded time, the lower barrier leaf index wins, so workflow resume and query replay select the same exception. Later sibling failures do not replace the exception that has already been thrown into the parent step.
135
135
136
136
```php
137
-
use function Workflow\V2\{all, startActivity, startChild};
137
+
use function Workflow\V2\{all, activity, child};
138
138
use Workflow\V2\Workflow;
139
139
140
140
final class OrderWorkflow extends Workflow
141
141
{
142
142
public function handle(): array
143
143
{
144
144
[$charge, $shipment] = all([
145
-
startActivity(ChargeCustomer::class),
146
-
startChild(ShipOrderWorkflow::class),
145
+
fn () => activity(ChargeCustomer::class),
146
+
fn () => child(ShipOrderWorkflow::class),
147
147
]);
148
148
149
149
return compact('charge', 'shipment');
@@ -156,24 +156,24 @@ final class OrderWorkflow extends Workflow
156
156
The current concurrency surface does not yet include:
157
157
158
158
- launch handles that can be started and awaited separately from `all([...])` barriers or `async(...)`
159
-
- built-in bounded-concurrency helpers beyond explicit nested `all([...])` groups plus `startActivity()` / `startChild()` builders
159
+
- built-in bounded-concurrency helpers beyond explicit nested `all([...])` groups
160
160
161
161
## Child Workflows in Parallel
162
162
163
-
Child workflows can also run in their own `all([...startChild(...)])` barrier. It works the same way as parallel activity execution, but for child workflows: the parent fans out several child runs durably and resumes only when the whole child barrier can make progress.
163
+
Child workflows can also run in their own `all([...])` barrier. It works the same way as parallel activity execution, but for child workflows: the parent fans out several child runs durably and resumes only when the whole child barrier can make progress.
0 commit comments