@tawandotorg/nestjs-async-lock v1.1.10
NestJS Async Lock
A simple, extensible, and framework-agnostic async lock (mutex) solution for NestJS. This package provides atomic locks for synchronizing access to shared resources, supporting both Redis and in-memory stores. In other words, it prevents several processes, or concurrent code, from executing a section of code at the same time.
Features
- Atomic locks (mutexes) for critical section protection
- Multiple backends: Redis (distributed) and in-memory (single process)
- Automatic and manual lock management
- NestJS integration: Injectable, testable, and idiomatic
- TypeScript support
Installation
npm install @tawandotorg/nestjs-async-lock
# or
yarn add @tawandotorg/nestjs-async-lock
Quick Start
1. Import the Module
import { AsyncLockModule, MemoryStore } from '@tawandotorg/nestjs-async-lock';
import Redis from 'ioredis';
@Module({
imports: [
AsyncLockModule.forRoot({
default: 'memory', // or 'redis'
stores: {
// choose one
memory: { driver: new MemoryStore() },
redis: { driver: new Redis() },
},
}),
],
})
export class AppModule {}
2. Inject and Use the Lock Service
Example
import { Injectable } from '@nestjs/common';
import { AsyncLockService } from '@tawandotorg/nestjs-async-lock';
@Injectable()
export class OrderService {
constructor(private readonly lockService: AsyncLockService) {}
async processOrder(orderId: string) {
// Manual locking
const lock = await this.lockService.acquireLock(`order.processing.${orderId}`);
try {
// ...process the order...
} finally {
await this.lockService.releaseLock(lock);
}
}
async processOrderAuto(orderId: string) {
// Automatic locking
return this.lockService.runWithLock(`order.processing.${orderId}`, 10000, async () => {
// ...process the order...
return 'Order processed successfully';
});
}
}
Configuration
Configure the lock store and options via AsyncLockModule.forRoot()
.
Supported Stores
- redis: Distributed, recommended for multi-instance deployments. When using Redis, this package uses Redlock under the hood for distributed locking. See the Redlock documentation for more details on the algorithm and guarantees.
- memory: Fast, for single-process or testing environments.
Example: Redis Store
import Redis from 'ioredis';
AsyncLockModule.forRoot({
default: 'redis',
stores: {
redis: { driver: new Redis() },
},
});
Example: Memory Store
import { MemoryStore } from '@tawandotorg/nestjs-async-lock';
AsyncLockModule.forRoot({
default: 'memory',
stores: {
memory: { driver: new MemoryStore() },
},
});
API
acquireLock(resource: string, ttl = 10000)
Acquires a lock for the given resource. Throws if the lock cannot be acquired.
runWithLock(resource: string, ttl: number, fn: () => Promise<T>): Promise<T>
Runs the provided function with a lock held for the resource. Releases the lock automatically after execution.
releaseLock(lock)
Releases the acquired lock.
License
MIT
Contributing
Pull requests and issues are welcome! Please open an issue to discuss your ideas or report bugs.
Inspiration
This package is inspired by the AdonisJS Locks concept, but is a custom implementation for NestJS.