Skip to content

Commit 182804a

Browse files
Update V2 docs for unified helper API
Replace all references to removed functions (startActivity, startChild, awaitSignal, awaitWithTimeout, parallel) with their unified equivalents. Add timer sugar documentation. V1 versioned docs untouched. Ref: zorporation/durable-workflow#278
1 parent 7790afd commit 182804a

File tree

15 files changed

+93
-87
lines changed

15 files changed

+93
-87
lines changed

docs/constraints/structural-limits.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Structural limits cap the resource consumption of a single workflow run. When an
1515
| `pending_timer_count` | 2,000 | Pending timers open simultaneously |
1616
| `pending_signal_count` | 5,000 | Unprocessed signals pending simultaneously |
1717
| `pending_update_count` | 500 | Unresolved updates pending simultaneously |
18-
| `command_batch_size` | 1,000 | Items in a single parallel fan-out (`all()` / `parallel()`) |
18+
| `command_batch_size` | 1,000 | Items in a single parallel fan-out (`all()`) |
1919
| `payload_size_bytes` | 2 MiB | Serialized size of a single argument payload |
2020
| `memo_size_bytes` | 256 KiB | Serialized size of non-indexed memo metadata |
2121
| `search_attribute_size_bytes` | 40 KiB | Serialized size of indexed search-attribute metadata |
@@ -80,7 +80,7 @@ This protects against patterns like unbounded parallel fan-out loops that accumu
8080
// This will fail if $items exceeds the pending_activity_count limit
8181
$calls = [];
8282
foreach ($items as $item) {
83-
$calls[] = startActivity(ProcessItemActivity::class, $item);
83+
$calls[] = fn () => activity(ProcessItemActivity::class, $item);
8484
}
8585
return all($calls); // Also checked against command_batch_size
8686
```
@@ -91,7 +91,7 @@ To handle large batches within the limits, process items in bounded chunks:
9191
foreach (array_chunk($items, 500) as $chunk) {
9292
$calls = [];
9393
foreach ($chunk as $item) {
94-
$calls[] = startActivity(ProcessItemActivity::class, $item);
94+
$calls[] = fn () => activity(ProcessItemActivity::class, $item);
9595
}
9696
all($calls);
9797
}
@@ -116,7 +116,7 @@ if ($result->rejected()) {
116116

117117
### Command batch size
118118

119-
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.
120120

121121
### Payload size
122122

@@ -156,7 +156,7 @@ This catches runaway loops that create unbounded events in a single task without
156156
foreach (array_chunk($items, 500) as $chunk) {
157157
$calls = [];
158158
foreach ($chunk as $item) {
159-
$calls[] = startActivity(ProcessItemActivity::class, $item);
159+
$calls[] = fn () => activity(ProcessItemActivity::class, $item);
160160
}
161161
all($calls); // Each chunk is a separate task execution
162162
}

docs/defining-workflows/activities.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,19 @@ $result = activity(
7777
);
7878
```
7979

80-
The same pattern works with `startActivity()` for async activity calls:
80+
The same pattern works with closures inside `all()` for parallel activity calls:
8181

8282
```php
83-
use function Workflow\V2\startActivity;
83+
use function Workflow\V2\all;
8484
use Workflow\V2\Support\ActivityOptions;
8585

86-
$handle = startActivity(
87-
MyActivity::class,
88-
new ActivityOptions(queue: 'batch'),
89-
$name,
90-
);
86+
$results = all([
87+
fn () => activity(
88+
MyActivity::class,
89+
new ActivityOptions(queue: 'batch'),
90+
$name,
91+
),
92+
]);
9193
```
9294

9395
### Available options

docs/features/child-workflows.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,28 +44,28 @@ final class ParentWorkflow extends Workflow
4444
- Parent workflows can signal the current child through that handle with `signal()`, `signalWithArguments()`, or method-call sugar such as `$this->child()?->approvedBy('Taylor')`.
4545
- Query replay keeps those handles read-only, while inline update application can still use the handle to emit a real child signal exactly once.
4646
- 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.
4949
- 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.
5050
- 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.
5151
- 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.
5252

5353
## Parallel Child Barrier
5454

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.
5656

5757
```php
5858
use function Workflow\V2\all;
59-
use function Workflow\V2\startChild;
59+
use function Workflow\V2\child;
6060
use Workflow\V2\Workflow;
6161

6262
final class ParentWorkflow extends Workflow
6363
{
6464
public function handle(): array
6565
{
6666
$children = all([
67-
startChild(FirstChildWorkflow::class),
68-
startChild(SecondChildWorkflow::class),
67+
fn () => child(FirstChildWorkflow::class),
68+
fn () => child(SecondChildWorkflow::class),
6969
]);
7070

7171
return $children;
@@ -113,7 +113,7 @@ final class ParentWorkflow extends Workflow
113113

114114
- `$this->child()` returns the latest visible child handle or `null`.
115115
- `$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.
117117
- 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()`.
118118

119119
## Handle Availability
@@ -153,7 +153,7 @@ When a parent workflow closes — whether by completing, failing, timing out, be
153153

154154
### Setting the policy
155155

156-
Pass a `ChildWorkflowOptions` as the first argument to `child()` or `startChild()`:
156+
Pass a `ChildWorkflowOptions` as the first argument to `child()`:
157157

158158
```php
159159
use function Workflow\V2\child;
@@ -174,11 +174,11 @@ final class ParentWorkflow extends Workflow
174174
}
175175
```
176176

177-
The same pattern works with `startChild()` for parallel barriers:
177+
The same pattern works with closures inside `all()` for parallel barriers:
178178

179179
```php
180180
use function Workflow\V2\all;
181-
use function Workflow\V2\startChild;
181+
use function Workflow\V2\child;
182182
use Workflow\V2\Enums\ParentClosePolicy;
183183
use Workflow\V2\Support\ChildWorkflowOptions;
184184

@@ -187,8 +187,8 @@ $cancelOptions = new ChildWorkflowOptions(
187187
);
188188

189189
$results = all([
190-
startChild(FirstChild::class, $cancelOptions),
191-
startChild(SecondChild::class, $cancelOptions, 'arg'),
190+
fn () => child(FirstChild::class, $cancelOptions),
191+
fn () => child(SecondChild::class, $cancelOptions, 'arg'),
192192
]);
193193
```
194194

@@ -220,6 +220,6 @@ Waterline shows the `parent_close_policy` in:
220220

221221
The current surface does not include:
222222

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
224224

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.

docs/features/concurrency.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import ConcurrencySimulator from '@site/src/components/ConcurrencySimulator';
66

77
# Concurrency
88

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.
1010

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.
1212

1313
## Series
1414

@@ -46,17 +46,17 @@ class MyWorkflow extends Workflow
4646
This example will execute 3 activities in parallel, waiting for the completion of all activities and collecting the results.
4747

4848
```php
49-
use function Workflow\V2\{all, startActivity};
49+
use function Workflow\V2\{all, activity};
5050
use Workflow\V2\Workflow;
5151

5252
class MyWorkflow extends Workflow
5353
{
5454
public function handle()
5555
{
5656
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),
6060
]);
6161
}
6262
}
@@ -72,25 +72,25 @@ class MyWorkflow extends Workflow
7272
title="Parallel Execution Simulator"
7373
/>
7474

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.
7676

7777
## Nested Barriers
7878

7979
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.
8080

8181
```php
82-
use function Workflow\V2\{all, parallel, startActivity};
82+
use function Workflow\V2\{all, activity};
8383
use Workflow\V2\Workflow;
8484

8585
final class NestedWorkflow extends Workflow
8686
{
8787
public function handle(): array
8888
{
8989
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),
9494
]),
9595
]);
9696
}
@@ -101,7 +101,7 @@ In that example, Waterline exposes three open leaf waits, not one synthetic "nes
101101

102102
## Async Callback
103103

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`.
105105

106106
```php
107107
use function Workflow\V2\{activity, async};
@@ -125,7 +125,7 @@ final class CustomerWorkflow extends Workflow
125125
}
126126
```
127127

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`.
129129

130130
## Mixed Activity + Child Barriers
131131

@@ -134,16 +134,16 @@ The same `all()` helper can also fan in a mixed group of activities and child wo
134134
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.
135135

136136
```php
137-
use function Workflow\V2\{all, startActivity, startChild};
137+
use function Workflow\V2\{all, activity, child};
138138
use Workflow\V2\Workflow;
139139

140140
final class OrderWorkflow extends Workflow
141141
{
142142
public function handle(): array
143143
{
144144
[$charge, $shipment] = all([
145-
startActivity(ChargeCustomer::class),
146-
startChild(ShipOrderWorkflow::class),
145+
fn () => activity(ChargeCustomer::class),
146+
fn () => child(ShipOrderWorkflow::class),
147147
]);
148148

149149
return compact('charge', 'shipment');
@@ -156,24 +156,24 @@ final class OrderWorkflow extends Workflow
156156
The current concurrency surface does not yet include:
157157

158158
- 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
160160

161161
## Child Workflows in Parallel
162162

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.
164164

165165
```php
166-
use function Workflow\V2\{all, startChild};
166+
use function Workflow\V2\{all, child};
167167
use Workflow\V2\Workflow;
168168

169169
final class ParentWorkflow extends Workflow
170170
{
171171
public function handle(): array
172172
{
173173
return all([
174-
startChild(MyChild1::class),
175-
startChild(MyChild2::class),
176-
startChild(MyChild3::class),
174+
fn () => child(MyChild1::class),
175+
fn () => child(MyChild2::class),
176+
fn () => child(MyChild3::class),
177177
]);
178178
}
179179
}

docs/features/queries.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Queries replay committed history for the current selected run and then invoke th
1515
```php
1616
use Workflow\QueryMethod;
1717
use Workflow\V2\Workflow;
18-
use function Workflow\V2\awaitSignal;
18+
use function Workflow\V2\signal;
1919

2020
final class ApprovalWorkflow extends Workflow
2121
{
@@ -25,7 +25,7 @@ final class ApprovalWorkflow extends Workflow
2525
{
2626
$this->stage = 'waiting-for-approval';
2727

28-
awaitSignal('approved-by');
28+
signal('approved-by');
2929

3030
$this->stage = 'approved';
3131
}

0 commit comments

Comments
 (0)