Skip to content

Commit

Permalink
Add docs for timeout (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
smaye81 authored Sep 22, 2023
1 parent ee22395 commit f801b29
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 99 deletions.
2 changes: 1 addition & 1 deletion docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ and we gauge interest in new languages with [GitHub polls][poll-discussions].
[connect-swift]: https://github.com/connectrpc/connect-swift
[swift-launch-blog-post]: https://buf.build/blog/announcing-connect-swift
[connect-protocol]: /docs/protocol
[demo]: https://github.com/bufbuild/examples-go
[demo]: https://github.com/connectrpc/examples-go
[go-getting-started]: /docs/go/getting-started
[kotlin-getting-started]: /docs/kotlin/getting-started
[swift-getting-started]: /docs/swift/getting-started
Expand Down
33 changes: 0 additions & 33 deletions docs/node/_error-details.md

This file was deleted.

69 changes: 69 additions & 0 deletions docs/web/cancellation-and-timeouts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: Cancellation & Timeouts
sidebar_position: 6
---

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.


## Cancellation

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";

const client = createPromiseClient(ElizaService, ...);

// For the sake of this example, let's cancel the request right away
const abort = new AbortController();
abort.abort();

try {
await client.say({sentence: "I feel..."}, { signal: abort.signal });
} catch (err) {
if (err instanceof ConnectError && err.code != Code.Canceled) {
// handle the genuine error, ignoring cancelled requests
}
}
```

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. Here is an example:

```ts
try {
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
}
}
```

When a timeout is reached before the request finishes, a `ConnectError` with
code `DeadlineExceeded` is raised.

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/).
2 changes: 1 addition & 1 deletion docs/web/choosing-a-protocol.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Choosing a protocol
sidebar_position: 16
sidebar_position: 8
---

In addition to the [Connect protocol](/docs/protocol), [@connectrpc/connect-web](https://www.npmjs.com/package/@connectrpc/connect-web)
Expand Down
2 changes: 1 addition & 1 deletion docs/web/common-errors.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Common errors
sidebar_position: 18
sidebar_position: 10
---

This page explains how to fix common errors when using Connect from a web browser
Expand Down
58 changes: 3 additions & 55 deletions docs/web/errors.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
---
title: Errors
sidebar_position: 5
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 All @@ -34,12 +24,9 @@ With the gRPC-web protocol, errors are usually not human-readable, but
Connect provides a common type that represents errors consistently across
all supported protocols.


## Working with errors

All errors are represented by [`ConnectError`](https://github.com/connectrpc/connect-es/blob/1c1dc4cfd300e120d07a486f488d5693139f9dee/packages/connect/src/connect-error.ts#L27),
a subtype of the built-in `Error` class. Using a try-catch block, we can catch
any error that occurred during a call:
All errors are represented by [`ConnectError`](https://github.com/connectrpc/connect-es/blob/1c1dc4cfd300e120d07a486f488d5693139f9dee/packages/connect/src/connect-error.ts#L27), a subtype of the built-in `Error` class. Using a try-catch block, we can catch any error that occurred during a call:

```ts
import { ConnectError } from "@connectrpc/connect";
Expand All @@ -62,10 +49,9 @@ try {
}
```


## Error codes

The `code` property holds one of Connects [error codes](/docs/protocol#error-codes).
The `code` property holds one of Connect's [error codes](/docs/protocol#error-codes).
All error codes are available through the TypeScript enumeration [`Code`](https://github.com/connectrpc/connect-es/blob/1c1dc4cfd300e120d07a486f488d5693139f9dee/packages/connect/src/code.ts#L16).
Note that a code is an integer value, but can easily be converted to and
from a string value.
Expand Down Expand Up @@ -139,41 +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.


## Cancellation

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.

Connect converts those errors into a `ConnectError` with code `Canceled`,
so that you can handle cancellation appropriately:

```ts
import { createPromiseClient, ConnectError, Code } from "@connectrpc/connect";

const client = createPromiseClient(ElizaService, ...);

// For the sake of this example, let's cancel the request right away
const abort = new AbortController();
abort.abort();

try {
await client.say({sentence: "I feel..."}, { signal: abort.signal });
} catch (err) {
if (err instanceof ConnectError && err.code != Code.Canceled) {
// handle the genuine error, ignoring cancelled requests
}
}
```

There is no silver bullet to error handling with async/await and cancellation.
In general, we recommend to let 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.

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 and cancellation differently.
2 changes: 1 addition & 1 deletion docs/web/generating-code.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Generating code
sidebar_position: 3
sidebar_position: 2
---

We mentioned earlier that the ELIZA service defines a Protocol Buffer schema.
Expand Down
2 changes: 1 addition & 1 deletion docs/web/get-requests-and-caching.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Get Requests and Caching
sidebar_position: 21
sidebar_position: 12
---

Connect supports performing idempotent, side-effect free requests using an HTTP
Expand Down
2 changes: 1 addition & 1 deletion docs/web/headers-and-trailers.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Headers & trailers
sidebar_position: 6
sidebar_position: 5
---


Expand Down
2 changes: 1 addition & 1 deletion docs/web/ssr.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Server-Side Rendering (SSR)
sidebar_position: 22
sidebar_position: 13
---

Many frameworks offer server-side rendering (SSR) support, which is the ability to render a page on the server-side and
Expand Down
4 changes: 2 additions & 2 deletions docs/web/supported-browsers-and-frameworks.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Supported Browsers & Frameworks
sidebar_position: 17
title: Supported browsers & frameworks
sidebar_position: 9
---

Connect supports all modern web browsers that implement the widely
Expand Down
2 changes: 1 addition & 1 deletion docs/web/testing.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Testing
sidebar_position: 20
sidebar_position: 11
---

Testing a client application can be a crucial part of ensuring its functionality
Expand Down
2 changes: 1 addition & 1 deletion docs/web/using-clients.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Using clients
sidebar_position: 4
sidebar_position: 3
---

Connect ships with two client shapes for TypeScript, one with classic callbacks,
Expand Down

0 comments on commit f801b29

Please sign in to comment.