better-lock 3.1.0 → 3.2.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 (38) hide show
  1. package/README.md +8 -0
  2. package/dist/better_lock.d.ts +13 -7
  3. package/dist/better_lock.js +55 -1
  4. package/dist/better_lock.js.map +1 -1
  5. package/dist/errors.d.ts +1 -0
  6. package/dist/errors.js +7 -1
  7. package/dist/errors.js.map +1 -1
  8. package/dist/types.d.ts +4 -0
  9. package/docs/assets/search.js +1 -1
  10. package/docs/classes/BetterLockError.html +3 -3
  11. package/docs/classes/BetterLockExecutionTimeoutError.html +6 -6
  12. package/docs/classes/BetterLockInternalError.html +3 -3
  13. package/docs/classes/BetterLockInvalidArgumentError.html +4 -4
  14. package/docs/classes/BetterLockJobAbortedError.html +5 -5
  15. package/docs/classes/BetterLockQueueOverflowError.html +8 -8
  16. package/docs/classes/BetterLockWaitTimeoutError.html +6 -6
  17. package/docs/classes/_internal_.BetterLock.html +189 -7
  18. package/docs/classes/_internal_.KeyQueue.html +4 -4
  19. package/docs/classes/_internal_.LockJob.html +13 -13
  20. package/docs/functions/_internal_.__home_panta_dev_pantas_better_lock_src_errors_.isAcquisitionFailureError.html +62 -0
  21. package/docs/index.html +13 -2
  22. package/docs/interfaces/BetterLockJobOptions.html +27 -4
  23. package/docs/interfaces/BetterLockOptions.html +26 -8
  24. package/docs/modules/_internal_.__home_panta_dev_pantas_better_lock_src_errors_.html +6 -1
  25. package/docs/types/BetterLockErrorName.html +1 -1
  26. package/docs/types/BetterLockExecutor.html +1 -1
  27. package/docs/types/BetterLockKey.html +1 -1
  28. package/docs/types/BetterLockQueueEjectionStrategy.html +1 -1
  29. package/docs/types/_internal_.ICallback.html +1 -1
  30. package/docs/types/_internal_.ICallbackExecutor.html +1 -1
  31. package/docs/types/_internal_.IErrorExports.html +1 -1
  32. package/docs/types/_internal_.IPromiseExecutor.html +1 -1
  33. package/docs/variables/BetterLock.html +1 -1
  34. package/package.json +1 -1
  35. package/spec/better_lock.spec.ts +100 -0
  36. package/src/better_lock.ts +89 -8
  37. package/src/errors.ts +14 -1
  38. package/src/types.ts +5 -0
@@ -23,7 +23,7 @@ but also old-school callbacks, with varargs return values.</p>
23
23
  <li>
24
24
  <h4>TResult</h4></li></ul><aside class="tsd-sources">
25
25
  <ul>
26
- <li>Defined in <a href="https://github.com/panta82/better-lock/blob/336aa4f/src/types.ts#L14">types.ts:14</a></li></ul></aside></div>
26
+ <li>Defined in <a href="https://github.com/panta82/better-lock/blob/91aeb2b/src/types.ts#L14">types.ts:14</a></li></ul></aside></div>
27
27
  <div class="col-4 col-menu menu-sticky-wrap menu-highlight">
28
28
  <div class="tsd-navigation settings">
29
29
  <details class="tsd-index-accordion"><summary class="tsd-accordion-summary">
@@ -37,7 +37,7 @@ It can either accept a done() function, or return a promise.</p>
37
37
  <h5>lockDone: <a href="_internal_.ICallback.html" class="tsd-signature-type" data-tsd-kind="Type alias">ICallback</a><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type" data-tsd-kind="Type parameter">TResult</span><span class="tsd-signature-symbol">&gt;</span></h5></li></ul></div>
38
38
  <h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources">
39
39
  <ul>
40
- <li>Defined in <a href="https://github.com/panta82/better-lock/blob/336aa4f/src/types.ts#L22">types.ts:22</a></li></ul></aside></div>
40
+ <li>Defined in <a href="https://github.com/panta82/better-lock/blob/91aeb2b/src/types.ts#L22">types.ts:22</a></li></ul></aside></div>
41
41
  <div class="col-4 col-menu menu-sticky-wrap menu-highlight">
42
42
  <div class="tsd-navigation settings">
43
43
  <details class="tsd-index-accordion"><summary class="tsd-accordion-summary">
@@ -16,7 +16,7 @@
16
16
  <h1>Type alias IErrorExports</h1></div>
17
17
  <div class="tsd-signature">IError<wbr/>Exports<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">typeof </span><a href="../modules/_internal_.__home_panta_dev_pantas_better_lock_src_errors_.html" class="tsd-signature-type" data-tsd-kind="Namespace">&quot;/home/panta/dev/pantas/better-lock/src/errors&quot;</a></div><aside class="tsd-sources">
18
18
  <ul>
19
- <li>Defined in <a href="https://github.com/panta82/better-lock/blob/336aa4f/src/types.ts#L3">types.ts:3</a></li></ul></aside></div>
19
+ <li>Defined in <a href="https://github.com/panta82/better-lock/blob/91aeb2b/src/types.ts#L3">types.ts:3</a></li></ul></aside></div>
20
20
  <div class="col-4 col-menu menu-sticky-wrap menu-highlight">
21
21
  <div class="tsd-navigation settings">
22
22
  <details class="tsd-index-accordion"><summary class="tsd-accordion-summary">
@@ -29,7 +29,7 @@
29
29
  <li class="tsd-description">
30
30
  <h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type" data-tsd-kind="Type parameter">TResult</span><span class="tsd-signature-symbol">&gt;</span></h4></li></ul></li></ul></div><aside class="tsd-sources">
31
31
  <ul>
32
- <li>Defined in <a href="https://github.com/panta82/better-lock/blob/336aa4f/src/types.ts#L23">types.ts:23</a></li></ul></aside></div>
32
+ <li>Defined in <a href="https://github.com/panta82/better-lock/blob/91aeb2b/src/types.ts#L23">types.ts:23</a></li></ul></aside></div>
33
33
  <div class="col-4 col-menu menu-sticky-wrap menu-highlight">
34
34
  <div class="tsd-navigation settings">
35
35
  <details class="tsd-index-accordion"><summary class="tsd-accordion-summary">
@@ -15,7 +15,7 @@
15
15
  <h1>Variable BetterLock<code class="tsd-tag ts-flagConst">Const</code> </h1></div>
16
16
  <div class="tsd-signature">Better<wbr/>Lock<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">typeof </span><a href="../modules/_internal_.html" class="tsd-signature-type" data-tsd-kind="Namespace">&lt;internal&gt;</a><span class="tsd-signature-symbol">.</span><a href="../classes/_internal_.BetterLock.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLock</a><span class="tsd-signature-symbol"> &amp; </span><span class="tsd-signature-symbol">{ </span>BetterLock<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">typeof </span><a href="../modules/_internal_.html" class="tsd-signature-type" data-tsd-kind="Namespace">&lt;internal&gt;</a><span class="tsd-signature-symbol">.</span><a href="../classes/_internal_.BetterLock.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLock</a><span class="tsd-signature-symbol">; </span>Error<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">typeof </span><a href="../classes/BetterLockError.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLockError</a><span class="tsd-signature-symbol">; </span>ExecutionTimeoutError<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">typeof </span><a href="../classes/BetterLockExecutionTimeoutError.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLockExecutionTimeoutError</a><span class="tsd-signature-symbol">; </span>InternalError<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">typeof </span><a href="../classes/BetterLockInternalError.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLockInternalError</a><span class="tsd-signature-symbol">; </span>InvalidArgumentError<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">typeof </span><a href="../classes/BetterLockInvalidArgumentError.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLockInvalidArgumentError</a><span class="tsd-signature-symbol">; </span>JobAbortedError<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">typeof </span><a href="../classes/BetterLockJobAbortedError.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLockJobAbortedError</a><span class="tsd-signature-symbol">; </span>QueueOverflowError<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">typeof </span><a href="../classes/BetterLockQueueOverflowError.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLockQueueOverflowError</a><span class="tsd-signature-symbol">; </span>WaitTimeoutError<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">typeof </span><a href="../classes/BetterLockWaitTimeoutError.html" class="tsd-signature-type" data-tsd-kind="Class">BetterLockWaitTimeoutError</a><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol"> = ...</span></div><aside class="tsd-sources">
17
17
  <ul>
18
- <li>Defined in <a href="https://github.com/panta82/better-lock/blob/336aa4f/src/index.ts#L43">index.ts:43</a></li></ul></aside></div>
18
+ <li>Defined in <a href="https://github.com/panta82/better-lock/blob/91aeb2b/src/index.ts#L43">index.ts:43</a></li></ul></aside></div>
19
19
  <div class="col-4 col-menu menu-sticky-wrap menu-highlight">
20
20
  <div class="tsd-navigation settings">
21
21
  <details class="tsd-index-accordion"><summary class="tsd-accordion-summary">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-lock",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "A (better) node.js lock library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -686,6 +686,106 @@ describe('BetterLock', () => {
686
686
  ]);
687
687
  });
688
688
  });
689
+
690
+ describe('acquireOr', () => {
691
+ describe('will correctly handle failureResults', () => {
692
+ it('from QueueOverflowError', testDone => {
693
+ const lock = new BetterLock({
694
+ wait_timeout: 200, // should never trigger
695
+ execution_timeout: 300, // should never trigger
696
+ queue_size: 2,
697
+ });
698
+
699
+ let cbCount = 0;
700
+ lock.acquireOr(0, waitCallback(25, null, 1), (err, res) => {
701
+ // The executing one
702
+ cbCount++;
703
+ expect(cbCount).toEqual(2);
704
+ expect(err).toBeNull();
705
+ expect(res).toEqual(1);
706
+ });
707
+ lock.acquireOr(0, waitCallback(5, null, 2), (err, res) => {
708
+ // This is the one that will get kicked out
709
+ cbCount++;
710
+ expect(cbCount).toEqual(1);
711
+ expect(err).toBeNull();
712
+ expect(res).toEqual(0);
713
+ });
714
+ lock.acquireOr(0, waitCallback(5, null, 3), (err, res) => {
715
+ cbCount++;
716
+ expect(cbCount).toEqual(3);
717
+ expect(err).toBeNull();
718
+ expect(res).toEqual(3);
719
+ testDone();
720
+ });
721
+ lock.acquireOr(0, waitCallback(5, null, 4), (err, res) => {
722
+ // This one will trigger the kicking out.
723
+ cbCount++;
724
+ expect(cbCount).toEqual(4);
725
+ expect(err).toBeNull();
726
+ expect(res).toEqual(4);
727
+ });
728
+ });
729
+
730
+ it('from WaitTimeoutError', async () => {
731
+ const lock = new BetterLock({
732
+ wait_timeout: 50,
733
+ execution_timeout: 100, // should never trigger
734
+ });
735
+
736
+ const promise1 = lock.acquireOr('fail1', waitCallback(75, null, 'ok1'));
737
+ const promise2 = lock.acquireOr('fail2', waitCallback(200000, null, 'ok2'));
738
+
739
+ // Enqueue after some time, this one should run
740
+ await waitPromise(50);
741
+ const promise3 = lock.acquireOr('fail3', waitCallback(50, null, 'ok3'));
742
+
743
+ const results = await Promise.all([promise1, promise2, promise3]);
744
+
745
+ expect(results).toEqual(['ok1', 'fail2', 'ok3']);
746
+ });
747
+
748
+ it('from AbortedError', async () => {
749
+ const lock = new BetterLock();
750
+
751
+ let noCallCount = 0;
752
+ const noCall = () => {
753
+ noCallCount++;
754
+ };
755
+
756
+ let cbCount = 0;
757
+ const callback = (err, res) => {
758
+ cbCount++;
759
+ expect(err).toBeNull();
760
+ expect(res).toEqual('fail');
761
+ };
762
+
763
+ lock.acquireOr('fail', noCall, callback);
764
+ lock.acquireOr('a', 'fail', noCall, callback);
765
+ lock.acquireOr('b', 'fail', noCall, callback);
766
+
767
+ lock.abortAll();
768
+
769
+ expect(lock.canAcquire()).toBeTruthy();
770
+ expect(lock.canAcquire('a')).toBeTruthy();
771
+ expect(lock.canAcquire('b')).toBeTruthy();
772
+ expect(noCallCount).toEqual(0);
773
+ expect(cbCount).toEqual(3);
774
+ });
775
+ });
776
+
777
+ it('will correctly pass other errors ', async () => {
778
+ const lock = new BetterLock({
779
+ execution_timeout: 10,
780
+ });
781
+
782
+ await expect(
783
+ lock.acquireOr('fail', async () => {
784
+ await waitPromise(20); // Should cause ExecutionTimeoutError.
785
+ })
786
+ ).rejects.toBeInstanceOf(BetterLock.ExecutionTimeoutError);
787
+ });
788
+ });
689
789
  });
690
790
 
691
791
  function waitCallback(ms: number, ...args): (done: (...args: any) => void) => void {
@@ -5,11 +5,12 @@ import {
5
5
  BetterLockJobAbortedError,
6
6
  BetterLockQueueOverflowError,
7
7
  BetterLockWaitTimeoutError,
8
+ isAcquisitionFailureError,
8
9
  } from './errors';
9
10
  import { KeyQueue, LockJob } from './internals';
10
11
  import { ILockJobOptions, IOptions } from './options';
11
12
  import * as tools from './tools';
12
- import { ICallback, ICallbackExecutor, ILockKey, IPromiseExecutor } from './types';
13
+ import { ICallback, ICallbackExecutor, ILockKey, IPromiseExecutor, IValidResult } from './types';
13
14
 
14
15
  /**
15
16
  * Main better lock class.
@@ -80,30 +81,30 @@ export class BetterLock {
80
81
  );
81
82
  }
82
83
 
83
- public acquire<TResult>(
84
+ public acquire<TResult extends IValidResult>(
84
85
  executor: IPromiseExecutor<TResult>,
85
86
  jobOptions?: ILockJobOptions
86
87
  ): Promise<TResult>;
87
- public acquire<TResult>(
88
+ public acquire<TResult extends IValidResult>(
88
89
  executor: ICallbackExecutor<TResult>,
89
90
  jobOptions?: ILockJobOptions
90
91
  ): Promise<TResult>;
91
- public acquire<TResult>(
92
+ public acquire<TResult extends IValidResult>(
92
93
  executor: ICallbackExecutor<TResult>,
93
94
  callback: ICallback<TResult>,
94
95
  jobOptions?: ILockJobOptions
95
96
  ): void;
96
- public acquire<TResult>(
97
+ public acquire<TResult extends IValidResult>(
97
98
  key: ILockKey | Array<ILockKey>,
98
99
  executor: IPromiseExecutor<TResult>,
99
100
  jobOptions?: ILockJobOptions
100
101
  ): Promise<TResult>;
101
- public acquire<TResult>(
102
+ public acquire<TResult extends IValidResult>(
102
103
  key: ILockKey | Array<ILockKey>,
103
104
  executor: ICallbackExecutor<TResult>,
104
105
  jobOptions?: ILockJobOptions
105
106
  ): Promise<TResult>;
106
- public acquire<TResult>(
107
+ public acquire<TResult extends IValidResult>(
107
108
  key: ILockKey | Array<ILockKey>,
108
109
  executor: ICallbackExecutor<TResult>,
109
110
  callback: ICallback<TResult>,
@@ -125,7 +126,7 @@ export class BetterLock {
125
126
  * @param jobOptions Options to be applied on this job only
126
127
  */
127
128
  public acquire(key, executor?, callback?, jobOptions?) {
128
- if (tools.isFunction(key) || tools.isObject(key)) {
129
+ if (tools.isFunction(key)) {
129
130
  // Presume we weren't given a key (first form)
130
131
  jobOptions = callback;
131
132
  callback = executor;
@@ -224,6 +225,86 @@ export class BetterLock {
224
225
  return (callback as any).promise;
225
226
  }
226
227
 
228
+ public acquireOr<TResult extends IValidResult>(
229
+ failureResult: TResult,
230
+ executor: IPromiseExecutor<TResult>,
231
+ jobOptions?: ILockJobOptions
232
+ ): Promise<TResult>;
233
+ public acquireOr<TResult extends IValidResult>(
234
+ failureResult: TResult,
235
+ executor: ICallbackExecutor<TResult>,
236
+ jobOptions?: ILockJobOptions
237
+ ): Promise<TResult>;
238
+ public acquireOr<TResult extends IValidResult>(
239
+ failureResult: TResult,
240
+ executor: ICallbackExecutor<TResult>,
241
+ callback: ICallback<TResult>,
242
+ jobOptions?: ILockJobOptions
243
+ ): void;
244
+ public acquireOr<TResult extends IValidResult>(
245
+ key: ILockKey | Array<ILockKey>,
246
+ failureResult: TResult,
247
+ executor: IPromiseExecutor<TResult>,
248
+ jobOptions?: ILockJobOptions
249
+ ): Promise<TResult>;
250
+ public acquireOr<TResult extends IValidResult>(
251
+ key: ILockKey | Array<ILockKey>,
252
+ failureResult: TResult,
253
+ executor: ICallbackExecutor<TResult>,
254
+ jobOptions?: ILockJobOptions
255
+ ): Promise<TResult>;
256
+ public acquireOr<TResult extends IValidResult>(
257
+ key: ILockKey | Array<ILockKey>,
258
+ failureResult: TResult,
259
+ executor: ICallbackExecutor<TResult>,
260
+ callback: ICallback<TResult>,
261
+ jobOptions?: ILockJobOptions
262
+ ): void;
263
+ /**
264
+ * The same as acquire, except if the lock can't be acquired (the executor never gets called), instead of throwing
265
+ * an error, the lock will resolve/callback with the provided failureResult value (for example, a `null`).
266
+ * @param key Named key or array of keys for this particular call. Calls with different keys will be run in parallel. Not required.
267
+ * @param failureResult The value to return if the executor never get called. This happens instead of rejecting.
268
+ * @param executor Function that will run inside the lock. Required.
269
+ * @param callback Function to be called after the executor finishes, or there is an execution timeout. Leave out to use promises.
270
+ * @param jobOptions Options to be applied on this job only
271
+ */
272
+ public acquireOr(key, failureResult, executor?, callback?, jobOptions?) {
273
+ if (tools.isFunction(failureResult)) {
274
+ // There is no key given. Reshuffle.
275
+ jobOptions = callback;
276
+ callback = executor;
277
+ executor = failureResult;
278
+ failureResult = key;
279
+ key = null;
280
+ }
281
+
282
+ if (tools.isFunction(callback)) {
283
+ const originalCallback = callback;
284
+ callback = (err, ...results) => {
285
+ if (isAcquisitionFailureError(err)) {
286
+ originalCallback(null, failureResult);
287
+ } else {
288
+ originalCallback(err, ...results);
289
+ }
290
+ };
291
+ }
292
+
293
+ // noinspection JSVoidFunctionReturnValueUsed
294
+ let promiseResult = this.acquire(key, executor, callback, jobOptions) as any;
295
+
296
+ if (typeof promiseResult !== 'undefined') {
297
+ promiseResult = promiseResult.catch(err => {
298
+ if (isAcquisitionFailureError(err)) {
299
+ return failureResult;
300
+ }
301
+ throw err;
302
+ });
303
+ }
304
+
305
+ return promiseResult;
306
+ }
307
+
227
308
  /**
228
309
  * Update state of given list of queues.
229
310
  */
package/src/errors.ts CHANGED
@@ -51,7 +51,12 @@ export class BetterLockInternalError extends BetterLockError {
51
51
  }
52
52
 
53
53
  export class BetterLockInvalidArgumentError extends BetterLockError {
54
- constructor(lockName, public argument, expected, actual) {
54
+ constructor(
55
+ lockName,
56
+ public argument,
57
+ expected,
58
+ actual
59
+ ) {
55
60
  super(lockName, `Argument "${argument}" must be ${expected} (got: "${actual}")`);
56
61
  this.argument = argument;
57
62
  }
@@ -125,3 +130,11 @@ export class BetterLockJobAbortedError extends BetterLockError {
125
130
  this.keys = job.keys;
126
131
  }
127
132
  }
133
+
134
+ export function isAcquisitionFailureError(err) {
135
+ return (
136
+ (err && err instanceof BetterLockQueueOverflowError) ||
137
+ err instanceof BetterLockWaitTimeoutError ||
138
+ err instanceof BetterLockJobAbortedError
139
+ );
140
+ }
package/src/types.ts CHANGED
@@ -27,3 +27,8 @@ export type IExecutor<TResult> = ICallbackExecutor<TResult> | IPromiseExecutor<T
27
27
  * Key types that can be used for a lock.
28
28
  */
29
29
  export type ILockKey = string | number | null | undefined;
30
+
31
+ /**
32
+ * Valid results are anything except functions
33
+ */
34
+ export type IValidResult = Exclude<any, (...args: any[]) => any>;