/** * RedlockToolkit - Advanced Redis Distributed Locking Library * Combines best practices from multiple locking implementations */ import { EventEmitter } from "events"; import { RedisClient, RedlockToolkitConfig, LockOptions, LockExecutionResult, LockReleaseResult, LockExtensionResult, LockSignal, OptimisticLockOptions, OptimisticLockResult, HybridLockOptions, LockCacheOptions, ILockToolkit } from "./core/types"; import { Lock } from "./core/lock"; import { CircuitBreakerManager } from "./patterns/circuit-breaker"; import { MetricsCollector } from "./utils/metrics"; import { LuaScript } from "./utils/scripts"; import { CacheManager } from "./managers/cache"; import { PubSubWaiter } from "./pubsub/pubsub-waiter"; import { SemaphorePermit } from "./primitives/semaphore"; import { CountDownLatch } from "./primitives/countdown-latch"; import { SemaphoreOptions, SemaphoreStatus, CountDownLatchOptions, CountDownLatchStatus } from "./core/types"; /** * Main RedlockToolkit class implementing advanced distributed locking */ export declare class RedlockToolkit extends EventEmitter implements ILockToolkit { private readonly clients; private readonly config; readonly defaultOptions: Required; readonly circuitBreaker: CircuitBreakerManager; readonly metrics: MetricsCollector; private readonly logger; private readonly consensusManager; readonly cacheManager: CacheManager; private readonly pessimisticStrategy; private readonly optimisticStrategy; private readonly hybridStrategy; readonly activeLocks: Map; readonly compatibilityLocks: Map; private readonly pubSubManager; readonly pubSubWaiter: PubSubWaiter | null; private readonly semaphoreStrategy; private readonly countDownLatchStrategy; readonly activeSemaphores: Map; constructor(config: RedlockToolkitConfig); /** * Lua scripts in this library access keys derived inside the script * (e.g. `key .. ':version'`) and accept multiple arbitrary KEYS. On Redis * Cluster both patterns fail with CROSSSLOT unless every resource name * carries an explicit hash tag (e.g. `{order:42}`) so that all related * keys land in the same slot. Warn loudly instead of failing at runtime. */ private warnIfClusterClients; /** * Validate configuration */ private validateConfig; /** * Setup event forwarding from internal components */ private setupEventForwarding; /** * Preload Lua scripts on all clients */ private preloadScripts; /** * Generate unique client identifier */ getClientId(client: RedisClient): string; /** * Get a single Redis client for non-consensus read operations */ getClientForRead(): RedisClient; /** * Generate lock key */ generateLockKey(resource: string): string; /** * Generate unique lock identifier */ generateIdentifier(): string; /** * Execute Lua script on client with fallback */ executeScript(client: RedisClient, script: LuaScript, keys: string[], args: (string | number)[]): Promise; /** * Execute operation on all clients with consensus and cleanup. */ executeWithConsensus(operation: (client: RedisClient) => Promise, cleanupContext?: { keys: string[]; identifier: string; script?: LuaScript; args?: (string | number)[]; }, options?: { evaluateResult?: (result: any) => boolean; successPolicy?: 'quorum' | 'any'; }): Promise; /** * Acquire distributed lock */ acquire(resources: string | string[], options?: Partial): Promise; /** * Acquire optimistic lock with version-based conflict detection */ acquireOptimistic(resources: string | string[], options?: OptimisticLockOptions): Promise; /** * Update optimistic lock with conflict detection */ updateOptimistic(resources: string | string[], expectedVersion: number, options?: OptimisticLockOptions): Promise; /** * Acquire lock using hybrid strategy (pessimistic + optimistic) */ acquireHybrid(resources: string | string[], options?: HybridLockOptions): Promise; /** * Enable lock caching */ enableCache(options?: LockCacheOptions): void; /** * Disable lock caching */ disableCache(): void; /** * Get cache statistics */ getCacheStats(): { size: number; hitRate: number; evictions: number; }; /** * Create Lock object from optimistic result */ createLockFromOptimistic(resources: string | string[], result: OptimisticLockResult, options: HybridLockOptions): Lock; /** * Extend lock implementation */ extendLock(lock: Lock, ttl: number, options?: Partial): Promise; /** * Release lock implementation */ releaseLockInternal(lock: Lock, options?: Partial): Promise; /** * Create auto-extending lock that executes a routine */ using(resources: string | string[], routine: (signal: LockSignal) => Promise, options?: Partial): Promise; /** * Backward-compatibility shim for the pre-refactor API (≤0.9.x): `acquireRedlock(resources, ttl, * options?)`. Identical to {@link acquire} but takes TTL as a POSITIONAL argument (the old * Redlock-named signature). The positional `ttl` wins over any `options.ttl`. Delegates to the * pessimistic strategy, which is mutually exclusive — verified by the exclusivity regression test. * Returns a {@link Lock} (the old `RedlockLock` class was folded into `Lock` by the refactor; both * expose `release()`/`extend()`). */ acquireRedlock(resources: string | string[], ttl: number, options?: Partial): Promise; /** * Backward-compatibility shim for `usingRedlock(resources, ttl, routine, options?)` (≤0.9.x). * Same as {@link using} but with TTL positional. The routine receives the auto-extension * {@link LockSignal} (AbortSignal-shaped: `aborted` + `addEventListener('abort', …)`). */ usingRedlock(resources: string | string[], ttl: number, routine: (signal: LockSignal) => Promise, options?: Partial): Promise; /** * Force release locks (admin operation) */ forceRelease(resources: string | string[]): Promise<{ releasedCount: number; totalAttempted: number; }>; /** * Get value from Redis with data parsing (compatibility method) */ get(key: string): Promise; /** * Acquire a distributed lock with optional data storage (compatibility method) */ acquireLock(key: string, clientId: string, data?: any, ttl?: number): Promise; /** * Release a lock using clientId (compatibility method) */ releaseLock(key: string, clientId: string): Promise; /** * Force release a lock (compatibility method) */ forceReleaseLock(key: string): Promise; /** * Get lock status */ getStatus(resources: string | string[]): Promise>; /** * Get all active locks */ getActiveLocks(): Lock[]; /** * Get metrics */ getMetrics(): import("./core/types").LockMetrics & { detailed: { lockDurationStats: ReturnType<() => { count: number; sum: number; average: number; p50: number; p90: number; p95: number; p99: number; }>; acquisitionLatencyStats: ReturnType<() => { count: number; sum: number; average: number; p50: number; p90: number; p95: number; p99: number; }>; releaseLatencyStats: ReturnType<() => { count: number; sum: number; average: number; p50: number; p90: number; p95: number; p99: number; }>; extensionLatencyStats: ReturnType<() => { count: number; sum: number; average: number; p50: number; p90: number; p95: number; p99: number; }>; uptimeMs: number; activeLockDetails: Array<{ identifier: string; resources: string[]; durationMs: number; extensions: number; }>; }; }; /** * Get performance summary */ getPerformanceSummary(): { successRate: number; averageAcquisitionLatency: number; averageReleaseLatency: number; averageLockDuration: number; retryRate: number; circuitBreakerHealth: { overallState: "healthy" | "degraded" | "unhealthy"; openCircuits: number; totalCircuits: number; }; }; /** * Export metrics in Prometheus format */ exportMetrics(): string; /** * Get circuit breaker metrics (compatibility method) */ getCircuitBreakerMetrics(): { state: string; successfulOperations: number; failedOperations: number; resetTimeout: number | undefined; failureThreshold: number | undefined; }; /** * Publish to Redis channel (compatibility method) */ publish(channel: string, value: unknown): Promise; /** * Create observable from Redis events (compatibility method) */ fromEvent(eventName: string): any; /** * Acquire a semaphore permit */ acquireSemaphore(resource: string, options: SemaphoreOptions): Promise; /** * Get semaphore status */ getSemaphoreStatus(resource: string, maxPermits: number): Promise; /** * Create a new CountDownLatch */ createCountDownLatch(name: string, options: CountDownLatchOptions): Promise; /** * Get a handle to an existing CountDownLatch (e.g. from another process). * Does not create any keys in Redis — the latch must already exist. */ getCountDownLatch(name: string, options?: { awaitTimeout?: number; pollInterval?: number; }): CountDownLatch; /** * Get CountDownLatch status */ getCountDownLatchStatus(name: string): Promise; /** * Reset metrics */ resetMetrics(): void; /** * Cleanup expired locks (maintenance operation). * Uses Node.js-side SCAN to avoid blocking Redis's single thread. */ cleanup(): Promise; /** * Gracefully shutdown */ shutdown(): Promise; } export * from "./core/types"; export * from "./core/errors"; export * from "./core/lock"; export * from "./patterns/circuit-breaker"; export * from "./utils/metrics"; export { OptimisticRedlock } from "./algorithms/optimistic-redlock"; export { CircuitBreakerManager } from "./patterns/circuit-breaker"; export { Lock } from "./core/lock"; export { MetricsCollector } from "./utils/metrics"; export { SemaphorePermit } from "./primitives/semaphore"; export { CountDownLatch } from "./primitives/countdown-latch"; export { PubSubManager } from "./pubsub/pubsub-manager"; export { PubSubWaiter } from "./pubsub/pubsub-waiter"; export default RedlockToolkit; //# sourceMappingURL=index.d.ts.map