npm package: @mukulchavan/resilient-http
Description: A smart wrapper around fetch/axios that adds controlled retries, backoff strategies, circuit breaker pattern, and failure metrics
Latest version: 1.0.0

# resilient-http

A smart wrapper around `fetch` and `axios` that adds controlled retries, backoff strategies, circuit breaker pattern, and failure metrics - all with minimal code changes.

## 🎯 The Problem

APIs fail all the time:
- Temporary network glitches
- 502 / 503 / 504 from backend
- Cold starts
- Rate limiting
- Partial outages

**What teams usually do:**
```javascript
try {
  await axios.get('/api/data');
} catch (e) {
  await axios.get('/api/data'); // naive retry
}
```

**Problems:**
- ❌ No backoff → thundering herd
- ❌ Infinite retries
- ❌ No failure tracking
- ❌ Can bring down entire system

## ✨ What This Library Does

A smart wrapper that adds:
- ✅ Controlled retries
- ✅ Backoff strategies (fixed, linear, exponential, jitter)
- ✅ Circuit breaker pattern
- ✅ Failure metrics

All with one line of code.

## 🔌 What Is a Circuit Breaker?

Think of it like MCB (Miniature Circuit Breaker) in your house.

| State | Meaning |
|-------|---------|
| **Closed** | API working → requests allowed |
| **Open** | API failing → requests blocked |
| **Half-Open** | Try few requests to test recovery |

**Why it matters:**
- Prevents hitting already failing services
- Saves latency & infra cost
- Improves user experience

## 📦 Installation

```bash
npm install resilient-http
```

## 🚀 Usage

### Fetch Example

```javascript
import { resilientFetch } from 'resilient-http';

const response = await resilientFetch('/api/orders', {
  retries: 3,
  backoff: 'exponential',
  retryOn: [502, 503, 504],
  circuitBreaker: {
    failureThreshold: 5,
    resetTimeout: 30000
  }
});

const data = await response.json();
```

### Axios Example

```javascript
import { createResilientAxios } from 'resilient-http';

const api = createResilientAxios({
  retries: 2,
  backoff: 'linear'
});

// Use it like regular axios
const response = await api.get('/products');
```

### With Metrics Hooks

```javascript
import { resilientFetch } from 'resilient-http';

const response = await resilientFetch('/api/data', {
  retries: 3,
  backoff: 'exponential',
  onRetry: ({ url, attempt, error }) => {
    console.log(`Retrying ${url} (attempt ${attempt})`);
  },
  onOpen: (url) => {
    console.log(`Circuit breaker opened for ${url}`);
  },
  onClose: (url) => {
    console.log(`Circuit breaker closed for ${url}`);
  }
});
```

## ⚙️ Configuration

### Retry Configuration

```typescript
interface RetryConfig {
  retries?: number;              // Number of retries (default: 3)
  backoff?: 'fixed' | 'linear' | 'exponential' | 'jitter';  // Backoff strategy (default: 'exponential')
  retryOn?: number[];            // HTTP status codes to retry on (default: [502, 503, 504])
  initialDelay?: number;         // Initial delay in ms (default: 500)
  maxDelay?: number;             // Maximum delay in ms (default: 30000)
  timeout?: number;              // Request timeout in ms (default: 0 = no timeout)
}
```

### Circuit Breaker Configuration

```typescript
interface CircuitBreakerConfig {
  failureThreshold?: number;     // Errors before opening circuit (default: 5)
  successThreshold?: number;     // Successes to close circuit in half-open (default: 2)
  resetTimeout?: number;         // Wait before half-open in ms (default: 30000)
}
```

### Backoff Strategies

| Type | Example Delays |
|------|----------------|
| **Fixed** | 500ms, 500ms, 500ms |
| **Linear** | 500ms, 1000ms, 1500ms |
| **Exponential** | 500ms, 1000ms, 2000ms, 4000ms |
| **Jitter** | Randomized exponential (reduces thundering herd) |

## 🔄 Retry Logic

### Retry Conditions

- Network errors (connection failures)
- HTTP status codes in `retryOn` list
- Timeout errors

### Backoff Calculation

The library automatically calculates delays based on the selected strategy:

- **Fixed**: Always uses `initialDelay`
- **Linear**: `initialDelay * attempt`
- **Exponential**: `initialDelay * 2^(attempt - 1)`
- **Jitter**: Exponential with random variation (30% jitter)

## 🔌 Circuit Breaker Logic

### How It Works

1. Track failures per endpoint
2. If failures ≥ `failureThreshold` → **OPEN**
3. Block calls immediately (fast fail)
4. After `resetTimeout` → **HALF-OPEN**
5. Test with limited calls
6. If `successThreshold` successes → **CLOSED**
7. If any failure → **OPEN** again

### Example Configuration

```javascript
{
  failureThreshold: 5,     // 5 errors before opening circuit
  successThreshold: 2,     // 2 successes to close circuit
  resetTimeout: 30000      // wait 30s before half-open
}
```

## 📊 Metrics Hooks

Track retries and circuit breaker state changes:

```javascript
{
  onRetry: ({ url, attempt, error, statusCode }) => {
    // Called on each retry attempt
  },
  onOpen: (url) => {
    // Called when circuit breaker opens
  },
  onClose: (url) => {
    // Called when circuit breaker closes
  }
}
```

## 🏗️ Architecture

### Components

1. **Request Wrapper** - Wraps fetch/axios calls, handles retries
2. **Retry Engine** - Determines if retry is allowed, calculates delay
3. **Circuit Store** - Maintains per-endpoint state (memory-based)
4. **Metrics Hook** - Callbacks for monitoring

## 📝 TypeScript Support

Full TypeScript support with type definitions included:

```typescript
import { resilientFetch, ResilientConfig } from 'resilient-http';

const config: ResilientConfig = {
  retries: 3,
  backoff: 'exponential',
  circuitBreaker: {
    failureThreshold: 5,
    resetTimeout: 30000
  }
};

const response = await resilientFetch('/api/data', config);
```

## 🧪 Testing

### Running Tests

```bash
# Install dependencies
npm install

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage
```

### Test Structure

The test suite includes:
- ✅ Backoff strategy tests (fixed, linear, exponential, jitter)
- ✅ Circuit breaker state transitions
- ✅ Retry logic and conditions
- ✅ Fetch wrapper integration
- ✅ Axios wrapper integration
- ✅ Metrics hooks verification

### Manual Testing

You can also test the library manually using the provided test script:

```bash
# Build the project first
npm run build

# Then run manual tests (requires ts-node)
npx ts-node test-manual.ts
```

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## 📄 License

MIT