Error recovery
Graceful error handling patterns.
Retry with exponential backoff
import { Mappa, RateLimitError, ApiError } from "@mappa-ai/mappa-node";
const mappa = new Mappa({
apiKey: process.env.MAPPA_API_KEY!,
});
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries = 3,
baseDelay = 1000
): Promise<T> {
let lastError: Error;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
// Don't retry client errors (except rate limits)
if (error instanceof ApiError && error.status < 500) {
if (!(error instanceof RateLimitError)) {
throw error;
}
}
// Calculate delay
let delay = baseDelay * Math.pow(2, attempt);
// Use Retry-After header if available
if (error instanceof RateLimitError && error.retryAfterMs) {
delay = error.retryAfterMs;
}
console.warn(`Attempt ${attempt + 1} failed, retrying in ${delay}ms`);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
throw lastError!;
}
// Usage
const report = await withRetry(() =>
mappa.reports.generateFromUrl({
url: "https://example.com/recording.mp3",
output: { template: "general_report" },
})
);
Circuit breaker pattern
class CircuitBreaker {
private failures = 0;
private lastFailure = 0;
private readonly threshold = 5;
private readonly resetTimeout = 60000;
async execute<T>(fn: () => Promise<T>): Promise<T> {
if (this.isOpen()) {
throw new Error("Circuit breaker is open");
}
try {
const result = await fn();
this.reset();
return result;
} catch (error) {
this.recordFailure();
throw error;
}
}
private isOpen(): boolean {
if (this.failures >= this.threshold) {
if (Date.now() - this.lastFailure > this.resetTimeout) {
this.reset();
return false;
}
return true;
}
return false;
}
private recordFailure(): void {
this.failures++;
this.lastFailure = Date.now();
}
private reset(): void {
this.failures = 0;
}
}
const breaker = new CircuitBreaker();
const report = await breaker.execute(() =>
mappa.reports.generateFromUrl({
url: "https://example.com/recording.mp3",
output: { template: "general_report" },
})
);