UNPKG

@magiceden/magiceden-sdk

Version:

A TypeScript SDK for interacting with Magic Eden's API across multiple chains.

88 lines (87 loc) 3.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isRetryableError = isRetryableError; exports.retryOperation = retryOperation; const ts_retry_promise_1 = require("ts-retry-promise"); const errors_1 = require("../../errors"); const errors_2 = require("../../errors"); const errors_3 = require("../../errors"); /** * Default retry configuration */ const DEFAULT_RETRY_CONFIG = { retries: 3, delay: 1000, timeout: 60000, // 1 minute total timeout maxBackOff: 30000, // 30 seconds max delay between retries backoff: (attempt, delay) => { // Exponential backoff with jitter to prevent thundering herd const calculatedDelay = delay * Math.pow(2, attempt); const jitter = calculatedDelay * 0.2 * Math.random(); // 20% jitter return Math.min(calculatedDelay + jitter, 30000); // Cap at 30 seconds }, retryIf: (error) => isRetryableError(error), }; /** * Determines if an error is retryable based on its type and properties */ function isRetryableError(error) { // Handle null/undefined errors if (!error) { return false; } // Always retry network errors (connection issues, timeouts) if (error instanceof errors_3.NetworkError) { return true; } // Always retry rate limit errors (with backoff) if (error instanceof errors_2.RateLimitError) { return true; } // Handle API errors based on status code if (error instanceof errors_1.ApiError) { const status = error.status; // Don't retry 4xx client errors (except those handled above like rate limits) if (status >= 400 && status < 500) { // Some 4xx errors might be worth retrying return (status === 400 || // Bad Request status === 408 || // Request Timeout status === 429); // Too Many Requests (should be caught by RateLimitError but just in case) } // Retry 5xx server errors if (status >= 500 && status < 600) { return true; } // By default, don't retry unknown errors return false; } return false; } /** * Retries an operation with exponential backoff * * @param operation The async function to retry * @param options Optional configuration to override defaults * @returns The result of the operation * @throws The last error encountered if all retries fail */ async function retryOperation(operation, options) { const mergedOptions = { ...DEFAULT_RETRY_CONFIG, ...options, }; try { return await (0, ts_retry_promise_1.retry)(operation, mergedOptions); } catch (error) { // Add retry information to the error message if (error instanceof Error) { const wasRetried = isRetryableError(error); const retries = wasRetried ? mergedOptions.retries || DEFAULT_RETRY_CONFIG.retries || 3 : 0; if (!error.message.includes('Failed after')) { error.message = `Failed after ${retries} ${retries === 1 ? 'retry' : 'retries'}: ${error.message}`; } } throw error; } }