@anchan828/nest-redlock 0.2.36 → 0.2.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/redlock.constants.d.ts +1 -0
- package/dist/esm/redlock.constants.js +1 -0
- package/dist/esm/redlock.decorator.d.ts +3 -0
- package/dist/esm/redlock.decorator.js +57 -0
- package/dist/esm/redlock.fake-service.d.ts +10 -0
- package/dist/esm/redlock.fake-service.js +28 -0
- package/dist/esm/redlock.interface.d.ts +54 -0
- package/dist/esm/redlock.interface.js +1 -0
- package/dist/esm/redlock.module-definition.d.ts +2 -0
- package/dist/esm/redlock.module-definition.js +2 -0
- package/dist/esm/redlock.module.d.ts +8 -0
- package/dist/esm/redlock.module.js +50 -0
- package/dist/esm/redlock.service.d.ts +6 -0
- package/dist/esm/redlock.service.js +27 -0
- package/package.json +19 -5
- /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
- /package/dist/{index.js → cjs/index.js} +0 -0
- /package/dist/{redlock.constants.d.ts → cjs/redlock.constants.d.ts} +0 -0
- /package/dist/{redlock.constants.js → cjs/redlock.constants.js} +0 -0
- /package/dist/{redlock.decorator.d.ts → cjs/redlock.decorator.d.ts} +0 -0
- /package/dist/{redlock.decorator.js → cjs/redlock.decorator.js} +0 -0
- /package/dist/{redlock.fake-service.d.ts → cjs/redlock.fake-service.d.ts} +0 -0
- /package/dist/{redlock.fake-service.js → cjs/redlock.fake-service.js} +0 -0
- /package/dist/{redlock.interface.d.ts → cjs/redlock.interface.d.ts} +0 -0
- /package/dist/{redlock.interface.js → cjs/redlock.interface.js} +0 -0
- /package/dist/{redlock.module-definition.d.ts → cjs/redlock.module-definition.d.ts} +0 -0
- /package/dist/{redlock.module-definition.js → cjs/redlock.module-definition.js} +0 -0
- /package/dist/{redlock.module.d.ts → cjs/redlock.module.d.ts} +0 -0
- /package/dist/{redlock.module.js → cjs/redlock.module.js} +0 -0
- /package/dist/{redlock.service.d.ts → cjs/redlock.service.d.ts} +0 -0
- /package/dist/{redlock.service.js → cjs/redlock.service.js} +0 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Redlock } from "./redlock.decorator";
|
|
2
|
+
export { FakeRedlockService } from "./redlock.fake-service";
|
|
3
|
+
export { LockedKeysHookArgs, PreLockedKeysHookArgs, RedlockKeyFunction, RedlockModuleOptions, UnlockedKeysHookArgs, } from "./redlock.interface";
|
|
4
|
+
export { RedlockModule } from "./redlock.module";
|
|
5
|
+
export { RedlockService } from "./redlock.service";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_DURATION = 5000;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_DURATION = 5000;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Settings } from "redlock";
|
|
2
|
+
import { RedlockKeyFunction } from "./redlock.interface";
|
|
3
|
+
export declare function Redlock<T extends (...args: any) => any = (...args: any) => any>(key: string | string[] | RedlockKeyFunction<T>, duration?: number, settings?: Partial<Settings>): MethodDecorator;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Inject } from "@nestjs/common";
|
|
2
|
+
import { DEFAULT_DURATION } from "./redlock.constants";
|
|
3
|
+
import { RedlockService } from "./redlock.service";
|
|
4
|
+
export function Redlock(key, duration, settings = {}) {
|
|
5
|
+
const injectRedlockService = Inject(RedlockService);
|
|
6
|
+
return (target, propertyKey, descriptor) => {
|
|
7
|
+
const serviceSymbol = "@redlockService";
|
|
8
|
+
injectRedlockService(target, serviceSymbol);
|
|
9
|
+
const originalMethod = descriptor.value;
|
|
10
|
+
descriptor.value = async function (...args) {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
12
|
+
const descriptorThis = this;
|
|
13
|
+
const redlockService = descriptorThis[serviceSymbol];
|
|
14
|
+
if (redlockService?.options?.decoratorEnabled !== undefined && !redlockService.options.decoratorEnabled) {
|
|
15
|
+
return await originalMethod.apply(descriptorThis, args);
|
|
16
|
+
}
|
|
17
|
+
const keys = getKeys(key, descriptorThis, args);
|
|
18
|
+
const useDuration = duration || redlockService.options?.duration || DEFAULT_DURATION;
|
|
19
|
+
await redlockService.options?.decoratorHooks?.preLockKeys?.({ keys, duration: useDuration });
|
|
20
|
+
const startTime = Date.now();
|
|
21
|
+
return await redlockService
|
|
22
|
+
.using(keys, useDuration, settings, async (signal) => {
|
|
23
|
+
if (signal.aborted) {
|
|
24
|
+
throw signal.error;
|
|
25
|
+
}
|
|
26
|
+
await redlockService.options?.decoratorHooks?.lockedKeys?.({
|
|
27
|
+
keys,
|
|
28
|
+
duration: useDuration,
|
|
29
|
+
elapsedTime: Date.now() - startTime,
|
|
30
|
+
});
|
|
31
|
+
const result = await originalMethod.apply(descriptorThis, args);
|
|
32
|
+
return result;
|
|
33
|
+
})
|
|
34
|
+
.finally(async () => {
|
|
35
|
+
await redlockService.options?.decoratorHooks?.unlockedKeys?.({
|
|
36
|
+
keys,
|
|
37
|
+
duration: useDuration,
|
|
38
|
+
elapsedTime: Date.now() - startTime,
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
return descriptor;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function getKeys(key, descriptorThis, args) {
|
|
46
|
+
const keys = new Set();
|
|
47
|
+
if (typeof key === "string") {
|
|
48
|
+
keys.add(key);
|
|
49
|
+
}
|
|
50
|
+
else if (Array.isArray(key)) {
|
|
51
|
+
key.forEach((k) => keys.add(k));
|
|
52
|
+
}
|
|
53
|
+
else if (typeof key === "function") {
|
|
54
|
+
[key(descriptorThis, ...args)].flat().forEach((k) => keys.add(k));
|
|
55
|
+
}
|
|
56
|
+
return Array.from(keys);
|
|
57
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { ExecutionResult, Lock, RedlockAbortSignal, Settings } from "redlock";
|
|
3
|
+
export declare class FakeRedlockService extends EventEmitter {
|
|
4
|
+
quit(): Promise<void>;
|
|
5
|
+
acquire(keys: string[], duration: number, settings?: Partial<Settings> | undefined): Promise<Lock>;
|
|
6
|
+
release(lock: Lock, settings?: Partial<Settings> | undefined): Promise<ExecutionResult>;
|
|
7
|
+
extend(existing: Lock, duration: number, settings?: Partial<Settings> | undefined): Promise<Lock>;
|
|
8
|
+
using<T>(keys: string[], duration: number, settings: Partial<Settings>, routine?: ((signal: RedlockAbortSignal) => Promise<T>) | undefined): Promise<T>;
|
|
9
|
+
using<T>(keys: string[], duration: number, routine: (signal: RedlockAbortSignal) => Promise<T>): Promise<T>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import { EventEmitter } from "events";
|
|
3
|
+
export class FakeRedlockService extends EventEmitter {
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
5
|
+
async quit() { }
|
|
6
|
+
async acquire(keys, duration, settings) {
|
|
7
|
+
return createLockFake();
|
|
8
|
+
}
|
|
9
|
+
async release(lock, settings) {
|
|
10
|
+
return { attempts: [] };
|
|
11
|
+
}
|
|
12
|
+
async extend(existing, duration, settings) {
|
|
13
|
+
return createLockFake();
|
|
14
|
+
}
|
|
15
|
+
async using(keys, duration, settingsOrRoutine, routine) {
|
|
16
|
+
const routineFunc = typeof settingsOrRoutine === "function" ? settingsOrRoutine : routine;
|
|
17
|
+
return await routineFunc?.({ aborted: false });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function createLockFake() {
|
|
21
|
+
let lock;
|
|
22
|
+
// eslint-disable-next-line prefer-const
|
|
23
|
+
lock = {
|
|
24
|
+
release: async () => ({ attempts: [] }),
|
|
25
|
+
extend: async (duration) => lock,
|
|
26
|
+
};
|
|
27
|
+
return lock;
|
|
28
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Redis, { Cluster } from "ioredis";
|
|
2
|
+
import { Settings } from "redlock";
|
|
3
|
+
export type PreLockedKeysHookArgs = {
|
|
4
|
+
keys: string[];
|
|
5
|
+
duration: number;
|
|
6
|
+
};
|
|
7
|
+
export type LockedKeysHookArgs = {
|
|
8
|
+
keys: string[];
|
|
9
|
+
duration: number;
|
|
10
|
+
elapsedTime: number;
|
|
11
|
+
};
|
|
12
|
+
export type UnlockedKeysHookArgs = {
|
|
13
|
+
keys: string[];
|
|
14
|
+
duration: number;
|
|
15
|
+
elapsedTime: number;
|
|
16
|
+
};
|
|
17
|
+
export type RedlockModuleOptions = {
|
|
18
|
+
clients: Iterable<Redis | Cluster>;
|
|
19
|
+
/**
|
|
20
|
+
* Default: true
|
|
21
|
+
* Used only with @Redlock decorator.
|
|
22
|
+
*/
|
|
23
|
+
decoratorEnabled?: boolean;
|
|
24
|
+
settings?: Partial<Settings>;
|
|
25
|
+
scripts?: {
|
|
26
|
+
readonly acquireScript?: string | ((script: string) => string);
|
|
27
|
+
readonly extendScript?: string | ((script: string) => string);
|
|
28
|
+
readonly releaseScript?: string | ((script: string) => string);
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Hooks called when using @Redlock decorator.
|
|
32
|
+
*/
|
|
33
|
+
decoratorHooks?: {
|
|
34
|
+
/**
|
|
35
|
+
* Called before redlock.using
|
|
36
|
+
*/
|
|
37
|
+
readonly preLockKeys?: (args: PreLockedKeysHookArgs) => void | Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Called first when the redlock.using callback is invoked.
|
|
40
|
+
*/
|
|
41
|
+
readonly lockedKeys?: (args: LockedKeysHookArgs) => void | Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Called after when the redlock.using callback is finished.
|
|
44
|
+
*/
|
|
45
|
+
readonly unlockedKeys?: (args: UnlockedKeysHookArgs) => void | Promise<void>;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Default duratiuon to use with Redlock decorator
|
|
49
|
+
*
|
|
50
|
+
* @type {number}
|
|
51
|
+
*/
|
|
52
|
+
duration?: number;
|
|
53
|
+
};
|
|
54
|
+
export type RedlockKeyFunction<T extends (...args: any) => any = (...args: any) => any> = (target: any, ...args: Parameters<T>) => string[] | string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { OnApplicationShutdown } from "@nestjs/common";
|
|
2
|
+
import { RedlockModuleOptions } from "./redlock.interface";
|
|
3
|
+
import { ConfigurableModuleClass } from "./redlock.module-definition";
|
|
4
|
+
export declare class RedlockModule extends ConfigurableModuleClass implements OnApplicationShutdown {
|
|
5
|
+
private readonly options;
|
|
6
|
+
constructor(options: RedlockModuleOptions);
|
|
7
|
+
onApplicationShutdown(): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Inject, Module } from "@nestjs/common";
|
|
14
|
+
import { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } from "./redlock.module-definition";
|
|
15
|
+
import { RedlockService } from "./redlock.service";
|
|
16
|
+
let RedlockModule = class RedlockModule extends ConfigurableModuleClass {
|
|
17
|
+
constructor(options) {
|
|
18
|
+
super();
|
|
19
|
+
this.options = options;
|
|
20
|
+
}
|
|
21
|
+
async onApplicationShutdown() {
|
|
22
|
+
for (const client of this.options.clients) {
|
|
23
|
+
switch (client.status) {
|
|
24
|
+
case "end":
|
|
25
|
+
continue;
|
|
26
|
+
case "ready":
|
|
27
|
+
await client.quit();
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
client.disconnect();
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
RedlockModule = __decorate([
|
|
37
|
+
Module({
|
|
38
|
+
providers: [
|
|
39
|
+
{
|
|
40
|
+
provide: RedlockService,
|
|
41
|
+
inject: [MODULE_OPTIONS_TOKEN],
|
|
42
|
+
useFactory: (options) => new RedlockService(options),
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
exports: [RedlockService],
|
|
46
|
+
}),
|
|
47
|
+
__param(0, Inject(MODULE_OPTIONS_TOKEN)),
|
|
48
|
+
__metadata("design:paramtypes", [Object])
|
|
49
|
+
], RedlockModule);
|
|
50
|
+
export { RedlockModule };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
14
|
+
import Redlock from "redlock";
|
|
15
|
+
import { MODULE_OPTIONS_TOKEN } from "./redlock.module-definition";
|
|
16
|
+
let RedlockService = class RedlockService extends Redlock {
|
|
17
|
+
constructor(options) {
|
|
18
|
+
super(options.clients, options.settings, options.scripts);
|
|
19
|
+
this.options = options;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
RedlockService = __decorate([
|
|
23
|
+
Injectable(),
|
|
24
|
+
__param(0, Inject(MODULE_OPTIONS_TOKEN)),
|
|
25
|
+
__metadata("design:paramtypes", [Object])
|
|
26
|
+
], RedlockService);
|
|
27
|
+
export { RedlockService };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anchan828/nest-redlock",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.37",
|
|
4
4
|
"description": "This is a [Nest](https://github.com/nestjs/nest) implementation of the redlock algorithm for distributed redis locks.",
|
|
5
5
|
"homepage": "https://github.com/anchan828/nest-redlock#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"author": "anchan828 <anchan828@gmail.com>",
|
|
15
|
-
"main": "dist/index.js",
|
|
16
|
-
"types": "dist/index.d.ts",
|
|
15
|
+
"main": "dist/cjs/index.js",
|
|
16
|
+
"types": "dist/cjs/index.d.ts",
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "tsc -p tsconfig.
|
|
18
|
+
"build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",
|
|
19
19
|
"copy:license": "cp ../../LICENSE ./",
|
|
20
20
|
"lint": "TIMING=1 eslint '**/*.ts'",
|
|
21
21
|
"lint:fix": "npm run lint -- --fix",
|
|
@@ -43,5 +43,19 @@
|
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
45
|
"packageManager": "npm@10.8.2",
|
|
46
|
-
"
|
|
46
|
+
"exports": {
|
|
47
|
+
".": {
|
|
48
|
+
"import": {
|
|
49
|
+
"types": "./dist/esm/index.d.ts",
|
|
50
|
+
"default": "./dist/esm/index.js"
|
|
51
|
+
},
|
|
52
|
+
"require": {
|
|
53
|
+
"types": "./dist/cjs/index.d.ts",
|
|
54
|
+
"default": "./dist/cjs/index.js"
|
|
55
|
+
},
|
|
56
|
+
"types": "./dist/cjs/index.d.ts",
|
|
57
|
+
"default": "./dist/cjs/index.js"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"gitHead": "aa32d82ce7d4ada796ca510f42a30554cc5b13cd"
|
|
47
61
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|