@anchan828/nest-redlock 0.2.35 → 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.
Files changed (33) hide show
  1. package/dist/esm/index.d.ts +5 -0
  2. package/dist/esm/index.js +4 -0
  3. package/dist/esm/redlock.constants.d.ts +1 -0
  4. package/dist/esm/redlock.constants.js +1 -0
  5. package/dist/esm/redlock.decorator.d.ts +3 -0
  6. package/dist/esm/redlock.decorator.js +57 -0
  7. package/dist/esm/redlock.fake-service.d.ts +10 -0
  8. package/dist/esm/redlock.fake-service.js +28 -0
  9. package/dist/esm/redlock.interface.d.ts +54 -0
  10. package/dist/esm/redlock.interface.js +1 -0
  11. package/dist/esm/redlock.module-definition.d.ts +2 -0
  12. package/dist/esm/redlock.module-definition.js +2 -0
  13. package/dist/esm/redlock.module.d.ts +8 -0
  14. package/dist/esm/redlock.module.js +50 -0
  15. package/dist/esm/redlock.service.d.ts +6 -0
  16. package/dist/esm/redlock.service.js +27 -0
  17. package/package.json +21 -7
  18. /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
  19. /package/dist/{index.js → cjs/index.js} +0 -0
  20. /package/dist/{redlock.constants.d.ts → cjs/redlock.constants.d.ts} +0 -0
  21. /package/dist/{redlock.constants.js → cjs/redlock.constants.js} +0 -0
  22. /package/dist/{redlock.decorator.d.ts → cjs/redlock.decorator.d.ts} +0 -0
  23. /package/dist/{redlock.decorator.js → cjs/redlock.decorator.js} +0 -0
  24. /package/dist/{redlock.fake-service.d.ts → cjs/redlock.fake-service.d.ts} +0 -0
  25. /package/dist/{redlock.fake-service.js → cjs/redlock.fake-service.js} +0 -0
  26. /package/dist/{redlock.interface.d.ts → cjs/redlock.interface.d.ts} +0 -0
  27. /package/dist/{redlock.interface.js → cjs/redlock.interface.js} +0 -0
  28. /package/dist/{redlock.module-definition.d.ts → cjs/redlock.module-definition.d.ts} +0 -0
  29. /package/dist/{redlock.module-definition.js → cjs/redlock.module-definition.js} +0 -0
  30. /package/dist/{redlock.module.d.ts → cjs/redlock.module.d.ts} +0 -0
  31. /package/dist/{redlock.module.js → cjs/redlock.module.js} +0 -0
  32. /package/dist/{redlock.service.d.ts → cjs/redlock.service.d.ts} +0 -0
  33. /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,4 @@
1
+ export { Redlock } from "./redlock.decorator";
2
+ export { FakeRedlockService } from "./redlock.fake-service";
3
+ export { RedlockModule } from "./redlock.module";
4
+ 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,2 @@
1
+ import { RedlockModuleOptions } from "./redlock.interface";
2
+ export declare const ConfigurableModuleClass: import("@nestjs/common").ConfigurableModuleCls<RedlockModuleOptions, "register", "create", {}>, MODULE_OPTIONS_TOKEN: string | symbol;
@@ -0,0 +1,2 @@
1
+ import { ConfigurableModuleBuilder } from "@nestjs/common";
2
+ export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder().build();
@@ -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,6 @@
1
+ import Redlock from "redlock";
2
+ import { RedlockModuleOptions } from "./redlock.interface";
3
+ export declare class RedlockService extends Redlock {
4
+ readonly options: RedlockModuleOptions;
5
+ constructor(options: RedlockModuleOptions);
6
+ }
@@ -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.35",
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,12 +12,12 @@
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.build.json",
18
+ "build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",
19
19
  "copy:license": "cp ../../LICENSE ./",
20
- "lint": "TIMING=1 eslint --ignore-path ../../.eslintignore '**/*.ts'",
20
+ "lint": "TIMING=1 eslint '**/*.ts'",
21
21
  "lint:fix": "npm run lint -- --fix",
22
22
  "test": "jest --coverage --runInBand --detectOpenHandles",
23
23
  "test:debug": "node --inspect-brk ../../node_modules/jest/bin/jest --runInBand --logHeapUsage",
@@ -43,5 +43,19 @@
43
43
  "access": "public"
44
44
  },
45
45
  "packageManager": "npm@10.8.2",
46
- "gitHead": "0f21b23a820b13d7db188f2fd5493f38a22fd4a2"
47
- }
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"
61
+ }
File without changes
File without changes