import { OnModuleInit, OnApplicationShutdown } from '@nestjs/common'; import { RedisLockService } from './redis-lock.service'; import { LockHeartbeatService } from './lock-heartbeat.service'; /** * Comprehensive lock cleanup service * * Provides safe and comprehensive lock cleanup mechanism for distributed environments. * Combines instance-based precise cleanup with heartbeat-based dead instance detection. * * **Cleanup Strategy:** * 1. **Immediate Precise Cleanup (0s):** * - Only cleans locks from the current instance * - Safe during rolling updates - won't affect other running instances * * 2. **Delayed Conservative Cleanup (60s):** * - Checks heartbeat of other instances * - Only cleans locks from dead instances (no heartbeat) * - Gives enough time for rolling updates to complete * * 3. **Graceful Shutdown Cleanup:** * - On SIGTERM/SIGINT, immediately cleans own locks * - Ensures locks are released before process exits * - Works with PM2 reload and Kubernetes rolling updates * * @example * ```typescript * // In your module * @Module({ * providers: [ * RedisLockService, * LockHeartbeatService, * ComprehensiveLockCleanupService, * ], * }) * export class AppModule {} * ``` */ export declare class ComprehensiveLockCleanupService implements OnModuleInit, OnApplicationShutdown { private readonly lockService; private readonly heartbeatService; private readonly cleanupKeyPrefixes?; private readonly logger; private readonly instanceId; /** * Grace period before cleaning other instances' locks (milliseconds) * @default 60000 (60 seconds) */ private readonly gracePeriod; constructor(lockService: RedisLockService, heartbeatService: LockHeartbeatService, cleanupKeyPrefixes?: string[]); onModuleInit(): Promise; /** * Clean up locks from the current instance * Safe to run immediately - only affects locks created by this instance */ private cleanupOwnLocks; /** * Clean up locks from dead instances * Only runs after grace period to avoid cleaning locks during rolling updates */ private cleanupDeadInstanceLocks; /** * Check if a lock belongs to the current instance * * @param lockValue - Lock value to check * @returns True if lock belongs to current instance */ private isOwnLock; /** * Extract instance ID from lock value * Lock value format: instanceId:timestamp:random:pid * * @param lockValue - Lock value * @returns Instance ID or null if cannot be extracted */ private extractInstanceId; /** * Manually trigger cleanup of all stale locks * Use with caution - this will clean both own and dead instance locks */ manualCleanup(): Promise<{ ownLocks: number; deadLocks: number; }>; private cleanupOwnLocksCount; private cleanupDeadInstanceLocksCount; private getCleanupKeyPrefixes; private releaseScannedLock; private isExecutionMarker; /** * Cleanup own locks on application shutdown * Called when receiving SIGTERM/SIGINT (graceful shutdown) */ onApplicationShutdown(signal?: string): Promise; }