From d20f07aceef8037c8f8901d4d46465e576fb22cd Mon Sep 17 00:00:00 2001 From: Niklas Keller Date: Thu, 2 Dec 2021 23:45:45 +0100 Subject: [PATCH] Update cancellation docs --- docs/cancellation/README.md | 44 +++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/docs/cancellation/README.md b/docs/cancellation/README.md index 3491e03..994707c 100644 --- a/docs/cancellation/README.md +++ b/docs/cancellation/README.md @@ -1,28 +1,38 @@ --- -layout: docs -title: Cancellation -permalink: /cancellation/ +layout: docs title: Cancellation permalink: /cancellation/ --- -Amp provides primitives to allow the cancellation of operations, namely `CancellationTokenSource` and `CancellationToken`. +Amp provides a `Cancellation` primitive to allow the cancellation of operations. ```php -$tokenSource = new CancellationTokenSource; -$promise = asyncRequest("...", $tokenSource->getToken()); - -Loop::delay(1000, function () use ($tokenSource) { - $tokenSource->cancel(); -}); - -$result = yield $promise; +request("...", new Amp\TimeoutCancellation(30)); ``` -Every operation that supports cancellation accepts an instance of `CancellationToken` as (optional) argument. Within a coroutine, `$token->throwIfRequested()` can be used to fail the operation with a `CancelledException`. As `$token` is often an optional parameter and might be `null`, these calls need to be guared with a `if ($token)` or similar check. Instead of doing so, it's often easier to simply set the token to `$token = $token ?? new NullCancellationToken` at the beginning of the method. +```php +$deferredCancellation = new Amp\DeferredCancellation(); +Loop::onSignal(SIG_INT, function () use ($deferredCancellation) { + $deferredCancellation->cancel(); +}); -While `throwIfRequested()` works well within coroutines, some operations might want to subscribe with a callback instead. They can do so using `CancellationToken::subscribe()` to subscribe any cancellation requests that might happen. +request("...", $deferredCancellation->getCancellation()); +``` -If the operation consists of any sub-operations that support cancellation, it passes that same `CancellationToken` instance down to these sub-operations. - -The original caller creates a `CancellationToken` by creating an instance of `CancellationTokenSource` and passing `$cancellationTokenSource->getToken()` to the operation as shown in the above example. Only the original caller has access to the `CancellationTokenSource` and can cancel the operation using `CancellationTokenSource::cancel()`, similar to the way it works with `Deferred` and `Promise`. +Every operation that supports cancellation accepts an instance of `Cancellation` as (optional) +argument. `$cancellation->throwIfRequested()` can be used to fail the operation with a `CancelledException`. +As `$cancellation` is often an optional parameter and might be `null`, these calls need to be guarded with +a `if ($cancellation)` or similar check. Instead of doing so, it's often easier to simply set the token +to `$cancellation ??= new NullCancellationToken` at the beginning of the method. + +While `throwIfRequested()` works well, some operations might want to subscribe with a callback instead. They can do so +using `Cancellation::subscribe()` to subscribe any cancellation requests that might happen. + +If the operation consists of any sub-operations that support cancellation, it passes that same `Cancellation` +instance down to these sub-operations. + +The original caller creates a `Cancellation` by creating an instance of `DeferredCancellation` and +passing `$deferred->getCancellation()` to the operation as shown in the above example, or using one of the other +implementations of `Cancellation`, such as `TimeoutCancellation`. Only the original caller has access to +the `DeferredCancellation` and can cancel the operation using `DeferredCancellation::cancel()`, similar to the way it +works with `DeferredFuture` and `Future`. {:.note} > Cancellations are advisory only. A DNS resolver might ignore cancellation requests after the query has been sent as the response has to be processed anyway and can still be cached. An HTTP client might continue a nearly finished HTTP request to reuse the connection, but might abort a chunked encoding response as it cannot know whether continuing is actually cheaper than aborting.