Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

(docs) - Add docs for the retryExchange (#599)

* add docs for the retry-exchange

* Apply suggestions from code review

Co-Authored-By: Will Golledge <35961363+wgolledge@users.noreply.github.com>

* Put retryExchange options into a list, add a list of available exchanges to concepts/core

* move order of retryExchange in docs so that it sits between the cacheExchange and fetchExchange

* create new retryExchange api page

* Add introduction and rename file

* Add missing order key to retry API page

* Add missing link to API index page

Co-authored-by: Will Golledge <35961363+wgolledge@users.noreply.github.com>
Co-authored-by: wgolledge <wiggiumg@gmail.com>
Co-authored-by: Phil Pluckthun <phil@kitten.sh>

authored by

Jovi De Croock
Will Golledge
wgolledge
Phil Pluckthun
and committed by
GitHub
541bcaa3 8506ea17

+128 -63
+1
docs/advanced/README.md
··· 14 14 - [**Server-side Rendering**](./server-side-rendering.md) guides us through how to set up server-side rendering and rehydration. 15 15 - [**Auto-populate Mutations**](./auto-populate-mutations.md) presents the `populateExchange` addon which can make it easier to 16 16 update normalized data after mutations. 17 + - [**Retrying operations**](./retry-operations.md) shows the `retryExchange` which allows you to retry operations when they've failed. 17 18 - [**Testing**](./testing.md) covers how to test components that use `urql` particularly in React.
+93
docs/advanced/retry-operations.md
··· 1 + --- 2 + title: Retrying Operations 3 + order: 4 4 + --- 5 + 6 + # Retrying Operations 7 + 8 + The `retryExchange` lets us retry specific operation, by default it will 9 + retry only network errors but we can specify additional options to add 10 + functionality. 11 + 12 + ## Installation and Setup 13 + 14 + First install `@urql/exchange-retry` alongside `urql`: 15 + 16 + ```sh 17 + yarn add @urql/exchange-retry 18 + # or 19 + npm install --save @urql/exchange-retry 20 + ``` 21 + 22 + You'll then need to add the `retryExchange`, exposed by this package, to your `urql` Client: 23 + 24 + ```js 25 + import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql'; 26 + import { retryExchange } from '@urql/exchange-retry'; 27 + 28 + // None of these options have to be added, these are the default values. 29 + const options = { 30 + initialDelayMs: 1000, 31 + maxDelayMs: 15000, 32 + randomDelay: true, 33 + maxNumberAttempts: 2, 34 + retryIf: err => err && err.networkError, 35 + }; 36 + 37 + // Note the position of the retryExchange - it should be placed prior to the 38 + // fetchExchange and after the cacheExchange for it to function correctly 39 + const client = createClient({ 40 + url: 'http://localhost:1234/graphql', 41 + exchanges: [ 42 + dedupExchange, 43 + cacheExchange, 44 + retryExchange(options), // Use the retryExchange factory to add a new exchange 45 + fetchExchange, 46 + ], 47 + }); 48 + ``` 49 + 50 + We want to place the `retryExchange` after the `fetchExchange` so that retries are only performed _after_ the operation has passed through the cache and has attempted to fetch. 51 + 52 + ## The Options 53 + 54 + There are a set of optional options that allow for fine-grained control over the `retry` mechanism. 55 + 56 + We have the `initialDelayMs` to specify at what interval the `retrying` should start, this means that if we specify `1000` that when our `operation` fails we'll wait 1 second and then retry it. 57 + 58 + Next up is the `maxDelayMs`, our `retryExchange` will keep increasing the time between retries so we don't spam our server with requests it can't complete, this option ensures we don't exceed a certain threshold. This time between requests will increase with a random `back-off` factor multiplied by the `initialDelayMs`, read more about the [thundering herd problem](https://en.wikipedia.org/wiki/Thundering_herd_problem). 59 + 60 + Talking about increasing the `delay` randomly, `randomDelay` allows us to disable this. When this option is set to `false` we'll only increase the time between attempts with the `initialDelayMs`. This means if we fail the first time we'll have 1 second wait, next fail we'll have 2 seconds and so on. 61 + 62 + We don't want to infinitley attempt an `operation`, we can declare how many times it should attempt the `operation` with `maxNumberAttempts`. 63 + 64 + [For more information on the available options check out the API Docs.](../api/retry-exchange.md) 65 + 66 + ## Reacting to Different Errors 67 + 68 + We can introduce specific triggers for the `retryExchange` to start retrying operations, 69 + let's look at an example: 70 + 71 + ```js 72 + import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql'; 73 + import { retryExchange } from '@urql/exchange-retry'; 74 + 75 + const client = createClient({ 76 + url: 'http://localhost:1234/graphql', 77 + exchanges: [ 78 + dedupExchange, 79 + cacheExchange, 80 + fetchExchange, 81 + retryExchange({ 82 + retryIf: error => { 83 + if ((error && error.graphQLErrors.length > 0) || error.networkError) { 84 + return true; 85 + } 86 + }, 87 + }), 88 + ], 89 + }); 90 + ``` 91 + 92 + In the above example we'll retry when we have `graphQLErrors` or a `networkError`, we can go 93 + more granular and check for certain errors in `graphQLErrors`.
+1 -1
docs/advanced/testing.md
··· 1 1 --- 2 2 title: Testing 3 - order: 4 3 + order: 5 4 4 --- 5 5 6 6 # Testing
+1
docs/api/README.md
··· 15 15 - [`urql` React API docs](./urql.md) 16 16 - [`@urql/preact` Preact API docs](./preact.md) 17 17 - [`@urql/exchange-graphcache` API docs](./graphcache.md) 18 + - [`@urql/exchange-retry` API docs](./retry-exchange.md)
+1 -1
docs/api/core.md
··· 204 204 | meta | `?OperationDebugMeta` | Metadata that is only available in development for devtools. | 205 205 | suspense | `?boolean` | Whether suspense is enabled. | 206 206 | preferGetMethod | `?number` | Instructs the `fetchExchange` to use HTTP GET for queries. | 207 - | additionalTypenames | `?number` | Allows you to tell the operation that it depends on certain typenames (used in document-cache.) | 207 + | additionalTypenames | `?number` | Allows you to tell the operation that it depends on certain typenames (used in document-cache.) | 208 208 209 209 It also accepts additional, untyped parameters that can be used to send more 210 210 information to custom exchanges.
+23
docs/api/retry-exchange.md
··· 1 + --- 2 + title: @urql/exchange-retry 3 + order: 4 4 + --- 5 + 6 + # Retry Exchange 7 + 8 + The `@urql/exchange-retry` package contains an addon `retryExchange` for `urql` that may be used to 9 + let failed operations be retried, typically when a previous operation has failed with a network 10 + error. 11 + 12 + [Read more about how to use and configure the `retryExchange` on the "Retry Operations" 13 + page.](../advanced/retry-operations.md) 14 + 15 + ## Options 16 + 17 + | Option | Description | 18 + | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 19 + | `initialDelayMs` | Specify at what interval the `retrying` should start, this means that if we specify `1000` that when our `operation` fails we'll wait 1 second and then retry it. | 20 + | `maxDelayMs` | The maximum delay between retries. The `retryExchange` will keep increasing the time between retries so that the server doesn't receive simultaneous requests it can't complete. This time between requests will increase with a random `back-off` factor applied to the `initialDelayMs`, read more about the [thundering herd problem](https://en.wikipedia.org/wiki/Thundering_herd_problem). | 21 + | `randomDelay` | Allows the randomized delay described above to be disabled. When this option is set to `false` there will be exactly a `initialDelayMs` wait between each retry. | 22 + | `maxNumberAttempts` | Allows the max number of retries to be defined. | 23 + | `retryIf` | Apply a custom test to the returned error to determine whether it should be retried. |
+7
docs/concepts/exchanges.md
··· 20 20 - `cacheExchange`: The default caching logic with ["Document Caching"](../basics/document-caching.md) 21 21 - `fetchExchange`: Sends an operation to the API using `fetch` and adds results to the output stream 22 22 23 + Other available exchanges: 24 + 25 + - `retryExchange`: Allows operations to be retried 26 + - `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/FormidableLabs/urql-devtools) 27 + - `multipartFetchExchange`: Provides multipart file upload capability 28 + - `suspenseExchange` (experimental): Allows the use of React Suspense on the client-side with `urql`'s built-in suspense mode 29 + 23 30 It is also possible to apply custom exchanges to override the default logic. 24 31 25 32 ## An Exchange Signature
+1 -61
exchanges/retry/README.md
··· 2 2 3 3 `@urql/exchange-retry` is an exchange for the [`urql`](../../README.md) GraphQL client that allows operations (queries, mutations, subscriptions) to be retried based on an `options` parameter. 4 4 5 - The `retryExchange` is of type `Options => Exchange`. 6 - 7 - It periodically retries requests that fail due to network errors. It accepts five optional options: 8 - 9 - - `initialDelayMs` - the minimum delay between retries, defaults to 1000 10 - - `maxDelayMs` - the maximum delay that can be applied to an operation, defaults to 15000 11 - - `randomDelay` - whether to apply a random delay to protect against thundering herd, defaults to true 12 - - `maxNumberAttempts` - the maximum number of attempts to retry any given operation, defaults to Infinity 13 - - `retryIf` - optional function to apply to errors to determine whether they should be retried 14 - 15 - The `retryExchange` will exponentially increase the delay from `minDelayMs` up to `maxDelayMs` with some random jitter added to avoid the [thundering herd problem](https://en.wikipedia.org/wiki/Thundering_herd_problem). 16 - 17 5 ## Quick Start Guide 18 6 19 7 First install `@urql/exchange-retry` alongside `urql`: ··· 24 12 npm install --save @urql/exchange-retry 25 13 ``` 26 14 27 - You'll then need to add the `retryExchange`, that this package exposes, to your 28 - `urql` Client: 29 - 30 - ```js 31 - import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql'; 32 - import { retryExchange } from '@urql/exchange-retry'; 33 - 34 - const options = { 35 - initialDelayMs: 50, 36 - maxDelayMs: 500, 37 - randomDelay: true, 38 - maxNumberAttempts: 10, 39 - retryIf: err => err.message === '[GraphQL] Error Message A', 40 - }; 41 - 42 - const client = createClient({ 43 - url: 'http://localhost:1234/graphql', 44 - exchanges: [ 45 - dedupExchange, 46 - cacheExchange, 47 - fetchExchange, 48 - retryExchange(options), // Use the retryExchange factory to add a new exchange 49 - ], 50 - }); 51 - ``` 52 - 53 - You'll likely want to place the `retryExchange` after the `fetchExchange` so that retries are only performed _after_ the operation has passed through the cache and has attempted to fetch. 54 - 55 - ## Usage 56 - 57 - After installing `@urql/exchange-retry` and adding it to your `urql` client, `urql` will retry operations based on the options passed to the `retryExchange`. 58 - 59 - ```js 60 - import React from 'react'; 61 - import { useQuery } from 'urql'; 62 - 63 - const LoadingIndicator = () => <h1>Loading...</h1>; 64 - 65 - const YourContent = () => { 66 - const [{ fetching, data }] = useQuery({ query: allPostsQuery }); 67 - // Unlike a normal query, if the first request resulted in an error, 68 - // the query will be automatically retried based on the `retryExchange` options 69 - return !fetching && <div>{data}</div>; 70 - }; 71 - 72 - return <YourContent />; 73 - ``` 74 - 75 - <!-- TODO?: Add code sandbox demo --> 15 + Read more about the [retry exchange](https://formidable.com/open-source/urql/docs/advanced/retry-operations).