Skip to content

Commit

Permalink
Add introductory paragraph; switch timeout example to server-streamin…
Browse files Browse the repository at this point in the history
…g call
  • Loading branch information
timostamm committed Sep 22, 2023
1 parent 21543ce commit 43f3916
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 75 deletions.
33 changes: 0 additions & 33 deletions docs/node/_error-details.md

This file was deleted.

59 changes: 29 additions & 30 deletions docs/web/cancellation-and-timeouts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ title: Cancellation & Timeouts
sidebar_position: 6
---

## Cancellation
There may be cases where you want to cancel a call, because you are no longer
interested in the response. For example, you want to show search results as soon
as the user starts typing, but when the user enters another term, you want to
cancel the previous call. Let's take a look at cancellation, and the complementary
topic of timeouts.


There may be cases where you want to cancel a call, for example because the
user closed a dialog. All client methods take an optional [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
as an argument for this purpose. If this signal is aborted, the browser stops
the request, and the fetch API raises an `AbortError` to abort the code path
of the application.
## Cancellation

Connect converts those errors into a `ConnectError` with code `Canceled`,
so that you can handle cancellation appropriately:
To cancel a call, you can pass an [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to every client method.
If the signal triggers, the network call is cancelled, and the response promise
for your call is rejected:

```ts
import { createPromiseClient, ConnectError, Code } from "@connectrpc/connect";
Expand All @@ -32,39 +34,36 @@ try {
}
```

Note that our client raises a `ConnectError` with code `Canceled`, instead of a
`DOMException` that fetch() would raise.

## Timeouts

Similar to the `signal` option for cancellation, there is also the `timeoutMs` option, which
allows you to specify a timeout, in milliseconds, for an individual call. The timeout value is
specified in the same options object described above.

When a timeout is reached before the request has been completed, a `ConnectError` with code `DeadlineExceeded` will
be thrown.
## Timeouts

An example using a timeout of 3 seconds:
Similar to the `signal` option for cancellation, there is also the `timeoutMs`
option, which allows you to specify a timeout, in milliseconds, for an individual
call. Here is an example:

```ts
try {
await client.say({sentence: "Hello"}, { timeoutMs: 3000 });
const req = { name: "Joe" };
// If this call takes more than 200 milliseconds, it is canceled
for await (const res of client.introduce(req, { timeoutMs: 200 })) {
console.log(res.sentence);
}
} catch (err) {
// Note that our client raises a ConnectError with Code.DeadlineExceeded
if (err instanceof ConnectError && err.code === Code.DeadlineExceeded) {
// handle the timeout error
}
}
```

The timeout value is sent to the server, and honored on the server (and typically also on the client). This allows for
propagation of the timeout to upstream services.

Timeouts in Connect are the equivalent of [deadlines](https://grpc.io/docs/guides/deadlines/) in gRPC. They both
behave similarly in that they will throw a "deadline exceeded" error. Since Connect's defined error codes map to the
same codes and semantics as gRPC, this allows for easy interop between the two protocols.

There is no silver bullet to error handling with async/await and cancellation or
timeout errors as they both can force you to handle exceptional flow. In general, we
recommend to let the exception travel up to a central error handler in your application,
and only catch errors in the case they need to be explicitly handled in your business logic.
When a timeout is reached before the request finishes, a `ConnectError` with
code `DeadlineExceeded` is raised.

But your use case may vary, and we encourage you to [roll your own client](/docs/web/using-clients#roll-your-own-client)
if you want to represent errors differently when handling cancellations and timeouts.
When you specify a timeout, the value is sent to the server in a request header
that is understood by Connect, gRCP, and gRPC-web servers. Servers _and_ clients
honor the timeout, which can be immensely helpful for streaming calls in a fragile
network environment. Timeouts can also be propagated to upstream services.
In gRPC, the concept is also known as [deadlines](https://grpc.io/docs/guides/deadlines/).
12 changes: 0 additions & 12 deletions docs/web/errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,6 @@ sidebar_position: 4
---


<!--
TODO

- explain timeoutMs
- explain assertion alternative and connectErrorFromReason() ?
- link to mapped clients for Either or neverthrow?

-->



Similar to the familiar "404 Not Found" and "500 Internal Server Error" status
codes you may have seen in HTTP, Connect uses a set of [16 error codes](/docs/protocol#error-codes).
Expand Down Expand Up @@ -135,5 +125,3 @@ in this example, but any protobuf message can be transmitted as error details.
Alternatively, `findDetails()` takes a registry as an argument. See the
[protobuf-es documentation](https://github.com/bufbuild/protobuf-es/blob/main/docs/runtime_api.md#registries)
for details.

For some practical examples of handling specific errors, check out the [Cancellation & Timeouts](./cancellation-and-timeouts.mdx) docs.

0 comments on commit 43f3916

Please sign in to comment.