Skip to content

Commit

Permalink
feat(client): Deprecate isFatalConnectionProblem option in favour o…
Browse files Browse the repository at this point in the history
…f `shouldRetry`
  • Loading branch information
enisdenjo committed Apr 25, 2022
1 parent 67c7996 commit d8dcf21
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 4 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,26 @@ ReactDOM.render(document.getElementByID('graphiql'), <App />);

</details>

<details id="retry-non-close-events">
<summary><a href="#retry-non-close-events">🔗</a> Client usage with retry on any connection problem</summary>

```typescript
import { createClient } from 'graphql-ws';
import { waitForHealthy } from './my-servers';

const client = createClient({
url: 'ws://any.retry:4000/graphql',
// by default the client will immediately fail on any non-fatal
// `CloseEvent` problem thrown during the connection phase
//
// see `retryAttempts` documentation about which `CloseEvent`s are
// considered fatal regardless
shouldRetry: () => true,
});
```

</details>

<details id="retry-strategy">
<summary><a href="#retry-strategy">🔗</a> Client usage with custom retry timeout strategy</summary>

Expand Down
34 changes: 33 additions & 1 deletion docs/interfaces/client.ClientOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Configuration used for the GraphQL over WebSocket client.
- [isFatalConnectionProblem](client.ClientOptions.md#isfatalconnectionproblem)
- [onNonLazyError](client.ClientOptions.md#onnonlazyerror)
- [retryWait](client.ClientOptions.md#retrywait)
- [shouldRetry](client.ClientOptions.md#shouldretry)

## Properties

Expand Down Expand Up @@ -259,6 +260,8 @@ ___

`Optional` **isFatalConnectionProblem**(`errOrCloseEvent`): `boolean`

**`deprecated`** Use `shouldRetry` instead.

Check if the close event or connection error is fatal. If you return `true`,
the client will fail immediately without additional retries; however, if you
return `false`, the client will keep retrying until the `retryAttempts` have
Expand All @@ -271,7 +274,7 @@ Beware, the library classifies a few close events as fatal regardless of
what is returned. They are listed in the documentation of the `retryAttempts`
option.

**`default`** 'Any non-CloseEvent'
**`default`** 'Any non-`CloseEvent`'

#### Parameters

Expand Down Expand Up @@ -339,3 +342,32 @@ by timing the resolution of the returned promise with the retries count.
#### Returns

`Promise`<`void`\>

___

### shouldRetry

`Optional` **shouldRetry**(`errOrCloseEvent`): `boolean`

Check if the close event or connection error is fatal. If you return `false`,
the client will fail immediately without additional retries; however, if you
return `true`, the client will keep retrying until the `retryAttempts` have
been exceeded.

The argument is whatever has been thrown during the connection phase.

Beware, the library classifies a few close events as fatal regardless of
what is returned here. They are listed in the documentation of the `retryAttempts`
option.

**`default`** 'Only `CloseEvent`s'

#### Parameters

| Name | Type |
| :------ | :------ |
| `errOrCloseEvent` | `unknown` |

#### Returns

`boolean`
32 changes: 31 additions & 1 deletion src/__tests__/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1612,7 +1612,10 @@ describe('reconnecting', () => {
createClient({
url,
retryAttempts: Infinity, // keep retrying forever
isFatalConnectionProblem: () => true, // even if all connection probles are fatal
// even if all connection problems are fatal
shouldRetry: () => false,
// @deprecated
isFatalConnectionProblem: () => true,
}),
{
query: 'subscription { ping }',
Expand Down Expand Up @@ -1648,6 +1651,33 @@ describe('reconnecting', () => {
it('should report fatal connection problems immediately', async () => {
const { url, ...server } = await startTServer();

const sub = tsubscribe(
createClient({
url,
retryAttempts: Infinity, // keep retrying forever
shouldRetry: (err) => {
expect((err as CloseEvent).code).toBe(4444);
expect((err as CloseEvent).reason).toBe('Is fatal?');
return false;
},
}),
{
query: 'subscription { ping }',
},
);

await server.waitForClient((client) => {
client.close(4444, 'Is fatal?');
});

await sub.waitForError((err) => {
expect((err as CloseEvent).code).toBe(4444);
}, 20);
});

it('should report fatal connection problems immediately (using deprecated `isFatalConnectionProblem`)', async () => {
const { url, ...server } = await startTServer();

const sub = tsubscribe(
createClient({
url,
Expand Down
25 changes: 23 additions & 2 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,23 @@ export interface ClientOptions<
*/
retryWait?: (retries: number) => Promise<void>;
/**
* Check if the close event or connection error is fatal. If you return `false`,
* the client will fail immediately without additional retries; however, if you
* return `true`, the client will keep retrying until the `retryAttempts` have
* been exceeded.
*
* The argument is whatever has been thrown during the connection phase.
*
* Beware, the library classifies a few close events as fatal regardless of
* what is returned here. They are listed in the documentation of the `retryAttempts`
* option.
*
* @default 'Only `CloseEvent`s'
*/
shouldRetry?: (errOrCloseEvent: unknown) => boolean;
/**
* @deprecated Use `shouldRetry` instead.
*
* Check if the close event or connection error is fatal. If you return `true`,
* the client will fail immediately without additional retries; however, if you
* return `false`, the client will keep retrying until the `retryAttempts` have
Expand All @@ -367,7 +384,7 @@ export interface ClientOptions<
* what is returned. They are listed in the documentation of the `retryAttempts`
* option.
*
* @default 'Any non-CloseEvent'
* @default 'Any non-`CloseEvent`'
*/
isFatalConnectionProblem?: (errOrCloseEvent: unknown) => boolean;
/**
Expand Down Expand Up @@ -470,6 +487,7 @@ export function createClient<
),
);
},
shouldRetry = isLikeCloseEvent,
isFatalConnectionProblem = (errOrCloseEvent) =>
// non `CloseEvent`s are fatal by default
!isLikeCloseEvent(errOrCloseEvent),
Expand Down Expand Up @@ -827,7 +845,10 @@ export function createClient<
// retries are not allowed or we tried to many times, report error
if (!retryAttempts || retries >= retryAttempts) throw errOrCloseEvent;

// throw fatal connection problems immediately
// throw non-retryable connection problems
if (!shouldRetry(errOrCloseEvent)) throw errOrCloseEvent;

// @deprecated throw fatal connection problems immediately
if (isFatalConnectionProblem(errOrCloseEvent)) throw errOrCloseEvent;

// looks good, start retrying
Expand Down

0 comments on commit d8dcf21

Please sign in to comment.