mini-semaphore 1.3.17 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/cjs/core.js +41 -2
- package/cjs/deque.js +9 -4
- package/cjs/index.d.ts +32 -6
- package/cjs/index.js +3 -2
- package/cjs/object.js +108 -14
- package/esm/core.mjs +37 -0
- package/esm/deque.mjs +9 -4
- package/esm/index.d.mts +32 -6
- package/esm/index.mjs +2 -2
- package/esm/object.mjs +105 -12
- package/index.d.ts +32 -6
- package/package.json +1 -1
- package/umd/index.d.ts +32 -6
- package/umd/index.js +7 -6
- package/webpack/index.d.ts +32 -6
- package/webpack/index.js +5 -4
- package/webpack-esm/index.d.mts +32 -6
- package/webpack-esm/index.mjs +6 -5
package/README.md
CHANGED
|
@@ -163,6 +163,69 @@ async function resolve(id: string | number): Promise<TType> {
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
> ## Abortable Semaphore
|
|
169
|
+
|
|
170
|
+
Starting from version **1.4.3**, `mini-semaphore` introduces support for abortable semaphores.
|
|
171
|
+
This feature allows you to cancel pending tasks and notify listeners when an abort event occurs.
|
|
172
|
+
This is particularly useful in scenarios where you need to terminate ongoing operations gracefully.
|
|
173
|
+
|
|
174
|
+
### Key Features
|
|
175
|
+
|
|
176
|
+
- **Abort Method**: Immediately cancels all pending tasks and restores the semaphore's capacity.
|
|
177
|
+
- **Event Emission**: Emits an `abort` event to notify listeners of the cancellation.
|
|
178
|
+
- **Listener Management**: Provides `onAbort` and `offAbort` methods to register and remove event listeners.
|
|
179
|
+
|
|
180
|
+
### Example Usage
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { createWithAbort } from "mini-semaphore";
|
|
184
|
+
|
|
185
|
+
// Create an abortable semaphore with a capacity of 3
|
|
186
|
+
const semaphore = createWithAbort(3);
|
|
187
|
+
|
|
188
|
+
// Register an abort event listener
|
|
189
|
+
semaphore.onAbort((reason) => {
|
|
190
|
+
console.log("Abort event received:", reason.message);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Simulate tasks
|
|
194
|
+
const task = async (id: number) => {
|
|
195
|
+
try {
|
|
196
|
+
await semaphore.acquire();
|
|
197
|
+
console.log(`Task ${id} started`);
|
|
198
|
+
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate work
|
|
199
|
+
console.log(`Task ${id} completed`);
|
|
200
|
+
semaphore.release();
|
|
201
|
+
} catch (e) {
|
|
202
|
+
console.log(`Task ${id} aborted:`, e.message);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// Start tasks
|
|
207
|
+
const tasks = [1, 2, 3, 4, 5].map((id) => task(id));
|
|
208
|
+
|
|
209
|
+
// Abort all pending tasks after 2 seconds
|
|
210
|
+
setTimeout(() => {
|
|
211
|
+
semaphore.abort();
|
|
212
|
+
}, 2000);
|
|
213
|
+
|
|
214
|
+
// Wait for all tasks to settle
|
|
215
|
+
Promise.allSettled(tasks).then(() => {
|
|
216
|
+
console.log("All tasks settled");
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Explanation
|
|
221
|
+
|
|
222
|
+
1. **Creating an Abortable Semaphore**: Use `createWithAbort` to create a semaphore with abort capabilities.
|
|
223
|
+
2. **Registering Listeners**: Use `onAbort` to listen for abort events and handle cleanup or logging.
|
|
224
|
+
3. **Aborting Tasks**: Call `abort` to cancel all pending tasks. Tasks that are already running will not be interrupted but will complete normally.
|
|
225
|
+
4. **Graceful Cleanup**: Use `offAbort` to remove listeners when they are no longer needed.
|
|
226
|
+
|
|
227
|
+
This feature enhances the flexibility of `mini-semaphore`, making it suitable for more complex concurrency control scenarios.
|
|
228
|
+
|
|
166
229
|
> ## Authors
|
|
167
230
|
|
|
168
231
|
+ **jeffy-g** - [jeffy-g](https://github.com/jeffy-g)
|
package/cjs/core.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.release = exports.acquire = void 0;
|
|
3
|
+
exports.releaseWithAbort = exports.acquireWithAbort = exports.release = exports.acquire = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {import("./index").TVoidFunction} TVoidFunction
|
|
6
6
|
* @typedef {import("./index").Deque<TVoidFunction>} Deque
|
|
7
|
+
* @typedef {import("./index").TFlowableLockWithAbort} TFlowableLockWithAbort
|
|
8
|
+
* @typedef {import("./index").Deque<TResolver>} DequeWithAbort
|
|
7
9
|
* @typedef {import("./index").ISimplifiedLock} ISimplifiedLock
|
|
8
10
|
* @typedef {import("./index").TFlowableLock} TFlowableLock
|
|
9
11
|
* @typedef {import("./index").IFlowableLock} IFlowableLock
|
|
@@ -62,4 +64,41 @@ const release = (dis) => {
|
|
|
62
64
|
dis.capacity = dis.limit;
|
|
63
65
|
}
|
|
64
66
|
};
|
|
65
|
-
exports.release = release;
|
|
67
|
+
exports.release = release;
|
|
68
|
+
/**
|
|
69
|
+
* @param {TFlowableLockWithAbort} dis
|
|
70
|
+
* @returns {Promise<void>}
|
|
71
|
+
*/
|
|
72
|
+
const acquireWithAbort = (dis) => {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
if (dis.capacity > 0) {
|
|
75
|
+
dis.capacity--, resolve();
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
dis.q.push({
|
|
79
|
+
resolve, reject
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
exports.acquireWithAbort = acquireWithAbort;
|
|
85
|
+
/**
|
|
86
|
+
* @param {TFlowableLockWithAbort} dis
|
|
87
|
+
* @returns {void}
|
|
88
|
+
*/
|
|
89
|
+
const releaseWithAbort = (dis) => {
|
|
90
|
+
/** @type {DequeWithAbort} */
|
|
91
|
+
let dq;
|
|
92
|
+
if ((dq = dis.q).length) {
|
|
93
|
+
const resolver = dq.shift();
|
|
94
|
+
resolver && resolver.resolve() || (
|
|
95
|
+
/* istanbul ignore next */
|
|
96
|
+
THROW());
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
if (dis.capacity < dis.limit) {
|
|
100
|
+
dis.capacity++;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
exports.releaseWithAbort = releaseWithAbort;
|
package/cjs/deque.js
CHANGED
|
@@ -57,24 +57,28 @@ class Deque {
|
|
|
57
57
|
constructor(ic) {
|
|
58
58
|
/**
|
|
59
59
|
* capacity
|
|
60
|
+
* @internal
|
|
60
61
|
*/
|
|
61
62
|
this._c = gc(ic || 16);
|
|
62
63
|
/**
|
|
63
64
|
* current length (size
|
|
65
|
+
* @internal
|
|
64
66
|
*/
|
|
65
67
|
this._l = 0;
|
|
66
68
|
/**
|
|
67
69
|
* current front position
|
|
70
|
+
* @internal
|
|
68
71
|
*/
|
|
69
72
|
this._f = 0;
|
|
70
|
-
/**
|
|
71
|
-
*
|
|
72
|
-
*/
|
|
73
|
-
this.length = 0;
|
|
74
73
|
/**
|
|
75
74
|
* @type {T[]}
|
|
75
|
+
* @internal
|
|
76
76
|
*/
|
|
77
77
|
this._a = [];
|
|
78
|
+
/**
|
|
79
|
+
* current length (size
|
|
80
|
+
*/
|
|
81
|
+
this.length = 0;
|
|
78
82
|
}
|
|
79
83
|
/**
|
|
80
84
|
* @param {T} s subject
|
|
@@ -109,6 +113,7 @@ exports.Deque = Deque;
|
|
|
109
113
|
* @template {any} T
|
|
110
114
|
* @param {Deque<T>} dis
|
|
111
115
|
* @param {number} n expected capacity
|
|
116
|
+
* @todo test code
|
|
112
117
|
*/
|
|
113
118
|
const rt = (dis, n) => {
|
|
114
119
|
const oc = dis._c;
|
package/cjs/index.d.ts
CHANGED
|
@@ -7,23 +7,24 @@
|
|
|
7
7
|
export declare class Deque<T extends any> {
|
|
8
8
|
/**
|
|
9
9
|
* capacity
|
|
10
|
-
* @
|
|
10
|
+
* @internal
|
|
11
11
|
*/
|
|
12
12
|
_c: number;
|
|
13
13
|
/**
|
|
14
14
|
* current length (size
|
|
15
|
-
* @
|
|
15
|
+
* @internal
|
|
16
16
|
*/
|
|
17
17
|
_l: number;
|
|
18
18
|
/**
|
|
19
19
|
* current front position
|
|
20
|
-
* @
|
|
20
|
+
* @internal
|
|
21
21
|
*/
|
|
22
22
|
_f: number;
|
|
23
23
|
/**
|
|
24
|
-
* @
|
|
24
|
+
* @internal
|
|
25
25
|
*/
|
|
26
26
|
_a: T[];
|
|
27
|
+
|
|
27
28
|
/**
|
|
28
29
|
* default capacity `16`
|
|
29
30
|
* @param ic initial capacity
|
|
@@ -95,6 +96,20 @@ export declare type TFlowableLock<T = TVoidFunction> = IFlowableLock & {
|
|
|
95
96
|
};
|
|
96
97
|
export declare type TVoidFunction = () => void;
|
|
97
98
|
|
|
99
|
+
export declare type TResolver = {
|
|
100
|
+
resolve: () => void;
|
|
101
|
+
reject: (reason: any) => void;
|
|
102
|
+
};
|
|
103
|
+
export declare interface IProcessAbortedError {
|
|
104
|
+
readonly message: "Process Aborted";
|
|
105
|
+
}
|
|
106
|
+
export type TAbortListener = (reason: IProcessAbortedError) => void;
|
|
107
|
+
export declare type TFlowableLockWithAbort = IFlowableLock & {
|
|
108
|
+
readonly q: Deque<TResolver>;
|
|
109
|
+
abort(): void;
|
|
110
|
+
onAbort(listener: TAbortListener): void;
|
|
111
|
+
offAbort(listener: TAbortListener): void;
|
|
112
|
+
};
|
|
98
113
|
|
|
99
114
|
/**
|
|
100
115
|
* #### Mini Semaphore
|
|
@@ -160,7 +175,7 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
160
175
|
}
|
|
161
176
|
|
|
162
177
|
/**
|
|
163
|
-
* object implementation of `
|
|
178
|
+
* object implementation of `TFlowableLock`
|
|
164
179
|
*
|
|
165
180
|
* + constructs a semaphore object limited at `capacity`
|
|
166
181
|
*
|
|
@@ -168,7 +183,18 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
168
183
|
* @date 2020/2/7
|
|
169
184
|
* @version 1.0
|
|
170
185
|
*/
|
|
171
|
-
export declare const create: (capacity: number) =>
|
|
186
|
+
export declare const create: (capacity: number) => TFlowableLock;
|
|
187
|
+
/**
|
|
188
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
189
|
+
*
|
|
190
|
+
* + constructs a semaphore object limited at `capacity`
|
|
191
|
+
*
|
|
192
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
193
|
+
* @date 2025/5/12
|
|
194
|
+
* @version 1.4
|
|
195
|
+
*/
|
|
196
|
+
export declare const createWithAbort: (capacity: number) => TFlowableLockWithAbort;
|
|
197
|
+
|
|
172
198
|
|
|
173
199
|
declare namespace fr {
|
|
174
200
|
/**
|
package/cjs/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.version = exports.restrictor = exports.Deque = exports.create = exports.MiniSemaphore = void 0;
|
|
3
|
+
exports.version = exports.restrictor = exports.Deque = exports.createWithAbort = exports.create = exports.MiniSemaphore = void 0;
|
|
4
4
|
var class_1 = require("./class");
|
|
5
5
|
Object.defineProperty(exports, "MiniSemaphore", { enumerable: true, get: function () { return class_1.MiniSemaphore; } });
|
|
6
6
|
var object_1 = require("./object");
|
|
7
7
|
Object.defineProperty(exports, "create", { enumerable: true, get: function () { return object_1.create; } });
|
|
8
|
+
Object.defineProperty(exports, "createWithAbort", { enumerable: true, get: function () { return object_1.createWithAbort; } });
|
|
8
9
|
var deque_1 = require("./deque");
|
|
9
10
|
Object.defineProperty(exports, "Deque", { enumerable: true, get: function () { return deque_1.Deque; } });
|
|
10
11
|
var flow_restrictor_1 = require("./flow-restrictor");
|
|
11
12
|
Object.defineProperty(exports, "restrictor", { enumerable: true, get: function () { return flow_restrictor_1.restrictor; } });
|
|
12
|
-
exports.version = "v1.
|
|
13
|
+
exports.version = "v1.4.4";
|
package/cjs/object.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.create = void 0;
|
|
3
|
+
exports.createWithAbort = exports.create = void 0;
|
|
4
4
|
/*!
|
|
5
5
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
6
6
|
Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
|
|
@@ -17,6 +17,26 @@ const core = require("./core");
|
|
|
17
17
|
const deque_1 = require("./deque");
|
|
18
18
|
const a = core.acquire;
|
|
19
19
|
const r = core.release;
|
|
20
|
+
const aa = core.acquireWithAbort;
|
|
21
|
+
const ra = core.releaseWithAbort;
|
|
22
|
+
/**
|
|
23
|
+
* @template {core.IFlowableLock & { q: Deque<unknown>}} T
|
|
24
|
+
* @param {number} capacity
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
const createBase = (capacity) => {
|
|
28
|
+
return /** @type {T} */ ({
|
|
29
|
+
capacity,
|
|
30
|
+
limit: capacity,
|
|
31
|
+
q: new deque_1.Deque(capacity),
|
|
32
|
+
/**
|
|
33
|
+
* @param {number} restriction
|
|
34
|
+
*/
|
|
35
|
+
setRestriction(restriction) {
|
|
36
|
+
this.limit = this.capacity = restriction;
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
};
|
|
20
40
|
/**
|
|
21
41
|
* object implementation of `IFlowableLock`
|
|
22
42
|
*
|
|
@@ -27,10 +47,13 @@ const r = core.release;
|
|
|
27
47
|
* @version 1.0
|
|
28
48
|
*/
|
|
29
49
|
const create = (capacity) => {
|
|
50
|
+
/** @type {core.TFlowableLock} */
|
|
51
|
+
const base = createBase(capacity);
|
|
30
52
|
return /** @satisfies {core.TFlowableLock} */ ({
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
53
|
+
...base,
|
|
54
|
+
get pending() {
|
|
55
|
+
return this.q.length;
|
|
56
|
+
},
|
|
34
57
|
/**
|
|
35
58
|
*
|
|
36
59
|
* @param {boolean} [lazy]
|
|
@@ -42,15 +65,6 @@ const create = (capacity) => {
|
|
|
42
65
|
release() {
|
|
43
66
|
r(this);
|
|
44
67
|
},
|
|
45
|
-
/**
|
|
46
|
-
* @param {number} restriction
|
|
47
|
-
*/
|
|
48
|
-
setRestriction(restriction) {
|
|
49
|
-
this.limit = this.capacity = restriction;
|
|
50
|
-
},
|
|
51
|
-
get pending() {
|
|
52
|
-
return this.q.length;
|
|
53
|
-
},
|
|
54
68
|
/**
|
|
55
69
|
* @template {any} T
|
|
56
70
|
* @param {() => Promise<T>} process
|
|
@@ -68,4 +82,84 @@ const create = (capacity) => {
|
|
|
68
82
|
}
|
|
69
83
|
});
|
|
70
84
|
};
|
|
71
|
-
exports.create = create;
|
|
85
|
+
exports.create = create;
|
|
86
|
+
/**
|
|
87
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
88
|
+
*
|
|
89
|
+
* + constructs a semaphore object limited at `capacity`
|
|
90
|
+
*
|
|
91
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
92
|
+
* @date 2025/5/12
|
|
93
|
+
* @version 1.4
|
|
94
|
+
*/
|
|
95
|
+
const createWithAbort = (capacity) => {
|
|
96
|
+
/** @type {core.TFlowableLockWithAbort} */
|
|
97
|
+
const base = createBase(capacity);
|
|
98
|
+
const abortListeners = [];
|
|
99
|
+
return /** @satisfies {core.TFlowableLockWithAbort} */ ({
|
|
100
|
+
...base,
|
|
101
|
+
get pending() {
|
|
102
|
+
return this.q.length;
|
|
103
|
+
},
|
|
104
|
+
/**
|
|
105
|
+
* @returns {Promise<void>}
|
|
106
|
+
*/
|
|
107
|
+
acquire() {
|
|
108
|
+
return aa(this);
|
|
109
|
+
},
|
|
110
|
+
release() {
|
|
111
|
+
ra(this);
|
|
112
|
+
},
|
|
113
|
+
/**
|
|
114
|
+
* @template {any} T
|
|
115
|
+
* @param {() => Promise<T>} process
|
|
116
|
+
* @returns {Promise<T>}
|
|
117
|
+
*/
|
|
118
|
+
async flow(process) {
|
|
119
|
+
let result;
|
|
120
|
+
try {
|
|
121
|
+
await aa(this);
|
|
122
|
+
result = await process();
|
|
123
|
+
ra(this);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
/**
|
|
130
|
+
* @throws {AggregateError} description
|
|
131
|
+
*/
|
|
132
|
+
abort() {
|
|
133
|
+
const reason = {
|
|
134
|
+
message: "Process Aborted"
|
|
135
|
+
};
|
|
136
|
+
abortListeners.forEach(listener => listener(reason));
|
|
137
|
+
const dq = this.q;
|
|
138
|
+
let resolver;
|
|
139
|
+
while (resolver = dq.shift()) {
|
|
140
|
+
resolver.reject(reason);
|
|
141
|
+
}
|
|
142
|
+
this.capacity = this.limit;
|
|
143
|
+
},
|
|
144
|
+
/**
|
|
145
|
+
* Registers an event listener for the "abort" event.
|
|
146
|
+
* @param {core.TAbortListener} listener
|
|
147
|
+
*/
|
|
148
|
+
onAbort(listener) {
|
|
149
|
+
if (!abortListeners.includes(listener)) {
|
|
150
|
+
abortListeners.push(listener);
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
/**
|
|
154
|
+
* Removes an event listener for the "abort" event.
|
|
155
|
+
* @param {core.TAbortListener} listener
|
|
156
|
+
*/
|
|
157
|
+
offAbort(listener) {
|
|
158
|
+
const idx = abortListeners.findIndex(ls => listener === ls);
|
|
159
|
+
if (idx !== -1) {
|
|
160
|
+
/*return */ abortListeners.splice(idx, 1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
exports.createWithAbort = createWithAbort;
|
package/esm/core.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @typedef {import("./index.mjs").TVoidFunction} TVoidFunction
|
|
3
3
|
* @typedef {import("./index.mjs").Deque<TVoidFunction>} Deque
|
|
4
|
+
* @typedef {import("./index.mjs").TFlowableLockWithAbort} TFlowableLockWithAbort
|
|
5
|
+
* @typedef {import("./index.mjs").Deque<TResolver>} DequeWithAbort
|
|
4
6
|
* @typedef {import("./index.mjs").ISimplifiedLock} ISimplifiedLock
|
|
5
7
|
* @typedef {import("./index.mjs").TFlowableLock} TFlowableLock
|
|
6
8
|
* @typedef {import("./index.mjs").IFlowableLock} IFlowableLock
|
|
@@ -57,4 +59,39 @@ export const release = (dis) => {
|
|
|
57
59
|
console.warn("inconsistent release!");
|
|
58
60
|
dis.capacity = dis.limit;
|
|
59
61
|
}
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* @param {TFlowableLockWithAbort} dis
|
|
65
|
+
* @returns {Promise<void>}
|
|
66
|
+
*/
|
|
67
|
+
export const acquireWithAbort = (dis) => {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
if (dis.capacity > 0) {
|
|
70
|
+
dis.capacity--, resolve();
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
dis.q.push({
|
|
74
|
+
resolve, reject
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* @param {TFlowableLockWithAbort} dis
|
|
81
|
+
* @returns {void}
|
|
82
|
+
*/
|
|
83
|
+
export const releaseWithAbort = (dis) => {
|
|
84
|
+
/** @type {DequeWithAbort} */
|
|
85
|
+
let dq;
|
|
86
|
+
if ((dq = dis.q).length) {
|
|
87
|
+
const resolver = dq.shift();
|
|
88
|
+
resolver && resolver.resolve() || (
|
|
89
|
+
/* istanbul ignore next */
|
|
90
|
+
THROW());
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
if (dis.capacity < dis.limit) {
|
|
94
|
+
dis.capacity++;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
60
97
|
};
|
package/esm/deque.mjs
CHANGED
|
@@ -54,24 +54,28 @@ export class Deque {
|
|
|
54
54
|
constructor(ic) {
|
|
55
55
|
/**
|
|
56
56
|
* capacity
|
|
57
|
+
* @internal
|
|
57
58
|
*/
|
|
58
59
|
this._c = gc(ic || 16);
|
|
59
60
|
/**
|
|
60
61
|
* current length (size
|
|
62
|
+
* @internal
|
|
61
63
|
*/
|
|
62
64
|
this._l = 0;
|
|
63
65
|
/**
|
|
64
66
|
* current front position
|
|
67
|
+
* @internal
|
|
65
68
|
*/
|
|
66
69
|
this._f = 0;
|
|
67
|
-
/**
|
|
68
|
-
*
|
|
69
|
-
*/
|
|
70
|
-
this.length = 0;
|
|
71
70
|
/**
|
|
72
71
|
* @type {T[]}
|
|
72
|
+
* @internal
|
|
73
73
|
*/
|
|
74
74
|
this._a = [];
|
|
75
|
+
/**
|
|
76
|
+
* current length (size
|
|
77
|
+
*/
|
|
78
|
+
this.length = 0;
|
|
75
79
|
}
|
|
76
80
|
/**
|
|
77
81
|
* @param {T} s subject
|
|
@@ -105,6 +109,7 @@ export class Deque {
|
|
|
105
109
|
* @template {any} T
|
|
106
110
|
* @param {Deque<T>} dis
|
|
107
111
|
* @param {number} n expected capacity
|
|
112
|
+
* @todo test code
|
|
108
113
|
*/
|
|
109
114
|
const rt = (dis, n) => {
|
|
110
115
|
const oc = dis._c;
|
package/esm/index.d.mts
CHANGED
|
@@ -7,23 +7,24 @@
|
|
|
7
7
|
export declare class Deque<T extends any> {
|
|
8
8
|
/**
|
|
9
9
|
* capacity
|
|
10
|
-
* @
|
|
10
|
+
* @internal
|
|
11
11
|
*/
|
|
12
12
|
_c: number;
|
|
13
13
|
/**
|
|
14
14
|
* current length (size
|
|
15
|
-
* @
|
|
15
|
+
* @internal
|
|
16
16
|
*/
|
|
17
17
|
_l: number;
|
|
18
18
|
/**
|
|
19
19
|
* current front position
|
|
20
|
-
* @
|
|
20
|
+
* @internal
|
|
21
21
|
*/
|
|
22
22
|
_f: number;
|
|
23
23
|
/**
|
|
24
|
-
* @
|
|
24
|
+
* @internal
|
|
25
25
|
*/
|
|
26
26
|
_a: T[];
|
|
27
|
+
|
|
27
28
|
/**
|
|
28
29
|
* default capacity `16`
|
|
29
30
|
* @param ic initial capacity
|
|
@@ -95,6 +96,20 @@ export declare type TFlowableLock<T = TVoidFunction> = IFlowableLock & {
|
|
|
95
96
|
};
|
|
96
97
|
export declare type TVoidFunction = () => void;
|
|
97
98
|
|
|
99
|
+
export declare type TResolver = {
|
|
100
|
+
resolve: () => void;
|
|
101
|
+
reject: (reason: any) => void;
|
|
102
|
+
};
|
|
103
|
+
export declare interface IProcessAbortedError {
|
|
104
|
+
readonly message: "Process Aborted";
|
|
105
|
+
}
|
|
106
|
+
export type TAbortListener = (reason: IProcessAbortedError) => void;
|
|
107
|
+
export declare type TFlowableLockWithAbort = IFlowableLock & {
|
|
108
|
+
readonly q: Deque<TResolver>;
|
|
109
|
+
abort(): void;
|
|
110
|
+
onAbort(listener: TAbortListener): void;
|
|
111
|
+
offAbort(listener: TAbortListener): void;
|
|
112
|
+
};
|
|
98
113
|
|
|
99
114
|
/**
|
|
100
115
|
* #### Mini Semaphore
|
|
@@ -160,7 +175,7 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
160
175
|
}
|
|
161
176
|
|
|
162
177
|
/**
|
|
163
|
-
* object implementation of `
|
|
178
|
+
* object implementation of `TFlowableLock`
|
|
164
179
|
*
|
|
165
180
|
* + constructs a semaphore object limited at `capacity`
|
|
166
181
|
*
|
|
@@ -168,7 +183,18 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
168
183
|
* @date 2020/2/7
|
|
169
184
|
* @version 1.0
|
|
170
185
|
*/
|
|
171
|
-
export declare const create: (capacity: number) =>
|
|
186
|
+
export declare const create: (capacity: number) => TFlowableLock;
|
|
187
|
+
/**
|
|
188
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
189
|
+
*
|
|
190
|
+
* + constructs a semaphore object limited at `capacity`
|
|
191
|
+
*
|
|
192
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
193
|
+
* @date 2025/5/12
|
|
194
|
+
* @version 1.4
|
|
195
|
+
*/
|
|
196
|
+
export declare const createWithAbort: (capacity: number) => TFlowableLockWithAbort;
|
|
197
|
+
|
|
172
198
|
|
|
173
199
|
declare namespace fr {
|
|
174
200
|
/**
|
package/esm/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { MiniSemaphore } from "./class.mjs";
|
|
2
|
-
export { create } from "./object.mjs";
|
|
2
|
+
export { create, createWithAbort } from "./object.mjs";
|
|
3
3
|
export { Deque } from "./deque.mjs";
|
|
4
4
|
export { restrictor } from "./flow-restrictor.mjs";
|
|
5
|
-
export const version = "v1.
|
|
5
|
+
export const version = "v1.4.4";
|
package/esm/object.mjs
CHANGED
|
@@ -14,6 +14,26 @@ import * as core from "./core.mjs";
|
|
|
14
14
|
import { Deque } from "./deque.mjs";
|
|
15
15
|
const a = core.acquire;
|
|
16
16
|
const r = core.release;
|
|
17
|
+
const aa = core.acquireWithAbort;
|
|
18
|
+
const ra = core.releaseWithAbort;
|
|
19
|
+
/**
|
|
20
|
+
* @template {core.IFlowableLock & { q: Deque<unknown>}} T
|
|
21
|
+
* @param {number} capacity
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
const createBase = (capacity) => {
|
|
25
|
+
return /** @type {T} */ ({
|
|
26
|
+
capacity,
|
|
27
|
+
limit: capacity,
|
|
28
|
+
q: new Deque(capacity),
|
|
29
|
+
/**
|
|
30
|
+
* @param {number} restriction
|
|
31
|
+
*/
|
|
32
|
+
setRestriction(restriction) {
|
|
33
|
+
this.limit = this.capacity = restriction;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
};
|
|
17
37
|
/**
|
|
18
38
|
* object implementation of `IFlowableLock`
|
|
19
39
|
*
|
|
@@ -24,10 +44,13 @@ const r = core.release;
|
|
|
24
44
|
* @version 1.0
|
|
25
45
|
*/
|
|
26
46
|
export const create = (capacity) => {
|
|
47
|
+
/** @type {core.TFlowableLock} */
|
|
48
|
+
const base = createBase(capacity);
|
|
27
49
|
return /** @satisfies {core.TFlowableLock} */ ({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
...base,
|
|
51
|
+
get pending() {
|
|
52
|
+
return this.q.length;
|
|
53
|
+
},
|
|
31
54
|
/**
|
|
32
55
|
*
|
|
33
56
|
* @param {boolean} [lazy]
|
|
@@ -39,15 +62,6 @@ export const create = (capacity) => {
|
|
|
39
62
|
release() {
|
|
40
63
|
r(this);
|
|
41
64
|
},
|
|
42
|
-
/**
|
|
43
|
-
* @param {number} restriction
|
|
44
|
-
*/
|
|
45
|
-
setRestriction(restriction) {
|
|
46
|
-
this.limit = this.capacity = restriction;
|
|
47
|
-
},
|
|
48
|
-
get pending() {
|
|
49
|
-
return this.q.length;
|
|
50
|
-
},
|
|
51
65
|
/**
|
|
52
66
|
* @template {any} T
|
|
53
67
|
* @param {() => Promise<T>} process
|
|
@@ -64,4 +78,83 @@ export const create = (capacity) => {
|
|
|
64
78
|
}
|
|
65
79
|
}
|
|
66
80
|
});
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
84
|
+
*
|
|
85
|
+
* + constructs a semaphore object limited at `capacity`
|
|
86
|
+
*
|
|
87
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
88
|
+
* @date 2025/5/12
|
|
89
|
+
* @version 1.4
|
|
90
|
+
*/
|
|
91
|
+
export const createWithAbort = (capacity) => {
|
|
92
|
+
/** @type {core.TFlowableLockWithAbort} */
|
|
93
|
+
const base = createBase(capacity);
|
|
94
|
+
const abortListeners = [];
|
|
95
|
+
return /** @satisfies {core.TFlowableLockWithAbort} */ ({
|
|
96
|
+
...base,
|
|
97
|
+
get pending() {
|
|
98
|
+
return this.q.length;
|
|
99
|
+
},
|
|
100
|
+
/**
|
|
101
|
+
* @returns {Promise<void>}
|
|
102
|
+
*/
|
|
103
|
+
acquire() {
|
|
104
|
+
return aa(this);
|
|
105
|
+
},
|
|
106
|
+
release() {
|
|
107
|
+
ra(this);
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* @template {any} T
|
|
111
|
+
* @param {() => Promise<T>} process
|
|
112
|
+
* @returns {Promise<T>}
|
|
113
|
+
*/
|
|
114
|
+
async flow(process) {
|
|
115
|
+
let result;
|
|
116
|
+
try {
|
|
117
|
+
await aa(this);
|
|
118
|
+
result = await process();
|
|
119
|
+
ra(this);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
/**
|
|
126
|
+
* @throws {AggregateError} description
|
|
127
|
+
*/
|
|
128
|
+
abort() {
|
|
129
|
+
const reason = {
|
|
130
|
+
message: "Process Aborted"
|
|
131
|
+
};
|
|
132
|
+
abortListeners.forEach(listener => listener(reason));
|
|
133
|
+
const dq = this.q;
|
|
134
|
+
let resolver;
|
|
135
|
+
while (resolver = dq.shift()) {
|
|
136
|
+
resolver.reject(reason);
|
|
137
|
+
}
|
|
138
|
+
this.capacity = this.limit;
|
|
139
|
+
},
|
|
140
|
+
/**
|
|
141
|
+
* Registers an event listener for the "abort" event.
|
|
142
|
+
* @param {core.TAbortListener} listener
|
|
143
|
+
*/
|
|
144
|
+
onAbort(listener) {
|
|
145
|
+
if (!abortListeners.includes(listener)) {
|
|
146
|
+
abortListeners.push(listener);
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
/**
|
|
150
|
+
* Removes an event listener for the "abort" event.
|
|
151
|
+
* @param {core.TAbortListener} listener
|
|
152
|
+
*/
|
|
153
|
+
offAbort(listener) {
|
|
154
|
+
const idx = abortListeners.findIndex(ls => listener === ls);
|
|
155
|
+
if (idx !== -1) {
|
|
156
|
+
/*return */ abortListeners.splice(idx, 1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
67
160
|
};
|
package/index.d.ts
CHANGED
|
@@ -7,23 +7,24 @@
|
|
|
7
7
|
export declare class Deque<T extends any> {
|
|
8
8
|
/**
|
|
9
9
|
* capacity
|
|
10
|
-
* @
|
|
10
|
+
* @internal
|
|
11
11
|
*/
|
|
12
12
|
_c: number;
|
|
13
13
|
/**
|
|
14
14
|
* current length (size
|
|
15
|
-
* @
|
|
15
|
+
* @internal
|
|
16
16
|
*/
|
|
17
17
|
_l: number;
|
|
18
18
|
/**
|
|
19
19
|
* current front position
|
|
20
|
-
* @
|
|
20
|
+
* @internal
|
|
21
21
|
*/
|
|
22
22
|
_f: number;
|
|
23
23
|
/**
|
|
24
|
-
* @
|
|
24
|
+
* @internal
|
|
25
25
|
*/
|
|
26
26
|
_a: T[];
|
|
27
|
+
|
|
27
28
|
/**
|
|
28
29
|
* default capacity `16`
|
|
29
30
|
* @param ic initial capacity
|
|
@@ -95,6 +96,20 @@ export declare type TFlowableLock<T = TVoidFunction> = IFlowableLock & {
|
|
|
95
96
|
};
|
|
96
97
|
export declare type TVoidFunction = () => void;
|
|
97
98
|
|
|
99
|
+
export declare type TResolver = {
|
|
100
|
+
resolve: () => void;
|
|
101
|
+
reject: (reason: any) => void;
|
|
102
|
+
};
|
|
103
|
+
export declare interface IProcessAbortedError {
|
|
104
|
+
readonly message: "Process Aborted";
|
|
105
|
+
}
|
|
106
|
+
export type TAbortListener = (reason: IProcessAbortedError) => void;
|
|
107
|
+
export declare type TFlowableLockWithAbort = IFlowableLock & {
|
|
108
|
+
readonly q: Deque<TResolver>;
|
|
109
|
+
abort(): void;
|
|
110
|
+
onAbort(listener: TAbortListener): void;
|
|
111
|
+
offAbort(listener: TAbortListener): void;
|
|
112
|
+
};
|
|
98
113
|
|
|
99
114
|
/**
|
|
100
115
|
* #### Mini Semaphore
|
|
@@ -160,7 +175,7 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
160
175
|
}
|
|
161
176
|
|
|
162
177
|
/**
|
|
163
|
-
* object implementation of `
|
|
178
|
+
* object implementation of `TFlowableLock`
|
|
164
179
|
*
|
|
165
180
|
* + constructs a semaphore object limited at `capacity`
|
|
166
181
|
*
|
|
@@ -168,7 +183,18 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
168
183
|
* @date 2020/2/7
|
|
169
184
|
* @version 1.0
|
|
170
185
|
*/
|
|
171
|
-
export declare const create: (capacity: number) =>
|
|
186
|
+
export declare const create: (capacity: number) => TFlowableLock;
|
|
187
|
+
/**
|
|
188
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
189
|
+
*
|
|
190
|
+
* + constructs a semaphore object limited at `capacity`
|
|
191
|
+
*
|
|
192
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
193
|
+
* @date 2025/5/12
|
|
194
|
+
* @version 1.4
|
|
195
|
+
*/
|
|
196
|
+
export declare const createWithAbort: (capacity: number) => TFlowableLockWithAbort;
|
|
197
|
+
|
|
172
198
|
|
|
173
199
|
declare namespace fr {
|
|
174
200
|
/**
|
package/package.json
CHANGED
package/umd/index.d.ts
CHANGED
|
@@ -7,23 +7,24 @@
|
|
|
7
7
|
export declare class Deque<T extends any> {
|
|
8
8
|
/**
|
|
9
9
|
* capacity
|
|
10
|
-
* @
|
|
10
|
+
* @internal
|
|
11
11
|
*/
|
|
12
12
|
_c: number;
|
|
13
13
|
/**
|
|
14
14
|
* current length (size
|
|
15
|
-
* @
|
|
15
|
+
* @internal
|
|
16
16
|
*/
|
|
17
17
|
_l: number;
|
|
18
18
|
/**
|
|
19
19
|
* current front position
|
|
20
|
-
* @
|
|
20
|
+
* @internal
|
|
21
21
|
*/
|
|
22
22
|
_f: number;
|
|
23
23
|
/**
|
|
24
|
-
* @
|
|
24
|
+
* @internal
|
|
25
25
|
*/
|
|
26
26
|
_a: T[];
|
|
27
|
+
|
|
27
28
|
/**
|
|
28
29
|
* default capacity `16`
|
|
29
30
|
* @param ic initial capacity
|
|
@@ -95,6 +96,20 @@ export declare type TFlowableLock<T = TVoidFunction> = IFlowableLock & {
|
|
|
95
96
|
};
|
|
96
97
|
export declare type TVoidFunction = () => void;
|
|
97
98
|
|
|
99
|
+
export declare type TResolver = {
|
|
100
|
+
resolve: () => void;
|
|
101
|
+
reject: (reason: any) => void;
|
|
102
|
+
};
|
|
103
|
+
export declare interface IProcessAbortedError {
|
|
104
|
+
readonly message: "Process Aborted";
|
|
105
|
+
}
|
|
106
|
+
export type TAbortListener = (reason: IProcessAbortedError) => void;
|
|
107
|
+
export declare type TFlowableLockWithAbort = IFlowableLock & {
|
|
108
|
+
readonly q: Deque<TResolver>;
|
|
109
|
+
abort(): void;
|
|
110
|
+
onAbort(listener: TAbortListener): void;
|
|
111
|
+
offAbort(listener: TAbortListener): void;
|
|
112
|
+
};
|
|
98
113
|
|
|
99
114
|
/**
|
|
100
115
|
* #### Mini Semaphore
|
|
@@ -160,7 +175,7 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
160
175
|
}
|
|
161
176
|
|
|
162
177
|
/**
|
|
163
|
-
* object implementation of `
|
|
178
|
+
* object implementation of `TFlowableLock`
|
|
164
179
|
*
|
|
165
180
|
* + constructs a semaphore object limited at `capacity`
|
|
166
181
|
*
|
|
@@ -168,7 +183,18 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
168
183
|
* @date 2020/2/7
|
|
169
184
|
* @version 1.0
|
|
170
185
|
*/
|
|
171
|
-
export declare const create: (capacity: number) =>
|
|
186
|
+
export declare const create: (capacity: number) => TFlowableLock;
|
|
187
|
+
/**
|
|
188
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
189
|
+
*
|
|
190
|
+
* + constructs a semaphore object limited at `capacity`
|
|
191
|
+
*
|
|
192
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
193
|
+
* @date 2025/5/12
|
|
194
|
+
* @version 1.4
|
|
195
|
+
*/
|
|
196
|
+
export declare const createWithAbort: (capacity: number) => TFlowableLockWithAbort;
|
|
197
|
+
|
|
172
198
|
|
|
173
199
|
declare namespace fr {
|
|
174
200
|
/**
|
package/umd/index.js
CHANGED
|
@@ -1,7 +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,(()=>(()=>{"use strict";var e={139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.create=void 0;const r=i(461),n=i(761),s=r.acquire,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
;const
|
|
7
|
-
|
|
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={139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createWithAbort=t.create=void 0;const r=i(461),n=i(761),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(){
|
|
3
|
+
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);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)}}}},461:(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=>{t?setTimeout((()=>r(e,i)),4):r(e,i)}));t.release=e=>{let t
|
|
4
|
+
;(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++}},464:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(518);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(),
|
|
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){return n(e,1,t)}}})()},518:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSemaphore=void 0
|
|
6
|
+
;const r=i(461),n=i(761),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)}}}},761:(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,this.length=this._l=t+1}shift(){const e=this._l;if(0===e)return
|
|
7
|
+
;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)}}}},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(518);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return n.create}}),Object.defineProperty(e,"createWithAbort",{
|
|
8
|
+
enumerable:!0,get:function(){return n.createWithAbort}});var s=i(761);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return s.Deque}});var a=i(464);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return a.restrictor}}),e.version="v1.4.4"})(),r})()));
|
package/webpack/index.d.ts
CHANGED
|
@@ -7,23 +7,24 @@
|
|
|
7
7
|
export declare class Deque<T extends any> {
|
|
8
8
|
/**
|
|
9
9
|
* capacity
|
|
10
|
-
* @
|
|
10
|
+
* @internal
|
|
11
11
|
*/
|
|
12
12
|
_c: number;
|
|
13
13
|
/**
|
|
14
14
|
* current length (size
|
|
15
|
-
* @
|
|
15
|
+
* @internal
|
|
16
16
|
*/
|
|
17
17
|
_l: number;
|
|
18
18
|
/**
|
|
19
19
|
* current front position
|
|
20
|
-
* @
|
|
20
|
+
* @internal
|
|
21
21
|
*/
|
|
22
22
|
_f: number;
|
|
23
23
|
/**
|
|
24
|
-
* @
|
|
24
|
+
* @internal
|
|
25
25
|
*/
|
|
26
26
|
_a: T[];
|
|
27
|
+
|
|
27
28
|
/**
|
|
28
29
|
* default capacity `16`
|
|
29
30
|
* @param ic initial capacity
|
|
@@ -95,6 +96,20 @@ export declare type TFlowableLock<T = TVoidFunction> = IFlowableLock & {
|
|
|
95
96
|
};
|
|
96
97
|
export declare type TVoidFunction = () => void;
|
|
97
98
|
|
|
99
|
+
export declare type TResolver = {
|
|
100
|
+
resolve: () => void;
|
|
101
|
+
reject: (reason: any) => void;
|
|
102
|
+
};
|
|
103
|
+
export declare interface IProcessAbortedError {
|
|
104
|
+
readonly message: "Process Aborted";
|
|
105
|
+
}
|
|
106
|
+
export type TAbortListener = (reason: IProcessAbortedError) => void;
|
|
107
|
+
export declare type TFlowableLockWithAbort = IFlowableLock & {
|
|
108
|
+
readonly q: Deque<TResolver>;
|
|
109
|
+
abort(): void;
|
|
110
|
+
onAbort(listener: TAbortListener): void;
|
|
111
|
+
offAbort(listener: TAbortListener): void;
|
|
112
|
+
};
|
|
98
113
|
|
|
99
114
|
/**
|
|
100
115
|
* #### Mini Semaphore
|
|
@@ -160,7 +175,7 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
160
175
|
}
|
|
161
176
|
|
|
162
177
|
/**
|
|
163
|
-
* object implementation of `
|
|
178
|
+
* object implementation of `TFlowableLock`
|
|
164
179
|
*
|
|
165
180
|
* + constructs a semaphore object limited at `capacity`
|
|
166
181
|
*
|
|
@@ -168,7 +183,18 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
168
183
|
* @date 2020/2/7
|
|
169
184
|
* @version 1.0
|
|
170
185
|
*/
|
|
171
|
-
export declare const create: (capacity: number) =>
|
|
186
|
+
export declare const create: (capacity: number) => TFlowableLock;
|
|
187
|
+
/**
|
|
188
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
189
|
+
*
|
|
190
|
+
* + constructs a semaphore object limited at `capacity`
|
|
191
|
+
*
|
|
192
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
193
|
+
* @date 2025/5/12
|
|
194
|
+
* @version 1.4
|
|
195
|
+
*/
|
|
196
|
+
export declare const createWithAbort: (capacity: number) => TFlowableLockWithAbort;
|
|
197
|
+
|
|
172
198
|
|
|
173
199
|
declare namespace fr {
|
|
174
200
|
/**
|
package/webpack/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
-
(()=>{"use strict";var e={139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.create=void 0;const r=i(461),n=i(761),s=r.acquire,a=r.release
|
|
3
|
-
;(
|
|
2
|
+
(()=>{"use strict";var e={139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createWithAbort=t.create=void 0;const r=i(461),n=i(761),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){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
|
|
3
|
+
;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)}}}},461:(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=>{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,
|
|
4
|
+
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++}},464:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(518);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})(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)
|
|
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)}}})()},518:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSemaphore=void 0;const r=i(461),n=i(761),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)}}}},
|
|
5
|
-
761:(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.
|
|
6
|
-
;return e[r](s,s.exports,i),s.exports}var r={};(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.version=e.restrictor=e.Deque=e.create=e.MiniSemaphore=void 0;var t=i(518);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return n.create}});var s=i(761);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return s.Deque}});var a=i(464);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return a.restrictor}}),e.version="v1.
|
|
6
|
+
761:(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,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)}}}},t={};function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}}
|
|
7
|
+
;return e[r](s,s.exports,i),s.exports}var r={};(()=>{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(518);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);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(761);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return s.Deque}});var a=i(464);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return a.restrictor}}),e.version="v1.4.4"})(),module.exports=r})();
|
package/webpack-esm/index.d.mts
CHANGED
|
@@ -7,23 +7,24 @@
|
|
|
7
7
|
export declare class Deque<T extends any> {
|
|
8
8
|
/**
|
|
9
9
|
* capacity
|
|
10
|
-
* @
|
|
10
|
+
* @internal
|
|
11
11
|
*/
|
|
12
12
|
_c: number;
|
|
13
13
|
/**
|
|
14
14
|
* current length (size
|
|
15
|
-
* @
|
|
15
|
+
* @internal
|
|
16
16
|
*/
|
|
17
17
|
_l: number;
|
|
18
18
|
/**
|
|
19
19
|
* current front position
|
|
20
|
-
* @
|
|
20
|
+
* @internal
|
|
21
21
|
*/
|
|
22
22
|
_f: number;
|
|
23
23
|
/**
|
|
24
|
-
* @
|
|
24
|
+
* @internal
|
|
25
25
|
*/
|
|
26
26
|
_a: T[];
|
|
27
|
+
|
|
27
28
|
/**
|
|
28
29
|
* default capacity `16`
|
|
29
30
|
* @param ic initial capacity
|
|
@@ -95,6 +96,20 @@ export declare type TFlowableLock<T = TVoidFunction> = IFlowableLock & {
|
|
|
95
96
|
};
|
|
96
97
|
export declare type TVoidFunction = () => void;
|
|
97
98
|
|
|
99
|
+
export declare type TResolver = {
|
|
100
|
+
resolve: () => void;
|
|
101
|
+
reject: (reason: any) => void;
|
|
102
|
+
};
|
|
103
|
+
export declare interface IProcessAbortedError {
|
|
104
|
+
readonly message: "Process Aborted";
|
|
105
|
+
}
|
|
106
|
+
export type TAbortListener = (reason: IProcessAbortedError) => void;
|
|
107
|
+
export declare type TFlowableLockWithAbort = IFlowableLock & {
|
|
108
|
+
readonly q: Deque<TResolver>;
|
|
109
|
+
abort(): void;
|
|
110
|
+
onAbort(listener: TAbortListener): void;
|
|
111
|
+
offAbort(listener: TAbortListener): void;
|
|
112
|
+
};
|
|
98
113
|
|
|
99
114
|
/**
|
|
100
115
|
* #### Mini Semaphore
|
|
@@ -160,7 +175,7 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
160
175
|
}
|
|
161
176
|
|
|
162
177
|
/**
|
|
163
|
-
* object implementation of `
|
|
178
|
+
* object implementation of `TFlowableLock`
|
|
164
179
|
*
|
|
165
180
|
* + constructs a semaphore object limited at `capacity`
|
|
166
181
|
*
|
|
@@ -168,7 +183,18 @@ export declare class MiniSemaphore implements TFlowableLock {
|
|
|
168
183
|
* @date 2020/2/7
|
|
169
184
|
* @version 1.0
|
|
170
185
|
*/
|
|
171
|
-
export declare const create: (capacity: number) =>
|
|
186
|
+
export declare const create: (capacity: number) => TFlowableLock;
|
|
187
|
+
/**
|
|
188
|
+
* object implementation of `TFlowableLockWithAbort`
|
|
189
|
+
*
|
|
190
|
+
* + constructs a semaphore object limited at `capacity`
|
|
191
|
+
*
|
|
192
|
+
* @param {number} capacity limitation of concurrent async by `capacity`
|
|
193
|
+
* @date 2025/5/12
|
|
194
|
+
* @version 1.4
|
|
195
|
+
*/
|
|
196
|
+
export declare const createWithAbort: (capacity: number) => TFlowableLockWithAbort;
|
|
197
|
+
|
|
172
198
|
|
|
173
199
|
declare namespace fr {
|
|
174
200
|
/**
|
package/webpack-esm/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
-
var e={139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.create=void 0;const r=i(461),
|
|
3
|
-
;(
|
|
4
|
-
;
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
var e={139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createWithAbort=t.create=void 0;const r=i(461),s=i(761),n=r.acquire,a=r.release,c=r.acquireWithAbort,o=r.releaseWithAbort,l=e=>({capacity:e,limit:e,q:new s.Deque(e),setRestriction(e){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),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)
|
|
3
|
+
;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)}}}},461:(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=>{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})}))
|
|
4
|
+
;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++}},464:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(518);t.restrictor=(()=>{const{MiniSemaphore:e}=r,t=new e(1);let i=Object.create(null);async function s(r,s,n){const a=await(async(r,s)=>{await t.acquire(!1);let n=i[r];if(n||(i[r]=n=new e(s)),n.limit!==s)throw t.release(),new ReferenceError(`Cannot get object with different restriction: key: '${String(r)}', lock.limit: ${n.limit} <-> restriction: ${s},`);return t.release(),n})(r,s),c=a.flow(n);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)
|
|
5
|
+
;const s=i,n=Object.create(null),a=Object.keys(s);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=s[i];l.last&&Date.now()-l.last>=e?(o++,r&&c.push(i)):n[i]=l}return i=n,t.release(),r&&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)}}})()},518:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSemaphore=void 0;const r=i(461),s=i(761),n=r.acquire,a=r.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)}}}},
|
|
6
|
+
761:(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 s=this._f+t&this._c-1;this._a[s]=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,s)=>{for(let n=0;n<s;++n)i[n+r]=e[n+t],e[n+t]=void 0})(e._a,0,e._a,i,t)}}}},t={};function i(r){var s=t[r];if(void 0!==s)return s.exports;var n=t[r]={exports:{}}
|
|
7
|
+
;return e[r](n,n.exports,i),n.exports}var r={};(()=>{var e=r;Object.defineProperty(e,"BJ",{value:!0}),e.rE=e.Ws=e.Jj=e.Xz=e.vt=e.C=void 0;var t=i(518);Object.defineProperty(e,"C",{enumerable:!0,get:function(){return t.MiniSemaphore}});var s=i(139);Object.defineProperty(e,"vt",{enumerable:!0,get:function(){return s.create}}),Object.defineProperty(e,"Xz",{enumerable:!0,get:function(){return s.createWithAbort}});var n=i(761);Object.defineProperty(e,"Jj",{enumerable:!0,get:function(){return n.Deque}});var a=i(464);Object.defineProperty(e,"Ws",{enumerable:!0,get:function(){return a.restrictor}}),e.rE="v1.4.4"})();const s=r.Jj,n=r.C,a=r.BJ,c=r.vt,o=r.Xz,l=r.Ws,h=r.rE;export{s as Deque,n as MiniSemaphore,a as __esModule,c as create,o as createWithAbort,l as restrictor,h as version};
|