murlock 3.4.1 → 4.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.
package/README.md CHANGED
@@ -117,7 +117,6 @@ In the example above, the `ConfigModule` and `ConfigService` are used to provide
117
117
 
118
118
  For more details on usage and configuration, please refer to the API documentation below.
119
119
 
120
-
121
120
  ## Using Custom Lock Key
122
121
 
123
122
  By default, murlock use class and method name prefix for example Userservice:createUser:{userId}. By setting lockKeyPrefix as 'custom' you can define by yourself manually.
@@ -142,6 +141,7 @@ import { MurLockModule } from 'murlock';
142
141
  })
143
142
  export class AppModule {}
144
143
  ```
144
+
145
145
  ```typescript
146
146
  import { MurLock } from 'murlock';
147
147
 
@@ -175,9 +175,9 @@ If we assume userId as 65782628 Lockey here will be someCustomKey:65782628
175
175
 
176
176
  ## Using `MurLockService` Directly
177
177
 
178
- While the `@MurLock()` decorator provides a convenient and declarative way to handle locking within your NestJS application, there may be cases where you need more control over the lock lifecycle. For such cases, `MurLockService` offers a programmatic way to manage locks.
178
+ While the `@MurLock()` decorator provides a convenient and declarative way to handle locking within your NestJS application, there may be cases where you need more control over the lock lifecycle. For such cases, `MurLockService` offers a programmatic way to manage locks, allowing for fine-grained control over the lock and unlock process through the `runWithLock` method.
179
179
 
180
- #### Injecting `MurLockService`
180
+ ### Injecting `MurLockService`
181
181
 
182
182
  First, inject `MurLockService` into your service:
183
183
 
@@ -195,61 +195,58 @@ export class YourService {
195
195
 
196
196
  #### Acquiring a Lock
197
197
 
198
- You can acquire a lock by calling the `acquireLock` method with a unique `lockKey` and the desired `lockTime`:
198
+ You no longer need to manually manage `lock` and `unlock`. Instead, use the `runWithLock` method, which handles both acquiring and releasing the lock:
199
199
 
200
200
  ```typescript
201
201
  async performTaskWithLock() {
202
202
  const lockKey = 'unique_lock_key';
203
- const lockTime = 3000; // Duration for which the lock should be held in milliseconds
203
+ const lockTime = 3000; // Duration for which the lock should be held, in milliseconds
204
204
 
205
205
  try {
206
- await this.murLockService.acquireLock(lockKey, lockTime);
207
- // Proceed with the operation that requires the lock
206
+ await this.murLockService.runWithLock(lockKey, lockTime, async () => {
207
+ // Proceed with the operation that requires the lock
208
+ });
208
209
  } catch (error) {
209
- // Handle the error if the lock could not be acquired
210
+ // Handle the error if the lock could not be acquired or any other exceptions
210
211
  throw error;
211
- } finally {
212
- // Make sure to release the lock
213
- await this.murLockService.releaseLock(lockKey);
214
212
  }
215
213
  }
216
214
  ```
217
215
 
218
- #### Releasing a Lock
219
-
220
- To release a lock, use the `releaseLock` method:
221
-
222
- ```typescript
223
- await this.murLockService.releaseLock(lockKey);
224
- ```
225
-
226
- #### Handling Errors
216
+ ### Handling Errors
227
217
 
228
- Make sure to handle exceptions gracefully, especially when you are unable to acquire a lock:
218
+ The `runWithLock` method throws an exception if the lock cannot be acquired within the specified time or if an error occurs during the execution of the function:
229
219
 
230
220
  ```typescript
231
221
  try {
232
- // Lock acquisition attempts
222
+ await this.murLockService.runWithLock(lockKey, lockTime, async () => {
223
+ // Locked operations
224
+ });
233
225
  } catch (error) {
234
226
  // Error handling logic
235
- } finally {
236
- // Always release the lock in a finally block
237
227
  }
238
228
  ```
239
229
 
240
- #### Best Practices and Considerations
241
-
242
- - Always release locks in a `finally` block to avoid deadlocks.
243
- - Use meaningful lock keys that are unique to the resources they represent.
244
- - Even with `ignoreUnlockFail` set to true, you should implement your error handling logic. This could include logging and retry mechanisms for critical operations.
245
- - Keep lock durations as short as possible to prevent system blockage.
246
-
247
230
  Directly using `MurLockService` gives you finer control over lock management but also increases the responsibility to ensure locks are correctly managed throughout your application's lifecycle.
248
231
 
249
232
  ---
250
233
 
251
234
  This refined section is suitable for developers looking for documentation on using `MurLockService` directly in their projects and adheres to the typical conventions found in README files for open-source projects.
252
235
 
236
+ ## Best Practices and Considerations
237
+
238
+ - **Short-lived Locks**: Ensure that locks are short-lived to prevent deadlocks and to increase the efficiency of your application.
239
+ **Error Handling**: Robustly handle errors during lock acquisition:
240
+ - **Graceful Failures**: If a lock cannot be obtained, handle the situation gracefully, potentially logging the incident and retrying the operation.
241
+ - **Consider Failures in Unlocking**: Even with `ignoreUnlockFail` set to true, implement error handling strategies to log and manage unlock failures, ensuring they do not disrupt the application flow.
242
+ - **Logging**: Adjust the `logLevel` based on your environment. Use 'debug' for development and 'error' or 'warn' for production.
243
+ - **Consistency**: Use consistent lock keys that clearly represent the resources or operations they are meant to protect.
244
+ - **Customizable Lock Keys**: Utilize the `lockKeyPrefix` to tailor how lock keys are constructed:
245
+ - **Default**: Automatically includes the class and method name, e.g., `Userservice:createUser:{userId}`.
246
+ - **Custom**: Set `lockKeyPrefix` to 'custom' and define lock keys explicitly to fine-tune lock scope and granularity.
247
+ - **Resource Cleanup**: Even though `runWithLock` manages lock cleanup, ensure your application logic correctly handles any necessary cleanup or rollback in case of errors.
248
+ - **Use of Finally Block**: Explicitly manage lock release in a `finally` block to ensure that locks are always released, preventing potential deadlocks and resource leaks.
249
+
253
250
  ## API Documentation
254
251
 
255
252
  ### MurLock(releaseTime: number, ...keyParams: string[])
@@ -261,22 +258,21 @@ A method decorator to indicate that a particular method should be locked.
261
258
 
262
259
  ### Configuration Options
263
260
 
264
- - **redisOptions:** Configuration options for the Redis client.
265
- - **wait:** Time (in milliseconds) to wait before retrying if a lock isn't obtained.
266
- - **maxAttempts:** Maximum number of attempts to obtain a lock.
267
- - **logLevel:** Logging level. Can be one of 'none', 'error', 'warn', 'log', or 'debug'.
268
- - **ignoreUnlockFail (optional):** When set to `true`, the library will not throw an exception if it fails to release a lock. Defaults to `false` to maintain backward compatibility.
261
+ Here are the customizable options for `MurLockModule`, allowing you to tailor its behavior to best fit your application's needs:
262
+
263
+ - **redisOptions:** Configuration settings for the Redis client, such as the connection URL.
264
+ - **wait:** Time in milliseconds to wait before retrying to obtain a lock if the initial attempt fails.
265
+ - **maxAttempts:** The maximum number of attempts to try and acquire a lock before giving up.
266
+ - **logLevel:** Determines the level of logging used within the module. Options include 'none', 'error', 'warn', 'log', or 'debug'.
267
+ - **ignoreUnlockFail (optional):** When set to `true`, the module will not throw an exception if releasing a lock fails. This setting helps in scenarios where failing silently is preferred over interrupting the application flow. Defaults to `false` to ensure that failures are noticed and handled appropriately.
268
+ - **lockKeyPrefix (optional)**: Specifies how lock keys are prefixed, allowing for greater flexibility:
269
+ - **Default**: Uses class and method names as prefixes, e.g., `Userservice:createUser:{userId}`.
270
+ - **Custom**: Set this to 'custom' to define lock keys manually in your service methods, allowing for specific lock key constructions beyond the standard naming.
269
271
 
270
272
  ### MurLockService
271
273
 
272
274
  A NestJS injectable service to interact with the locking mechanism directly.
273
275
 
274
- ## Best Practices
275
-
276
- - **Short-lived Locks:** Ensure that locks are short-lived to prevent deadlocks and increase the efficiency of your application.
277
- - **Error Handling:** Always handle errors gracefully. If a lock isn't obtained, it's often better to return a failure or retry after some time.
278
- - **Logging:** Adjust the `logLevel` based on your environment. Use 'debug' for development and 'error' or 'warn' for production.
279
-
280
276
  ## Limitations
281
277
 
282
278
  - **Redis Persistence:** Ensure that your Redis instance has RDB persistence enabled. This ensures that in case of a crash, locks are not lost.
@@ -13,8 +13,6 @@ exports.MurLock = void 0;
13
13
  const common_1 = require("@nestjs/common");
14
14
  const exceptions_1 = require("../exceptions");
15
15
  const murlock_service_1 = require("../murlock.service");
16
- const utils_1 = require("../utils");
17
- const als_service_1 = require("../als/als.service");
18
16
  function getParameterNames(func) {
19
17
  const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
20
18
  const ARGUMENT_NAMES = /([^\s,]+)/g;
@@ -24,10 +22,8 @@ function getParameterNames(func) {
24
22
  }
25
23
  function MurLock(releaseTime, ...keyParams) {
26
24
  const injectMurlockService = (0, common_1.Inject)(murlock_service_1.MurLockService);
27
- const injectAsyncStorageService = (0, common_1.Inject)(als_service_1.AsyncStorageService);
28
25
  return (target, propertyKey, descriptor) => {
29
26
  injectMurlockService(target, 'murlockServiceDecorator');
30
- injectAsyncStorageService(target, 'asyncStorageService');
31
27
  const originalMethod = descriptor.value;
32
28
  const methodParameterNames = getParameterNames(originalMethod);
33
29
  function constructLockKey(args, lockKeyPrefix = 'default') {
@@ -59,21 +55,12 @@ function MurLock(releaseTime, ...keyParams) {
59
55
  descriptor.value = function (...args) {
60
56
  return __awaiter(this, void 0, void 0, function* () {
61
57
  const murLockService = this.murlockServiceDecorator;
62
- const asyncStorageService = this.asyncStorageService;
63
58
  const lockKey = constructLockKey(args, murLockService.options.lockKeyPrefix);
64
59
  if (!murLockService) {
65
60
  throw new exceptions_1.MurLockException('MurLockService is not available.');
66
61
  }
67
- return asyncStorageService.runWithNewContext(() => __awaiter(this, void 0, void 0, function* () {
68
- asyncStorageService.registerContext();
69
- asyncStorageService.setClientID('clientId', (0, utils_1.generateUuid)());
70
- yield acquireLock(lockKey, murLockService, releaseTime);
71
- try {
72
- return yield originalMethod.apply(this, args);
73
- }
74
- finally {
75
- yield releaseLock(lockKey, murLockService);
76
- }
62
+ return murLockService.runWithLock(lockKey, releaseTime, () => __awaiter(this, void 0, void 0, function* () {
63
+ return originalMethod.apply(this, args);
77
64
  }));
78
65
  });
79
66
  };
@@ -81,30 +68,6 @@ function MurLock(releaseTime, ...keyParams) {
81
68
  };
82
69
  }
83
70
  exports.MurLock = MurLock;
84
- function acquireLock(lockKey, murLockService, releaseTime) {
85
- return __awaiter(this, void 0, void 0, function* () {
86
- let isLockSuccessful = false;
87
- try {
88
- isLockSuccessful = yield murLockService.lock(lockKey, releaseTime);
89
- }
90
- catch (error) {
91
- throw new exceptions_1.MurLockException(`Failed to acquire lock for key ${lockKey}: ${error.message}`);
92
- }
93
- if (!isLockSuccessful) {
94
- throw new exceptions_1.MurLockException(`Could not obtain lock for key ${lockKey}`);
95
- }
96
- });
97
- }
98
- function releaseLock(lockKey, murLockService) {
99
- return __awaiter(this, void 0, void 0, function* () {
100
- try {
101
- yield murLockService.unlock(lockKey);
102
- }
103
- catch (error) {
104
- throw new exceptions_1.MurLockException(`Failed to release lock for key ${lockKey}: ${error.message}`);
105
- }
106
- });
107
- }
108
71
  function isNumber(value) {
109
72
  const parsedValue = parseFloat(value);
110
73
  if (!isNaN(parsedValue)) {
@@ -1 +1 @@
1
- {"version":3,"file":"murlock.decorator.js","sourceRoot":"","sources":["../../lib/decorators/murlock.decorator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"murlock.decorator.js","sourceRoot":"","sources":["../../lib/decorators/murlock.decorator.ts"],"names":[],"mappings":"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"}
@@ -11,9 +11,11 @@ export declare class MurLockService implements OnModuleInit, OnApplicationShutdo
11
11
  constructor(options: MurLockModuleOptions, asyncStorageService: AsyncStorageService);
12
12
  onModuleInit(): Promise<void>;
13
13
  onApplicationShutdown(signal?: string): Promise<void>;
14
- private getClientId;
15
14
  private sleep;
16
15
  private log;
17
- lock(lockKey: string, releaseTime: number, attemptsRemaining?: number): Promise<boolean>;
18
- unlock(lockKey: string): Promise<void>;
16
+ private lock;
17
+ private unlock;
18
+ private acquireLock;
19
+ private releaseLock;
20
+ runWithLock<R>(lockKey: string, releaseTime: number, fn: () => Promise<R>): Promise<R>;
19
21
  }
@@ -29,6 +29,7 @@ const fs_1 = require("fs");
29
29
  const path_1 = require("path");
30
30
  const exceptions_1 = require("./exceptions");
31
31
  const als_service_1 = require("./als/als.service");
32
+ const utils_1 = require("./utils");
32
33
  let MurLockService = MurLockService_1 = class MurLockService {
33
34
  constructor(options, asyncStorageService) {
34
35
  this.options = options;
@@ -55,9 +56,6 @@ let MurLockService = MurLockService_1 = class MurLockService {
55
56
  }
56
57
  });
57
58
  }
58
- getClientId() {
59
- return this.asyncStorageService.get('clientId');
60
- }
61
59
  sleep(ms) {
62
60
  return new Promise((resolve) => setTimeout(resolve, ms));
63
61
  }
@@ -67,9 +65,8 @@ let MurLockService = MurLockService_1 = class MurLockService {
67
65
  this.logger[level](message, context);
68
66
  }
69
67
  }
70
- lock(lockKey, releaseTime, attemptsRemaining = this.options.maxAttempts) {
68
+ lock(lockKey, releaseTime, clientId) {
71
69
  return __awaiter(this, void 0, void 0, function* () {
72
- const clientId = this.getClientId();
73
70
  this.log('debug', `MurLock Client ID is ${clientId}`);
74
71
  const attemptLock = (attemptsRemaining) => __awaiter(this, void 0, void 0, function* () {
75
72
  if (attemptsRemaining === 0) {
@@ -101,9 +98,8 @@ let MurLockService = MurLockService_1 = class MurLockService {
101
98
  return attemptLock(this.options.maxAttempts);
102
99
  });
103
100
  }
104
- unlock(lockKey) {
101
+ unlock(lockKey, clientId) {
105
102
  return __awaiter(this, void 0, void 0, function* () {
106
- const clientId = this.getClientId();
107
103
  const result = yield this.redisClient.sendCommand([
108
104
  'EVAL',
109
105
  this.unlockScript,
@@ -121,6 +117,44 @@ let MurLockService = MurLockService_1 = class MurLockService {
121
117
  }
122
118
  });
123
119
  }
120
+ acquireLock(lockKey, clientId, releaseTime) {
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ let isLockSuccessful = false;
123
+ try {
124
+ isLockSuccessful = yield this.lock(lockKey, releaseTime, clientId);
125
+ }
126
+ catch (error) {
127
+ throw new exceptions_1.MurLockException(`Failed to acquire lock for key ${lockKey}: ${error.message}`);
128
+ }
129
+ if (!isLockSuccessful) {
130
+ throw new exceptions_1.MurLockException(`Could not obtain lock for key ${lockKey}`);
131
+ }
132
+ });
133
+ }
134
+ releaseLock(lockKey, clientId) {
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ try {
137
+ yield this.unlock(lockKey, clientId);
138
+ }
139
+ catch (error) {
140
+ throw new exceptions_1.MurLockException(`Failed to release lock for key ${lockKey}: ${error.message}`);
141
+ }
142
+ });
143
+ }
144
+ runWithLock(lockKey, releaseTime, fn) {
145
+ return __awaiter(this, void 0, void 0, function* () {
146
+ this.asyncStorageService.registerContext();
147
+ this.asyncStorageService.setClientID('clientId', (0, utils_1.generateUuid)());
148
+ const clientId = this.asyncStorageService.get('clientId');
149
+ yield this.acquireLock(lockKey, clientId, releaseTime);
150
+ try {
151
+ return yield fn();
152
+ }
153
+ finally {
154
+ yield this.releaseLock(lockKey, clientId);
155
+ }
156
+ });
157
+ }
124
158
  };
125
159
  exports.MurLockService = MurLockService;
126
160
  exports.MurLockService = MurLockService = MurLockService_1 = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"murlock.service.js","sourceRoot":"","sources":["../lib/murlock.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"murlock.service.js","sourceRoot":"","sources":["../lib/murlock.service.ts"],"names":[],"mappings":"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"}