2017-05-26 19:56:02 +02:00
---
2021-12-03 00:09:53 +01:00
layout: "docs"
title: "Cancellation"
permalink: "/cancellation/"
2017-05-26 19:56:02 +02:00
---
2021-12-02 23:45:45 +01:00
Amp provides a `Cancellation` primitive to allow the cancellation of operations.
2017-05-16 18:51:48 +02:00
2017-05-27 19:46:14 +02:00
```php
2021-12-02 23:45:45 +01:00
request("...", new Amp\TimeoutCancellation(30));
```
2017-05-27 19:46:14 +02:00
2021-12-02 23:45:45 +01:00
```php
$deferredCancellation = new Amp\DeferredCancellation();
Loop::onSignal(SIG_INT, function () use ($deferredCancellation) {
$deferredCancellation->cancel();
2017-05-27 19:46:14 +02:00
});
2021-12-02 23:45:45 +01:00
request("...", $deferredCancellation->getCancellation());
2017-05-27 19:46:14 +02:00
```
2021-12-02 23:45:45 +01:00
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.
2017-05-27 19:46:14 +02:00
2021-12-02 23:45:45 +01:00
If the operation consists of any sub-operations that support cancellation, it passes that same `Cancellation`
instance down to these sub-operations.
2017-05-27 19:46:14 +02:00
2021-12-02 23:45:45 +01:00
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` .
2017-05-16 18:51:48 +02:00
2017-05-26 19:56:02 +02:00
{:.note}
2017-05-27 19:46:14 +02:00
> 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.