NestJSRxJSLockModule
NestJS RxJS implementation of distributed lock for NestJS using Redlock
TODO
- [] Add module tests
- [] Remove
nestjs-redis
dependency, use ioredis directly - [] Add
lock$
docs usage example
Installation
Add @rnw-community/nestjs-rxjs-lock
to your project using you package manager of choice.
Configuration
We need to create own LockModule to "wrap" typed module and service returned from
the NestJSRxJSLockModule.registerTypedAsync()
, this will
allow us to use typesafe LockCodesEnum
in our business logic.
// eslint-disable-next-line max-classes-per-file
import { Injectable, Module } from '@nestjs/common';
import { NestJSRxJSLockModule } from '@rnw-community/nestjs-rxjs-lock';
import { LockCodesEnum } from '@seezona/admin-api-backend/src/generic/enum/lock-codes.enum';
// Create a enum which would be typesafe to use in your locks
enum LockCodesEnum {
DB_USER_CREATE = 'DB_USER_CREATE',
}
const [BaseLockModule, BaseLockService] = NestJSRxJSLockModule.registerTypedAsync<LockCodesEnum>({
retryCount: 3,
defaultExpireMs: 5000,
});
@Injectable()
export class LockService extends BaseLockService {}
@Module({
imports: [BaseLockModule],
providers: [LockService],
exports: [LockService],
})
export class LockModule {}
Methods
NestJSRxJSLockModule.registerTypedAsync
-
options
is aNestJSRxJSLockModuleOptions
which extends Redlock.Options object with default values):-
retryCount
is a number of lock attempts -
defaultExpireMs
is a default lock expiration time in milliseconds
-
Setup section for more details
Example(seeNestJSRxJSService.lock$
Arguments
-
name
- unique lock identifier like user id in our setup example -
prefix
- typesafeLockCodesEnum
value from the setup, used as a prefix for the lock key -
handler$
- business logic wrapped in RxJS observable -
expireMs
- lock expiration time in milliseconds, a module configuration default value is used if not provided
Redis lock key will be formed as
lock:[prefix]:[name]
and will be expired afterexpireMs
milliseconds and wil retryretryCount
times.
Usage
@Injectable()
export class MyUserService {
constructor(private readonly lock: LockService /*...other dependencies...*/) {}
createUserInDb$(user): Observable<User> {
// business logic
}
createUser$(user: User): Observable<User> {
return this.lock.lock$(user.id, LockCodesEnum.DB_USER_CREATE, () => this.createUserInDb$(user));
}
}
lock$
method will throw an error if lock is not acquired
License
This library is licensed under The MIT License.