Skip to content
This repository was archived by the owner on Jun 16, 2025. It is now read-only.

Commit 51c8f90

Browse files
committed
Add captureResults parameter to TaskGroup constructor; implement all() method for improved task result handling
1 parent ddad941 commit 51c8f90

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

basic.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ function mergeFiles(string ...$files): string
115115
$taskGroup->spawn(file_get_contents(...), $file);
116116
}
117117

118-
return array_merge("\n", await $taskGroup);
118+
return array_merge("\n", await $taskGroup->all());
119119
}
120120
```
121121

@@ -2170,6 +2170,83 @@ The `getErrors()` method will return an array of exceptions.
21702170

21712171
The `TaskGroup` class allows you to cancel all tasks in the group using the `cancel()` method.
21722172

2173+
This method behaves the same way as `TaskGroup::dispose`,
2174+
with the only difference being that it allows you to pass a specific exception.
2175+
2176+
```php
2177+
use Async\TaskGroup;
2178+
2179+
$taskGroup = new Async\TaskGroup(captureResults: false);
2180+
$taskGroup->add(spawn {
2181+
try {
2182+
suspend;
2183+
} catch (Throwable $throwable) {
2184+
echo "Task was cancelled: ", $throwable->getMessage(), "\n";
2185+
}
2186+
});
2187+
2188+
// pass control to the task
2189+
suspend;
2190+
2191+
$taskGroup->cancel(new \Async\CancellationException('Custom cancellation message'));
2192+
```
2193+
2194+
**Expected output:**
2195+
2196+
```
2197+
Task was cancelled: Custom cancellation message
2198+
```
2199+
2200+
#### TaskGroup error handling
2201+
2202+
`TaskGroup` does not introduce additional logic for handling coroutine exceptions.
2203+
When a developer uses the expression `await $taskGroup`, they are capturing the exceptions
2204+
of all tasks contained within `$taskGroup`.
2205+
In other words, `await $taskGroup` is equivalent to simultaneously using `await $coroutine` for each task.
2206+
If no one awaits `$taskGroup`, the exception handling follows the general `Flow`,
2207+
and the error will propagate to the `Scope`.
2208+
2209+
An additional method `TaskGroup::all(bool $ignoreErrors = false, $nullOnFail = false): Awaitable {}` provides a trigger
2210+
that fires when all tasks in the group have completed.
2211+
At the same time, it captures any errors, which can be retrieved using `TaskGroup::getErrors()`.
2212+
2213+
```php
2214+
// Returns an array of all tasks with their results ignoring errors
2215+
return $taskGroup->all(ignoreErrors: true);
2216+
```
2217+
2218+
The trigger `TaskGroup::all()` returns an array of results with numeric indices,
2219+
where each index corresponds to the ordinal number of the task.
2220+
If a task completed with an error, its numeric index will be missing from the array.
2221+
2222+
Using the option `$nullOnFail`, you can specify that the results of failed
2223+
tasks should be filled with `NULL` instead.
2224+
2225+
```php
2226+
$taskGroup = new Async\TaskGroup(captureResults: true);
2227+
$taskGroup->add(spawn {return 'result 1';});
2228+
$taskGroup->add(spawn {throw new Exception('Error')});
2229+
2230+
var_dump(await $taskGroup->all(ignoreErrors: true, nullOnFail: true));
2231+
```
2232+
2233+
**Expected output:**
2234+
2235+
```php
2236+
array(2) {
2237+
[0]=>
2238+
string(8) "result 1"
2239+
[1]=>
2240+
NULL
2241+
}
2242+
```
2243+
2244+
The method `TaskGroup::getErrors()` returns an array with numeric indices and exceptions,
2245+
where each index corresponds to the ordinal number of the task.
2246+
2247+
> **Note:** The method `TaskGroup::disposeResults` clears all results and errors at the moment it is called.
2248+
> Coroutines then reset their ordinal indices starting from zero.
2249+
21732250
### Context
21742251

21752252
#### Motivation

examples/Async/TaskGroup.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ final class TaskGroup implements Awaitable
88
{
99
public function __construct(
1010
private ?Scope $scope = null,
11-
private bool $ignoreErrors = false
11+
private bool $captureResults = false
1212
) {}
1313

14+
public function all(bool $ignoreErrors = false, $nullOnFail = false): Awaitable {}
1415
public function race(bool $ignoreErrors = false): Awaitable {}
1516
public function firstResult(bool $ignoreErrors = false): Awaitable {}
1617
public function getResults(): array {}

0 commit comments

Comments
 (0)