@nestjs-redisx/locks 1.0.0

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/LICENSE +21 -0
  2. package/README.md +50 -0
  3. package/dist/index.d.ts +9 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +635 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/index.mjs +625 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/dist/lock/api/decorators/with-lock.decorator.d.ts +105 -0
  10. package/dist/lock/api/decorators/with-lock.decorator.d.ts.map +1 -0
  11. package/dist/lock/application/ports/lock-service.port.d.ts +120 -0
  12. package/dist/lock/application/ports/lock-service.port.d.ts.map +1 -0
  13. package/dist/lock/application/ports/lock-store.port.d.ts +63 -0
  14. package/dist/lock/application/ports/lock-store.port.d.ts.map +1 -0
  15. package/dist/lock/application/services/lock-decorator-initializer.service.d.ts +19 -0
  16. package/dist/lock/application/services/lock-decorator-initializer.service.d.ts.map +1 -0
  17. package/dist/lock/application/services/lock.service.d.ts +90 -0
  18. package/dist/lock/application/services/lock.service.d.ts.map +1 -0
  19. package/dist/lock/domain/entities/lock.entity.d.ts +130 -0
  20. package/dist/lock/domain/entities/lock.entity.d.ts.map +1 -0
  21. package/dist/lock/infrastructure/adapters/redis-lock-store.adapter.d.ts +45 -0
  22. package/dist/lock/infrastructure/adapters/redis-lock-store.adapter.d.ts.map +1 -0
  23. package/dist/lock/infrastructure/scripts/lua-scripts.d.ts +24 -0
  24. package/dist/lock/infrastructure/scripts/lua-scripts.d.ts.map +1 -0
  25. package/dist/locks.plugin.d.ts +41 -0
  26. package/dist/locks.plugin.d.ts.map +1 -0
  27. package/dist/shared/constants/index.d.ts +13 -0
  28. package/dist/shared/constants/index.d.ts.map +1 -0
  29. package/dist/shared/errors/index.d.ts +64 -0
  30. package/dist/shared/errors/index.d.ts.map +1 -0
  31. package/dist/shared/types/index.d.ts +97 -0
  32. package/dist/shared/types/index.d.ts.map +1 -0
  33. package/package.json +78 -0
@@ -0,0 +1,130 @@
1
+ import { ILockStore } from '../../application/ports/lock-store.port';
2
+ /**
3
+ * Represents an acquired distributed lock.
4
+ */
5
+ export interface ILock {
6
+ /** Lock key */
7
+ readonly key: string;
8
+ /** Unique token identifying lock ownership */
9
+ readonly token: string;
10
+ /** Lock TTL in milliseconds */
11
+ readonly ttl: number;
12
+ /** Timestamp when lock was acquired */
13
+ readonly acquiredAt: Date;
14
+ /** Timestamp when lock will expire */
15
+ readonly expiresAt: Date;
16
+ /** Whether auto-renewal is active */
17
+ readonly isAutoRenewing: boolean;
18
+ /**
19
+ * Releases the lock.
20
+ *
21
+ * @throws {LockNotOwnedError} If lock is not owned by this token
22
+ */
23
+ release(): Promise<void>;
24
+ /**
25
+ * Extends lock TTL.
26
+ *
27
+ * @param ttl - New TTL in milliseconds
28
+ * @throws {LockNotOwnedError} If lock was already released
29
+ * @throws {LockExtensionError} If extension fails
30
+ */
31
+ extend(ttl: number): Promise<void>;
32
+ /**
33
+ * Checks if lock is still held.
34
+ *
35
+ * @returns True if lock is held by this token
36
+ */
37
+ isHeld(): Promise<boolean>;
38
+ /**
39
+ * Stops automatic lock renewal.
40
+ */
41
+ stopAutoRenew(): void;
42
+ }
43
+ /**
44
+ * Lock entity implementation.
45
+ *
46
+ * Represents a distributed lock with automatic renewal capability.
47
+ * The lock maintains ownership through a unique token and can be
48
+ * extended or released explicitly.
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const lock = new Lock('my-resource', 'token-123', 30000, store);
53
+ *
54
+ * // Start auto-renewal every 15 seconds
55
+ * lock.startAutoRenew(15000);
56
+ *
57
+ * try {
58
+ * // Do work...
59
+ * await performOperation();
60
+ * } finally {
61
+ * await lock.release();
62
+ * }
63
+ * ```
64
+ */
65
+ export declare class Lock implements ILock {
66
+ private readonly store;
67
+ readonly key: string;
68
+ readonly token: string;
69
+ readonly ttl: number;
70
+ readonly acquiredAt: Date;
71
+ private _expiresAt;
72
+ private autoRenewTimer;
73
+ private released;
74
+ /**
75
+ * Creates a new Lock instance.
76
+ *
77
+ * @param key - Lock key in Redis
78
+ * @param token - Unique ownership token
79
+ * @param ttl - Time-to-live in milliseconds
80
+ * @param store - Lock store for persistence operations
81
+ */
82
+ constructor(key: string, token: string, ttl: number, store: ILockStore);
83
+ /**
84
+ * Gets the expiration timestamp.
85
+ */
86
+ get expiresAt(): Date;
87
+ /**
88
+ * Checks if auto-renewal is active.
89
+ */
90
+ get isAutoRenewing(): boolean;
91
+ /**
92
+ * Releases the lock.
93
+ *
94
+ * Stops auto-renewal and removes the lock from Redis.
95
+ * Idempotent - can be called multiple times safely.
96
+ *
97
+ * @throws {LockNotOwnedError} If lock is not owned by this token
98
+ */
99
+ release(): Promise<void>;
100
+ /**
101
+ * Extends the lock TTL.
102
+ *
103
+ * @param ttl - New TTL in milliseconds
104
+ * @throws {LockNotOwnedError} If lock was already released
105
+ * @throws {LockExtensionError} If extension fails (lock expired or not owned)
106
+ */
107
+ extend(ttl: number): Promise<void>;
108
+ /**
109
+ * Checks if lock is still held.
110
+ *
111
+ * @returns False if released, otherwise checks Redis
112
+ */
113
+ isHeld(): Promise<boolean>;
114
+ /**
115
+ * Starts automatic lock renewal.
116
+ *
117
+ * The lock will be extended at the specified interval
118
+ * until stopAutoRenew() is called or extension fails.
119
+ *
120
+ * @param intervalMs - Renewal interval in milliseconds
121
+ */
122
+ startAutoRenew(intervalMs: number): void;
123
+ /**
124
+ * Stops automatic lock renewal.
125
+ *
126
+ * Safe to call multiple times.
127
+ */
128
+ stopAutoRenew(): void;
129
+ }
130
+ //# sourceMappingURL=lock.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.entity.d.ts","sourceRoot":"","sources":["../../../../src/lock/domain/entities/lock.entity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,eAAe;IACf,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,+BAA+B;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,uCAAuC;IACvC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAE1B,sCAAsC;IACtC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAEzB,qCAAqC;IACrC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IAEjC;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC;;;;OAIG;IACH,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3B;;OAEG;IACH,aAAa,IAAI,IAAI,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,IAAK,YAAW,KAAK;IAsB9B,OAAO,CAAC,QAAQ,CAAC,KAAK;IArBxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAE1B,OAAO,CAAC,UAAU,CAAO;IACzB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;;;;OAOG;gBAED,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACM,KAAK,EAAE,UAAU;IASpC;;OAEG;IACH,IAAI,SAAS,IAAI,IAAI,CAEpB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED;;;;;;;OAOG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAe9B;;;;;;OAMG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxC;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAOhC;;;;;;;OAOG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAqBxC;;;;OAIG;IACH,aAAa,IAAI,IAAI;CAMtB"}
@@ -0,0 +1,45 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { IRedisDriver } from '@nestjs-redisx/core';
3
+ import { ILockStore } from '../../application/ports/lock-store.port';
4
+ /**
5
+ * Redis-based lock store implementation.
6
+ *
7
+ * Uses atomic Redis operations for lock management:
8
+ * - SET NX PX for acquiring locks
9
+ * - Lua scripts for safe release and extension
10
+ */
11
+ export declare class RedisLockStoreAdapter implements ILockStore, OnModuleInit {
12
+ private readonly driver;
13
+ private releaseSha;
14
+ private extendSha;
15
+ constructor(driver: IRedisDriver);
16
+ /**
17
+ * Lifecycle hook: loads Lua scripts into Redis on initialization.
18
+ */
19
+ onModuleInit(): Promise<void>;
20
+ /**
21
+ * Acquires lock using SET NX PX.
22
+ */
23
+ acquire(key: string, token: string, ttlMs: number): Promise<boolean>;
24
+ /**
25
+ * Releases lock if owned by token (Lua script).
26
+ */
27
+ release(key: string, token: string): Promise<boolean>;
28
+ /**
29
+ * Extends lock TTL if owned by token (Lua script).
30
+ */
31
+ extend(key: string, token: string, ttlMs: number): Promise<boolean>;
32
+ /**
33
+ * Checks if lock key exists.
34
+ */
35
+ exists(key: string): Promise<boolean>;
36
+ /**
37
+ * Checks if lock is held by specific token.
38
+ */
39
+ isHeldBy(key: string, token: string): Promise<boolean>;
40
+ /**
41
+ * Force removes lock without ownership check.
42
+ */
43
+ forceRelease(key: string): Promise<boolean>;
44
+ }
45
+ //# sourceMappingURL=redis-lock-store.adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-lock-store.adapter.d.ts","sourceRoot":"","sources":["../../../../src/lock/infrastructure/adapters/redis-lock-store.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAgB,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAGrE;;;;;;GAMG;AACH,qBACa,qBAAsB,YAAW,UAAU,EAAE,YAAY;IAIlC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHzD,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,SAAS,CAAuB;gBAEW,MAAM,EAAE,YAAY;IAEvE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAMnC;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ1E;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU3D;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUzE;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK3C;;OAEG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5D;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAIlD"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Inline Lua scripts for lock operations.
3
+ *
4
+ * Scripts are stored as inline strings to avoid issues with file reading
5
+ * after build (dist directory doesn't contain .lua files).
6
+ */
7
+ /**
8
+ * Release lock if owned by token.
9
+ *
10
+ * KEYS[1] = lock key
11
+ * ARGV[1] = owner token
12
+ * Returns: 1 if released, 0 if not owned or doesn't exist
13
+ */
14
+ export declare const RELEASE_LOCK_SCRIPT: string;
15
+ /**
16
+ * Extend lock TTL if owned by token.
17
+ *
18
+ * KEYS[1] = lock key
19
+ * ARGV[1] = owner token
20
+ * ARGV[2] = TTL in milliseconds
21
+ * Returns: 1 if extended, 0 if not owned or doesn't exist
22
+ */
23
+ export declare const EXTEND_LOCK_SCRIPT: string;
24
+ //# sourceMappingURL=lua-scripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lua-scripts.d.ts","sourceRoot":"","sources":["../../../../src/lock/infrastructure/scripts/lua-scripts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,QAMxB,CAAC;AAET;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,QAMvB,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Locks plugin for NestJS RedisX.
3
+ * Provides distributed locking with auto-renewal and retry strategies.
4
+ */
5
+ import { Provider } from '@nestjs/common';
6
+ import { IRedisXPlugin } from '@nestjs-redisx/core';
7
+ import { ILocksPluginOptions } from './shared/types';
8
+ /**
9
+ * Distributed locks plugin for NestJS RedisX.
10
+ *
11
+ * Provides distributed locking with auto-renewal and retry strategies.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * @Module({
16
+ * imports: [
17
+ * RedisModule.forRoot({
18
+ * clients: { host: 'localhost', port: 6379 },
19
+ * plugins: [
20
+ * new LocksPlugin({
21
+ * defaultTtl: 30000,
22
+ * keyPrefix: '_lock:',
23
+ * autoRenew: { enabled: true },
24
+ * }),
25
+ * ],
26
+ * }),
27
+ * ],
28
+ * })
29
+ * export class AppModule {}
30
+ * ```
31
+ */
32
+ export declare class LocksPlugin implements IRedisXPlugin {
33
+ private readonly options;
34
+ readonly name = "locks";
35
+ readonly version = "0.1.0";
36
+ readonly description = "Distributed locking with auto-renewal and retry strategies";
37
+ constructor(options?: ILocksPluginOptions);
38
+ getProviders(): Provider[];
39
+ getExports(): Array<string | symbol | Provider>;
40
+ }
41
+ //# sourceMappingURL=locks.plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locks.plugin.d.ts","sourceRoot":"","sources":["../src/locks.plugin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAqBrD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,WAAY,YAAW,aAAa;IAKnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,OAAO,WAAW;IAC3B,QAAQ,CAAC,WAAW,gEAAgE;gBAEvD,OAAO,GAAE,mBAAwB;IAE9D,YAAY,IAAI,QAAQ,EAAE;IA2C1B,UAAU,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;CAGhD"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Injection token for locks plugin options
3
+ */
4
+ export declare const LOCKS_PLUGIN_OPTIONS: unique symbol;
5
+ /**
6
+ * Injection token for lock service
7
+ */
8
+ export declare const LOCK_SERVICE: unique symbol;
9
+ /**
10
+ * Injection token for lock store
11
+ */
12
+ export declare const LOCK_STORE: unique symbol;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/constants/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,oBAAoB,eAAqC,CAAC;AAEvE;;GAEG;AACH,eAAO,MAAM,YAAY,eAA6B,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,UAAU,eAA2B,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { RedisXError, ErrorCode } from '@nestjs-redisx/core';
2
+ /**
3
+ * Base error class for all lock-related errors.
4
+ */
5
+ export declare class LockError extends RedisXError {
6
+ readonly lockKey: string;
7
+ constructor(message: string, code: ErrorCode, lockKey: string, cause?: Error);
8
+ }
9
+ /**
10
+ * Error thrown when lock acquisition fails.
11
+ */
12
+ export declare class LockAcquisitionError extends LockError {
13
+ readonly reason: 'timeout' | 'held' | 'error';
14
+ constructor(key: string, reason: 'timeout' | 'held' | 'error', cause?: Error);
15
+ }
16
+ /**
17
+ * Error thrown when attempting to release or extend a lock not owned by the caller.
18
+ */
19
+ export declare class LockNotOwnedError extends LockError {
20
+ readonly token: string;
21
+ constructor(key: string, token: string);
22
+ toJSON(): {
23
+ token: string;
24
+ name: string;
25
+ message: string;
26
+ code: string;
27
+ timestamp: string;
28
+ context?: Record<string, unknown>;
29
+ stack?: string;
30
+ cause?: {
31
+ name: string;
32
+ message: string;
33
+ stack?: string;
34
+ };
35
+ };
36
+ }
37
+ /**
38
+ * Error thrown when lock extension fails.
39
+ */
40
+ export declare class LockExtensionError extends LockError {
41
+ readonly token: string;
42
+ constructor(key: string, token: string, cause?: Error);
43
+ toJSON(): {
44
+ token: string;
45
+ name: string;
46
+ message: string;
47
+ code: string;
48
+ timestamp: string;
49
+ context?: Record<string, unknown>;
50
+ stack?: string;
51
+ cause?: {
52
+ name: string;
53
+ message: string;
54
+ stack?: string;
55
+ };
56
+ };
57
+ }
58
+ /**
59
+ * Error thrown when a lock has expired.
60
+ */
61
+ export declare class LockExpiredError extends LockError {
62
+ constructor(key: string);
63
+ }
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;GAEG;AACH,qBAAa,SAAU,SAAQ,WAAW;aAItB,OAAO,EAAE,MAAM;gBAF/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACC,OAAO,EAAE,MAAM,EAC/B,KAAK,CAAC,EAAE,KAAK;CAIhB;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;aAG/B,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO;gBADpD,GAAG,EAAE,MAAM,EACK,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,EACpD,KAAK,CAAC,EAAE,KAAK;CAIhB;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;aAG5B,KAAK,EAAE,MAAM;gBAD7B,GAAG,EAAE,MAAM,EACK,KAAK,EAAE,MAAM;IAKtB,MAAM;;;;;;;;;;;iBAoCijpH,CAAC;;;CA9BlkpH;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;aAG7B,KAAK,EAAE,MAAM;gBAD7B,GAAG,EAAE,MAAM,EACK,KAAK,EAAE,MAAM,EAC7B,KAAK,CAAC,EAAE,KAAK;IAKN,MAAM;;;;;;;;;;;iBAgBijpH,CAAC;;;CAVlkpH;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,SAAS;gBACjC,GAAG,EAAE,MAAM;CAGxB"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Configuration options for the Locks plugin
3
+ * @public
4
+ */
5
+ export interface ILocksPluginOptions {
6
+ /**
7
+ * Default TTL for locks in milliseconds
8
+ * @default 30000
9
+ */
10
+ defaultTtl?: number;
11
+ /**
12
+ * Maximum TTL for locks in milliseconds
13
+ * @default 300000
14
+ */
15
+ maxTtl?: number;
16
+ /**
17
+ * Key prefix for lock keys
18
+ * @default '_lock:'
19
+ */
20
+ keyPrefix?: string;
21
+ /**
22
+ * Retry configuration for lock acquisition
23
+ */
24
+ retry?: {
25
+ /**
26
+ * Maximum number of retries
27
+ * @default 3
28
+ */
29
+ maxRetries?: number;
30
+ /**
31
+ * Initial delay between retries in milliseconds
32
+ * @default 100
33
+ */
34
+ initialDelay?: number;
35
+ /**
36
+ * Maximum delay between retries in milliseconds
37
+ * @default 3000
38
+ */
39
+ maxDelay?: number;
40
+ /**
41
+ * Multiplier for exponential backoff
42
+ * @default 2
43
+ */
44
+ multiplier?: number;
45
+ };
46
+ /**
47
+ * Auto-renewal configuration
48
+ */
49
+ autoRenew?: {
50
+ /**
51
+ * Enable auto-renewal
52
+ * @default true
53
+ */
54
+ enabled?: boolean;
55
+ /**
56
+ * Fraction of TTL to use as renewal interval
57
+ * @default 0.5
58
+ */
59
+ intervalFraction?: number;
60
+ };
61
+ }
62
+ /**
63
+ * Options for lock acquisition
64
+ */
65
+ export interface ILockOptions {
66
+ /**
67
+ * Lock TTL in milliseconds
68
+ */
69
+ ttl?: number;
70
+ /**
71
+ * Maximum time to wait for lock acquisition in milliseconds
72
+ */
73
+ waitTimeout?: number;
74
+ /**
75
+ * Enable auto-renewal for this lock
76
+ */
77
+ autoRenew?: boolean;
78
+ /**
79
+ * Retry configuration for this specific lock
80
+ */
81
+ retry?: {
82
+ /**
83
+ * Maximum number of retries
84
+ */
85
+ maxRetries?: number;
86
+ /**
87
+ * Initial delay between retries in milliseconds
88
+ */
89
+ initialDelay?: number;
90
+ };
91
+ }
92
+ /**
93
+ * Alias for plugin options (for consistency with plugin naming)
94
+ * @public
95
+ */
96
+ export type LocksPluginOptions = ILocksPluginOptions;
97
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE;QACN;;;WAGG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;QAEpB;;;WAGG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;QAEtB;;;WAGG;QACH,QAAQ,CAAC,EAAE,MAAM,CAAC;QAElB;;;WAGG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IAEF;;OAEG;IACH,SAAS,CAAC,EAAE;QACV;;;WAGG;QACH,OAAO,CAAC,EAAE,OAAO,CAAC;QAElB;;;WAGG;QACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,KAAK,CAAC,EAAE;QACN;;WAEG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;QAEpB;;WAEG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@nestjs-redisx/locks",
3
+ "version": "1.0.0",
4
+ "description": "Distributed locks plugin for NestJS RedisX with auto-renewal and retry strategies",
5
+ "author": "NestJS RedisX Team",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "require": "./dist/index.js",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "test": "SKIP_INTEGRATION=true vitest run",
25
+ "test:watch": "SKIP_INTEGRATION=true vitest",
26
+ "test:cov": "SKIP_INTEGRATION=true vitest run --coverage",
27
+ "test:integration": "vitest run test/integration/locks.integration.spec.ts",
28
+ "test:integration:watch": "vitest watch test/integration/locks.integration.spec.ts",
29
+ "docker:up": "docker-compose up -d",
30
+ "docker:down": "docker-compose down",
31
+ "docker:logs": "docker-compose logs -f redis",
32
+ "test:docker": "npm run docker:up && sleep 3 && npm run test:integration; TEST_EXIT=$?; npm run docker:down; exit $TEST_EXIT",
33
+ "test:all": "npm test && npm run test:integration",
34
+ "lint": "eslint \"{src,test}/**/*.ts\"",
35
+ "format": "prettier --write \"{src,test}/**/*.ts\""
36
+ },
37
+ "keywords": [
38
+ "nestjs",
39
+ "redis",
40
+ "locks",
41
+ "distributed",
42
+ "mutex",
43
+ "semaphore",
44
+ "auto-renewal",
45
+ "retry"
46
+ ],
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "https://github.com/nestjs-redisx/nestjs-redisx.git",
50
+ "directory": "packages/locks"
51
+ },
52
+ "homepage": "https://nestjs-redisx.dev/en/reference/locks/",
53
+ "bugs": {
54
+ "url": "https://github.com/nestjs-redisx/nestjs-redisx/issues"
55
+ },
56
+ "peerDependencies": {
57
+ "@nestjs-redisx/core": "^1.0.0",
58
+ "@nestjs/common": "^10.0.0",
59
+ "@nestjs/core": "^10.0.0",
60
+ "reflect-metadata": "^0.2.0",
61
+ "rxjs": "^7.8.0"
62
+ },
63
+ "devDependencies": {
64
+ "@nestjs/testing": "^10.0.0",
65
+ "@types/node": "^20.0.0",
66
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
67
+ "@typescript-eslint/parser": "^6.0.0",
68
+ "eslint": "^8.0.0",
69
+ "prettier": "^3.0.0",
70
+ "tsup": "^8.0.0",
71
+ "typescript": "^5.3.0",
72
+ "vitest": "^1.6.0",
73
+ "@vitest/coverage-v8": "^1.6.0"
74
+ },
75
+ "publishConfig": {
76
+ "access": "public"
77
+ }
78
+ }