mini-semaphore 1.4.4 → 1.5.2
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/cjs/class.d.ts +85 -0
- package/cjs/core.d.ts +107 -0
- package/cjs/core.js +11 -8
- package/cjs/deque.d.ts +28 -0
- package/cjs/flow-restrictor.d.ts +21 -0
- package/cjs/index.d.ts +1 -1
- package/cjs/index.js +1 -1
- package/cjs/object.d.ts +86 -0
- package/cjs/object.js +21 -8
- package/esm/core.mjs +11 -8
- package/esm/index.d.mts +1 -1
- package/esm/index.mjs +1 -1
- package/esm/object.mjs +21 -8
- package/index.d.ts +1 -1
- package/package.json +38 -1
- package/umd/index.d.ts +1 -1
- package/umd/index.js +7 -7
- package/webpack/index.d.ts +1 -1
- package/webpack/index.js +6 -6
- package/webpack-esm/index.d.mts +1 -1
- package/webpack-esm/index.mjs +7 -6
package/cjs/class.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
3
|
+
Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
|
|
4
|
+
Released under the MIT license
|
|
5
|
+
https://opensource.org/licenses/mit-license.php
|
|
6
|
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* @file minimal implementation of semaphore (class implementation
|
|
10
|
+
* @author jeffy-g <hirotom1107@gmail.com>
|
|
11
|
+
* @version 1.0
|
|
12
|
+
*/
|
|
13
|
+
import * as core from "./core";
|
|
14
|
+
import { Deque } from "./deque";
|
|
15
|
+
export type * from "./core";
|
|
16
|
+
/**
|
|
17
|
+
* #### Mini Semaphore
|
|
18
|
+
*
|
|
19
|
+
* + minimal implementation of semaphore
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* import { MiniSemaphore } from "mini-semaphore";
|
|
23
|
+
*
|
|
24
|
+
* const s = new MiniSemaphore(10);
|
|
25
|
+
* async function fetchTypeData(type_id) {
|
|
26
|
+
* await s.acquire();
|
|
27
|
+
* try {
|
|
28
|
+
* return fetch(`https://esi.evetech.net/latest/universe/types/${type_id}/`);
|
|
29
|
+
* } finally {
|
|
30
|
+
* s.release();
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* //
|
|
35
|
+
* // or automatic acquire/release
|
|
36
|
+
* //
|
|
37
|
+
* async function fetchTypeData(type_id) {
|
|
38
|
+
* return s.flow(async () => fetch(`https://esi.evetech.net/latest/universe/types/${type_id}/`));
|
|
39
|
+
* }
|
|
40
|
+
*
|
|
41
|
+
* @date 2020/2/7
|
|
42
|
+
* @version 1.0
|
|
43
|
+
*/
|
|
44
|
+
export declare class MiniSemaphore implements core.TFlowableLock {
|
|
45
|
+
/**
|
|
46
|
+
* spare capacity
|
|
47
|
+
*/
|
|
48
|
+
capacity: number;
|
|
49
|
+
/**
|
|
50
|
+
* limitation
|
|
51
|
+
*/
|
|
52
|
+
limit: number;
|
|
53
|
+
/**
|
|
54
|
+
* queue of Promise's `resolve`
|
|
55
|
+
*/
|
|
56
|
+
q: Deque<core.TVoidFunction>;
|
|
57
|
+
/**
|
|
58
|
+
* constructs a semaphore instance limited at `capacity`
|
|
59
|
+
*
|
|
60
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
61
|
+
*/
|
|
62
|
+
constructor(capacity: number);
|
|
63
|
+
/**
|
|
64
|
+
* If there is enough capacity, execute the `resolve` immediately
|
|
65
|
+
*
|
|
66
|
+
* If not, put it in a queue and wait for the currently pending process to execute `release`
|
|
67
|
+
*
|
|
68
|
+
* @param {boolean=} lazy
|
|
69
|
+
*/
|
|
70
|
+
acquire(lazy?: boolean): Promise<void>;
|
|
71
|
+
release(): void;
|
|
72
|
+
/**
|
|
73
|
+
* @param {number} restriction
|
|
74
|
+
*/
|
|
75
|
+
setRestriction(restriction: number): void;
|
|
76
|
+
get pending(): number;
|
|
77
|
+
/**
|
|
78
|
+
* automatic acquire/release
|
|
79
|
+
*
|
|
80
|
+
* @template {any} T description
|
|
81
|
+
* @param {() => Promise<T>} process
|
|
82
|
+
* @param {boolean=} lazy
|
|
83
|
+
*/
|
|
84
|
+
flow<T>(process: () => Promise<T>, lazy?: boolean): Promise<T>;
|
|
85
|
+
}
|
package/cjs/core.d.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
3
|
+
Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
|
|
4
|
+
Released under the MIT license
|
|
5
|
+
https://opensource.org/licenses/mit-license.php
|
|
6
|
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* @file minimal implementation of semaphore (core
|
|
10
|
+
* @author jeffy-g <hirotom1107@gmail.com>
|
|
11
|
+
* @version 1.0
|
|
12
|
+
*/
|
|
13
|
+
import type { Deque } from "./deque";
|
|
14
|
+
/**
|
|
15
|
+
* basic of simplified lock interface
|
|
16
|
+
*/
|
|
17
|
+
export interface ISimplifiedLock {
|
|
18
|
+
/**
|
|
19
|
+
* acquire the process rights
|
|
20
|
+
*
|
|
21
|
+
* @param {boolean} lazy Whether the privilege acquisition process is deffer. default `true`
|
|
22
|
+
*/
|
|
23
|
+
acquire(lazy?: boolean): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* release the pending of one
|
|
26
|
+
*/
|
|
27
|
+
release(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Change sharing restrictions to the value of `restriction`
|
|
30
|
+
* @param {number} restriction
|
|
31
|
+
*/
|
|
32
|
+
setRestriction(restriction: number): void;
|
|
33
|
+
/**
|
|
34
|
+
* Get the number of currently pending processes
|
|
35
|
+
* @type {number}
|
|
36
|
+
*/
|
|
37
|
+
readonly pending: number;
|
|
38
|
+
/**
|
|
39
|
+
* limitation
|
|
40
|
+
* @type {number}
|
|
41
|
+
*/
|
|
42
|
+
limit: number;
|
|
43
|
+
/**
|
|
44
|
+
* capacity
|
|
45
|
+
* @type {number}
|
|
46
|
+
*/
|
|
47
|
+
capacity: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* extention of `ISimplifiedLock` interface
|
|
51
|
+
*/
|
|
52
|
+
export interface IFlowableLock extends ISimplifiedLock {
|
|
53
|
+
/**
|
|
54
|
+
* combination of acquire/release
|
|
55
|
+
*
|
|
56
|
+
* + acquire/release is automatic
|
|
57
|
+
*
|
|
58
|
+
* @param lazy Whether the privilege acquisition process is deffer. default `true`
|
|
59
|
+
*/
|
|
60
|
+
flow<T>(f: () => Promise<T>, lazy?: boolean): Promise<T>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* internal type for `createMiniSemaphore`
|
|
64
|
+
*/
|
|
65
|
+
export type TFlowableLock<T = TVoidFunction> = IFlowableLock & {
|
|
66
|
+
/**
|
|
67
|
+
* pending
|
|
68
|
+
*/
|
|
69
|
+
readonly q: Deque<T>;
|
|
70
|
+
};
|
|
71
|
+
export type TResolver = {
|
|
72
|
+
resolve: () => void;
|
|
73
|
+
reject: (reason: any) => void;
|
|
74
|
+
};
|
|
75
|
+
export type TAbortListener = (reason: IProcessAbortedError) => void;
|
|
76
|
+
export type TFlowableLockWithAbort = IFlowableLock & {
|
|
77
|
+
readonly q: Deque<TResolver>;
|
|
78
|
+
abort(): void;
|
|
79
|
+
onAbort(listener: TAbortListener): void;
|
|
80
|
+
offAbort(listener: TAbortListener): void;
|
|
81
|
+
};
|
|
82
|
+
export declare interface IProcessAbortedError {
|
|
83
|
+
readonly message: "Process Aborted";
|
|
84
|
+
}
|
|
85
|
+
export type TVoidFunction = () => void;
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @param {TFlowableLock} dis
|
|
89
|
+
* @param {boolean} [lazy] default: true
|
|
90
|
+
* @returns {Promise<void>}
|
|
91
|
+
*/
|
|
92
|
+
export declare const acquire: (dis: TFlowableLock, lazy?: boolean) => Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* @param {TFlowableLock} dis
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
export declare const release: (dis: TFlowableLock) => void;
|
|
98
|
+
/**
|
|
99
|
+
* @param {TFlowableLockWithAbort} dis
|
|
100
|
+
* @returns {Promise<void>}
|
|
101
|
+
*/
|
|
102
|
+
export declare const acquireWithAbort: (dis: TFlowableLockWithAbort) => Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* @param {TFlowableLockWithAbort} dis
|
|
105
|
+
* @returns {void}
|
|
106
|
+
*/
|
|
107
|
+
export declare const releaseWithAbort: (dis: TFlowableLockWithAbort) => void;
|
package/cjs/core.js
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.releaseWithAbort = exports.acquireWithAbort = exports.release = exports.acquire = void 0;
|
|
4
4
|
/**
|
|
5
|
-
* @
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* @import {
|
|
6
|
+
* TResolver,
|
|
7
|
+
* TVoidFunction,
|
|
8
|
+
* TFlowableLockWithAbort,
|
|
9
|
+
* ISimplifiedLock,
|
|
10
|
+
* TFlowableLock,
|
|
11
|
+
* IFlowableLock,
|
|
12
|
+
* Deque,
|
|
13
|
+
* } from "./index.mjs";
|
|
14
|
+
* @typedef {Deque<TResolver>} DequeWithAbort
|
|
12
15
|
*/
|
|
13
16
|
/**
|
|
14
17
|
* Throws an error indicating an inconsistent state in mini-semaphore.
|
|
@@ -51,7 +54,7 @@ exports.acquire = acquire;
|
|
|
51
54
|
* @returns {void}
|
|
52
55
|
*/
|
|
53
56
|
const release = (dis) => {
|
|
54
|
-
/** @type {Deque} */
|
|
57
|
+
/** @type {Deque<TVoidFunction>} */
|
|
55
58
|
let dq;
|
|
56
59
|
if ((dq = dis.q).length) {
|
|
57
60
|
(dq.shift() || /* istanbul ignore next */ THROW)();
|
package/cjs/deque.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ### Implementation restricted to FIFO
|
|
3
|
+
*
|
|
4
|
+
* This class uses a ring buffer for efficient FIFO operations.
|
|
5
|
+
* The maximum buffer size is **`1073741824`**.
|
|
6
|
+
*
|
|
7
|
+
* This class is based on https://github.com/petkaantonov/deque/blob/master/js/deque.js
|
|
8
|
+
* Released under the MIT License: https://github.com/petkaantonov/deque/blob/master/LICENSE
|
|
9
|
+
*
|
|
10
|
+
* @template {any} T
|
|
11
|
+
*/
|
|
12
|
+
export declare class Deque<T extends any> {
|
|
13
|
+
_c: number;
|
|
14
|
+
_l: number;
|
|
15
|
+
_f: number;
|
|
16
|
+
_a: T[];
|
|
17
|
+
length: number;
|
|
18
|
+
/**
|
|
19
|
+
* default capacity `16`
|
|
20
|
+
* @param {number=} ic initial capacity
|
|
21
|
+
*/
|
|
22
|
+
constructor(ic?: number);
|
|
23
|
+
/**
|
|
24
|
+
* @param {T} s subject
|
|
25
|
+
*/
|
|
26
|
+
push(s: T): void;
|
|
27
|
+
shift(): T | undefined;
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IFlowableLock } from "./class";
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
* @date 2020/6/18
|
|
5
|
+
*/
|
|
6
|
+
type TFlowableLockWithTimeStamp = IFlowableLock & {
|
|
7
|
+
last?: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {import("./index").IFlowableLock & { last?: number }} TFlowableLockWithTimeStamp
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Flow Restriction
|
|
14
|
+
*/
|
|
15
|
+
export declare const restrictor: {
|
|
16
|
+
getLockByKey: (key: PropertyKey) => Promise<TFlowableLockWithTimeStamp | undefined>;
|
|
17
|
+
cleanup: (timeSpan: number, debug?: true) => Promise<number>;
|
|
18
|
+
multi: <T>(key: PropertyKey, restriction: number, pb: () => Promise<T>) => Promise<T>;
|
|
19
|
+
one: <T>(key: PropertyKey, pb: () => Promise<T>) => Promise<T>;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
package/cjs/index.d.ts
CHANGED
|
@@ -213,7 +213,7 @@ declare namespace fr {
|
|
|
213
213
|
* @param key
|
|
214
214
|
* @returns `IFlowableLock` instance or `undefined`
|
|
215
215
|
*/
|
|
216
|
-
export const getLockByKey: (key: string | number) => Promise<IFlowableLock>;
|
|
216
|
+
export const getLockByKey: (key: string | number) => Promise<IFlowableLock | undefined>;
|
|
217
217
|
/**
|
|
218
218
|
* Allocate a semaphore for each `key`, and limit the number of shares with the value of `restriction`
|
|
219
219
|
*
|
package/cjs/index.js
CHANGED
|
@@ -10,4 +10,4 @@ var deque_1 = require("./deque");
|
|
|
10
10
|
Object.defineProperty(exports, "Deque", { enumerable: true, get: function () { return deque_1.Deque; } });
|
|
11
11
|
var flow_restrictor_1 = require("./flow-restrictor");
|
|
12
12
|
Object.defineProperty(exports, "restrictor", { enumerable: true, get: function () { return flow_restrictor_1.restrictor; } });
|
|
13
|
-
exports.version = "v1.
|
|
13
|
+
exports.version = "v1.5.2";
|
package/cjs/object.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
3
|
+
Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
|
|
4
|
+
Released under the MIT license
|
|
5
|
+
https://opensource.org/licenses/mit-license.php
|
|
6
|
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* @file minimal implementation of semaphore (object implementation
|
|
10
|
+
* @author jeffy-g <hirotom1107@gmail.com>
|
|
11
|
+
* @version 1.0
|
|
12
|
+
*/
|
|
13
|
+
import * as core from "./core";
|
|
14
|
+
import { Deque } from "./deque";
|
|
15
|
+
export type * from "./core";
|
|
16
|
+
/**
|
|
17
|
+
* object implementation of `IFlowableLock`
|
|
18
|
+
*
|
|
19
|
+
* + constructs a semaphore object limited at `capacity`
|
|
20
|
+
*
|
|
21
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
22
|
+
* @date 2020/2/7
|
|
23
|
+
* @version 1.0
|
|
24
|
+
*/
|
|
25
|
+
export declare const create: (capacity: number) => {
|
|
26
|
+
pending: number;
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param {boolean} [lazy]
|
|
30
|
+
* @returns {Promise<void>}
|
|
31
|
+
*/
|
|
32
|
+
acquire(lazy?: boolean): Promise<void>;
|
|
33
|
+
release(): void;
|
|
34
|
+
/**
|
|
35
|
+
* @template {any} T
|
|
36
|
+
* @param {() => Promise<T>} process
|
|
37
|
+
* @param {boolean} [lazy]
|
|
38
|
+
* @returns {Promise<T>}
|
|
39
|
+
*/
|
|
40
|
+
flow<T>(process: () => Promise<T>, lazy?: boolean): Promise<T>;
|
|
41
|
+
setRestriction(restriction: number): void;
|
|
42
|
+
limit: number;
|
|
43
|
+
capacity: number;
|
|
44
|
+
q: Deque<core.TVoidFunction>;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
48
|
+
*
|
|
49
|
+
* + constructs a semaphore object limited at `capacity`
|
|
50
|
+
*
|
|
51
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
52
|
+
* @date 2025/5/12
|
|
53
|
+
* @version 1.4
|
|
54
|
+
*/
|
|
55
|
+
export declare const createWithAbort: (capacity: number) => {
|
|
56
|
+
pending: number;
|
|
57
|
+
/**
|
|
58
|
+
* @returns {Promise<void>}
|
|
59
|
+
*/
|
|
60
|
+
acquire(): Promise<void>;
|
|
61
|
+
release(): void;
|
|
62
|
+
/**
|
|
63
|
+
* @template {any} T
|
|
64
|
+
* @param {() => Promise<T>} process
|
|
65
|
+
* @returns {Promise<T>}
|
|
66
|
+
*/
|
|
67
|
+
flow<T>(process: () => Promise<T>): Promise<T>;
|
|
68
|
+
/**
|
|
69
|
+
* @throws {AggregateError} description
|
|
70
|
+
*/
|
|
71
|
+
abort(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Registers an event listener for the "abort" event.
|
|
74
|
+
* @param {TAbortListener} listener
|
|
75
|
+
*/
|
|
76
|
+
onAbort(listener: core.TAbortListener): void;
|
|
77
|
+
/**
|
|
78
|
+
* Removes an event listener for the "abort" event.
|
|
79
|
+
* @param {TAbortListener} listener
|
|
80
|
+
*/
|
|
81
|
+
offAbort(listener: core.TAbortListener): void;
|
|
82
|
+
setRestriction(restriction: number): void;
|
|
83
|
+
limit: number;
|
|
84
|
+
capacity: number;
|
|
85
|
+
q: Deque<core.TResolver>;
|
|
86
|
+
};
|
package/cjs/object.js
CHANGED
|
@@ -20,7 +20,17 @@ const r = core.release;
|
|
|
20
20
|
const aa = core.acquireWithAbort;
|
|
21
21
|
const ra = core.releaseWithAbort;
|
|
22
22
|
/**
|
|
23
|
-
* @
|
|
23
|
+
* @import {
|
|
24
|
+
* TResolver,
|
|
25
|
+
* TFlowableLock,
|
|
26
|
+
* IFlowableLock,
|
|
27
|
+
* TAbortListener,
|
|
28
|
+
* IProcessAbortedError,
|
|
29
|
+
* TFlowableLockWithAbort,
|
|
30
|
+
* } from "./index.mjs";
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* @template {IFlowableLock & { q: Deque<unknown>}} T
|
|
24
34
|
* @param {number} capacity
|
|
25
35
|
* @returns
|
|
26
36
|
*/
|
|
@@ -47,9 +57,9 @@ const createBase = (capacity) => {
|
|
|
47
57
|
* @version 1.0
|
|
48
58
|
*/
|
|
49
59
|
const create = (capacity) => {
|
|
50
|
-
/** @type {
|
|
60
|
+
/** @type {TFlowableLock} */
|
|
51
61
|
const base = createBase(capacity);
|
|
52
|
-
return /** @satisfies {
|
|
62
|
+
return /** @satisfies {TFlowableLock} */ ({
|
|
53
63
|
...base,
|
|
54
64
|
get pending() {
|
|
55
65
|
return this.q.length;
|
|
@@ -93,10 +103,11 @@ exports.create = create;
|
|
|
93
103
|
* @version 1.4
|
|
94
104
|
*/
|
|
95
105
|
const createWithAbort = (capacity) => {
|
|
96
|
-
/** @type {
|
|
106
|
+
/** @type {TFlowableLockWithAbort} */
|
|
97
107
|
const base = createBase(capacity);
|
|
108
|
+
/** @type {TAbortListener[]} */
|
|
98
109
|
const abortListeners = [];
|
|
99
|
-
return /** @satisfies {
|
|
110
|
+
return /** @satisfies {TFlowableLockWithAbort} */ ({
|
|
100
111
|
...base,
|
|
101
112
|
get pending() {
|
|
102
113
|
return this.q.length;
|
|
@@ -116,6 +127,7 @@ const createWithAbort = (capacity) => {
|
|
|
116
127
|
* @returns {Promise<T>}
|
|
117
128
|
*/
|
|
118
129
|
async flow(process) {
|
|
130
|
+
/** @type {T | undefined} */
|
|
119
131
|
let result;
|
|
120
132
|
try {
|
|
121
133
|
await aa(this);
|
|
@@ -123,13 +135,14 @@ const createWithAbort = (capacity) => {
|
|
|
123
135
|
ra(this);
|
|
124
136
|
}
|
|
125
137
|
finally {
|
|
126
|
-
return result;
|
|
138
|
+
return /** @type {T} */ (result);
|
|
127
139
|
}
|
|
128
140
|
},
|
|
129
141
|
/**
|
|
130
142
|
* @throws {AggregateError} description
|
|
131
143
|
*/
|
|
132
144
|
abort() {
|
|
145
|
+
/** @type {IProcessAbortedError} */
|
|
133
146
|
const reason = {
|
|
134
147
|
message: "Process Aborted"
|
|
135
148
|
};
|
|
@@ -143,7 +156,7 @@ const createWithAbort = (capacity) => {
|
|
|
143
156
|
},
|
|
144
157
|
/**
|
|
145
158
|
* Registers an event listener for the "abort" event.
|
|
146
|
-
* @param {
|
|
159
|
+
* @param {TAbortListener} listener
|
|
147
160
|
*/
|
|
148
161
|
onAbort(listener) {
|
|
149
162
|
if (!abortListeners.includes(listener)) {
|
|
@@ -152,7 +165,7 @@ const createWithAbort = (capacity) => {
|
|
|
152
165
|
},
|
|
153
166
|
/**
|
|
154
167
|
* Removes an event listener for the "abort" event.
|
|
155
|
-
* @param {
|
|
168
|
+
* @param {TAbortListener} listener
|
|
156
169
|
*/
|
|
157
170
|
offAbort(listener) {
|
|
158
171
|
const idx = abortListeners.findIndex(ls => listener === ls);
|
package/esm/core.mjs
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* TResolver,
|
|
4
|
+
* TVoidFunction,
|
|
5
|
+
* TFlowableLockWithAbort,
|
|
6
|
+
* ISimplifiedLock,
|
|
7
|
+
* TFlowableLock,
|
|
8
|
+
* IFlowableLock,
|
|
9
|
+
* Deque,
|
|
10
|
+
* } from "./index.mjs";
|
|
11
|
+
* @typedef {Deque<TResolver>} DequeWithAbort
|
|
9
12
|
*/
|
|
10
13
|
/**
|
|
11
14
|
* Throws an error indicating an inconsistent state in mini-semaphore.
|
|
@@ -47,7 +50,7 @@ export const acquire = (dis, lazy = true) => {
|
|
|
47
50
|
* @returns {void}
|
|
48
51
|
*/
|
|
49
52
|
export const release = (dis) => {
|
|
50
|
-
/** @type {Deque} */
|
|
53
|
+
/** @type {Deque<TVoidFunction>} */
|
|
51
54
|
let dq;
|
|
52
55
|
if ((dq = dis.q).length) {
|
|
53
56
|
(dq.shift() || /* istanbul ignore next */ THROW)();
|
package/esm/index.d.mts
CHANGED
|
@@ -213,7 +213,7 @@ declare namespace fr {
|
|
|
213
213
|
* @param key
|
|
214
214
|
* @returns `IFlowableLock` instance or `undefined`
|
|
215
215
|
*/
|
|
216
|
-
export const getLockByKey: (key: string | number) => Promise<IFlowableLock>;
|
|
216
|
+
export const getLockByKey: (key: string | number) => Promise<IFlowableLock | undefined>;
|
|
217
217
|
/**
|
|
218
218
|
* Allocate a semaphore for each `key`, and limit the number of shares with the value of `restriction`
|
|
219
219
|
*
|
package/esm/index.mjs
CHANGED
package/esm/object.mjs
CHANGED
|
@@ -17,7 +17,17 @@ const r = core.release;
|
|
|
17
17
|
const aa = core.acquireWithAbort;
|
|
18
18
|
const ra = core.releaseWithAbort;
|
|
19
19
|
/**
|
|
20
|
-
* @
|
|
20
|
+
* @import {
|
|
21
|
+
* TResolver,
|
|
22
|
+
* TFlowableLock,
|
|
23
|
+
* IFlowableLock,
|
|
24
|
+
* TAbortListener,
|
|
25
|
+
* IProcessAbortedError,
|
|
26
|
+
* TFlowableLockWithAbort,
|
|
27
|
+
* } from "./index.mjs";
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* @template {IFlowableLock & { q: Deque<unknown>}} T
|
|
21
31
|
* @param {number} capacity
|
|
22
32
|
* @returns
|
|
23
33
|
*/
|
|
@@ -44,9 +54,9 @@ const createBase = (capacity) => {
|
|
|
44
54
|
* @version 1.0
|
|
45
55
|
*/
|
|
46
56
|
export const create = (capacity) => {
|
|
47
|
-
/** @type {
|
|
57
|
+
/** @type {TFlowableLock} */
|
|
48
58
|
const base = createBase(capacity);
|
|
49
|
-
return /** @satisfies {
|
|
59
|
+
return /** @satisfies {TFlowableLock} */ ({
|
|
50
60
|
...base,
|
|
51
61
|
get pending() {
|
|
52
62
|
return this.q.length;
|
|
@@ -89,10 +99,11 @@ export const create = (capacity) => {
|
|
|
89
99
|
* @version 1.4
|
|
90
100
|
*/
|
|
91
101
|
export const createWithAbort = (capacity) => {
|
|
92
|
-
/** @type {
|
|
102
|
+
/** @type {TFlowableLockWithAbort} */
|
|
93
103
|
const base = createBase(capacity);
|
|
104
|
+
/** @type {TAbortListener[]} */
|
|
94
105
|
const abortListeners = [];
|
|
95
|
-
return /** @satisfies {
|
|
106
|
+
return /** @satisfies {TFlowableLockWithAbort} */ ({
|
|
96
107
|
...base,
|
|
97
108
|
get pending() {
|
|
98
109
|
return this.q.length;
|
|
@@ -112,6 +123,7 @@ export const createWithAbort = (capacity) => {
|
|
|
112
123
|
* @returns {Promise<T>}
|
|
113
124
|
*/
|
|
114
125
|
async flow(process) {
|
|
126
|
+
/** @type {T | undefined} */
|
|
115
127
|
let result;
|
|
116
128
|
try {
|
|
117
129
|
await aa(this);
|
|
@@ -119,13 +131,14 @@ export const createWithAbort = (capacity) => {
|
|
|
119
131
|
ra(this);
|
|
120
132
|
}
|
|
121
133
|
finally {
|
|
122
|
-
return result;
|
|
134
|
+
return /** @type {T} */ (result);
|
|
123
135
|
}
|
|
124
136
|
},
|
|
125
137
|
/**
|
|
126
138
|
* @throws {AggregateError} description
|
|
127
139
|
*/
|
|
128
140
|
abort() {
|
|
141
|
+
/** @type {IProcessAbortedError} */
|
|
129
142
|
const reason = {
|
|
130
143
|
message: "Process Aborted"
|
|
131
144
|
};
|
|
@@ -139,7 +152,7 @@ export const createWithAbort = (capacity) => {
|
|
|
139
152
|
},
|
|
140
153
|
/**
|
|
141
154
|
* Registers an event listener for the "abort" event.
|
|
142
|
-
* @param {
|
|
155
|
+
* @param {TAbortListener} listener
|
|
143
156
|
*/
|
|
144
157
|
onAbort(listener) {
|
|
145
158
|
if (!abortListeners.includes(listener)) {
|
|
@@ -148,7 +161,7 @@ export const createWithAbort = (capacity) => {
|
|
|
148
161
|
},
|
|
149
162
|
/**
|
|
150
163
|
* Removes an event listener for the "abort" event.
|
|
151
|
-
* @param {
|
|
164
|
+
* @param {TAbortListener} listener
|
|
152
165
|
*/
|
|
153
166
|
offAbort(listener) {
|
|
154
167
|
const idx = abortListeners.findIndex(ls => listener === ls);
|
package/index.d.ts
CHANGED
|
@@ -213,7 +213,7 @@ declare namespace fr {
|
|
|
213
213
|
* @param key
|
|
214
214
|
* @returns `IFlowableLock` instance or `undefined`
|
|
215
215
|
*/
|
|
216
|
-
export const getLockByKey: (key: string | number) => Promise<IFlowableLock>;
|
|
216
|
+
export const getLockByKey: (key: string | number) => Promise<IFlowableLock | undefined>;
|
|
217
217
|
/**
|
|
218
218
|
* Allocate a semaphore for each `key`, and limit the number of shares with the value of `restriction`
|
|
219
219
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mini-semaphore",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "A lightweight version of Semaphore",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "./cjs/index.js",
|
|
@@ -8,6 +8,43 @@
|
|
|
8
8
|
"unpkg": "./umd/index.js",
|
|
9
9
|
"sideEffects": false,
|
|
10
10
|
"types": "./index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./index.d.ts",
|
|
14
|
+
"import": "./esm/index.mjs",
|
|
15
|
+
"require": "./cjs/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./class": {
|
|
18
|
+
"import": "./esm/class.mjs",
|
|
19
|
+
"require": "./cjs/class.js"
|
|
20
|
+
},
|
|
21
|
+
"./object": {
|
|
22
|
+
"import": "./esm/object.mjs",
|
|
23
|
+
"require": "./cjs/object.js"
|
|
24
|
+
},
|
|
25
|
+
"./deque": {
|
|
26
|
+
"import": "./esm/deque.mjs",
|
|
27
|
+
"require": "./cjs/deque.js"
|
|
28
|
+
},
|
|
29
|
+
"./flow-restrictor": {
|
|
30
|
+
"import": "./esm/flow-restrictor.mjs",
|
|
31
|
+
"require": "./cjs/flow-restrictor.js"
|
|
32
|
+
},
|
|
33
|
+
"./umd": {
|
|
34
|
+
"import": "./umd/index.js",
|
|
35
|
+
"require": "./umd/index.js",
|
|
36
|
+
"types": "./umd/index.d.ts"
|
|
37
|
+
},
|
|
38
|
+
"./webpack": {
|
|
39
|
+
"import": "./webpack/index.js",
|
|
40
|
+
"require": "./webpack/index.js",
|
|
41
|
+
"types": "./webpack/index.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"./webpack-esm": {
|
|
44
|
+
"import": "./webpack-esm/index.mjs",
|
|
45
|
+
"types": "./webpack-esm/index.d.mts"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
11
48
|
"author": "jeffy-g",
|
|
12
49
|
"license": "MIT",
|
|
13
50
|
"bugs": {
|
package/umd/index.d.ts
CHANGED
|
@@ -213,7 +213,7 @@ declare namespace fr {
|
|
|
213
213
|
* @param key
|
|
214
214
|
* @returns `IFlowableLock` instance or `undefined`
|
|
215
215
|
*/
|
|
216
|
-
export const getLockByKey: (key: string | number) => Promise<IFlowableLock>;
|
|
216
|
+
export const getLockByKey: (key: string | number) => Promise<IFlowableLock | undefined>;
|
|
217
217
|
/**
|
|
218
218
|
* Allocate a semaphore for each `key`, and limit the number of shares with the value of `restriction`
|
|
219
219
|
*
|
package/umd/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
-
((e,t)=>{'object'==typeof exports&&'object'==typeof module?module.exports=t():'function'==typeof define&&define.amd?define([],t):'object'==typeof exports?exports.MiniSema=t():e.MiniSema=t()})(globalThis,(
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
new ReferenceError(`Cannot get object with different restriction: key: '${String(r)}', lock.limit: ${s.limit} <-> restriction: ${n},`);return t.release(),s})(r,n),o=a.flow(s);return a.last=Date.now(),o}return{getLockByKey:async e=>{await t.acquire(!1);const r=i[e];return t.release(),r},cleanup:async(e,r)=>{await t.acquire(!1);const n=i,s=Object.create(null),a=Object.keys(n);let o,c=0;!e&&(e=1),e*=1e3,r&&(o=[]);for(let t=0,i=a.length;t<i;){const i=a[t++],l=n[i];l.last&&Date.now()-l.last>=e?(c++,r&&o.push(i)):s[i]=l}return i=s,t.release(),r&&console.log(`eliminated: [\n${o.join(",\n")}\n]\nlived: [\n${Object.keys(s).join(",\n")}\n]`),c},multi:n,one:async function(e,t){
|
|
6
|
-
;const r=i(
|
|
7
|
-
;
|
|
8
|
-
|
|
2
|
+
((e,t)=>{'object'==typeof exports&&'object'==typeof module?module.exports=t():'function'==typeof define&&define.amd?define([],t):'object'==typeof exports?exports.MiniSema=t():e.MiniSema=t()})(globalThis,()=>(()=>{"use strict";var e={684(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSemaphore=void 0;const r=i(721),n=i(884),s=r.acquire,a=r.release;t.MiniSemaphore=class{constructor(e){this.limit=this.capacity=e,this.q=new n.Deque(e)}acquire(e){return s(this,e)}release(){a(this)}setRestriction(e){this.limit=this.capacity=e}get pending(){return this.q.length}async flow(e,t){await s(this,t);try{return await e()}finally{a(this)}}}},721(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.releaseWithAbort=t.acquireWithAbort=t.release=t.acquire=void 0;const i=()=>{
|
|
3
|
+
throw new Error("mini-semaphore: Detected an inconsistent state, possibly due to a logic error or unexpected behavior.")},r=(e,t)=>{e.capacity>0?(e.capacity--,t()):e.q.push(t)};t.acquire=(e,t=!0)=>new Promise(i=>{t?setTimeout(()=>r(e,i),4):r(e,i)});t.release=e=>{let t;(t=e.q).length?(t.shift()||i)():e.capacity++,e.capacity>e.limit&&(console.warn("inconsistent release!"),e.capacity=e.limit)};t.acquireWithAbort=e=>new Promise((t,i)=>{e.capacity>0?(e.capacity--,t()):e.q.push({resolve:t,reject:i})});t.releaseWithAbort=e=>{let t;if((t=e.q).length){const e=t.shift();e&&e.resolve()||i()}else e.capacity<e.limit&&e.capacity++}},884(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.Deque=void 0;const i=e=>(e=>(e>>>=0,e--,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,
|
|
4
|
+
1+(e|=e>>16)))(Math.min(Math.max(16,0|e),1073741824));t.Deque=class{constructor(e){this._c=i(e||16),this._l=0,this._f=0,this._a=[],this.length=0}push(e){const t=this._l;this._c<t+1&&r(this,i(1.5*this._c+16));const n=this._f+t&this._c-1;this._a[n]=e,this.length=this._l=t+1}shift(){const e=this._l;if(0===e)return;const t=this._f,i=this._a[t];return this._a[t]=void 0,this._f=t+1&this._c-1,this.length=this._l=e-1,i}};const r=(e,t)=>{const i=e._c;e._c=t;const r=e._f+e._l;if(r>i){const t=r&i-1;((e,t,i,r,n)=>{for(let s=0;s<n;++s)i[s+r]=e[s+t],e[s+t]=void 0})(e._a,0,e._a,i,t)}}},650(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(684);t.restrictor=(()=>{const{MiniSemaphore:e}=r,t=new e(1);let i=Object.create(null);async function n(r,n,s){
|
|
5
|
+
const a=await(async(r,n)=>{await t.acquire(!1);let s=i[r];if(s||(i[r]=s=new e(n)),s.limit!==n)throw t.release(),new ReferenceError(`Cannot get object with different restriction: key: '${String(r)}', lock.limit: ${s.limit} <-> restriction: ${n},`);return t.release(),s})(r,n),o=a.flow(s);return a.last=Date.now(),o}return{getLockByKey:async e=>{await t.acquire(!1);const r=i[e];return t.release(),r},cleanup:async(e,r)=>{await t.acquire(!1);const n=i,s=Object.create(null),a=Object.keys(n);let o,c=0;!e&&(e=1),e*=1e3,r&&(o=[]);for(let t=0,i=a.length;t<i;){const i=a[t++],l=n[i];l.last&&Date.now()-l.last>=e?(c++,r&&o.push(i)):s[i]=l}return i=s,t.release(),r&&console.log(`eliminated: [\n${o.join(",\n")}\n]\nlived: [\n${Object.keys(s).join(",\n")}\n]`),c},multi:n,one:async function(e,t){
|
|
6
|
+
return n(e,1,t)}}})()},121(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.createWithAbort=t.create=void 0;const r=i(721),n=i(884),s=r.acquire,a=r.release,o=r.acquireWithAbort,c=r.releaseWithAbort,l=e=>({capacity:e,limit:e,q:new n.Deque(e),setRestriction(e){this.limit=this.capacity=e}});t.create=e=>({...l(e),get pending(){return this.q.length},acquire(e){return s(this,e)},release(){a(this)},async flow(e,t){await s(this,t);try{return await e()}finally{a(this)}}});t.createWithAbort=e=>{const t=l(e),i=[];return{...t,get pending(){return this.q.length},acquire(){return o(this)},release(){c(this)},async flow(e){let t;try{await o(this),t=await e(),c(this)}finally{return t}},abort(){const e={message:"Process Aborted"};i.forEach(t=>t(e));const t=this.q;let r;for(;r=t.shift();)r.reject(e)
|
|
7
|
+
;this.capacity=this.limit},onAbort(e){i.includes(e)||i.push(e)},offAbort(e){const t=i.findIndex(t=>e===t);-1!==t&&i.splice(t,1)}}}}},t={};function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,i),s.exports}var r={};return(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.version=e.restrictor=e.Deque=e.createWithAbort=e.create=e.MiniSemaphore=void 0;var t=i(684);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(121);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return n.create}}),Object.defineProperty(e,"createWithAbort",{enumerable:!0,get:function(){return n.createWithAbort}});var s=i(884);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){
|
|
8
|
+
return s.Deque}});var a=i(650);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return a.restrictor}}),e.version="v1.5.2"})(),r})());
|
package/webpack/index.d.ts
CHANGED
|
@@ -213,7 +213,7 @@ declare namespace fr {
|
|
|
213
213
|
* @param key
|
|
214
214
|
* @returns `IFlowableLock` instance or `undefined`
|
|
215
215
|
*/
|
|
216
|
-
export const getLockByKey: (key: string | number) => Promise<IFlowableLock>;
|
|
216
|
+
export const getLockByKey: (key: string | number) => Promise<IFlowableLock | undefined>;
|
|
217
217
|
/**
|
|
218
218
|
* Allocate a semaphore for each `key`, and limit the number of shares with the value of `restriction`
|
|
219
219
|
*
|
package/webpack/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
-
(()=>{"use strict";var e={
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
;const n=i,s=Object.create(null),a=Object.keys(n);let c,o=0;!e&&(e=1),e*=1e3,r&&(c=[]);for(let t=0,i=a.length;t<i;){const i=a[t++],l=n[i];l.last&&Date.now()-l.last>=e?(o++,r&&c.push(i)):s[i]=l}return i=s,t.release(),r&&console.log(`eliminated: [\n${c.join(",\n")}\n]\nlived: [\n${Object.keys(s).join(",\n")}\n]`),o},multi:n,one:async function(e,t){return n(e,1,t)}}})()},
|
|
6
|
-
|
|
7
|
-
;
|
|
2
|
+
(()=>{"use strict";var e={684(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSemaphore=void 0;const r=i(721),n=i(884),s=r.acquire,a=r.release;t.MiniSemaphore=class{constructor(e){this.limit=this.capacity=e,this.q=new n.Deque(e)}acquire(e){return s(this,e)}release(){a(this)}setRestriction(e){this.limit=this.capacity=e}get pending(){return this.q.length}async flow(e,t){await s(this,t);try{return await e()}finally{a(this)}}}},721(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.releaseWithAbort=t.acquireWithAbort=t.release=t.acquire=void 0;const i=()=>{throw new Error("mini-semaphore: Detected an inconsistent state, possibly due to a logic error or unexpected behavior.")},r=(e,t)=>{e.capacity>0?(e.capacity--,t()):e.q.push(t)};t.acquire=(e,t=!0)=>new Promise(i=>{
|
|
3
|
+
t?setTimeout(()=>r(e,i),4):r(e,i)});t.release=e=>{let t;(t=e.q).length?(t.shift()||i)():e.capacity++,e.capacity>e.limit&&(console.warn("inconsistent release!"),e.capacity=e.limit)};t.acquireWithAbort=e=>new Promise((t,i)=>{e.capacity>0?(e.capacity--,t()):e.q.push({resolve:t,reject:i})});t.releaseWithAbort=e=>{let t;if((t=e.q).length){const e=t.shift();e&&e.resolve()||i()}else e.capacity<e.limit&&e.capacity++}},884(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.Deque=void 0;const i=e=>(e=>(e>>>=0,e--,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,1+(e|=e>>16)))(Math.min(Math.max(16,0|e),1073741824));t.Deque=class{constructor(e){this._c=i(e||16),this._l=0,this._f=0,this._a=[],this.length=0}push(e){const t=this._l;this._c<t+1&&r(this,i(1.5*this._c+16));const n=this._f+t&this._c-1;this._a[n]=e,
|
|
4
|
+
this.length=this._l=t+1}shift(){const e=this._l;if(0===e)return;const t=this._f,i=this._a[t];return this._a[t]=void 0,this._f=t+1&this._c-1,this.length=this._l=e-1,i}};const r=(e,t)=>{const i=e._c;e._c=t;const r=e._f+e._l;if(r>i){const t=r&i-1;((e,t,i,r,n)=>{for(let s=0;s<n;++s)i[s+r]=e[s+t],e[s+t]=void 0})(e._a,0,e._a,i,t)}}},650(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(684);t.restrictor=(()=>{const{MiniSemaphore:e}=r,t=new e(1);let i=Object.create(null);async function n(r,n,s){const a=await(async(r,n)=>{await t.acquire(!1);let s=i[r];if(s||(i[r]=s=new e(n)),s.limit!==n)throw t.release(),new ReferenceError(`Cannot get object with different restriction: key: '${String(r)}', lock.limit: ${s.limit} <-> restriction: ${n},`);return t.release(),s
|
|
5
|
+
})(r,n),c=a.flow(s);return a.last=Date.now(),c}return{getLockByKey:async e=>{await t.acquire(!1);const r=i[e];return t.release(),r},cleanup:async(e,r)=>{await t.acquire(!1);const n=i,s=Object.create(null),a=Object.keys(n);let c,o=0;!e&&(e=1),e*=1e3,r&&(c=[]);for(let t=0,i=a.length;t<i;){const i=a[t++],l=n[i];l.last&&Date.now()-l.last>=e?(o++,r&&c.push(i)):s[i]=l}return i=s,t.release(),r&&console.log(`eliminated: [\n${c.join(",\n")}\n]\nlived: [\n${Object.keys(s).join(",\n")}\n]`),o},multi:n,one:async function(e,t){return n(e,1,t)}}})()},121(e,t,i){Object.defineProperty(t,"__esModule",{value:!0}),t.createWithAbort=t.create=void 0;const r=i(721),n=i(884),s=r.acquire,a=r.release,c=r.acquireWithAbort,o=r.releaseWithAbort,l=e=>({capacity:e,limit:e,q:new n.Deque(e),setRestriction(e){
|
|
6
|
+
this.limit=this.capacity=e}});t.create=e=>({...l(e),get pending(){return this.q.length},acquire(e){return s(this,e)},release(){a(this)},async flow(e,t){await s(this,t);try{return await e()}finally{a(this)}}});t.createWithAbort=e=>{const t=l(e),i=[];return{...t,get pending(){return this.q.length},acquire(){return c(this)},release(){o(this)},async flow(e){let t;try{await c(this),t=await e(),o(this)}finally{return t}},abort(){const e={message:"Process Aborted"};i.forEach(t=>t(e));const t=this.q;let r;for(;r=t.shift();)r.reject(e);this.capacity=this.limit},onAbort(e){i.includes(e)||i.push(e)},offAbort(e){const t=i.findIndex(t=>e===t);-1!==t&&i.splice(t,1)}}}}},t={};function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,i),s.exports}var r={}
|
|
7
|
+
;(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.version=e.restrictor=e.Deque=e.createWithAbort=e.create=e.MiniSemaphore=void 0;var t=i(684);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(121);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return n.create}}),Object.defineProperty(e,"createWithAbort",{enumerable:!0,get:function(){return n.createWithAbort}});var s=i(884);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return s.Deque}});var a=i(650);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return a.restrictor}}),e.version="v1.5.2"})(),module.exports=r})();
|
package/webpack-esm/index.d.mts
CHANGED
|
@@ -213,7 +213,7 @@ declare namespace fr {
|
|
|
213
213
|
* @param key
|
|
214
214
|
* @returns `IFlowableLock` instance or `undefined`
|
|
215
215
|
*/
|
|
216
|
-
export const getLockByKey: (key: string | number) => Promise<IFlowableLock>;
|
|
216
|
+
export const getLockByKey: (key: string | number) => Promise<IFlowableLock | undefined>;
|
|
217
217
|
/**
|
|
218
218
|
* Allocate a semaphore for each `key`, and limit the number of shares with the value of `restriction`
|
|
219
219
|
*
|
package/webpack-esm/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
-
var e={
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
;const
|
|
6
|
-
|
|
7
|
-
;
|
|
2
|
+
var e={684(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSemaphore=void 0;const i=r(721),s=r(884),n=i.acquire,a=i.release;t.MiniSemaphore=class{constructor(e){this.limit=this.capacity=e,this.q=new s.Deque(e)}acquire(e){return n(this,e)}release(){a(this)}setRestriction(e){this.limit=this.capacity=e}get pending(){return this.q.length}async flow(e,t){await n(this,t);try{return await e()}finally{a(this)}}}},721(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.releaseWithAbort=t.acquireWithAbort=t.release=t.acquire=void 0;const r=()=>{throw new Error("mini-semaphore: Detected an inconsistent state, possibly due to a logic error or unexpected behavior.")},i=(e,t)=>{e.capacity>0?(e.capacity--,t()):e.q.push(t)};t.acquire=(e,t=!0)=>new Promise(r=>{
|
|
3
|
+
t?setTimeout(()=>i(e,r),4):i(e,r)});t.release=e=>{let t;(t=e.q).length?(t.shift()||r)():e.capacity++,e.capacity>e.limit&&(console.warn("inconsistent release!"),e.capacity=e.limit)};t.acquireWithAbort=e=>new Promise((t,r)=>{e.capacity>0?(e.capacity--,t()):e.q.push({resolve:t,reject:r})});t.releaseWithAbort=e=>{let t;if((t=e.q).length){const e=t.shift();e&&e.resolve()||r()}else e.capacity<e.limit&&e.capacity++}},884(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.Deque=void 0;const r=e=>(e=>(e>>>=0,e--,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,1+(e|=e>>16)))(Math.min(Math.max(16,0|e),1073741824));t.Deque=class{constructor(e){this._c=r(e||16),this._l=0,this._f=0,this._a=[],this.length=0}push(e){const t=this._l;this._c<t+1&&i(this,r(1.5*this._c+16));const s=this._f+t&this._c-1;this._a[s]=e,
|
|
4
|
+
this.length=this._l=t+1}shift(){const e=this._l;if(0===e)return;const t=this._f,r=this._a[t];return this._a[t]=void 0,this._f=t+1&this._c-1,this.length=this._l=e-1,r}};const i=(e,t)=>{const r=e._c;e._c=t;const i=e._f+e._l;if(i>r){const t=i&r-1;((e,t,r,i,s)=>{for(let n=0;n<s;++n)r[n+i]=e[n+t],e[n+t]=void 0})(e._a,0,e._a,r,t)}}},650(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const i=r(684);t.restrictor=(()=>{const{MiniSemaphore:e}=i,t=new e(1);let r=Object.create(null);async function s(i,s,n){const a=await(async(i,s)=>{await t.acquire(!1);let n=r[i];if(n||(r[i]=n=new e(s)),n.limit!==s)throw t.release(),new ReferenceError(`Cannot get object with different restriction: key: '${String(i)}', lock.limit: ${n.limit} <-> restriction: ${s},`);return t.release(),n
|
|
5
|
+
})(i,s),c=a.flow(n);return a.last=Date.now(),c}return{getLockByKey:async e=>{await t.acquire(!1);const i=r[e];return t.release(),i},cleanup:async(e,i)=>{await t.acquire(!1);const s=r,n=Object.create(null),a=Object.keys(s);let c,o=0;!e&&(e=1),e*=1e3,i&&(c=[]);for(let t=0,r=a.length;t<r;){const r=a[t++],l=s[r];l.last&&Date.now()-l.last>=e?(o++,i&&c.push(r)):n[r]=l}return r=n,t.release(),i&&console.log(`eliminated: [\n${c.join(",\n")}\n]\nlived: [\n${Object.keys(n).join(",\n")}\n]`),o},multi:s,one:async function(e,t){return s(e,1,t)}}})()},121(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.createWithAbort=t.create=void 0;const i=r(721),s=r(884),n=i.acquire,a=i.release,c=i.acquireWithAbort,o=i.releaseWithAbort,l=e=>({capacity:e,limit:e,q:new s.Deque(e),setRestriction(e){
|
|
6
|
+
this.limit=this.capacity=e}});t.create=e=>({...l(e),get pending(){return this.q.length},acquire(e){return n(this,e)},release(){a(this)},async flow(e,t){await n(this,t);try{return await e()}finally{a(this)}}});t.createWithAbort=e=>{const t=l(e),r=[];return{...t,get pending(){return this.q.length},acquire(){return c(this)},release(){o(this)},async flow(e){let t;try{await c(this),t=await e(),o(this)}finally{return t}},abort(){const e={message:"Process Aborted"};r.forEach(t=>t(e));const t=this.q;let i;for(;i=t.shift();)i.reject(e);this.capacity=this.limit},onAbort(e){r.includes(e)||r.push(e)},offAbort(e){const t=r.findIndex(t=>e===t);-1!==t&&r.splice(t,1)}}}}},t={};function r(i){var s=t[i];if(void 0!==s)return s.exports;var n=t[i]={exports:{}};return e[i](n,n.exports,r),n.exports}var i={}
|
|
7
|
+
;(()=>{var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.version=e.restrictor=e.Deque=e.createWithAbort=e.create=e.MiniSemaphore=void 0;var t=r(684);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var s=r(121);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return s.create}}),Object.defineProperty(e,"createWithAbort",{enumerable:!0,get:function(){return s.createWithAbort}});var n=r(884);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return n.Deque}});var a=r(650);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return a.restrictor}}),e.version="v1.5.2"})();const s=i.Deque,n=i.MiniSemaphore,a=i.__esModule,c=i.create,o=i.createWithAbort,l=i.restrictor,h=i.version
|
|
8
|
+
;export{s as Deque,n as MiniSemaphore,a as __esModule,c as create,o as createWithAbort,l as restrictor,h as version,i as default};
|