Skip to main content

Getting Started with Resilience

This guide walks you through the most common use cases for the Resilience library, from simple function wrapping to adding retries and timeouts.
1

Wrapping Your First Function

Start by wrapping an async function with basic resilience features. The withResilience function converts any function into a resilient version.
import { withResilience } from '@oldwhisper/resilience';

async function fetchUserData(userId: string) {
  const response = await fetch(`/api/users/${userId}`);
  return response.json();
}

// Wrap it with resilience
const resilientFetch = withResilience(fetchUserData, {
  name: 'fetchUserData',
  timeoutMs: 5000 // 5 second timeout
});

// Use it like the original function
const userData = await resilientFetch('user-123');
The withResilience function always returns an async function, even if your original function is synchronous.
2

Adding Retries

Network calls can fail temporarily. Add automatic retries to handle transient failures:
const resilientFetch = withResilience(fetchUserData, {
  name: 'fetchUserData',
  retries: 3, // Retry up to 3 times
  timeoutMs: 5000
});
This will attempt the function up to 4 times total (1 initial attempt + 3 retries) before throwing an error.
3

Configuring Backoff Strategies

Add delays between retries to avoid overwhelming a failing service.
Wait the same amount of time between each retry:
const resilientFetch = withResilience(fetchUserData, {
  name: 'fetchUserData',
  retries: 3,
  backoff: {
    type: 'fixed',
    delayMs: 1000 // Wait 1 second between retries
  }
});
4

Combining Features

Combine timeouts, retries, and backoff for robust error handling:
import { withResilience } from '@oldwhisper/resilience';

async function callExternalAPI(endpoint: string) {
  const response = await fetch(`https://api.example.com${endpoint}`);
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }
  return response.json();
}

const resilientAPICall = withResilience(callExternalAPI, {
  name: 'externalAPI',
  timeoutMs: 3000,      // Timeout after 3 seconds
  retries: 3,           // Retry 3 times
  backoff: {
    type: 'exponential',
    baseDelayMs: 200,
    maxDelayMs: 5000,
    jitter: true
  }
});

try {
  const data = await resilientAPICall('/data');
  console.log('Success:', data);
} catch (error) {
  console.error('Failed after retries:', error);
}
5

Using WrapperInit for Quick Setup

The WrapperInit class provides a convenient way to wrap functions with built-in metrics tracking:
import { WrapperInit } from '@oldwhisper/resilience';

const metrics = new WrapperInit();

// Wrap an async function
const resilientFetch = metrics.wrap(fetchUserData, {
  retries: 3,
  timeoutMs: 5000,
  backoff: { type: 'fixed', delayMs: 1000 }
});

await resilientFetch('user-123');

// Check metrics
console.log('Total calls:', metrics.functionCalls);
console.log('Calls per function:', metrics.f_store);
WrapperInit.wrap() automatically tracks function attempts and includes metrics hooks.

Common Patterns

Database Queries

import { withResilience } from '@oldwhisper/resilience';

async function queryDatabase(sql: string) {
  // Your database query logic
  return db.query(sql);
}

const resilientQuery = withResilience(queryDatabase, {
  name: 'dbQuery',
  timeoutMs: 10000,
  retries: 2,
  backoff: { type: 'fixed', delayMs: 500 }
});

API Calls

const resilientAPICall = withResilience(fetchData, {
  name: 'apiCall',
  timeoutMs: 5000,
  retries: 3,
  backoff: {
    type: 'exponential',
    baseDelayMs: 100,
    maxDelayMs: 3000,
    jitter: true
  }
});

Synchronous Functions

You can wrap synchronous functions too, but note they become async:
function calculateSum(a: number, b: number) {
  return a + b;
}

const resilientSum = withResilience(calculateSum, {
  name: 'sum',
  timeoutMs: 1000
});

// Must use await, even though the original is sync
const result = await resilientSum(5, 3);

Next Steps

Metrics Tracking

Learn how to track and monitor your resilient functions

Error Handling

Advanced error handling with retry filters and circuit breakers

Build docs developers (and LLMs) love