Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Patterns for building resilient API clients and real-time connections with retry logic, circuit breakers, and graceful degradation. Use when building production systems that need to handle failures. Triggers on retry logic, circuit breaker, connection resilience, exponential backoff, API client, fault tolerance.
Patterns for building resilient API clients and real-time connections with retry logic, circuit breakers, and graceful degradation. Use when building production systems that need to handle failures. Triggers on retry logic, circuit breaker, connection resilience, exponential backoff, API client, fault tolerance.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
Build API clients and real-time connections that handle failures gracefully with retries, circuit breakers, and fallbacks.
npx clawhub@latest install resilient-connections
Building API clients that need to handle transient failures Real-time connections that should reconnect automatically Systems that need graceful degradation Any production system calling external services
interface RetryOptions { maxRetries: number; baseDelay: number; maxDelay: number; jitter?: boolean; } async function withRetry<T>( fn: () => Promise<T>, options: RetryOptions ): Promise<T> { const { maxRetries, baseDelay, maxDelay, jitter = true } = options; for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await fn(); } catch (error) { if (attempt === maxRetries) throw error; // Calculate delay with exponential backoff let delay = Math.min(baseDelay * 2 ** attempt, maxDelay); // Add jitter to prevent thundering herd if (jitter) { delay = delay * (0.5 + Math.random()); } await sleep(delay); } } throw new Error('Unreachable'); } // Usage const data = await withRetry( () => fetch('/api/data').then(r => r.json()), { maxRetries: 3, baseDelay: 1000, maxDelay: 30000 } );
enum CircuitState { Closed, // Normal operation Open, // Failing, reject requests HalfOpen, // Testing if recovered } class CircuitBreaker { private state = CircuitState.Closed; private failures = 0; private lastFailure = 0; constructor( private threshold: number = 5, private timeout: number = 30000 ) {} async execute<T>(fn: () => Promise<T>): Promise<T> { if (this.state === CircuitState.Open) { if (Date.now() - this.lastFailure > this.timeout) { this.state = CircuitState.HalfOpen; } else { throw new Error('Circuit breaker is open'); } } try { const result = await fn(); this.onSuccess(); return result; } catch (error) { this.onFailure(); throw error; } } private onSuccess() { this.failures = 0; this.state = CircuitState.Closed; } private onFailure() { this.failures++; this.lastFailure = Date.now(); if (this.failures >= this.threshold) { this.state = CircuitState.Open; } } }
interface FetchOptions extends RequestInit { timeout?: number; retries?: number; } async function resilientFetch( url: string, options: FetchOptions = {} ): Promise<Response> { const { timeout = 10000, retries = 3, ...fetchOptions } = options; const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); const fetchWithTimeout = async () => { try { const response = await fetch(url, { ...fetchOptions, signal: controller.signal, }); if (!response.ok && response.status >= 500) { throw new Error(`Server error: ${response.status}`); } return response; } finally { clearTimeout(timeoutId); } }; return withRetry(fetchWithTimeout, { maxRetries: retries, baseDelay: 1000, maxDelay: 10000, }); }
class ReconnectingWebSocket { private ws: WebSocket | null = null; private retries = 0; private maxRetries = 10; constructor( private url: string, private onMessage: (data: unknown) => void ) { this.connect(); } private connect() { this.ws = new WebSocket(this.url); this.ws.onopen = () => { this.retries = 0; }; this.ws.onmessage = (event) => { this.onMessage(JSON.parse(event.data)); }; this.ws.onclose = () => { if (this.retries < this.maxRetries) { const delay = Math.min(1000 * 2 ** this.retries, 30000); this.retries++; setTimeout(() => this.connect(), delay); } }; } send(data: unknown) { if (this.ws?.readyState === WebSocket.OPEN) { this.ws.send(JSON.stringify(data)); } } close() { this.maxRetries = 0; // Prevent reconnection this.ws?.close(); } }
async function fetchWithFallback<T>( primary: () => Promise<T>, fallback: () => Promise<T>, cache?: T ): Promise<T> { try { return await primary(); } catch (primaryError) { console.warn('Primary failed, trying fallback:', primaryError); try { return await fallback(); } catch (fallbackError) { console.warn('Fallback failed:', fallbackError); if (cache !== undefined) { console.warn('Using cached data'); return cache; } throw fallbackError; } } } // Usage const data = await fetchWithFallback( () => fetchFromPrimaryAPI(), () => fetchFromBackupAPI(), cachedData );
Meta-skill: ai/skills/meta/realtime-dashboard/ โ Complete realtime dashboard guide realtime-react-hooks โ Hook usage websocket-hub-patterns โ Server patterns
NEVER retry non-idempotent requests โ POST/PUT might succeed but fail to respond NEVER use fixed delays โ Always add jitter to prevent thundering herd NEVER retry 4xx errors โ Client errors won't resolve themselves NEVER keep circuit open forever โ Always have a timeout to half-open NEVER hide connection failures โ Show users the degraded state
// Exponential backoff const delay = Math.min(baseDelay * 2 ** attempt, maxDelay); // With jitter const jitteredDelay = delay * (0.5 + Math.random()); // Retry check const shouldRetry = error.status >= 500 || error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET'; // Circuit breaker states Closed -> (failures >= threshold) -> Open Open -> (timeout elapsed) -> HalfOpen HalfOpen -> (success) -> Closed HalfOpen -> (failure) -> Open
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.