better-lock 3.1.0 → 3.3.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 (40) hide show
  1. package/README.md +35 -1
  2. package/dist/better_lock.d.ts +13 -7
  3. package/dist/better_lock.js +60 -5
  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 +3 -4
  35. package/spec/better_lock.spec.ts +112 -0
  36. package/src/better_lock.ts +97 -13
  37. package/src/errors.ts +14 -1
  38. package/src/types.ts +5 -0
  39. package/tsconfig.build.json +6 -0
  40. package/tsconfig.json +1 -0
@@ -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;
@@ -189,9 +190,12 @@ export class BetterLock {
189
190
  const job = new LockJob(keys, executor, callback, effectiveJobOptions);
190
191
 
191
192
  // Set incoming stack
192
- if (effectiveJobOptions.extend_stack_traces) {
193
+ if (
194
+ effectiveJobOptions.extend_stack_traces &&
195
+ typeof (Error as any).captureStackTrace === 'function'
196
+ ) {
193
197
  const tempErr = new Error();
194
- Error.captureStackTrace(tempErr, this.acquire);
198
+ (Error as any).captureStackTrace(tempErr, this.acquire);
195
199
  job.incoming_stack = tempErr.stack;
196
200
  }
197
201
 
@@ -224,6 +228,86 @@ export class BetterLock {
224
228
  return (callback as any).promise;
225
229
  }
226
230
 
231
+ public acquireOr<TResult extends IValidResult>(
232
+ failureResult: TResult,
233
+ executor: IPromiseExecutor<TResult>,
234
+ jobOptions?: ILockJobOptions
235
+ ): Promise<TResult>;
236
+ public acquireOr<TResult extends IValidResult>(
237
+ failureResult: TResult,
238
+ executor: ICallbackExecutor<TResult>,
239
+ jobOptions?: ILockJobOptions
240
+ ): Promise<TResult>;
241
+ public acquireOr<TResult extends IValidResult>(
242
+ failureResult: TResult,
243
+ executor: ICallbackExecutor<TResult>,
244
+ callback: ICallback<TResult>,
245
+ jobOptions?: ILockJobOptions
246
+ ): void;
247
+ public acquireOr<TResult extends IValidResult>(
248
+ key: ILockKey | Array<ILockKey>,
249
+ failureResult: TResult,
250
+ executor: IPromiseExecutor<TResult>,
251
+ jobOptions?: ILockJobOptions
252
+ ): Promise<TResult>;
253
+ public acquireOr<TResult extends IValidResult>(
254
+ key: ILockKey | Array<ILockKey>,
255
+ failureResult: TResult,
256
+ executor: ICallbackExecutor<TResult>,
257
+ jobOptions?: ILockJobOptions
258
+ ): Promise<TResult>;
259
+ public acquireOr<TResult extends IValidResult>(
260
+ key: ILockKey | Array<ILockKey>,
261
+ failureResult: TResult,
262
+ executor: ICallbackExecutor<TResult>,
263
+ callback: ICallback<TResult>,
264
+ jobOptions?: ILockJobOptions
265
+ ): void;
266
+ /**
267
+ * The same as acquire, except if the lock can't be acquired (the executor never gets called), instead of throwing
268
+ * an error, the lock will resolve/callback with the provided failureResult value (for example, a `null`).
269
+ * @param key Named key or array of keys for this particular call. Calls with different keys will be run in parallel. Not required.
270
+ * @param failureResult The value to return if the executor never get called. This happens instead of rejecting.
271
+ * @param executor Function that will run inside the lock. Required.
272
+ * @param callback Function to be called after the executor finishes, or there is an execution timeout. Leave out to use promises.
273
+ * @param jobOptions Options to be applied on this job only
274
+ */
275
+ public acquireOr(key, failureResult, executor?, callback?, jobOptions?) {
276
+ if (tools.isFunction(failureResult)) {
277
+ // There is no key given. Reshuffle.
278
+ jobOptions = callback;
279
+ callback = executor;
280
+ executor = failureResult;
281
+ failureResult = key;
282
+ key = null;
283
+ }
284
+
285
+ if (tools.isFunction(callback)) {
286
+ const originalCallback = callback;
287
+ callback = (err, ...results) => {
288
+ if (isAcquisitionFailureError(err)) {
289
+ originalCallback(null, failureResult);
290
+ } else {
291
+ originalCallback(err, ...results);
292
+ }
293
+ };
294
+ }
295
+
296
+ // noinspection JSVoidFunctionReturnValueUsed
297
+ let promiseResult = this.acquire(key, executor, callback, jobOptions) as any;
298
+
299
+ if (typeof promiseResult !== 'undefined') {
300
+ promiseResult = promiseResult.catch(err => {
301
+ if (isAcquisitionFailureError(err)) {
302
+ return failureResult;
303
+ }
304
+ throw err;
305
+ });
306
+ }
307
+
308
+ return promiseResult;
309
+ }
310
+
227
311
  /**
228
312
  * Update state of given list of queues.
229
313
  */
@@ -275,7 +359,7 @@ export class BetterLock {
275
359
  // We want to do the rest of this in a separate context, because we don't want user executor code
276
360
  // to ever interfere with the code calling acquire().
277
361
 
278
- setImmediate(() => {
362
+ setTimeout(() => {
279
363
  // Make sure job hasn't been ended in the meantime
280
364
  if (job.executed_at || job.ended_at) {
281
365
  return;
@@ -336,7 +420,7 @@ export class BetterLock {
336
420
  // "promise" is just some random value. We don't have to wait
337
421
  lockDone(null, executorResult);
338
422
  }
339
- });
423
+ }, 0);
340
424
  }
341
425
 
342
426
  private onWaitTimeout(job: LockJob<any>) {
@@ -403,7 +487,7 @@ export class BetterLock {
403
487
  job.callback.apply(null, callbackArgs);
404
488
  } finally {
405
489
  // Whatever happens, schedule a queue update
406
- setImmediate(() => this.update(queuesToUpdate));
490
+ setTimeout(() => this.update(queuesToUpdate), 0);
407
491
  }
408
492
  }
409
493
 
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>;
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "types": []
5
+ }
6
+ }
package/tsconfig.json CHANGED
@@ -2,6 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "target": "es5",
4
4
  "module": "commonjs",
5
+ "lib": ["es2018", "dom"],
5
6
  "declaration": true,
6
7
  "outDir": "./dist",
7
8
  "strict": false,