* Execute a function with a distributed lock * @param lockName - Name of the lock * @param fn - Function to execute while holding the lock * @param options - Lock options * @returns Promise - Result of the function execution
(
lockName: string,
fn: () => Promise<T>,
options?: Partial<DistributedLockOptions>
)
| 227 | * @returns Promise<T> - Result of the function execution |
| 228 | */ |
| 229 | async withLock<T>( |
| 230 | lockName: string, |
| 231 | fn: () => Promise<T>, |
| 232 | options?: Partial<DistributedLockOptions> |
| 233 | ): Promise<T | null> { |
| 234 | const lockResult = await this.acquire(lockName, options); |
| 235 | |
| 236 | if (!lockResult.acquired) { |
| 237 | const skipMessage = options?.skipOnFailure |
| 238 | ? `[DistributedLock] Skipping execution for: ${lockName} (skipOnFailure=true)` |
| 239 | : `[DistributedLock] Could not acquire lock for: ${lockName}, skipping execution`; |
| 240 | |
| 241 | logger.debug(skipMessage); |
| 242 | return null; |
| 243 | } |
| 244 | |
| 245 | try { |
| 246 | logger.debug( |
| 247 | `[DistributedLock] Executing function with lock: ${lockName}` |
| 248 | ); |
| 249 | const result = await fn(); |
| 250 | logger.debug( |
| 251 | `[DistributedLock] Function completed successfully with lock: ${lockName}` |
| 252 | ); |
| 253 | return result; |
| 254 | } catch (error) { |
| 255 | logger.error( |
| 256 | `[DistributedLock] Error executing function with lock ${lockName}:`, |
| 257 | error |
| 258 | ); |
| 259 | throw error; |
| 260 | } finally { |
| 261 | if (lockResult.release) { |
| 262 | await lockResult.release(); |
| 263 | } |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | /** |
| 268 | * Check if a lock is currently held |