murlock 3.4.1-beta.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 +38 -42
- package/dist/decorators/murlock.decorator.js +2 -39
- package/dist/decorators/murlock.decorator.js.map +1 -1
- package/dist/murlock.service.d.ts +5 -3
- package/dist/murlock.service.js +41 -7
- package/dist/murlock.service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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.
|
|
207
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
265
|
-
|
|
266
|
-
- **
|
|
267
|
-
- **
|
|
268
|
-
- **
|
|
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
|
|
68
|
-
|
|
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":";;;;;;;;;;;;AAAA,2CAAwC;AACxC,8CAAiD;AACjD,wDAAoD;
|
|
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
|
|
18
|
-
unlock
|
|
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
|
}
|
package/dist/murlock.service.js
CHANGED
|
@@ -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,
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAiG;AACjG,iCAAsD;AACtD,2BAAkC;AAClC,+BAA4B;AAE5B,6CAAuE;AACvE,mDAAwD;
|
|
1
|
+
{"version":3,"file":"murlock.service.js","sourceRoot":"","sources":["../lib/murlock.service.ts"],"names":[],"mappings":"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"}
|