better-lock 2.0.3 → 3.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/.idea/prettier.xml +1 -0
- package/README.md +55 -41
- package/dist/better_lock.js +38 -35
- package/dist/better_lock.js.map +1 -1
- package/dist/errors.d.ts +3 -1
- package/dist/errors.js +11 -12
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internals.js +2 -2
- package/dist/internals.js.map +1 -1
- package/dist/options.d.ts +17 -0
- package/dist/types.d.ts +1 -1
- package/docs/assets/highlight.css +3 -3
- package/docs/assets/main.js +4 -2
- package/docs/assets/search.js +1 -1
- package/docs/assets/style.css +424 -538
- package/docs/classes/BetterLockError.html +109 -5
- package/docs/classes/BetterLockExecutionTimeoutError.html +122 -5
- package/docs/classes/BetterLockInternalError.html +101 -5
- package/docs/classes/BetterLockInvalidArgumentError.html +112 -5
- package/docs/classes/BetterLockJobAbortedError.html +115 -5
- package/docs/classes/BetterLockQueueOverflowError.html +142 -5
- package/docs/classes/BetterLockWaitTimeoutError.html +122 -5
- package/docs/classes/_internal_.BetterLock.html +297 -65
- package/docs/classes/_internal_.KeyQueue.html +126 -7
- package/docs/classes/_internal_.LockJob.html +225 -27
- package/docs/index.html +83 -13
- package/docs/interfaces/BetterLockJobOptions.html +89 -9
- package/docs/interfaces/BetterLockOptions.html +149 -17
- package/docs/modules/_internal_.__home_panta_dev_pantas_better_lock_src_errors_.html +80 -1
- package/docs/modules/_internal_.html +68 -7
- package/docs/modules.html +96 -5
- package/docs/types/BetterLockErrorName.html +61 -0
- package/docs/types/BetterLockExecutor.html +63 -0
- package/docs/types/BetterLockKey.html +61 -0
- package/docs/types/BetterLockQueueEjectionStrategy.html +59 -0
- package/docs/types/_internal_.ICallback.html +59 -0
- package/docs/types/_internal_.ICallbackExecutor.html +73 -0
- package/docs/types/_internal_.IErrorExports.html +52 -0
- package/docs/types/_internal_.IPromiseExecutor.html +65 -0
- package/docs/variables/BetterLock.html +59 -0
- package/package.json +6 -6
- package/spec/better_lock.spec.ts +97 -1
- package/src/better_lock.ts +33 -28
- package/src/errors.ts +5 -2
- package/src/index.ts +2 -1
- package/src/options.ts +22 -0
- package/src/types.ts +2 -2
- package/docs/assets/icons.css +0 -1043
- package/docs/assets/icons.png +0 -0
- package/docs/assets/icons@2x.png +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!DOCTYPE html><html class="default"><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>BetterLock | better-lock</title><meta name="description" content="Documentation for better-lock"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script async src="../assets/search.js" id="search-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os"</script><header class="tsd-page-toolbar">
|
|
2
|
+
<div class="tsd-toolbar-contents container">
|
|
3
|
+
<div class="table-cell" id="tsd-search" data-base="..">
|
|
4
|
+
<div class="field"><label for="tsd-search-field" class="tsd-widget search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M15.7824 13.833L12.6666 10.7177C12.5259 10.5771 12.3353 10.499 12.1353 10.499H11.6259C12.4884 9.39596 13.001 8.00859 13.001 6.49937C13.001 2.90909 10.0914 0 6.50048 0C2.90959 0 0 2.90909 0 6.49937C0 10.0896 2.90959 12.9987 6.50048 12.9987C8.00996 12.9987 9.39756 12.4863 10.5008 11.6239V12.1332C10.5008 12.3332 10.5789 12.5238 10.7195 12.6644L13.8354 15.7797C14.1292 16.0734 14.6042 16.0734 14.8948 15.7797L15.7793 14.8954C16.0731 14.6017 16.0731 14.1267 15.7824 13.833ZM6.50048 10.499C4.29094 10.499 2.50018 8.71165 2.50018 6.49937C2.50018 4.29021 4.28781 2.49976 6.50048 2.49976C8.71001 2.49976 10.5008 4.28708 10.5008 6.49937C10.5008 8.70852 8.71314 10.499 6.50048 10.499Z" fill="var(--color-text)"></path></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div>
|
|
5
|
+
<ul class="results">
|
|
6
|
+
<li class="state loading">Preparing search index...</li>
|
|
7
|
+
<li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">better-lock</a></div>
|
|
8
|
+
<div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="1" y="3" width="14" height="2" fill="var(--color-text)"></rect><rect x="1" y="7" width="14" height="2" fill="var(--color-text)"></rect><rect x="1" y="11" width="14" height="2" fill="var(--color-text)"></rect></svg></a></div></div></header>
|
|
9
|
+
<div class="container container-main">
|
|
10
|
+
<div class="col-8 col-content">
|
|
11
|
+
<div class="tsd-page-title">
|
|
12
|
+
<ul class="tsd-breadcrumb">
|
|
13
|
+
<li><a href="../modules.html">better-lock</a></li>
|
|
14
|
+
<li><a href="BetterLock.html">BetterLock</a></li></ul>
|
|
15
|
+
<h1>Variable BetterLock<code class="tsd-tag ts-flagConst">Const</code> </h1></div>
|
|
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"><internal></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><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"><internal></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
|
+
<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>
|
|
19
|
+
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
|
|
20
|
+
<div class="tsd-navigation settings">
|
|
21
|
+
<details class="tsd-index-accordion"><summary class="tsd-accordion-summary">
|
|
22
|
+
<h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M4.93896 8.531L12 15.591L19.061 8.531L16.939 6.409L12 11.349L7.06098 6.409L4.93896 8.531Z" fill="var(--color-text)"></path></svg> Settings</h3></summary>
|
|
23
|
+
<div class="tsd-accordion-details">
|
|
24
|
+
<div class="tsd-filter-visibility">
|
|
25
|
+
<h4 class="uppercase">Member Visibility</h4><form>
|
|
26
|
+
<ul id="tsd-filter-options">
|
|
27
|
+
<li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></form></div>
|
|
28
|
+
<div class="tsd-theme-toggle">
|
|
29
|
+
<h4 class="uppercase">Theme</h4><select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div>
|
|
30
|
+
<nav class="tsd-navigation primary">
|
|
31
|
+
<details class="tsd-index-accordion" open><summary class="tsd-accordion-summary">
|
|
32
|
+
<h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M4.93896 8.531L12 15.591L19.061 8.531L16.939 6.409L12 11.349L7.06098 6.409L4.93896 8.531Z" fill="var(--color-text)"></path></svg> Modules</h3></summary>
|
|
33
|
+
<div class="tsd-accordion-details">
|
|
34
|
+
<ul>
|
|
35
|
+
<li><a href="../modules.html">better-<wbr/>lock</a>
|
|
36
|
+
<ul>
|
|
37
|
+
<li class="tsd-kind-namespace"><a href="../modules/_internal_.html"><internal></a>
|
|
38
|
+
<ul>
|
|
39
|
+
<li class="tsd-kind-namespace tsd-parent-kind-namespace"><a href="../modules/_internal_.__home_panta_dev_pantas_better_lock_src_errors_.html">"/home/panta/dev/pantas/better-<wbr/>lock/src/errors"</a></li></ul></li></ul></li></ul></div></details></nav>
|
|
40
|
+
<nav class="tsd-navigation secondary menu-sticky">
|
|
41
|
+
<ul>
|
|
42
|
+
<li class="tsd-kind-reference"><a href="../modules.html#default" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><rect fill="var(--color-icon-background)" stroke="#FF4D82" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12" id="icon-8388608-path"></rect><path d="M10.354 17V8.24H13.066C13.586 8.24 14.042 8.348 14.434 8.564C14.826 8.772 15.13 9.064 15.346 9.44C15.562 9.816 15.67 10.256 15.67 10.76C15.67 11.352 15.514 11.86 15.202 12.284C14.898 12.708 14.482 13 13.954 13.16L15.79 17H14.518L12.838 13.28H11.434V17H10.354ZM11.434 12.308H13.066C13.514 12.308 13.874 12.168 14.146 11.888C14.418 11.6 14.554 11.224 14.554 10.76C14.554 10.288 14.418 9.912 14.146 9.632C13.874 9.352 13.514 9.212 13.066 9.212H11.434V12.308Z" fill="var(--color-text)" id="icon-8388608-text"></path></svg>default</a></li>
|
|
43
|
+
<li class="tsd-kind-class"><a href="../classes/BetterLockError.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-class)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6" id="icon-128-path"></rect><path d="M11.898 16.1201C11.098 16.1201 10.466 15.8961 10.002 15.4481C9.53803 15.0001 9.30603 14.3841 9.30603 13.6001V9.64012C9.30603 8.85612 9.53803 8.24012 10.002 7.79212C10.466 7.34412 11.098 7.12012 11.898 7.12012C12.682 7.12012 13.306 7.34812 13.77 7.80412C14.234 8.25212 14.466 8.86412 14.466 9.64012H13.386C13.386 9.14412 13.254 8.76412 12.99 8.50012C12.734 8.22812 12.37 8.09212 11.898 8.09212C11.426 8.09212 11.054 8.22412 10.782 8.48812C10.518 8.75212 10.386 9.13212 10.386 9.62812V13.6001C10.386 14.0961 10.518 14.4801 10.782 14.7521C11.054 15.0161 11.426 15.1481 11.898 15.1481C12.37 15.1481 12.734 15.0161 12.99 14.7521C13.254 14.4801 13.386 14.0961 13.386 13.6001H14.466C14.466 14.3761 14.234 14.9921 13.77 15.4481C13.306 15.8961 12.682 16.1201 11.898 16.1201Z" fill="var(--color-text)" id="icon-128-text"></path></svg>Better<wbr/>Lock<wbr/>Error</a></li>
|
|
44
|
+
<li class="tsd-kind-class"><a href="../classes/BetterLockExecutionTimeoutError.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-128-path"></use><use href="#icon-128-text"></use></svg>Better<wbr/>Lock<wbr/>Execution<wbr/>Timeout<wbr/>Error</a></li>
|
|
45
|
+
<li class="tsd-kind-class"><a href="../classes/BetterLockInternalError.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-128-path"></use><use href="#icon-128-text"></use></svg>Better<wbr/>Lock<wbr/>Internal<wbr/>Error</a></li>
|
|
46
|
+
<li class="tsd-kind-class"><a href="../classes/BetterLockInvalidArgumentError.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-128-path"></use><use href="#icon-128-text"></use></svg>Better<wbr/>Lock<wbr/>Invalid<wbr/>Argument<wbr/>Error</a></li>
|
|
47
|
+
<li class="tsd-kind-class"><a href="../classes/BetterLockJobAbortedError.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-128-path"></use><use href="#icon-128-text"></use></svg>Better<wbr/>Lock<wbr/>Job<wbr/>Aborted<wbr/>Error</a></li>
|
|
48
|
+
<li class="tsd-kind-class"><a href="../classes/BetterLockQueueOverflowError.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-128-path"></use><use href="#icon-128-text"></use></svg>Better<wbr/>Lock<wbr/>Queue<wbr/>Overflow<wbr/>Error</a></li>
|
|
49
|
+
<li class="tsd-kind-class"><a href="../classes/BetterLockWaitTimeoutError.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-128-path"></use><use href="#icon-128-text"></use></svg>Better<wbr/>Lock<wbr/>Wait<wbr/>Timeout<wbr/>Error</a></li>
|
|
50
|
+
<li class="tsd-kind-interface"><a href="../interfaces/BetterLockJobOptions.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-interface)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6" id="icon-256-path"></rect><path d="M9.51 16V15.016H11.298V8.224H9.51V7.24H14.19V8.224H12.402V15.016H14.19V16H9.51Z" fill="var(--color-text)" id="icon-256-text"></path></svg>Better<wbr/>Lock<wbr/>Job<wbr/>Options</a></li>
|
|
51
|
+
<li class="tsd-kind-interface"><a href="../interfaces/BetterLockOptions.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-256-path"></use><use href="#icon-256-text"></use></svg>Better<wbr/>Lock<wbr/>Options</a></li>
|
|
52
|
+
<li class="tsd-kind-type-alias"><a href="../types/BetterLockErrorName.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><rect fill="var(--color-icon-background)" stroke="var(--color-ts)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6" id="icon-4194304-path"></rect><path d="M11.31 16V8.224H8.91V7.24H14.79V8.224H12.39V16H11.31Z" fill="var(--color-text)" id="icon-4194304-text"></path></svg>Better<wbr/>Lock<wbr/>Error<wbr/>Name</a></li>
|
|
53
|
+
<li class="tsd-kind-type-alias"><a href="../types/BetterLockExecutor.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-4194304-path"></use><use href="#icon-4194304-text"></use></svg>Better<wbr/>Lock<wbr/>Executor</a></li>
|
|
54
|
+
<li class="tsd-kind-type-alias"><a href="../types/BetterLockKey.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-4194304-path"></use><use href="#icon-4194304-text"></use></svg>Better<wbr/>Lock<wbr/>Key</a></li>
|
|
55
|
+
<li class="tsd-kind-type-alias"><a href="../types/BetterLockQueueEjectionStrategy.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><use href="#icon-4194304-path"></use><use href="#icon-4194304-text"></use></svg>Better<wbr/>Lock<wbr/>Queue<wbr/>Ejection<wbr/>Strategy</a></li>
|
|
56
|
+
<li class="current tsd-kind-variable"><a href="BetterLock.html" class="tsd-index-link"><svg class="tsd-kind-icon" width="24" height="24" viewBox="0 0 24 24"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-variable)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6" id="icon-32-path"></rect><path d="M11.106 16L8.85 7.24H9.966L11.454 13.192C11.558 13.608 11.646 13.996 11.718 14.356C11.79 14.708 11.842 14.976 11.874 15.16C11.906 14.976 11.954 14.708 12.018 14.356C12.09 13.996 12.178 13.608 12.282 13.192L13.758 7.24H14.85L12.582 16H11.106Z" fill="var(--color-text)" id="icon-32-text"></path></svg>Better<wbr/>Lock</a></li></ul></nav></div></div>
|
|
57
|
+
<div class="container tsd-generator">
|
|
58
|
+
<p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></div>
|
|
59
|
+
<div class="overlay"></div><script src="../assets/main.js"></script></body></html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-lock",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "A (better) node.js lock library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -27,18 +27,18 @@
|
|
|
27
27
|
"sync"
|
|
28
28
|
],
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@types/jest": "
|
|
30
|
+
"@types/jest": "29",
|
|
31
31
|
"@typescript-eslint/eslint-plugin": "^4.25.0",
|
|
32
32
|
"@typescript-eslint/parser": "^4.25.0",
|
|
33
33
|
"eslint": "^7.27.0",
|
|
34
34
|
"eslint-config-prettier": "^8.3.0",
|
|
35
35
|
"import-sort-style-module": "^6.0.0",
|
|
36
|
-
"jest": "
|
|
36
|
+
"jest": "29",
|
|
37
37
|
"prettier": "latest",
|
|
38
38
|
"prettier-plugin-import-sort": "0.0.7",
|
|
39
|
-
"ts-jest": "
|
|
40
|
-
"typedoc": "
|
|
41
|
-
"typedoc-plugin-missing-exports": "
|
|
39
|
+
"ts-jest": "29",
|
|
40
|
+
"typedoc": "0.23.0",
|
|
41
|
+
"typedoc-plugin-missing-exports": "0.23.0",
|
|
42
42
|
"typescript": "^4.3.2"
|
|
43
43
|
},
|
|
44
44
|
"author": "Ivan Pantic",
|
package/spec/better_lock.spec.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import BetterLock from '../src/index';
|
|
2
2
|
import { LockJob } from '../src/internals';
|
|
3
|
+
import { ILockJobOptions } from '../src/options';
|
|
3
4
|
|
|
4
5
|
describe('BetterLock', () => {
|
|
5
6
|
let baseDefaultOptions;
|
|
@@ -254,13 +255,48 @@ describe('BetterLock', () => {
|
|
|
254
255
|
});
|
|
255
256
|
|
|
256
257
|
describe('when overflowing', () => {
|
|
257
|
-
it('it will kick out the
|
|
258
|
+
it('it will kick out the correct job using the default "oldest" strategy', testDone => {
|
|
258
259
|
const lock = new BetterLock({
|
|
259
260
|
wait_timeout: 200, // should never trigger
|
|
260
261
|
execution_timeout: 300, // should never trigger
|
|
261
262
|
queue_size: 2,
|
|
262
263
|
});
|
|
263
264
|
|
|
265
|
+
let cbCount = 0;
|
|
266
|
+
lock.acquire(waitCallback(25, 1), arg => {
|
|
267
|
+
// The executing one
|
|
268
|
+
cbCount++;
|
|
269
|
+
expect(cbCount).toEqual(2);
|
|
270
|
+
expect(arg).toEqual(1);
|
|
271
|
+
});
|
|
272
|
+
lock.acquire(waitCallback(5, 2), err => {
|
|
273
|
+
// This is the one that will get kicked out
|
|
274
|
+
cbCount++;
|
|
275
|
+
expect(cbCount).toEqual(1);
|
|
276
|
+
expect(err).toBeInstanceOf(BetterLock.QueueOverflowError);
|
|
277
|
+
});
|
|
278
|
+
lock.acquire(waitCallback(5, 3), arg => {
|
|
279
|
+
cbCount++;
|
|
280
|
+
expect(cbCount).toEqual(3);
|
|
281
|
+
expect(arg).toEqual(3);
|
|
282
|
+
testDone();
|
|
283
|
+
});
|
|
284
|
+
lock.acquire(waitCallback(5, 4), arg => {
|
|
285
|
+
// This one will trigger the kicking out.
|
|
286
|
+
cbCount++;
|
|
287
|
+
expect(cbCount).toEqual(4);
|
|
288
|
+
expect(arg).toEqual(4);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('it will kick out the correct job using the "newest" strategy', testDone => {
|
|
293
|
+
const lock = new BetterLock({
|
|
294
|
+
wait_timeout: 200, // should never trigger
|
|
295
|
+
execution_timeout: 300, // should never trigger
|
|
296
|
+
queue_size: 2,
|
|
297
|
+
queue_ejection_strategy: 'newest',
|
|
298
|
+
});
|
|
299
|
+
|
|
264
300
|
let cbCount = 0;
|
|
265
301
|
lock.acquire(waitCallback(25, 1), arg => {
|
|
266
302
|
// The executing one
|
|
@@ -310,6 +346,7 @@ describe('BetterLock', () => {
|
|
|
310
346
|
wait_timeout: 0,
|
|
311
347
|
execution_timeout: 5,
|
|
312
348
|
queue_size: 1,
|
|
349
|
+
queue_ejection_strategy: 'newest',
|
|
313
350
|
});
|
|
314
351
|
|
|
315
352
|
return Promise.all([
|
|
@@ -590,6 +627,65 @@ describe('BetterLock', () => {
|
|
|
590
627
|
});
|
|
591
628
|
});
|
|
592
629
|
});
|
|
630
|
+
|
|
631
|
+
describe('will respect lock_condition', () => {
|
|
632
|
+
function runJob(
|
|
633
|
+
lock: InstanceType<typeof BetterLock>,
|
|
634
|
+
key: string,
|
|
635
|
+
expectedMs: number,
|
|
636
|
+
options?: ILockJobOptions
|
|
637
|
+
) {
|
|
638
|
+
const startedAt = new Date();
|
|
639
|
+
let executed = false;
|
|
640
|
+
return lock
|
|
641
|
+
.acquire(
|
|
642
|
+
key,
|
|
643
|
+
() => {
|
|
644
|
+
executed = true;
|
|
645
|
+
expectMs(new Date().valueOf() - startedAt.valueOf(), expectedMs);
|
|
646
|
+
return waitPromise(50);
|
|
647
|
+
},
|
|
648
|
+
options
|
|
649
|
+
)
|
|
650
|
+
.finally(() => {
|
|
651
|
+
expect(executed).toBeTruthy();
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
it('for global condition', async () => {
|
|
656
|
+
const lock = new BetterLock({
|
|
657
|
+
lock_condition: key => !String(key).startsWith('a'),
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
await Promise.all([
|
|
661
|
+
runJob(lock, 'a', 0),
|
|
662
|
+
runJob(lock, 'a', 0),
|
|
663
|
+
runJob(lock, 'a', 0),
|
|
664
|
+
runJob(lock, 'b', 0),
|
|
665
|
+
runJob(lock, 'b', 50),
|
|
666
|
+
runJob(lock, 'b', 100),
|
|
667
|
+
]);
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
it('for local condition', async () => {
|
|
671
|
+
const lock = new BetterLock({
|
|
672
|
+
lock_condition: key => !String(key).startsWith('a'),
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
const overrideToB = {
|
|
676
|
+
lock_condition: key => !String(key).startsWith('b'),
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
await Promise.all([
|
|
680
|
+
runJob(lock, 'b', 0, overrideToB),
|
|
681
|
+
runJob(lock, 'b', 0, overrideToB),
|
|
682
|
+
runJob(lock, 'b', 0, overrideToB),
|
|
683
|
+
runJob(lock, 'a', 0, overrideToB),
|
|
684
|
+
runJob(lock, 'a', 50, overrideToB),
|
|
685
|
+
runJob(lock, 'a', 100, overrideToB),
|
|
686
|
+
]);
|
|
687
|
+
});
|
|
688
|
+
});
|
|
593
689
|
});
|
|
594
690
|
|
|
595
691
|
function waitCallback(ms: number, ...args): (done: (...args: any) => void) => void {
|
package/src/better_lock.ts
CHANGED
|
@@ -133,23 +133,6 @@ export class BetterLock {
|
|
|
133
133
|
key = null;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
// Repackage "key" into an array of keys
|
|
137
|
-
const keys = [];
|
|
138
|
-
if (Array.isArray(key)) {
|
|
139
|
-
const arrayOfKeys = key;
|
|
140
|
-
// Make sure we don't add duplicates
|
|
141
|
-
const seenKeys = new Set();
|
|
142
|
-
for (let i = 0; i < arrayOfKeys.length; i++) {
|
|
143
|
-
const normalizedKey = this.normalizeAndValidateKey(arrayOfKeys[i]);
|
|
144
|
-
if (!seenKeys.has(normalizedKey)) {
|
|
145
|
-
keys.push(normalizedKey);
|
|
146
|
-
seenKeys.add(normalizedKey);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
keys.push(this.normalizeAndValidateKey(key));
|
|
151
|
-
}
|
|
152
|
-
|
|
153
136
|
// Create callback wrapper for promise interface
|
|
154
137
|
if (!tools.isFunction(callback)) {
|
|
155
138
|
if (jobOptions === undefined) {
|
|
@@ -159,6 +142,32 @@ export class BetterLock {
|
|
|
159
142
|
callback = tools.callbackWithPromise();
|
|
160
143
|
}
|
|
161
144
|
|
|
145
|
+
// Prepare job options
|
|
146
|
+
const effectiveJobOptions = jobOptions
|
|
147
|
+
? tools.assign({} as IOptions, [this.options, jobOptions])
|
|
148
|
+
: // No need to create new object since these will be read-only and are subset of global options
|
|
149
|
+
this.options;
|
|
150
|
+
|
|
151
|
+
// Repackage "key" into an array of keys, but only if lock_condition allows it.
|
|
152
|
+
// Otherwise, it stays an array and gets executed immediately.
|
|
153
|
+
const keys = [];
|
|
154
|
+
if (!effectiveJobOptions.lock_condition || effectiveJobOptions.lock_condition(key)) {
|
|
155
|
+
if (Array.isArray(key)) {
|
|
156
|
+
const arrayOfKeys = key;
|
|
157
|
+
// Make sure we don't add duplicates
|
|
158
|
+
const seenKeys = new Set();
|
|
159
|
+
for (let i = 0; i < arrayOfKeys.length; i++) {
|
|
160
|
+
const normalizedKey = this.normalizeAndValidateKey(arrayOfKeys[i]);
|
|
161
|
+
if (!seenKeys.has(normalizedKey)) {
|
|
162
|
+
keys.push(normalizedKey);
|
|
163
|
+
seenKeys.add(normalizedKey);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
keys.push(this.normalizeAndValidateKey(key));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
162
171
|
// Validate other options
|
|
163
172
|
if (!tools.isFunction(executor)) {
|
|
164
173
|
throw new BetterLockInvalidArgumentError(
|
|
@@ -177,12 +186,6 @@ export class BetterLock {
|
|
|
177
186
|
);
|
|
178
187
|
}
|
|
179
188
|
|
|
180
|
-
// Prepare job options
|
|
181
|
-
const effectiveJobOptions = jobOptions
|
|
182
|
-
? tools.assign({}, [this.options, jobOptions])
|
|
183
|
-
: // No need to create new object since these will be read-only and are subset of global options
|
|
184
|
-
this.options;
|
|
185
|
-
|
|
186
189
|
const job = new LockJob(keys, executor, callback, effectiveJobOptions);
|
|
187
190
|
|
|
188
191
|
// Set incoming stack
|
|
@@ -242,18 +245,20 @@ export class BetterLock {
|
|
|
242
245
|
|
|
243
246
|
// Handle wait queue overflow
|
|
244
247
|
if (tools.isNumber(this.options.queue_size) && this.options.queue_size < queue.jobs.length) {
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
const strategy = this.options.queue_ejection_strategy || 'oldest';
|
|
249
|
+
|
|
250
|
+
const targetJob = queue.jobs[strategy === 'oldest' ? 0 : queue.jobs.length - 1];
|
|
247
251
|
this.log(
|
|
248
|
-
`${queue.toString()} has overflown, so
|
|
252
|
+
`${queue.toString()} has overflown, so the ${strategy} job (${targetJob}) was kicked out`
|
|
249
253
|
);
|
|
250
254
|
|
|
251
|
-
this.endJob(
|
|
255
|
+
this.endJob(targetJob, [
|
|
252
256
|
new BetterLockQueueOverflowError(
|
|
253
257
|
this.options.name,
|
|
254
258
|
queue.key,
|
|
255
259
|
queue.jobs.length,
|
|
256
|
-
|
|
260
|
+
targetJob,
|
|
261
|
+
strategy
|
|
257
262
|
),
|
|
258
263
|
]);
|
|
259
264
|
}
|
package/src/errors.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { KeyQueue, LockJob } from './internals';
|
|
2
2
|
import { IErrorName } from './types';
|
|
3
|
+
import { IQueueEjectionStrategy } from './options';
|
|
3
4
|
|
|
4
5
|
export class BetterLockError extends Error {
|
|
5
6
|
/**
|
|
@@ -97,10 +98,11 @@ export class BetterLockQueueOverflowError extends BetterLockError {
|
|
|
97
98
|
public keys: string[];
|
|
98
99
|
public job_count: number;
|
|
99
100
|
public kicked_out_job_id: number;
|
|
101
|
+
public strategy: IQueueEjectionStrategy;
|
|
100
102
|
|
|
101
|
-
constructor(lockName, key, count, job: LockJob<any
|
|
103
|
+
constructor(lockName, key, count, job: LockJob<any>, strategy: IQueueEjectionStrategy) {
|
|
102
104
|
const keyDesignation = key === KeyQueue.DEFAULT_QUEUE_KEY ? '' : ` for key "${key}"`;
|
|
103
|
-
const message = `Too many jobs (${count}) are waiting${keyDesignation}. The
|
|
105
|
+
const message = `Too many jobs (${count}) are waiting${keyDesignation}. The ${strategy} job (${job}) was kicked out`;
|
|
104
106
|
|
|
105
107
|
super(lockName, message, job.incoming_stack);
|
|
106
108
|
|
|
@@ -108,6 +110,7 @@ export class BetterLockQueueOverflowError extends BetterLockError {
|
|
|
108
110
|
this.keys = job.keys;
|
|
109
111
|
this.job_count = count;
|
|
110
112
|
this.kicked_out_job_id = job.id;
|
|
113
|
+
this.strategy = strategy;
|
|
111
114
|
}
|
|
112
115
|
}
|
|
113
116
|
|
package/src/index.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
BetterLockQueueOverflowError,
|
|
9
9
|
BetterLockWaitTimeoutError,
|
|
10
10
|
} from './errors';
|
|
11
|
-
import { ILockJobOptions as BetterLockJobOptions, IOptions as BetterLockOptions } from './options';
|
|
11
|
+
import { ILockJobOptions as BetterLockJobOptions, IOptions as BetterLockOptions, IQueueEjectionStrategy as BetterLockQueueEjectionStrategy } from './options';
|
|
12
12
|
import {
|
|
13
13
|
IErrorName as BetterLockErrorName,
|
|
14
14
|
IExecutor as BetterLockExecutor,
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
|
|
18
18
|
export {
|
|
19
19
|
BetterLockOptions,
|
|
20
|
+
BetterLockQueueEjectionStrategy,
|
|
20
21
|
BetterLockJobOptions,
|
|
21
22
|
BetterLockExecutor,
|
|
22
23
|
BetterLockKey,
|
package/src/options.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ILockKey } from './types';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Options that apply on LockJob
|
|
3
5
|
*/
|
|
@@ -16,8 +18,17 @@ export interface ILockJobOptions {
|
|
|
16
18
|
* In any error produced by BetterLock, extend the stack trace to include incoming trace. Overrides BetterLockOptions value.
|
|
17
19
|
*/
|
|
18
20
|
extend_stack_traces?: boolean;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Before acquiring lock, call this function with the given key. If condition is rejected, the executor is immediately called, without locking.
|
|
24
|
+
* This can be used to more conveniently opt out of locking, without duplicating or extracting the executor.
|
|
25
|
+
* Overrides BetterLockOptions value.
|
|
26
|
+
*/
|
|
27
|
+
lock_condition?: (key: ILockKey | Array<ILockKey>) => boolean;
|
|
19
28
|
}
|
|
20
29
|
|
|
30
|
+
export type IQueueEjectionStrategy = 'oldest' | 'newest';
|
|
31
|
+
|
|
21
32
|
/**
|
|
22
33
|
* Options that apply on BetterLock instance
|
|
23
34
|
*/
|
|
@@ -38,6 +49,17 @@ export interface IOptions extends ILockJobOptions {
|
|
|
38
49
|
*/
|
|
39
50
|
queue_size?: number | null;
|
|
40
51
|
|
|
52
|
+
/**
|
|
53
|
+
* If queue is full, which job to eject. Defaults to 'oldest'.
|
|
54
|
+
*/
|
|
55
|
+
queue_ejection_strategy?: IQueueEjectionStrategy;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Before acquiring lock, call this function with the given key. If condition is rejected, the executor is immediately called, without locking.
|
|
59
|
+
* This can be used to more conveniently opt out of locking, without duplicating or extracting the executor.
|
|
60
|
+
*/
|
|
61
|
+
lock_condition?: (key: ILockKey | Array<ILockKey>) => boolean;
|
|
62
|
+
|
|
41
63
|
/**
|
|
42
64
|
* Lock name. This will be written in all logs and error messages, to help you distinguish between different locks
|
|
43
65
|
*/
|
package/src/types.ts
CHANGED
|
@@ -12,8 +12,8 @@ export type IErrorName = keyof IErrorExports;
|
|
|
12
12
|
* but also old-school callbacks, with varargs return values.
|
|
13
13
|
*/
|
|
14
14
|
export type ICallback<TResult> = TResult extends any[]
|
|
15
|
-
? (err
|
|
16
|
-
: (err
|
|
15
|
+
? (err: Error | null, ...result: TResult) => void
|
|
16
|
+
: (err: Error | null, result?: TResult) => void;
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Function that user will supply as the thing that will be running inside lock.
|