diff --git a/docs/v1/getting-started.md b/docs/v1/getting-started.md index 6a8d3e6..825a19f 100644 --- a/docs/v1/getting-started.md +++ b/docs/v1/getting-started.md @@ -21,6 +21,7 @@ The client focuses on predictable behavior, extensibility, and a clean developer - structured error classes - auth support - lifecycle hooks +- retry support - custom `fetch` support ## Quick example @@ -46,16 +47,46 @@ console.log(user.name); ## How requests work -A request in `@dfsync/client` follows this flow: +A request in `@dfsync/client` goes through the following lifecycle: -1. build final URL from `baseUrl`, `path`, and optional query params -2. merge default, client-level, and request-level headers -3. apply auth configuration -4. run `beforeRequest` hooks -5. send request with `fetch` -6. parse response as JSON, text, or `undefined` for `204` -7. throw structured errors for failed requests -8. run `afterResponse` or `onError` hooks +1. Build request URL + + The final URL is constructed from `baseUrl`, `path`, and optional query parameters. + +2. Merge headers + + Default headers, client-level headers, and request-level headers are combined. + +3. Apply authentication + + The configured auth strategy (Bearer, API key, or custom) is applied to the request. + +4. Run `beforeRequest` hooks + + Hooks can modify the request before it is sent. + +5. Execute the HTTP request + + The request is sent using the Fetch API. + +6. Retry if necessary + + If the request fails with a retryable error, it may be retried according to the configured retry policy. + +7. Parse the response + + The response body is parsed automatically: + - JSON → parsed object + - text → string + - `204 No Content` → `undefined` + +8. Handle errors + + Non-success responses and network failures are converted into structured errors. + +9. Run response hooks + - `afterResponse` runs for successful responses + - `onError` runs when an error occurs ## Runtime requirements diff --git a/docs/v1/retry.md b/docs/v1/retry.md index e69de29..fd8b6ff 100644 --- a/docs/v1/retry.md +++ b/docs/v1/retry.md @@ -0,0 +1,179 @@ +# Retry + +`@dfsync/client` supports configurable retry policies for transient failures. + +Retries are useful when communicating with external services that may temporarily fail or return `5xx` responses. + +The retry behavior can be configured globally for the client or overridden per request. + +--- + +## Basic retry configuration + +```ts +import { createClient } from '@dfsync/client'; + +const client = createClient({ + baseUrl: 'https://api.example.com', + retry: { + attempts: 2, + }, +}); +``` + +If a retryable error occurs, the request will be retried up to the configured number of attempts. + +## Retry conditions + +By default, retries happen for: + +- network errors +- HTTP 5xx responses + +Example: + +```ts +const client = createClient({ + baseUrl: 'https://api.example.com', + retry: { + attempts: 3, + }, +}); +``` + +## Retry backoff + +Two retry strategies are supported: + +### Fixed delay + +```ts +const client = createClient({ + baseUrl: 'https://api.example.com', + retry: { + attempts: 3, + backoff: 'fixed', + baseDelayMs: 300, + }, +}); +``` + +Retry delays: + +```bash +300ms +300ms +300ms +``` + +### Exponential backoff + +```ts +const client = createClient({ + baseUrl: 'https://api.example.com', + retry: { + attempts: 3, + backoff: 'exponential', + baseDelayMs: 300, + }, +}); +``` + +Retry delays: + +```bash +300ms +600ms +1200ms +``` + +If `attempts` is `0` (default), no retries are performed and retry delays are ignored. + +## Retry methods + +By default retries apply to: + +- `GET` +- `PUT` +- `DELETE` + +POST requests are **not retried by default**. + +Example enabling POST retries: + +```ts +const client = createClient({ + baseUrl: 'https://api.example.com', + retry: { + attempts: 2, + retryMethods: ['GET', 'POST'], + }, +}); +``` + +## Retry conditions configuration + +You can control which errors trigger retries. + +Supported conditions: + +- network-error +- 5xx +- 429 + +Example: + +```ts +const client = createClient({ + baseUrl: 'https://api.example.com', + retry: { + attempts: 2, + retryOn: ['network-error', '5xx', '429'], + }, +}); +``` + +## Per-request retry override + +Request-level configuration overrides the client configuration. + +```ts +await client.get('/users', { + retry: { + attempts: 1, + }, +}); +``` + +## Retry and hooks + +Hooks behave as follows when retries are enabled: + +| Hook | Behavior | +| --------------- | ------------------------------------- | +| `beforeRequest` | executed on every retry attempt | +| `afterResponse` | executed only on successful response | +| `onError` | executed once after the final failure | + +Example: + +```ts +const client = createClient({ + baseUrl: 'https://api.example.com', + retry: { attempts: 2 }, + hooks: { + onError(ctx) { + console.error(ctx.error); + }, + }, +}); +``` + +## Summary + +Retry is designed for **safe and predictable service-to-service communication** and works well for: + +- microservices +- external APIs +- background workers +- integration services diff --git a/index.html b/index.html index 0acd386..1276cab 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - dfsync — Reliable HTTP client for Node.js Microservices + dfsync — Reliable HTTP communication for Node.js environments. , - title: 'Auth & lifecycle hooks', - description: - 'Built-in support for bearer tokens, API keys, and request lifecycle hooks like beforeRequest, afterResponse, and onError.', + icon: , + title: 'Auth support', + description: 'Built-in support for bearer tokens, API keys, and custom auth flows.', + }, + { + icon: , + title: 'Retry support', + description: 'Built-in configurable retry policies for transient failures.', + }, + { + icon: , + title: 'Lifecycle hooks', + description: 'Built-in request lifecycle hooks like beforeRequest, afterResponse, and onError.', }, { icon: , @@ -36,11 +47,11 @@ export const Features = () => { - Why dfsync + Why @dfsync/client - A focused foundation for dependable HTTP communication between services — with sensible - defaults, auth strategies, and lifecycle hooks. + A lightweight HTTP client for service-to-service communication, with sensible defaults, + authentication strategies, lifecycle hooks, and retry support. diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx index 7e1a8c7..329fd05 100644 --- a/src/components/Footer/Footer.tsx +++ b/src/components/Footer/Footer.tsx @@ -31,7 +31,7 @@ export const Footer = () => { npm {