UNPKG

@gorbchain-xyz/chaindecode

Version:

GorbchainSDK V1.3+ - Complete Solana development toolkit with advanced cryptography, messaging, and collaboration features. Build secure applications with blockchain, DeFi, and end-to-end encryption.

290 lines (289 loc) 10.2 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { SDKError } from './base.js'; /** * Default retry options */ export const DEFAULT_RETRY_OPTIONS = { maxAttempts: 3, initialDelay: 1000, maxDelay: 30000, backoffMultiplier: 2, jitter: true, retryCondition: (error) => error instanceof SDKError && error.isRetryable(), onRetry: () => { // Default no-op } }; /** * Circuit breaker states */ export var CircuitBreakerState; (function (CircuitBreakerState) { CircuitBreakerState["CLOSED"] = "closed"; CircuitBreakerState["OPEN"] = "open"; CircuitBreakerState["HALF_OPEN"] = "half-open"; })(CircuitBreakerState || (CircuitBreakerState = {})); /** * Default circuit breaker options */ export const DEFAULT_CIRCUIT_BREAKER_OPTIONS = { failureThreshold: 5, resetTimeout: 60000, successThreshold: 2, monitoringWindow: 60000 }; /** * Circuit breaker implementation */ export class CircuitBreaker { constructor(options = {}) { this.state = CircuitBreakerState.CLOSED; this.failureCount = 0; this.successCount = 0; this.lastFailureTime = 0; this.options = Object.assign(Object.assign({}, DEFAULT_CIRCUIT_BREAKER_OPTIONS), options); } /** * Execute a function with circuit breaker protection */ execute(fn) { return __awaiter(this, void 0, void 0, function* () { if (this.state === CircuitBreakerState.OPEN) { if (Date.now() - this.lastFailureTime < this.options.resetTimeout) { throw new Error('Circuit breaker is open'); } this.state = CircuitBreakerState.HALF_OPEN; this.successCount = 0; } try { const result = yield fn(); this.onSuccess(); return result; } catch (error) { this.onFailure(); throw error; } }); } /** * Get current circuit breaker state */ getState() { return this.state; } /** * Reset circuit breaker to closed state */ reset() { this.state = CircuitBreakerState.CLOSED; this.failureCount = 0; this.successCount = 0; this.lastFailureTime = 0; } onSuccess() { this.failureCount = 0; if (this.state === CircuitBreakerState.HALF_OPEN) { this.successCount++; if (this.successCount >= this.options.successThreshold) { this.state = CircuitBreakerState.CLOSED; this.successCount = 0; } } } onFailure() { this.failureCount++; this.lastFailureTime = Date.now(); if (this.failureCount >= this.options.failureThreshold) { this.state = CircuitBreakerState.OPEN; } } } /** * Retry function with exponential backoff */ export function retry(fn_1) { return __awaiter(this, arguments, void 0, function* (fn, options = {}) { const config = Object.assign(Object.assign({}, DEFAULT_RETRY_OPTIONS), options); let lastError; // Ensure at least one attempt is made const attempts = Math.max(1, config.maxAttempts); for (let attempt = 1; attempt <= attempts; attempt++) { try { return yield fn(); } catch (error) { lastError = error; // Check if error is retryable if (!config.retryCondition(lastError)) { throw lastError; } // If this is the last attempt, throw the error if (attempt === attempts) { throw lastError; } // Calculate delay with exponential backoff const delay = calculateDelay(attempt, config); // Call onRetry callback config.onRetry(lastError, attempt); // Wait before retrying yield sleep(delay); } } throw lastError; }); } /** * Calculate retry delay with exponential backoff */ function calculateDelay(attempt, options) { const exponentialDelay = options.initialDelay * Math.pow(options.backoffMultiplier, attempt - 1); const delay = Math.min(exponentialDelay, options.maxDelay); if (options.jitter) { // Add jitter to prevent thundering herd const jitterRange = delay * 0.1; // 10% jitter const jitter = Math.random() * jitterRange * 2 - jitterRange; return Math.max(0, delay + jitter); } return delay; } /** * Sleep for the specified number of milliseconds */ function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Retry with circuit breaker */ export function retryWithCircuitBreaker(fn_1, circuitBreaker_1) { return __awaiter(this, arguments, void 0, function* (fn, circuitBreaker, retryOptions = {}) { return circuitBreaker.execute(() => __awaiter(this, void 0, void 0, function* () { return retry(fn, retryOptions); })); }); } /** * Batch retry - retry multiple operations with shared circuit breaker */ export function batchRetry(operations_1) { return __awaiter(this, arguments, void 0, function* (operations, options = {}) { const { retryOptions = {}, circuitBreakerOptions = {}, maxConcurrency = 5 } = options; const circuitBreaker = new CircuitBreaker(circuitBreakerOptions); // Limit concurrency const results = []; const chunks = chunkArray(operations, maxConcurrency); for (const chunk of chunks) { const chunkResults = yield Promise.all(chunk.map(op => retryWithCircuitBreaker(op, circuitBreaker, retryOptions))); results.push(...chunkResults); } return results; }); } /** * Chunk array into smaller arrays */ function chunkArray(array, chunkSize) { const chunks = []; for (let i = 0; i < array.length; i += chunkSize) { chunks.push(array.slice(i, i + chunkSize)); } return chunks; } /** * Retry decorator for class methods */ export function Retryable(options = {}) { return function (target, propertyKey, descriptor) { const originalMethod = descriptor.value; descriptor.value = function (...args) { return __awaiter(this, void 0, void 0, function* () { return retry(() => __awaiter(this, void 0, void 0, function* () { return originalMethod === null || originalMethod === void 0 ? void 0 : originalMethod.apply(this, args); }), options); }); }; return descriptor; }; } /** * Circuit breaker decorator for class methods */ export function WithCircuitBreaker(options = {}) { const circuitBreaker = new CircuitBreaker(options); return function (target, propertyKey, descriptor) { const originalMethod = descriptor.value; descriptor.value = function (...args) { return __awaiter(this, void 0, void 0, function* () { return circuitBreaker.execute(() => __awaiter(this, void 0, void 0, function* () { return originalMethod === null || originalMethod === void 0 ? void 0 : originalMethod.apply(this, args); })); }); }; return descriptor; }; } /** * Retry manager for coordinating multiple retry operations */ export class RetryManager { constructor(defaultRetryOptions = {}, defaultCircuitBreakerOptions = {}) { this.circuitBreakers = new Map(); this.defaultRetryOptions = Object.assign(Object.assign({}, DEFAULT_RETRY_OPTIONS), defaultRetryOptions); this.defaultCircuitBreakerOptions = Object.assign(Object.assign({}, DEFAULT_CIRCUIT_BREAKER_OPTIONS), defaultCircuitBreakerOptions); } /** * Get or create circuit breaker for a specific key */ getCircuitBreaker(key, options) { if (!this.circuitBreakers.has(key)) { this.circuitBreakers.set(key, new CircuitBreaker(Object.assign(Object.assign({}, this.defaultCircuitBreakerOptions), options))); } return this.circuitBreakers.get(key); } /** * Execute operation with retry and circuit breaker */ execute(key_1, fn_1) { return __awaiter(this, arguments, void 0, function* (key, fn, options = {}) { const circuitBreaker = this.getCircuitBreaker(key, options.circuitBreakerOptions); const retryOptions = Object.assign(Object.assign({}, this.defaultRetryOptions), options.retryOptions); return retryWithCircuitBreaker(fn, circuitBreaker, retryOptions); }); } /** * Reset circuit breaker for a specific key */ resetCircuitBreaker(key) { const circuitBreaker = this.circuitBreakers.get(key); if (circuitBreaker) { circuitBreaker.reset(); } } /** * Reset all circuit breakers */ resetAll() { Array.from(this.circuitBreakers.values()).forEach(circuitBreaker => { circuitBreaker.reset(); }); } /** * Get status of all circuit breakers */ getStatus() { const status = {}; Array.from(this.circuitBreakers.entries()).forEach(([key, circuitBreaker]) => { status[key] = circuitBreaker.getState(); }); return status; } }