/** * Fallback Service * * Code-first API for defining and managing fallbacks with sequential failover. * Uses ProductBuilder for CRUD operations and ProcessorService for execution. * Implements health-aware sequential failover with minimal latency. */ import { IFallbackDefineOptions, IFallbackSchema, IFallbackRunOptions, IFallbackDispatchOptions, IDefinedFallback, IResilienceServiceConfig } from './types'; import { IProductFallback } from '../types/productsBuilder.types'; /** * Error class for fallback operations */ export declare class FallbackError extends Error { code: string; details?: unknown; constructor(message: string, code: string, details?: unknown); } /** * Result of a fallback run with provider and failover information */ export interface IFallbackRunResult { data: T; provider: string; latency: number; wasHealthy: boolean; failoverCount: number; triedProviders: string[]; } /** * Fallback Service * * Provides code-first API for defining, creating, and managing fallbacks. * Uses ProductBuilder for CRUD operations and ProcessorService for execution. * Implements health-aware sequential failover with minimal latency. */ export declare class FallbackService { private config; private productBuilders; private processorCache; private _privateKey; private readonly productEnv; constructor(config: IResilienceServiceConfig & { private_key: string; access_key?: string; }); private resolvePE; /** * Gets or creates a cached ProductBuilder */ private createNewProductBuilder; private getOrCreateProductBuilder; private bootstrapFallbackForRun; private getProductBuilder; /** * Gets or creates a cached ProcessorService for minimal latency */ private getProcessor; /** * Define a fallback using code-first API * * @example * ```ts * const fallback = await fallbackService.define({ * product: 'my-product', * tag: 'payment-fallback', * name: 'Payment Provider Fallback', * input: { * amount: { type: 'number', required: true }, * currency: { type: 'string', required: true }, * }, * handler: async (ctx) => { * ctx.primary('stripe') * .healthcheck('stripe-health') * .app('stripe-app') * .action('charge') * .mapInput((input) => ({ body: { amount: input.amount } })) * .mapOutput((res) => ({ chargeId: res.id })) * .retries(2); * * ctx.fallback('paypal') * .healthcheck('paypal-health') * .app('paypal-app') * .action('payment') * .mapInput((input) => ({ body: { amount: input.amount } })) * .mapOutput((res) => ({ chargeId: res.id })) * .retries(2); * }, * }); * ``` */ define>(options: IFallbackDefineOptions): Promise; /** * Create a fallback from a defined fallback or schema */ create(product: string, fallback: IDefinedFallback | IFallbackSchema): Promise; /** * Fetch a fallback by tag */ fetch(product: string, tag: string): Promise; /** * Fetch all fallbacks for a product */ fetchAll(product: string): Promise; /** * Update an existing fallback */ update>(product: string, tag: string, fallback: Partial> | Partial): Promise; /** * Delete a fallback */ delete(product: string, tag: string): Promise; /** * Run a fallback with health-aware sequential failover * * Optimization strategies: * 1. Parallel health status lookups from Redis (O(1) per provider) * 2. Skip unhealthy providers immediately * 3. Cached processor instances to avoid re-initialization * 4. Exponential backoff only on failures * 5. Short-circuit on first success */ run(options: IFallbackRunOptions): Promise>; /** * Parallel health status lookup from Redis - O(n) with parallel I/O */ private getHealthStatusesParallel; /** * Order providers by health status: healthy > unknown > unhealthy * Maintains original order within each category (first provider = primary) */ private orderProvidersByHealth; /** * Execute provider action with exponential backoff retries */ private executeWithRetries; /** * Dispatch fallback for deferred execution via job queue * * Note: For immediate execution, use run() instead. * Dispatch schedules the fallback for background processing. */ dispatch(options: IFallbackDispatchOptions): Promise<{ jobId: string; }>; } export default FallbackService;