murlock 5.0.0 → 5.1.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
@@ -166,6 +166,8 @@ async anotherFunction(user: User): Promise<void> {
166
166
 
167
167
  When using `@MurLock` with other decorators (such as `@Transactional` from typeorm-transactional), you may encounter issues with parameter name extraction if the other decorator wraps the method before `@MurLock` is applied.
168
168
 
169
+ > **Note on minification / transpilation:** MurLock derives parameter names by parsing the method signature at runtime. Aggressive minifiers/bundlers (terser, esbuild, swc) may rename or strip parameter names, in which case **name-based** key params (e.g. `'userId'`, `'user.id'`) cannot be resolved and the decorator throws `Parameter ... not found`. If you minify your server build, either use **numeric index** key params (e.g. `'0'`, `'0.id'`) — which are always stable — or declare names explicitly with `@SetParamNames` (below).
170
+
169
171
  ### Problem
170
172
 
171
173
  TypeScript decorators execute in bottom-up order. If another decorator wraps the method before `@MurLock`, the parameter names cannot be extracted from the wrapped function:
@@ -519,6 +521,9 @@ Here are the customizable options for `MurLockModule`, allowing you to tailor it
519
521
  - **autoExtend (optional)**: When set to `true`, MurLock keeps the lock alive while the wrapped operation is still running by periodically extending its TTL (a "watchdog"). This prevents the lock from expiring mid-execution when an operation runs longer than `releaseTime`, which would otherwise let another instance acquire the same lock and break mutual exclusion. Defaults to `false`.
520
522
  - **extendInterval (optional)**: Interval in milliseconds between watchdog TTL extensions. Only used when `autoExtend` is `true`. Defaults to one third of the lock's `releaseTime` (`Math.floor(releaseTime / 3)`), guaranteeing at least two refresh attempts before the TTL would expire.
521
523
  - **onRedisError (optional)**: Callback `(error: Error) => void` invoked when the Redis client emits a runtime `error` event. Use it to plug in custom alerting or fail-fast behavior.
524
+ - **reentrant (optional)**: When set to `true`, locks become reentrant within the same async context: a method that locks a key and (directly or transitively) calls another method locking the **same** key reuses the existing lock instead of deadlocking. The underlying Redis lock is acquired once (outermost entry) and released when the outermost call completes. Defaults to `false`.
525
+ - **encodeKeyParts (optional)**: When set to `true`, each lock-key part derived from method arguments is URL-encoded so values containing the `:` separator cannot collide (e.g. `a:b` + `c` vs `a` + `b:c`). Changes the generated key format, so it is opt-in to avoid breaking existing keys across a rolling deploy. Defaults to `false`.
526
+ - **jitter (optional)**: When set to `true`, retry back-off delays use equal jitter (`delay/2 + random*delay/2`) to avoid a thundering herd when many workers wait on the same lock. Applies to both attempt-based and blocking modes. Defaults to `false`.
522
527
 
523
528
  ### MurLockService
524
529
 
@@ -1,21 +1,8 @@
1
1
  /// <reference types="node" />
2
2
  import { AsyncLocalStorage } from 'async_hooks';
3
- export declare class AsyncStorageManager<T> implements Map<string, T> {
3
+ export declare class AsyncStorageManager<T> {
4
4
  private readonly asyncLocalStorage;
5
- constructor(asyncLocalStorage?: AsyncLocalStorage<Map<string, T>>);
6
- private getStore;
7
- register(): void;
8
- runWithNewContext<R, TArgs extends any[]>(fn: (...args: TArgs) => R, ...args: TArgs): R;
9
- set(key: string, value: T): this;
10
- get(key: string): T | undefined;
11
- clear(): void;
12
- delete(key: string): boolean;
13
- forEach(callbackfn: (value: T, key: string, map: Map<string, T>) => void, thisArg?: any): void;
14
- has(key: string): boolean;
15
- get size(): number;
16
- entries(): IterableIterator<[string, T]>;
17
- keys(): IterableIterator<string>;
18
- values(): IterableIterator<T>;
19
- [Symbol.iterator](): IterableIterator<[string, T]>;
20
- [Symbol.toStringTag]: string;
5
+ constructor(asyncLocalStorage?: AsyncLocalStorage<T>);
6
+ run<R>(store: T, fn: () => R): R;
7
+ getStore(): T | undefined;
21
8
  }
@@ -8,67 +8,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
- var _a;
12
11
  Object.defineProperty(exports, "__esModule", { value: true });
13
12
  exports.AsyncStorageManager = void 0;
14
13
  const common_1 = require("@nestjs/common");
15
14
  const async_hooks_1 = require("async_hooks");
16
- const exceptions_1 = require("../exceptions");
17
15
  let AsyncStorageManager = class AsyncStorageManager {
18
16
  constructor(asyncLocalStorage = new async_hooks_1.AsyncLocalStorage()) {
19
17
  this.asyncLocalStorage = asyncLocalStorage;
20
- this[_a] = '[object AsyncContext]';
21
18
  }
22
- getStore() {
23
- const store = this.asyncLocalStorage.getStore();
24
- if (!store) {
25
- throw new exceptions_1.AsyncStorageManagerException('No active store found');
26
- }
27
- return store;
28
- }
29
- register() {
30
- this.asyncLocalStorage.enterWith(new Map());
31
- }
32
- runWithNewContext(fn, ...args) {
33
- return this.asyncLocalStorage.run(new Map(), fn, ...args);
34
- }
35
- set(key, value) {
36
- this.getStore().set(key, value);
37
- return this;
38
- }
39
- get(key) {
40
- return this.getStore().get(key);
41
- }
42
- clear() {
43
- return this.getStore().clear();
44
- }
45
- delete(key) {
46
- return this.getStore().delete(key);
19
+ run(store, fn) {
20
+ return this.asyncLocalStorage.run(store, fn);
47
21
  }
48
- forEach(callbackfn, thisArg) {
49
- return this.getStore().forEach(callbackfn, thisArg);
50
- }
51
- has(key) {
52
- return this.getStore().has(key);
53
- }
54
- get size() {
55
- return this.getStore().size;
56
- }
57
- entries() {
58
- return this.getStore().entries();
59
- }
60
- keys() {
61
- return this.getStore().keys();
62
- }
63
- values() {
64
- return this.getStore().values();
65
- }
66
- [Symbol.iterator]() {
67
- return this.getStore()[Symbol.iterator]();
22
+ getStore() {
23
+ return this.asyncLocalStorage.getStore();
68
24
  }
69
25
  };
70
26
  exports.AsyncStorageManager = AsyncStorageManager;
71
- _a = Symbol.toStringTag;
72
27
  exports.AsyncStorageManager = AsyncStorageManager = __decorate([
73
28
  (0, common_1.Injectable)(),
74
29
  __metadata("design:paramtypes", [Object])
@@ -1 +1 @@
1
- {"version":3,"file":"als-manager.js","sourceRoot":"","sources":["../../lib/als/als-manager.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,6CAAgD;AAChD,8CAA6D;AAGtD,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YAA6B,oBAAoB,IAAI,+BAAiB,EAAkB;QAA3D,sBAAiB,GAAjB,iBAAiB,CAA0C;QA+DxF,QAAoB,GAAW,uBAAuB,CAAC;IA/DoC,CAAC;IAEpF,QAAQ;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;QAChD,IAAI,CAAC,KAAK,EAAE;YACV,MAAM,IAAI,yCAA4B,CAAC,uBAAuB,CAAC,CAAC;SACjE;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,iBAAiB,CAAyB,EAAyB,EAAE,GAAG,IAAW;QACjF,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,GAAG,EAAa,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACvE,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAQ;QACvB,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,CAAC,UAAgE,EAAE,OAAa;QACrF,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC;IACnC,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC;IAClC,CAAC;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC5C,CAAC;CAGF,CAAA;AAjEY,kDAAmB;KAgE7B,MAAM,CAAC,WAAW;8BAhER,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;;GACA,mBAAmB,CAiE/B"}
1
+ {"version":3,"file":"als-manager.js","sourceRoot":"","sources":["../../lib/als/als-manager.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,6CAAgD;AAQzC,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YACmB,oBAAoB,IAAI,+BAAiB,EAAK;QAA9C,sBAAiB,GAAjB,iBAAiB,CAA6B;IAC9D,CAAC;IAGJ,GAAG,CAAI,KAAQ,EAAE,EAAW;QAC1B,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC;IAGD,QAAQ;QACN,OAAO,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;IAC3C,CAAC;CACF,CAAA;AAdY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;;GACA,mBAAmB,CAc/B"}
@@ -20,9 +20,7 @@ exports.AsyncStorageManagerModule = AsyncStorageManagerModule = __decorate([
20
20
  providers: [
21
21
  {
22
22
  provide: als_manager_1.AsyncStorageManager,
23
- useFactory: () => {
24
- return new als_manager_1.AsyncStorageManager(new async_hooks_1.AsyncLocalStorage());
25
- },
23
+ useFactory: () => new als_manager_1.AsyncStorageManager(new async_hooks_1.AsyncLocalStorage()),
26
24
  },
27
25
  als_service_1.AsyncStorageService,
28
26
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"als.module.js","sourceRoot":"","sources":["../../lib/als/als.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,+CAAoD;AACpD,+CAAoD;AACpD,6CAAgD;AAezC,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;CAAG,CAAA;AAA5B,8DAAyB;oCAAzB,yBAAyB;IAbrC,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,iCAAmB;gBAC5B,UAAU,EAAE,GAAG,EAAE;oBACf,OAAO,IAAI,iCAAmB,CAAS,IAAI,+BAAiB,EAAuB,CAAC,CAAC;gBACvF,CAAC;aACF;YACD,iCAAmB;SACpB;QACD,OAAO,EAAE,CAAC,iCAAmB,CAAC;KAC/B,CAAC;GACW,yBAAyB,CAAG"}
1
+ {"version":3,"file":"als.module.js","sourceRoot":"","sources":["../../lib/als/als.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,+CAAoD;AACpD,+CAAoE;AACpE,6CAAgD;AAgBzC,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;CAAG,CAAA;AAA5B,8DAAyB;oCAAzB,yBAAyB;IAdrC,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,iCAAmB;gBAC5B,UAAU,EAAE,GAAG,EAAE,CACf,IAAI,iCAAmB,CACrB,IAAI,+BAAiB,EAAkB,CACxC;aACJ;YACD,iCAAmB;SACpB;QACD,OAAO,EAAE,CAAC,iCAAmB,CAAC;KAC/B,CAAC;GACW,yBAAyB,CAAG"}
@@ -1,9 +1,11 @@
1
1
  import { AsyncStorageManager } from './als-manager';
2
+ export interface MurLockContext {
3
+ clientId: string;
4
+ holds: Map<string, number>;
5
+ }
2
6
  export declare class AsyncStorageService {
3
7
  private readonly asyncStorageManager;
4
- constructor(asyncStorageManager: AsyncStorageManager<string>);
5
- runWithNewContext<R, TArgs extends any[]>(fn: (...args: TArgs) => R, ...args: TArgs): R;
6
- registerContext(): void;
7
- get(key: string): string;
8
- setClientID(key: string, value: string): void;
8
+ constructor(asyncStorageManager: AsyncStorageManager<MurLockContext>);
9
+ run<R>(store: MurLockContext, fn: () => R): R;
10
+ getContext(): MurLockContext | undefined;
9
11
  }
@@ -16,17 +16,11 @@ let AsyncStorageService = class AsyncStorageService {
16
16
  constructor(asyncStorageManager) {
17
17
  this.asyncStorageManager = asyncStorageManager;
18
18
  }
19
- runWithNewContext(fn, ...args) {
20
- return this.asyncStorageManager.runWithNewContext(fn, ...args);
19
+ run(store, fn) {
20
+ return this.asyncStorageManager.run(store, fn);
21
21
  }
22
- registerContext() {
23
- this.asyncStorageManager.register();
24
- }
25
- get(key) {
26
- return this.asyncStorageManager.get(key);
27
- }
28
- setClientID(key, value) {
29
- this.asyncStorageManager.set(key, value);
22
+ getContext() {
23
+ return this.asyncStorageManager.getStore();
30
24
  }
31
25
  };
32
26
  exports.AsyncStorageService = AsyncStorageService;
@@ -1 +1 @@
1
- {"version":3,"file":"als.service.js","sourceRoot":"","sources":["../../lib/als/als.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+CAAoD;AAG7C,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YAA6B,mBAAgD;QAAhD,wBAAmB,GAAnB,mBAAmB,CAA6B;IAAG,CAAC;IAEjF,iBAAiB,CAAyB,EAAyB,EAAE,GAAG,IAAW;QACjF,OAAO,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACjE,CAAC;IAED,eAAe;QACb,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IAED,WAAW,CAAC,GAAW,EAAE,KAAa;QACpC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;CACF,CAAA;AAlBY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;qCAEuC,iCAAmB;GAD1D,mBAAmB,CAkB/B"}
1
+ {"version":3,"file":"als.service.js","sourceRoot":"","sources":["../../lib/als/als.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+CAAoD;AAa7C,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YACmB,mBAAwD;QAAxD,wBAAmB,GAAnB,mBAAmB,CAAqC;IACxE,CAAC;IAGJ,GAAG,CAAI,KAAqB,EAAE,EAAW;QACvC,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;IAGD,UAAU;QACR,OAAO,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC;IAC7C,CAAC;CACF,CAAA;AAdY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;qCAG6B,iCAAmB;GAFhD,mBAAmB,CAc/B"}
@@ -121,7 +121,8 @@ function MurLock(releaseTime, waitOrKeyParam, ...keyParams) {
121
121
  }
122
122
  return methodParameterNames.indexOf(source);
123
123
  }
124
- function constructLockKey(args, lockKeyPrefix = 'default') {
124
+ function constructLockKey(args, lockKeyPrefix = 'default', encodeKeyParts = false) {
125
+ const encodePart = (value) => encodeKeyParts ? encodeURIComponent(String(value)) : value;
125
126
  const lockKeyElements = [];
126
127
  if (lockKeyPrefix != 'custom') {
127
128
  lockKeyElements.push(target.constructor.name);
@@ -145,11 +146,11 @@ function MurLock(releaseTime, waitOrKeyParam, ...keyParams) {
145
146
  typeof parameterValue === 'object' &&
146
147
  parameterValue !== null &&
147
148
  path in parameterValue) {
148
- return parameterValue[path];
149
+ return encodePart(parameterValue[path]);
149
150
  }
150
- return parameterValue instanceof Object
151
+ return encodePart(parameterValue instanceof Object
151
152
  ? parameterValue.toString()
152
- : parameterValue;
153
+ : parameterValue);
153
154
  }
154
155
  if (lockKeyPrefix == 'custom') {
155
156
  return source;
@@ -161,7 +162,7 @@ function MurLock(releaseTime, waitOrKeyParam, ...keyParams) {
161
162
  const wrapped = function (...args) {
162
163
  return __awaiter(this, void 0, void 0, function* () {
163
164
  const murLockService = this.murlockServiceDecorator;
164
- const lockKey = constructLockKey(args, murLockService.options.lockKeyPrefix);
165
+ const lockKey = constructLockKey(args, murLockService.options.lockKeyPrefix, murLockService.options.encodeKeyParts);
165
166
  if (!murLockService) {
166
167
  throw new exceptions_1.MurLockException('MurLockService is not available.');
167
168
  }
@@ -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":";;;;;;;;;;;;AAAA,2CAAwC;AACxC,4BAA0B;AAC1B,8CAAiD;AACjD,wDAAoD;AAMvC,QAAA,eAAe,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAMhD,QAAA,mBAAmB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AA8CrE,SAAgB,aAAa,CAC3B,mBAA2C,EAC3C,GAAG,cAAwB;IAE3B,OAAO,UACL,MAAW,EACX,WAAmB,EACnB,UAA8B;QAE9B,IAAI,OAAO,mBAAmB,KAAK,QAAQ,EAAE;YAE3C,OAAO,CAAC,cAAc,CACpB,2BAAmB,EACnB,mBAAmB,EACnB,MAAM,EACN,WAAW,CACZ,CAAC;SACH;aAAM;YAEL,MAAM,UAAU,GAAG,CAAC,mBAAmB,EAAE,GAAG,cAAc,CAAC,CAAC;YAC5D,OAAO,CAAC,cAAc,CAAC,uBAAe,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;SAC1E;QACD,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC;AAxBD,sCAwBC;AAOD,SAAS,iBAAiB,CAAC,IAAc;IACvC,MAAM,cAAc,GAAG,kCAAkC,CAAC;IAE1D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAE1E,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE;QACrB,OAAO,EAAE,CAAC;KACX;IAGD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,UAAU,GAAG,EAAE,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACzC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE;YAC/D,QAAQ,GAAG,IAAI,CAAC;YAChB,UAAU,GAAG,IAAI,CAAC;SACnB;aAAM,IAAI,QAAQ,IAAI,IAAI,KAAK,UAAU,IAAI,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;YACvE,QAAQ,GAAG,KAAK,CAAC;SAClB;aAAM,IAAI,CAAC,QAAQ,EAAE;YACpB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE;gBAChD,KAAK,EAAE,CAAC;aACT;iBAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE;gBACvD,KAAK,EAAE,CAAC;aACT;iBAAM,IAAI,IAAI,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,EAAE;gBAEtC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACpE,IAAI,SAAS,EAAE;oBACb,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;iBACxB;gBACD,OAAO,GAAG,EAAE,CAAC;gBACb,SAAS;aACV;SACF;QAED,OAAO,IAAI,IAAI,CAAC;KACjB;IAGD,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE;QAClB,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpE,IAAI,SAAS,EAAE;YACb,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;SACxB;KACF;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAUD,SAAS,6BAA6B,CACpC,IAAc,EACd,MAAW,EACX,WAAmB;IAGnB,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAG3C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;QAC5D,OAAO,UAAU,CAAC;KACnB;IAID,MAAM,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAC5C,uBAAe,EACf,MAAM,EACN,WAAW,CACY,CAAC;IAE1B,IAAI,kBAAkB,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE;QACvD,OAAO,kBAAkB,CAAC;KAC3B;IAGD,OAAO,UAAU,CAAC;AACpB,CAAC;AAwBD,SAAgB,OAAO,CACrB,WAAmB,EACnB,cAAgE,EAChE,GAAG,SAAmB;IAEtB,IAAI,IAAwD,CAAC;IAC7D,IACE,OAAO,cAAc,KAAK,QAAQ;QAClC,OAAO,cAAc,KAAK,UAAU,EACpC;QACA,IAAI,GAAG,cAAc,CAAC;KACvB;SAAM;QACL,SAAS,GAAG;YACV,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;YACzD,GAAG,SAAS;SACb,CAAC;KACH;IAED,MAAM,oBAAoB,GAAG,IAAA,eAAM,EAAC,gCAAc,CAAC,CAAC;IAEpD,OAAO,CAAC,MAAW,EAAE,WAAmB,EAAE,UAA8B,EAAE,EAAE;QAC1E,oBAAoB,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;QAExD,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAIxC,MAAM,oBAAoB,GAAG,6BAA6B,CACxD,cAAc,EACd,MAAM,EACN,WAAW,CACZ,CAAC;QAGF,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,CACvC,2BAAmB,EACnB,MAAM,EACN,WAAW,CACiB,CAAC;QAI/B,IACE,oBAAoB,CAAC,MAAM,GAAG,CAAC;YAC/B,CAAC,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,EACzC;YACA,MAAM,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAC1C,uBAAe,EACf,MAAM,EACN,WAAW,CACZ,CAAC;YACF,IAAI,CAAC,gBAAgB,EAAE;gBACrB,OAAO,CAAC,cAAc,CACpB,uBAAe,EACf,oBAAoB,EACpB,MAAM,EACN,WAAW,CACZ,CAAC;aACH;SACF;QAMD,SAAS,qBAAqB,CAAC,MAAc;YAE3C,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE;gBACpB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;aACvB;YAGD,IAAI,aAAa,IAAI,MAAM,IAAI,aAAa,EAAE;gBAC5C,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;aAC9B;YAGD,OAAO,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QAED,SAAS,gBAAgB,CACvB,IAAW,EACX,aAAa,GAAG,SAAS,EACzB,cAAc,GAAG,KAAK;YAKtB,MAAM,UAAU,GAAG,CAAC,KAAU,EAAE,EAAE,CAChC,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAE7D,MAAM,eAAe,GAAa,EAAE,CAAC;YACrC,IAAI,aAAa,IAAI,QAAQ,EAAE;gBAC7B,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBAC9C,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aACnC;YAED,eAAe,CAAC,IAAI,CAClB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAC5B,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC3C,MAAM,cAAc,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;gBAErD,IAAI,cAAc,IAAI,CAAC,EAAE;oBACvB,MAAM,cAAc,GAAG,kBAAkB,CAAC;wBACxC,IAAI;wBACJ,MAAM;wBACN,cAAc;wBACd,IAAI;qBACL,CAAC,CAAC;oBACH,IACE,OAAO,cAAc,KAAK,WAAW;wBACrC,cAAc,KAAK,IAAI,EACvB;wBACA,MAAM,IAAI,6BAAgB,CACxB,aAAa,MAAM,wBAAwB,CAC5C,CAAC;qBACH;oBACD,IACE,IAAI;wBACJ,OAAO,cAAc,KAAK,QAAQ;wBAClC,cAAc,KAAK,IAAI;wBACvB,IAAI,IAAI,cAAc,EACtB;wBACA,OAAO,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;qBACzC;oBACD,OAAO,UAAU,CACf,cAAc,YAAY,MAAM;wBAC9B,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE;wBAC3B,CAAC,CAAC,cAAc,CACnB,CAAC;iBACH;gBAED,IAAI,aAAa,IAAI,QAAQ,EAAE;oBAC7B,OAAO,MAAM,CAAC;iBACf;gBAED,MAAM,IAAI,6BAAgB,CACxB,aAAa,MAAM,iCAAiC,CACrD,CAAC;YACJ,CAAC,CAAC,CACH,CAAC;YACF,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,MAAM,OAAO,GAAG,UAAgB,GAAG,IAAW;;gBAC5C,MAAM,cAAc,GAAmB,IAAI,CAAC,uBAAuB,CAAC;gBAEpE,MAAM,OAAO,GAAG,gBAAgB,CAC9B,IAAI,EACJ,cAAc,CAAC,OAAO,CAAC,aAAa,EACpC,cAAc,CAAC,OAAO,CAAC,cAAc,CACtC,CAAC;gBAEF,IAAI,CAAC,cAAc,EAAE;oBACnB,MAAM,IAAI,6BAAgB,CAAC,kCAAkC,CAAC,CAAC;iBAChE;gBAED,OAAO,cAAc,CAAC,WAAW,CAC/B,OAAO,EACP,WAAW,EACX,IAAI,EACJ,GAAS,EAAE;oBACT,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC1C,CAAC,CAAA,CACF,CAAC;YACJ,CAAC;SAAA,CAAC;QAEF,MAAM,YAAY,GAChB,OAAQ,OAAe,CAAC,eAAe,KAAK,UAAU;YACpD,CAAC,CAAE,OAAe,CAAC,eAAe,CAAC,cAAc,CAAC;YAClD,CAAC,CAAC,EAAE,CAAC;QACT,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE;YAC9B,MAAM,KAAK,GAAI,OAAe,CAAC,WAAW,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAC/D,OAAe,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;SACtD;QAKD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE;YACrC,KAAK,EAAE,WAAW;YAClB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QAEH,UAAU,CAAC,KAAK,GAAG,OAAO,CAAC;QAE3B,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC;AA5LD,0BA4LC;AAED,SAAS,QAAQ,CAAC,KAAK;IACrB,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;QACvB,OAAO,IAAI,CAAC;KACb;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,KAAU;IAC1B,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,kBAAkB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE;IAChE,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;KAC3B;IACD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE;QAClD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;KACxB;IACD,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC;AAC9B,CAAC"}
@@ -1,3 +1,4 @@
1
- export declare class MurLockRedisException extends Error {
1
+ import { MurLockException } from './murlock.exception';
2
+ export declare class MurLockRedisException extends MurLockException {
2
3
  constructor(message: string);
3
4
  }
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MurLockRedisException = void 0;
4
- class MurLockRedisException extends Error {
4
+ const murlock_exception_1 = require("./murlock.exception");
5
+ class MurLockRedisException extends murlock_exception_1.MurLockException {
5
6
  constructor(message) {
6
7
  super(message);
7
8
  this.name = "MurLockRedisException";
@@ -1 +1 @@
1
- {"version":3,"file":"murlock-redis.exception.js","sourceRoot":"","sources":["../../lib/exceptions/murlock-redis.exception.ts"],"names":[],"mappings":";;;AAAA,MAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AALD,sDAKC"}
1
+ {"version":3,"file":"murlock-redis.exception.js","sourceRoot":"","sources":["../../lib/exceptions/murlock-redis.exception.ts"],"names":[],"mappings":";;;AAAA,2DAAuD;AAQvD,MAAa,qBAAsB,SAAQ,oCAAgB;IACzD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AALD,sDAKC"}
@@ -11,6 +11,9 @@ export interface MurLockModuleOptions {
11
11
  autoExtend?: boolean;
12
12
  extendInterval?: number;
13
13
  onRedisError?: (error: Error) => void;
14
+ reentrant?: boolean;
15
+ encodeKeyParts?: boolean;
16
+ jitter?: boolean;
14
17
  }
15
18
  export interface MurLockModuleAsyncOptions {
16
19
  imports?: any[];
@@ -9,11 +9,16 @@ export declare class MurLockService implements OnModuleInit, OnApplicationShutdo
9
9
  private lockScript;
10
10
  private unlockScript;
11
11
  private extendScript;
12
+ private readonly scriptShas;
12
13
  constructor(options: MurLockModuleOptions, asyncStorageService: AsyncStorageService);
13
14
  onModuleInit(): Promise<void>;
14
15
  onApplicationShutdown(signal?: string): Promise<void>;
16
+ private validateOptions;
15
17
  private sleep;
18
+ private withJitter;
16
19
  private log;
20
+ private loadScripts;
21
+ private evalScript;
17
22
  private lock;
18
23
  private unlock;
19
24
  private extendLock;
@@ -22,6 +27,7 @@ export declare class MurLockService implements OnModuleInit, OnApplicationShutdo
22
27
  private releaseLock;
23
28
  runWithLock<R>(lockKey: string, releaseTime: number, fn: () => Promise<R>): Promise<R>;
24
29
  runWithLock<R>(lockKey: string, releaseTime: number, wait: number | ((retries: number) => number), fn: () => Promise<R>): Promise<R>;
30
+ private runReentrant;
25
31
  private registerRedisErrorHandlers;
26
32
  private blockingLock;
27
33
  }
@@ -35,9 +35,11 @@ let MurLockService = MurLockService_1 = class MurLockService {
35
35
  this.options = options;
36
36
  this.asyncStorageService = asyncStorageService;
37
37
  this.logger = new common_1.Logger(MurLockService_1.name);
38
+ this.scriptShas = {};
38
39
  }
39
40
  onModuleInit() {
40
41
  return __awaiter(this, void 0, void 0, function* () {
42
+ this.validateOptions();
41
43
  try {
42
44
  this.lockScript = yield (0, promises_1.readFile)((0, path_1.join)(__dirname, './lua/lock.lua'), 'utf8');
43
45
  this.unlockScript = yield (0, promises_1.readFile)((0, path_1.join)(__dirname, './lua/unlock.lua'), 'utf8');
@@ -54,6 +56,7 @@ let MurLockService = MurLockService_1 = class MurLockService {
54
56
  this.registerRedisErrorHandlers();
55
57
  try {
56
58
  yield this.redisClient.connect();
59
+ yield this.loadScripts();
57
60
  }
58
61
  catch (error) {
59
62
  this.log('error', `Failed to connect to Redis: ${error.message}`);
@@ -71,9 +74,28 @@ let MurLockService = MurLockService_1 = class MurLockService {
71
74
  }
72
75
  });
73
76
  }
77
+ validateOptions() {
78
+ const { maxAttempts, wait, extendInterval } = this.options;
79
+ if (!Number.isFinite(maxAttempts) || maxAttempts < 1) {
80
+ throw new exceptions_1.MurLockException(`Invalid MurLock option 'maxAttempts': ${maxAttempts} (must be an integer >= 1).`);
81
+ }
82
+ if (!Number.isFinite(wait) || wait < 0) {
83
+ throw new exceptions_1.MurLockException(`Invalid MurLock option 'wait': ${wait} (must be a number >= 0).`);
84
+ }
85
+ if (extendInterval !== undefined &&
86
+ (!Number.isFinite(extendInterval) || extendInterval <= 0)) {
87
+ throw new exceptions_1.MurLockException(`Invalid MurLock option 'extendInterval': ${extendInterval} (must be a number > 0).`);
88
+ }
89
+ }
74
90
  sleep(ms) {
75
91
  return new Promise((resolve) => setTimeout(resolve, ms));
76
92
  }
93
+ withJitter(delay) {
94
+ if (!this.options.jitter) {
95
+ return delay;
96
+ }
97
+ return Math.floor(delay / 2 + Math.random() * (delay / 2));
98
+ }
77
99
  log(level, message, context) {
78
100
  if (this.options.logLevel === 'none') {
79
101
  return;
@@ -88,6 +110,76 @@ let MurLockService = MurLockService_1 = class MurLockService {
88
110
  this.logger[level](message, context);
89
111
  }
90
112
  }
113
+ loadScripts() {
114
+ return __awaiter(this, void 0, void 0, function* () {
115
+ try {
116
+ this.scriptShas.lock = (yield this.redisClient.sendCommand([
117
+ 'SCRIPT',
118
+ 'LOAD',
119
+ this.lockScript,
120
+ ]));
121
+ this.scriptShas.unlock = (yield this.redisClient.sendCommand([
122
+ 'SCRIPT',
123
+ 'LOAD',
124
+ this.unlockScript,
125
+ ]));
126
+ this.scriptShas.extend = (yield this.redisClient.sendCommand([
127
+ 'SCRIPT',
128
+ 'LOAD',
129
+ this.extendScript,
130
+ ]));
131
+ }
132
+ catch (error) {
133
+ this.log('warn', `MurLock could not preload Lua scripts (will fall back to EVAL): ${error.message}`);
134
+ }
135
+ });
136
+ }
137
+ evalScript(name, script, keys, args) {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const numkeys = keys.length.toString();
140
+ const sha = this.scriptShas[name];
141
+ if (sha) {
142
+ try {
143
+ return yield this.redisClient.sendCommand([
144
+ 'EVALSHA',
145
+ sha,
146
+ numkeys,
147
+ ...keys,
148
+ ...args,
149
+ ]);
150
+ }
151
+ catch (error) {
152
+ if (!/NOSCRIPT/i.test(String(error === null || error === void 0 ? void 0 : error.message))) {
153
+ throw error;
154
+ }
155
+ try {
156
+ const fresh = (yield this.redisClient.sendCommand([
157
+ 'SCRIPT',
158
+ 'LOAD',
159
+ script,
160
+ ]));
161
+ this.scriptShas[name] = fresh;
162
+ return yield this.redisClient.sendCommand([
163
+ 'EVALSHA',
164
+ fresh,
165
+ numkeys,
166
+ ...keys,
167
+ ...args,
168
+ ]);
169
+ }
170
+ catch (_a) {
171
+ }
172
+ }
173
+ }
174
+ return yield this.redisClient.sendCommand([
175
+ 'EVAL',
176
+ script,
177
+ numkeys,
178
+ ...keys,
179
+ ...args,
180
+ ]);
181
+ });
182
+ }
91
183
  lock(lockKey, releaseTime, clientId, wait) {
92
184
  return __awaiter(this, void 0, void 0, function* () {
93
185
  this.log('debug', `MurLock Client ID is ${clientId}`);
@@ -99,32 +191,29 @@ let MurLockService = MurLockService_1 = class MurLockService {
99
191
  throw new exceptions_1.MurLockException(`Failed to obtain lock for key ${lockKey} after ${this.options.maxAttempts} attempts.`);
100
192
  }
101
193
  try {
102
- const isLockSuccessful = yield this.redisClient.sendCommand([
103
- 'EVAL',
104
- this.lockScript,
105
- '1',
106
- lockKey,
107
- clientId,
108
- releaseTime.toString(),
109
- ]);
194
+ const isLockSuccessful = yield this.evalScript('lock', this.lockScript, [lockKey], [clientId, releaseTime.toString()]);
110
195
  if (isLockSuccessful === 1) {
111
196
  this.log('log', `Successfully obtained lock for key ${lockKey}`);
112
197
  return true;
113
198
  }
114
199
  else {
115
- const delay = wait
200
+ const baseDelay = wait
116
201
  ? typeof wait === 'function'
117
202
  ? wait(this.options.maxAttempts - attemptsRemaining + 1)
118
203
  : wait
119
204
  : this.options.wait *
120
205
  (this.options.maxAttempts - attemptsRemaining + 1);
206
+ const delay = this.withJitter(baseDelay);
121
207
  this.log('warn', `Failed to obtain lock for key ${lockKey}, retrying in ${delay} ms...`);
122
208
  yield this.sleep(delay);
123
209
  return attemptLock(attemptsRemaining - 1);
124
210
  }
125
211
  }
126
212
  catch (error) {
127
- throw new exceptions_1.MurLockException(`Unexpected error when trying to obtain lock for key ${lockKey}: ${error.message}`);
213
+ if (error instanceof exceptions_1.MurLockException) {
214
+ throw error;
215
+ }
216
+ throw new exceptions_1.MurLockRedisException(`Unexpected error when trying to obtain lock for key ${lockKey}: ${error.message}`);
128
217
  }
129
218
  });
130
219
  return attemptLock(this.options.maxAttempts);
@@ -132,13 +221,7 @@ let MurLockService = MurLockService_1 = class MurLockService {
132
221
  }
133
222
  unlock(lockKey, clientId) {
134
223
  return __awaiter(this, void 0, void 0, function* () {
135
- const result = yield this.redisClient.sendCommand([
136
- 'EVAL',
137
- this.unlockScript,
138
- '1',
139
- lockKey,
140
- clientId,
141
- ]);
224
+ const result = yield this.evalScript('unlock', this.unlockScript, [lockKey], [clientId]);
142
225
  if (result === 0) {
143
226
  if (!this.options.ignoreUnlockFail) {
144
227
  throw new exceptions_1.MurLockException(`Failed to release lock for key ${lockKey}`);
@@ -151,14 +234,7 @@ let MurLockService = MurLockService_1 = class MurLockService {
151
234
  }
152
235
  extendLock(lockKey, clientId, releaseTime) {
153
236
  return __awaiter(this, void 0, void 0, function* () {
154
- const result = yield this.redisClient.sendCommand([
155
- 'EVAL',
156
- this.extendScript,
157
- '1',
158
- lockKey,
159
- clientId,
160
- releaseTime.toString(),
161
- ]);
237
+ const result = yield this.evalScript('extend', this.extendScript, [lockKey], [clientId, releaseTime.toString()]);
162
238
  return result === 1;
163
239
  });
164
240
  }
@@ -196,6 +272,9 @@ let MurLockService = MurLockService_1 = class MurLockService {
196
272
  isLockSuccessful = yield this.lock(lockKey, releaseTime, clientId, wait);
197
273
  }
198
274
  catch (error) {
275
+ if (error instanceof exceptions_1.MurLockException) {
276
+ throw error;
277
+ }
199
278
  throw new exceptions_1.MurLockException(`Failed to acquire lock for key ${lockKey}: ${error.message}`);
200
279
  }
201
280
  if (!isLockSuccessful) {
@@ -209,6 +288,9 @@ let MurLockService = MurLockService_1 = class MurLockService {
209
288
  yield this.unlock(lockKey, clientId);
210
289
  }
211
290
  catch (error) {
291
+ if (error instanceof exceptions_1.MurLockException) {
292
+ throw error;
293
+ }
212
294
  throw new exceptions_1.MurLockException(`Failed to release lock for key ${lockKey}: ${error.message}`);
213
295
  }
214
296
  });
@@ -224,17 +306,67 @@ let MurLockService = MurLockService_1 = class MurLockService {
224
306
  wait = waitOrFn;
225
307
  operation = fn;
226
308
  }
227
- this.asyncStorageService.registerContext();
228
- this.asyncStorageService.setClientID('clientId', (0, utils_1.generateUuid)());
229
- const clientId = this.asyncStorageService.get('clientId');
230
- yield this.acquireLock(lockKey, clientId, releaseTime, wait);
231
- const stopWatchdog = this.startWatchdog(lockKey, clientId, releaseTime);
309
+ if (!Number.isFinite(releaseTime) || releaseTime <= 0) {
310
+ throw new exceptions_1.MurLockException(`Invalid releaseTime for key ${lockKey}: ${releaseTime} (must be > 0).`);
311
+ }
312
+ if (!this.options.reentrant) {
313
+ const clientId = (0, utils_1.generateUuid)();
314
+ yield this.acquireLock(lockKey, clientId, releaseTime, wait);
315
+ const stopWatchdog = this.startWatchdog(lockKey, clientId, releaseTime);
316
+ try {
317
+ return yield operation();
318
+ }
319
+ finally {
320
+ stopWatchdog();
321
+ yield this.releaseLock(lockKey, clientId);
322
+ }
323
+ }
324
+ const existing = this.asyncStorageService.getContext();
325
+ if (existing) {
326
+ return this.runReentrant(existing, lockKey, releaseTime, wait, operation);
327
+ }
328
+ const context = {
329
+ clientId: (0, utils_1.generateUuid)(),
330
+ holds: new Map(),
331
+ };
332
+ return this.asyncStorageService.run(context, () => this.runReentrant(context, lockKey, releaseTime, wait, operation));
333
+ });
334
+ }
335
+ runReentrant(context, lockKey, releaseTime, wait, operation) {
336
+ var _a, _b, _c;
337
+ return __awaiter(this, void 0, void 0, function* () {
338
+ const depth = (_a = context.holds.get(lockKey)) !== null && _a !== void 0 ? _a : 0;
339
+ if (depth > 0) {
340
+ context.holds.set(lockKey, depth + 1);
341
+ try {
342
+ return yield operation();
343
+ }
344
+ finally {
345
+ const current = (_b = context.holds.get(lockKey)) !== null && _b !== void 0 ? _b : 1;
346
+ if (current <= 1) {
347
+ context.holds.delete(lockKey);
348
+ }
349
+ else {
350
+ context.holds.set(lockKey, current - 1);
351
+ }
352
+ }
353
+ }
354
+ yield this.acquireLock(lockKey, context.clientId, releaseTime, wait);
355
+ context.holds.set(lockKey, 1);
356
+ const stopWatchdog = this.startWatchdog(lockKey, context.clientId, releaseTime);
232
357
  try {
233
358
  return yield operation();
234
359
  }
235
360
  finally {
236
- stopWatchdog();
237
- yield this.releaseLock(lockKey, clientId);
361
+ const current = (_c = context.holds.get(lockKey)) !== null && _c !== void 0 ? _c : 1;
362
+ if (current <= 1) {
363
+ context.holds.delete(lockKey);
364
+ stopWatchdog();
365
+ yield this.releaseLock(lockKey, context.clientId);
366
+ }
367
+ else {
368
+ context.holds.set(lockKey, current - 1);
369
+ }
238
370
  }
239
371
  });
240
372
  }
@@ -264,26 +396,20 @@ let MurLockService = MurLockService_1 = class MurLockService {
264
396
  return __awaiter(this, void 0, void 0, function* () {
265
397
  while (true) {
266
398
  try {
267
- const isLockSuccessful = yield this.redisClient.sendCommand([
268
- 'EVAL',
269
- this.lockScript,
270
- '1',
271
- lockKey,
272
- clientId,
273
- releaseTime.toString(),
274
- ]);
399
+ const isLockSuccessful = yield this.evalScript('lock', this.lockScript, [lockKey], [clientId, releaseTime.toString()]);
275
400
  if (isLockSuccessful === 1) {
276
401
  this.log('log', `Successfully obtained lock for key ${lockKey} in blocking mode`);
277
402
  return true;
278
403
  }
279
404
  else {
280
- this.log('warn', `Lock busy for key ${lockKey}, waiting ${this.options.wait} ms before next attempt (blocking mode)...`);
281
- yield this.sleep(this.options.wait);
405
+ const delay = this.withJitter(this.options.wait);
406
+ this.log('warn', `Lock busy for key ${lockKey}, waiting ${delay} ms before next attempt (blocking mode)...`);
407
+ yield this.sleep(delay);
282
408
  }
283
409
  }
284
410
  catch (error) {
285
411
  this.log('error', `Unexpected error in blocking lock for key ${lockKey}: ${error.message}`);
286
- yield this.sleep(this.options.wait);
412
+ yield this.sleep(this.withJitter(this.options.wait));
287
413
  }
288
414
  }
289
415
  });