Initial Commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# constant
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Provides `createConstantBackoff`, a factory that creates a retry strategy returning a fixed, unchanging delay for every attempt. Constant backoff is the simplest possible strategy: every retry waits the same number of milliseconds before the next call. This is useful when the failure mode does not benefit from increasing delays (e.g., transient network hiccups with known recovery windows) and when predictable timing is more important than reducing thundering-herd pressure.
|
||||
|
||||
The returned function satisfies the `RetryStrategy` interface (`(attempt: number) => number`) and can be passed directly to `RetryConfig.delay` or any helper that accepts a strategy.
|
||||
|
||||
## Features
|
||||
|
||||
- Zero allocation per call — closure captures delay once at factory time
|
||||
- Deterministic: no randomness, no clock dependency
|
||||
- Composable with `applyJitter` for external jitter if needed
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```typescript
|
||||
import { createConstantBackoff } from "@suaveplan/retry";
|
||||
import { withRetry } from "@suaveplan/retry";
|
||||
|
||||
const strategy = createConstantBackoff({ delay: 200 });
|
||||
|
||||
const result = await withRetry(fetchUser, {
|
||||
maxAttempts: 5,
|
||||
delay: strategy,
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```typescript
|
||||
import { createConstantBackoff, applyJitter } from "@suaveplan/retry";
|
||||
|
||||
const base = createConstantBackoff({ delay: 500 });
|
||||
|
||||
// Wrap with full jitter externally to spread retries under load
|
||||
const withJitter = (attempt: number) => applyJitter(base(attempt), "full");
|
||||
|
||||
await withRetry(sendEmail, {
|
||||
maxAttempts: 10,
|
||||
delay: withJitter,
|
||||
shouldRetry: (err) => isTransient(err),
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `createConstantBackoff(opts)`
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `opts.delay` | `number` | Fixed delay in milliseconds returned for every attempt. |
|
||||
|
||||
**Returns:** `RetryStrategy` — `(attempt: number) => number`. The `attempt` argument is ignored.
|
||||
|
||||
**Throws:** Nothing.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The factory captures `delay` in a closure at construction time rather than reading from `opts` on each call, which avoids one property lookup per retry. The returned arrow function is a single expression with no branching, making it trivially inlineable by JIT compilers. For scenarios where the delay needs to vary per environment, the recommended pattern is to construct a new strategy at startup with the environment-configured value rather than mutating options at runtime.
|
||||
@@ -0,0 +1,32 @@
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import { createConstantBackoff } from "./constant.js";
|
||||
|
||||
describe("createConstantBackoff", () => {
|
||||
it("returns the same delay for attempt 1", { timeout: 5000 }, () => {
|
||||
const strategy = createConstantBackoff({ delay: 100 });
|
||||
expect(strategy(1)).toBe(100);
|
||||
});
|
||||
|
||||
it("returns the same delay for every attempt", { timeout: 5000 }, () => {
|
||||
const strategy = createConstantBackoff({ delay: 250 });
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
expect(strategy(i)).toBe(250);
|
||||
}
|
||||
});
|
||||
|
||||
it("works with delay of 0", { timeout: 5000 }, () => {
|
||||
const strategy = createConstantBackoff({ delay: 0 });
|
||||
expect(strategy(1)).toBe(0);
|
||||
expect(strategy(5)).toBe(0);
|
||||
});
|
||||
|
||||
it("works with large delays", { timeout: 5000 }, () => {
|
||||
const strategy = createConstantBackoff({ delay: 60_000 });
|
||||
expect(strategy(100)).toBe(60_000);
|
||||
});
|
||||
|
||||
it("ignores attempt number", { timeout: 5000 }, () => {
|
||||
const strategy = createConstantBackoff({ delay: 500 });
|
||||
expect(strategy(1)).toBe(strategy(999));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import type {
|
||||
ConstantBackoffOptions,
|
||||
RetryStrategy,
|
||||
} from "../../types/retry.types.js";
|
||||
|
||||
/**
|
||||
* Creates a retry strategy that always returns the same fixed delay.
|
||||
*
|
||||
* @param opts - `{ delay }` — fixed delay in milliseconds.
|
||||
* @returns A `RetryStrategy` that ignores the attempt number.
|
||||
*/
|
||||
export function createConstantBackoff(
|
||||
opts: ConstantBackoffOptions
|
||||
): RetryStrategy {
|
||||
const { delay } = opts;
|
||||
return (_attempt: number): number => delay;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { createConstantBackoff } from "./constant";
|
||||
Reference in New Issue
Block a user