-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #724 from anchan828/sesamecare-redlock
feat: add sesamecare-redlock package
- Loading branch information
Showing
22 changed files
with
1,135 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
services: | ||
redis: | ||
redis-redlock: | ||
image: redis:7.4.0-alpine | ||
command: redis-server --lazyfree-lazy-user-del yes | ||
ports: | ||
- "6379:6379" | ||
redis-sesamecare-redlock: | ||
image: redis:7.4.0-alpine | ||
command: redis-server --lazyfree-lazy-user-del yes | ||
ports: | ||
- "6380:6379" |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
* | ||
!dist/**/* | ||
dist/**/*.tsbuildinfo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const basePrettierConfig = require("../../.prettierrc"); | ||
|
||
module.exports = { | ||
...basePrettierConfig, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
# @anchan828/nest-sesamecare-redlock | ||
|
||
![npm](https://img.shields.io/npm/v/@anchan828/nest-sesamecare-redlock.svg) | ||
![NPM](https://img.shields.io/npm/l/@anchan828/nest-sesamecare-redlock.svg) | ||
|
||
This is a [Nest](https://github.com/nestjs/nest) implementation of the redlock algorithm for distributed redis locks. | ||
|
||
This package uses [@sesamecare-oss/redlock](https://github.com/sesamecare/redlock). | ||
|
||
> [!NOTE] | ||
> This is one of the solutions to provisionally address the various issues with node-redlock that don't seem likely to be resolved soon. For details, please see https://github.com/anchan828/nest-redlock/pull/723. | ||
## Installation | ||
|
||
```bash | ||
$ npm i --save @anchan828/nest-sesamecare-redlock ioredis | ||
``` | ||
|
||
## Quick Start | ||
|
||
### 1. Import module | ||
|
||
```ts | ||
import { RedlockModule } from "@anchan828/nest-sesamecare-redlock"; | ||
import Redis from "ioredis"; | ||
|
||
@Module({ | ||
imports: [ | ||
RedlockModule.register({ | ||
// See https://github.com/sesamecare/redlock#configuration | ||
clients: [new Redis({ host: "localhost" })], | ||
settings: { | ||
driftFactor: 0.01, | ||
retryCount: 10, | ||
retryDelay: 200, | ||
retryJitter: 200, | ||
automaticExtensionThreshold: 500, | ||
}, | ||
// Default duratiuon to use with Redlock decorator | ||
duration: 1000, | ||
}), | ||
], | ||
}) | ||
export class AppModule {} | ||
``` | ||
|
||
### 2. Add `Redlock` decorator | ||
|
||
```ts | ||
import { Redlock } from "@anchan828/nest-sesamecare-redlock"; | ||
|
||
@Injectable() | ||
export class ExampleService { | ||
@Redlock("lock-key") | ||
public async addComment(projectId: number, comment: string): Promise<void> {} | ||
} | ||
``` | ||
|
||
This is complete. redlock is working correctly! | ||
See [node-redlock](https://github.com/sesamecare/redlock) for more information on redlock. | ||
|
||
## Define complex resources (lock keys) | ||
|
||
Using constants causes the same lock key to be used for all calls. Let's reduce the scope a bit more. | ||
|
||
In this example, only certain projects are now locked. | ||
|
||
```ts | ||
import { Redlock } from "@anchan828/nest-sesamecare-redlock"; | ||
|
||
@Injectable() | ||
export class ExampleService { | ||
// The arguments define the class object to which the decorator is being added and the method arguments in order. | ||
@Redlock<ExampleService["addComment"]>( | ||
(target: ExampleService, projectId: number, comment: string) => `projects/${projectId}/comments`, | ||
) | ||
public async addComment(projectId: number, comment: string): Promise<void> {} | ||
} | ||
``` | ||
|
||
Of course, you can lock multiple keys. | ||
|
||
```ts | ||
@Injectable() | ||
export class ExampleService { | ||
@Redlock<ExampleService["updateComments"]>( | ||
(target: ExampleService, projectId: number, args: Array<{ commentId: number; comment: string }>) => | ||
args.map((arg) => `projects/${projectId}/comments/${arg.commentId}`), | ||
) | ||
public async updateComments(projectId: number, args: Array<{ commentId: number; comment: string }>): Promise<void> {} | ||
} | ||
``` | ||
|
||
## Using Redlock service | ||
|
||
If you want to use node-redlock as is, use RedlockService. | ||
|
||
```ts | ||
import { RedlockService } from "@anchan828/nest-sesamecare-redlock"; | ||
|
||
@Injectable() | ||
export class ExampleService { | ||
constructor(private readonly redlock: RedlockService) {} | ||
|
||
public async addComment(projectId: number, comment: string): Promise<void> { | ||
await this.redlock.using([`projects/${projectId}/comments`], 5000, (signal) => { | ||
// Do something... | ||
|
||
if (signal.aborted) { | ||
throw signal.error; | ||
} | ||
}); | ||
} | ||
} | ||
``` | ||
|
||
## Using fake RedlockService | ||
|
||
If you do not want to use Redis in your Unit tests, define the fake class as RedlockService. | ||
|
||
```ts | ||
const app = await Test.createTestingModule({ | ||
providers: [TestService, { provide: RedlockService, useClass: FakeRedlockService }], | ||
}).compile(); | ||
``` | ||
|
||
## Troubleshooting | ||
|
||
### Nest can't resolve dependencies of the XXX. Please make sure that the "@redlockService" property is available in the current context. | ||
|
||
This is the error output when using the Redlock decorator without importing the RedlockModule. | ||
|
||
```ts | ||
import { RedlockModule } from "@anchan828/nest-sesamecare-redlock"; | ||
import Redis from "ioredis"; | ||
|
||
@Module({ | ||
imports: [ | ||
RedlockModule.register({ | ||
clients: [new Redis({ host: "localhost" })], | ||
}), | ||
], | ||
}) | ||
export class AppModule {} | ||
``` | ||
|
||
#### What should I do with Unit tests, I don't want to use Redis. | ||
|
||
Use `FakeRedlockService` class. Register FakeRedlockService with the provider as RedlockService. | ||
|
||
```ts | ||
const app = await Test.createTestingModule({ | ||
providers: [TestService, { provide: RedlockService, useClass: FakeRedlockService }], | ||
}).compile(); | ||
``` | ||
|
||
## License | ||
|
||
[MIT](LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
const base = require("../../jest.config"); | ||
module.exports = { | ||
...base, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
{ | ||
"name": "@anchan828/nest-sesamecare-redlock", | ||
"version": "0.2.44", | ||
"description": "This is a [Nest](https://github.com/nestjs/nest) implementation of the redlock algorithm for distributed redis locks.", | ||
"homepage": "https://github.com/anchan828/nest-redlock#readme", | ||
"bugs": { | ||
"url": "https://github.com/anchan828/nest-redlock/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/anchan828/nest-redlock.git" | ||
}, | ||
"license": "MIT", | ||
"author": "anchan828 <[email protected]>", | ||
"main": "dist/cjs/index.js", | ||
"types": "dist/cjs/index.d.ts", | ||
"scripts": { | ||
"build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json", | ||
"copy:license": "cp ../../LICENSE ./", | ||
"lint": "TIMING=1 eslint '**/*.ts'", | ||
"lint:fix": "npm run lint -- --fix", | ||
"test": "jest --coverage --runInBand --detectOpenHandles", | ||
"test:debug": "node --inspect-brk ../../node_modules/jest/bin/jest --runInBand --logHeapUsage", | ||
"test:watch": "npm run test -- --watch", | ||
"watch": "tsc --watch" | ||
}, | ||
"dependencies": { | ||
"@sesamecare-oss/redlock": "^1.3.1" | ||
}, | ||
"devDependencies": { | ||
"@nestjs/common": "10.4.4", | ||
"@nestjs/core": "10.4.4", | ||
"@nestjs/platform-express": "10.4.4", | ||
"@nestjs/testing": "10.4.4", | ||
"ioredis": "5.4.1", | ||
"reflect-metadata": "0.2.2", | ||
"rxjs": "7.8.1" | ||
}, | ||
"volta": { | ||
"node": "20.17.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"packageManager": "[email protected]", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/esm/index.d.ts", | ||
"default": "./dist/esm/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/cjs/index.d.ts", | ||
"default": "./dist/cjs/index.js" | ||
}, | ||
"types": "./dist/cjs/index.d.ts", | ||
"default": "./dist/cjs/index.js" | ||
} | ||
} | ||
} |
Oops, something went wrong.