@asaidimu/utils-sync 2.0.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -50
- package/index.d.mts +285 -272
- package/index.d.ts +285 -272
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -1,3 +1,182 @@
|
|
|
1
|
+
interface DebouncerOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Quiet period in milliseconds. The last-enqueued function runs after
|
|
4
|
+
* no new calls have arrived for this duration.
|
|
5
|
+
* @default 300
|
|
6
|
+
*/
|
|
7
|
+
delay?: number;
|
|
8
|
+
/**
|
|
9
|
+
* If true, also fires immediately on the leading edge (first call in a
|
|
10
|
+
* quiet period), then debounces subsequent calls normally.
|
|
11
|
+
*
|
|
12
|
+
* Leading-edge semantics: the leading call fires immediately and clears
|
|
13
|
+
* _pendingFn. Any calls arriving *while* the leading execution is in flight
|
|
14
|
+
* register as a new trailing call and will be resolved by the trailing timer
|
|
15
|
+
* when the quiet period expires. Calls arriving during the leading execution
|
|
16
|
+
* are never lost.
|
|
17
|
+
*
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
leading?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Result when the debounced function successfully executed.
|
|
24
|
+
*/
|
|
25
|
+
type DebouncerOk<T> = {
|
|
26
|
+
status: "ok";
|
|
27
|
+
value: T;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Result when the debounced function threw an error.
|
|
31
|
+
*/
|
|
32
|
+
type DebouncerError = {
|
|
33
|
+
status: "error";
|
|
34
|
+
error: unknown;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Result when the debounced call was cancelled before execution.
|
|
38
|
+
*/
|
|
39
|
+
type DebouncerCancelled = {
|
|
40
|
+
status: "cancelled";
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Discriminated union of all possible Debouncer outcomes.
|
|
44
|
+
*
|
|
45
|
+
* - `DebouncerOk<T>`: function ran and returned a value.
|
|
46
|
+
* - `DebouncerError`: function ran and threw an error.
|
|
47
|
+
* - `DebouncerCancelled`: call was cancelled before it ran.
|
|
48
|
+
*/
|
|
49
|
+
type DebouncerResult<T> = DebouncerOk<T> | DebouncerError | DebouncerCancelled;
|
|
50
|
+
/**
|
|
51
|
+
* Collapses rapid successive calls into a single execution.
|
|
52
|
+
*
|
|
53
|
+
* Each call to `do()` returns a promise that resolves with the result of the
|
|
54
|
+
* debounced execution — i.e. all callers within the same quiet window share
|
|
55
|
+
* the same result. The function that actually runs is always the *last* one
|
|
56
|
+
* enqueued before the delay expires.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* const debounced = new Debouncer({ delay: 200 });
|
|
60
|
+
* // Called rapidly three times — only the last fn runs.
|
|
61
|
+
* const [a, b, c] = await Promise.all([
|
|
62
|
+
* debounced.do(() => fetch("/api/search?q=h")),
|
|
63
|
+
* debounced.do(() => fetch("/api/search?q=he")),
|
|
64
|
+
* debounced.do(() => fetch("/api/search?q=hel")),
|
|
65
|
+
* ]);
|
|
66
|
+
* // a.status === "ok" and a.value is the result of the third fetch.
|
|
67
|
+
* // b and c share the same result as a.
|
|
68
|
+
*/
|
|
69
|
+
declare class Debouncer<T = void> {
|
|
70
|
+
private _delay;
|
|
71
|
+
private _leading;
|
|
72
|
+
private _timer;
|
|
73
|
+
private _pendingFn;
|
|
74
|
+
private _pendingResolvers;
|
|
75
|
+
private _leadingFired;
|
|
76
|
+
constructor(options?: DebouncerOptions);
|
|
77
|
+
/**
|
|
78
|
+
* Enqueues a function and returns a promise that resolves with its result.
|
|
79
|
+
*
|
|
80
|
+
* All callers within the same quiet window share the same result — the
|
|
81
|
+
* function that actually runs is the *last* one enqueued before the delay
|
|
82
|
+
* expires. Use this when you need the return value of the debounced call.
|
|
83
|
+
*
|
|
84
|
+
* For fire-and-forget use (void fns, event handlers), prefer `fire()` to
|
|
85
|
+
* avoid unhandled-promise-rejection warnings and make intent explicit.
|
|
86
|
+
*
|
|
87
|
+
* @param fn - The function to debounce.
|
|
88
|
+
* @returns A promise resolving with a DebouncerResult discriminated union.
|
|
89
|
+
*/
|
|
90
|
+
do(fn: () => Promise<T> | T): Promise<DebouncerResult<T>>;
|
|
91
|
+
/**
|
|
92
|
+
* Enqueues a function without returning a promise (fire-and-forget).
|
|
93
|
+
*
|
|
94
|
+
* Identical debounce semantics to `do()` — the last-enqueued function runs
|
|
95
|
+
* after the quiet period. Use this for void callbacks, DOM event handlers,
|
|
96
|
+
* or any caller that doesn't care about the result. No dangling promise,
|
|
97
|
+
* no unhandled-rejection risk.
|
|
98
|
+
*
|
|
99
|
+
* @param fn - The function to debounce.
|
|
100
|
+
*/
|
|
101
|
+
fire(fn: () => Promise<T> | T): void;
|
|
102
|
+
/**
|
|
103
|
+
* Shared enqueue logic for both `do()` and `fire()`.
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
private _enqueue;
|
|
107
|
+
/**
|
|
108
|
+
* Immediately cancels any pending debounced execution.
|
|
109
|
+
* All waiting callers resolve with `{ status: "cancelled" }`.
|
|
110
|
+
*/
|
|
111
|
+
cancel(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Immediately executes the pending function (if any), bypassing the remaining delay.
|
|
114
|
+
* All waiting callers receive the result.
|
|
115
|
+
*/
|
|
116
|
+
flush(): Promise<DebouncerResult<T> | null>;
|
|
117
|
+
/** Returns true if a debounced call is currently pending. */
|
|
118
|
+
pending(): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Executes the latest pending function and resolves all waiting callers.
|
|
121
|
+
*/
|
|
122
|
+
private _fire;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Represents all errors within the sync system */
|
|
126
|
+
declare class SyncError extends Error {
|
|
127
|
+
constructor(message: string, cause?: unknown);
|
|
128
|
+
}
|
|
129
|
+
declare class TimeoutError extends SyncError {
|
|
130
|
+
constructor(message?: string);
|
|
131
|
+
}
|
|
132
|
+
declare class OnceExecutionConflict extends SyncError {
|
|
133
|
+
constructor(cause?: unknown);
|
|
134
|
+
}
|
|
135
|
+
declare class SerializerExecutionDone extends SyncError {
|
|
136
|
+
constructor(cause?: unknown);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A one-shot gate that starts closed and opens exactly once.
|
|
141
|
+
*
|
|
142
|
+
* All current and future `wait()` callers resolve immediately once `open()` is
|
|
143
|
+
* called. Unlike Once, Latch carries no return value and has no retry logic —
|
|
144
|
+
* it is a pure signalling primitive.
|
|
145
|
+
*
|
|
146
|
+
* Typical use: coordinate startup, signal that an initialisation phase is done,
|
|
147
|
+
* or gate downstream work on a single event.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* const ready = new Latch();
|
|
151
|
+
* // Consumer
|
|
152
|
+
* await ready.wait();
|
|
153
|
+
* // Producer (elsewhere)
|
|
154
|
+
* ready.open();
|
|
155
|
+
*/
|
|
156
|
+
declare class Latch {
|
|
157
|
+
private _open;
|
|
158
|
+
private _resolve;
|
|
159
|
+
private _promise;
|
|
160
|
+
constructor();
|
|
161
|
+
/**
|
|
162
|
+
* Opens the latch. All current and future waiters resolve immediately.
|
|
163
|
+
* Calling open() more than once is a no-op.
|
|
164
|
+
*/
|
|
165
|
+
open(): void;
|
|
166
|
+
/**
|
|
167
|
+
* Returns a promise that resolves when the latch is opened.
|
|
168
|
+
* If already open, resolves on the next microtask checkpoint.
|
|
169
|
+
*
|
|
170
|
+
* @param timeout - Optional maximum wait time in milliseconds.
|
|
171
|
+
* @throws {TimeoutError} If the latch does not open within the timeout.
|
|
172
|
+
*/
|
|
173
|
+
wait(timeout?: number): Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* Synchronously checks whether the latch has been opened.
|
|
176
|
+
*/
|
|
177
|
+
isOpen(): boolean;
|
|
178
|
+
}
|
|
179
|
+
|
|
1
180
|
interface MutexOptions {
|
|
2
181
|
/**
|
|
3
182
|
* Maximum number of pending requests allowed in the queue.
|
|
@@ -64,61 +243,7 @@ declare class Mutex {
|
|
|
64
243
|
/** Returns the number of operations waiting for the lock. */
|
|
65
244
|
pending(): number;
|
|
66
245
|
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Number of concurrent holders allowed.
|
|
70
|
-
* Inherits `capacity` and `yieldMode` from MutexOptions.
|
|
71
|
-
* @default 1 (equivalent to a Mutex)
|
|
72
|
-
*/
|
|
73
|
-
slots?: number;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* A counting semaphore — generalises Mutex to allow up to N concurrent holders.
|
|
77
|
-
*
|
|
78
|
-
* Useful for rate-limiting concurrency: e.g. "at most 3 in-flight HTTP requests".
|
|
79
|
-
* With slots=1 it behaves identically to Mutex.
|
|
80
|
-
*
|
|
81
|
-
* Accepts the same `capacity` and `yieldMode` options as Mutex, plus `slots`.
|
|
82
|
-
*/
|
|
83
|
-
declare class Semaphore {
|
|
84
|
-
private _slots;
|
|
85
|
-
private _available;
|
|
86
|
-
private _capacity;
|
|
87
|
-
private _yieldMode;
|
|
88
|
-
private waiters;
|
|
89
|
-
constructor(options?: SemaphoreOptions);
|
|
90
|
-
/**
|
|
91
|
-
* Acquires one slot. If all slots are taken, waits until one is released.
|
|
92
|
-
*
|
|
93
|
-
* @param timeout - Optional maximum wait time in milliseconds.
|
|
94
|
-
* @throws {TimeoutError} If a slot cannot be acquired within the timeout.
|
|
95
|
-
* @throws {Error} If the wait queue is full.
|
|
96
|
-
*/
|
|
97
|
-
acquire(timeout?: number): Promise<void>;
|
|
98
|
-
/**
|
|
99
|
-
* Attempts to acquire a slot without waiting.
|
|
100
|
-
* @returns `true` if a slot was acquired, `false` otherwise.
|
|
101
|
-
*/
|
|
102
|
-
tryAcquire(): boolean;
|
|
103
|
-
/**
|
|
104
|
-
* Releases one slot. If waiters are queued, the next one is scheduled
|
|
105
|
-
* according to yieldMode.
|
|
106
|
-
*
|
|
107
|
-
* @throws {Error} If no slot is currently held (release without acquire).
|
|
108
|
-
*/
|
|
109
|
-
release(): void;
|
|
110
|
-
/**
|
|
111
|
-
* Runs a function with one acquired slot, releasing it when done.
|
|
112
|
-
* Convenience wrapper — prefer this over manual acquire/release.
|
|
113
|
-
*/
|
|
114
|
-
run<T>(fn: () => Promise<T> | T, timeout?: number): Promise<T>;
|
|
115
|
-
/** Number of slots currently free. */
|
|
116
|
-
available(): number;
|
|
117
|
-
/** Number of callers waiting for a slot. */
|
|
118
|
-
pending(): number;
|
|
119
|
-
/** Total slot count (as configured). */
|
|
120
|
-
slots(): number;
|
|
121
|
-
}
|
|
246
|
+
|
|
122
247
|
type OnceResult<T> = {
|
|
123
248
|
value: T | null;
|
|
124
249
|
error?: unknown;
|
|
@@ -161,13 +286,6 @@ declare class Once<T = void> {
|
|
|
161
286
|
* @returns The result of the execution.
|
|
162
287
|
*/
|
|
163
288
|
doSync(fn: () => T): OnceResult<T>;
|
|
164
|
-
/**
|
|
165
|
-
* Returns true if the operation has completed (success or non-retryable failure)
|
|
166
|
-
* and the internal promise has been cleared.
|
|
167
|
-
*
|
|
168
|
-
* This is the canonical "safe to read" check — prefer it over `done()`.
|
|
169
|
-
*/
|
|
170
|
-
ready(): boolean;
|
|
171
289
|
/**
|
|
172
290
|
* Returns true if the operation is currently executing.
|
|
173
291
|
*
|
|
@@ -210,116 +328,18 @@ declare class Once<T = void> {
|
|
|
210
328
|
*/
|
|
211
329
|
private _awaitWithTimeout;
|
|
212
330
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
error?: unknown;
|
|
216
|
-
};
|
|
217
|
-
interface SerializerOptions {
|
|
218
|
-
/**
|
|
219
|
-
* Max items in queue. If full, .do() returns an error immediately.
|
|
220
|
-
* @default 1000
|
|
221
|
-
*/
|
|
222
|
-
capacity?: number;
|
|
331
|
+
|
|
332
|
+
interface RWMutexOptions {
|
|
223
333
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
* Includes backpressure protection via configurable queue capacity.
|
|
234
|
-
*/
|
|
235
|
-
declare class Serializer<T = void> {
|
|
236
|
-
private mutex;
|
|
237
|
-
private _done;
|
|
238
|
-
private _lastValue;
|
|
239
|
-
private _lastError;
|
|
240
|
-
private _hasRun;
|
|
241
|
-
constructor(options?: SerializerOptions);
|
|
242
|
-
/**
|
|
243
|
-
* Enqueue a function to be executed after all previous tasks complete.
|
|
244
|
-
*
|
|
245
|
-
* @param fn - The function to execute.
|
|
246
|
-
* @param timeout - Max time to wait to acquire the lock.
|
|
247
|
-
* @returns Object containing the value or error.
|
|
248
|
-
*/
|
|
249
|
-
do(fn: () => Promise<T> | T, timeout?: number): Promise<SerializerResult<T | null>>;
|
|
250
|
-
/**
|
|
251
|
-
* Returns the result of the last execution.
|
|
252
|
-
*
|
|
253
|
-
* Returns `{ value: null, error: undefined }` both when the serializer has
|
|
254
|
-
* never run and when it ran and returned null — use `hasRun()` to distinguish
|
|
255
|
-
* these two cases.
|
|
256
|
-
*/
|
|
257
|
-
peek(): SerializerResult<T | null>;
|
|
258
|
-
/**
|
|
259
|
-
* Returns true if at least one task has been executed (successfully or not).
|
|
260
|
-
*/
|
|
261
|
-
hasRun(): boolean;
|
|
262
|
-
/**
|
|
263
|
-
* Permanently closes the serializer.
|
|
264
|
-
* Subsequent calls to `do()` will fail immediately with SerializerExecutionDone.
|
|
265
|
-
*/
|
|
266
|
-
close(): void;
|
|
267
|
-
/** Returns the number of tasks currently waiting. */
|
|
268
|
-
pending(): number;
|
|
269
|
-
/** Returns true if a task is currently executing. */
|
|
270
|
-
running(): boolean;
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* A one-shot gate that starts closed and opens exactly once.
|
|
274
|
-
*
|
|
275
|
-
* All current and future `wait()` callers resolve immediately once `open()` is
|
|
276
|
-
* called. Unlike Once, Latch carries no return value and has no retry logic —
|
|
277
|
-
* it is a pure signalling primitive.
|
|
278
|
-
*
|
|
279
|
-
* Typical use: coordinate startup, signal that an initialisation phase is done,
|
|
280
|
-
* or gate downstream work on a single event.
|
|
281
|
-
*
|
|
282
|
-
* @example
|
|
283
|
-
* const ready = new Latch();
|
|
284
|
-
* // Consumer
|
|
285
|
-
* await ready.wait();
|
|
286
|
-
* // Producer (elsewhere)
|
|
287
|
-
* ready.open();
|
|
288
|
-
*/
|
|
289
|
-
declare class Latch {
|
|
290
|
-
private _open;
|
|
291
|
-
private _resolve;
|
|
292
|
-
private _promise;
|
|
293
|
-
constructor();
|
|
294
|
-
/**
|
|
295
|
-
* Opens the latch. All current and future waiters resolve immediately.
|
|
296
|
-
* Calling open() more than once is a no-op.
|
|
297
|
-
*/
|
|
298
|
-
open(): void;
|
|
299
|
-
/**
|
|
300
|
-
* Returns a promise that resolves when the latch is opened.
|
|
301
|
-
* If already open, resolves on the next microtask checkpoint.
|
|
302
|
-
*
|
|
303
|
-
* @param timeout - Optional maximum wait time in milliseconds.
|
|
304
|
-
* @throws {TimeoutError} If the latch does not open within the timeout.
|
|
305
|
-
*/
|
|
306
|
-
wait(timeout?: number): Promise<void>;
|
|
307
|
-
/**
|
|
308
|
-
* Synchronously checks whether the latch has been opened.
|
|
309
|
-
*/
|
|
310
|
-
isOpen(): boolean;
|
|
311
|
-
}
|
|
312
|
-
interface RWMutexOptions {
|
|
313
|
-
/**
|
|
314
|
-
* Controls how lock handoff is scheduled when a waiter is unblocked.
|
|
315
|
-
*
|
|
316
|
-
* - `"microtask"` (default): Uses queueMicrotask(fn). Near-zero latency
|
|
317
|
-
* between handoffs. Appropriate for RWMutex because readers are woken in
|
|
318
|
-
* bulk and writers are rarely contended enough to cause starvation.
|
|
319
|
-
*
|
|
320
|
-
* - `"macrotask"`: Uses setTimeout(fn, 0) to yield to the event loop between
|
|
321
|
-
* handoffs. Use if you observe microtask starvation under extreme write
|
|
322
|
-
* contention on this specific lock.
|
|
334
|
+
* Controls how lock handoff is scheduled when a waiter is unblocked.
|
|
335
|
+
*
|
|
336
|
+
* - `"microtask"` (default): Uses queueMicrotask(fn). Near-zero latency
|
|
337
|
+
* between handoffs. Appropriate for RWMutex because readers are woken in
|
|
338
|
+
* bulk and writers are rarely contended enough to cause starvation.
|
|
339
|
+
*
|
|
340
|
+
* - `"macrotask"`: Uses setTimeout(fn, 0) to yield to the event loop between
|
|
341
|
+
* handoffs. Use if you observe microtask starvation under extreme write
|
|
342
|
+
* contention on this specific lock.
|
|
323
343
|
*/
|
|
324
344
|
yieldMode?: "macrotask" | "microtask";
|
|
325
345
|
}
|
|
@@ -402,128 +422,121 @@ declare class RWMutex {
|
|
|
402
422
|
*/
|
|
403
423
|
private _schedule;
|
|
404
424
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
* Quiet period in milliseconds. The last-enqueued function runs after
|
|
408
|
-
* no new calls have arrived for this duration.
|
|
409
|
-
* @default 300
|
|
410
|
-
*/
|
|
411
|
-
delay?: number;
|
|
425
|
+
|
|
426
|
+
interface SemaphoreOptions extends MutexOptions {
|
|
412
427
|
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
* Leading-edge semantics: the leading call fires immediately and clears
|
|
417
|
-
* _pendingFn. Any calls arriving *while* the leading execution is in flight
|
|
418
|
-
* register as a new trailing call and will be resolved by the trailing timer
|
|
419
|
-
* when the quiet period expires. Calls arriving during the leading execution
|
|
420
|
-
* are never lost.
|
|
421
|
-
*
|
|
422
|
-
* @default false
|
|
428
|
+
* Number of concurrent holders allowed.
|
|
429
|
+
* Inherits `capacity` and `yieldMode` from MutexOptions.
|
|
430
|
+
* @default 1 (equivalent to a Mutex)
|
|
423
431
|
*/
|
|
424
|
-
|
|
432
|
+
slots?: number;
|
|
425
433
|
}
|
|
426
434
|
/**
|
|
427
|
-
*
|
|
428
|
-
*/
|
|
429
|
-
type DebouncerOk<T> = {
|
|
430
|
-
status: "ok";
|
|
431
|
-
value: T;
|
|
432
|
-
};
|
|
433
|
-
/**
|
|
434
|
-
* Result when the debounced function threw an error.
|
|
435
|
-
*/
|
|
436
|
-
type DebouncerError = {
|
|
437
|
-
status: "error";
|
|
438
|
-
error: unknown;
|
|
439
|
-
};
|
|
440
|
-
/**
|
|
441
|
-
* Result when the debounced call was cancelled before execution.
|
|
442
|
-
*/
|
|
443
|
-
type DebouncerCancelled = {
|
|
444
|
-
status: "cancelled";
|
|
445
|
-
};
|
|
446
|
-
/**
|
|
447
|
-
* Discriminated union of all possible Debouncer outcomes.
|
|
448
|
-
*
|
|
449
|
-
* - `DebouncerOk<T>`: function ran and returned a value.
|
|
450
|
-
* - `DebouncerError`: function ran and threw an error.
|
|
451
|
-
* - `DebouncerCancelled`: call was cancelled before it ran.
|
|
452
|
-
*/
|
|
453
|
-
type DebouncerResult<T> = DebouncerOk<T> | DebouncerError | DebouncerCancelled;
|
|
454
|
-
/**
|
|
455
|
-
* Collapses rapid successive calls into a single execution.
|
|
435
|
+
* A counting semaphore — generalises Mutex to allow up to N concurrent holders.
|
|
456
436
|
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
* the same result. The function that actually runs is always the *last* one
|
|
460
|
-
* enqueued before the delay expires.
|
|
437
|
+
* Useful for rate-limiting concurrency: e.g. "at most 3 in-flight HTTP requests".
|
|
438
|
+
* With slots=1 it behaves identically to Mutex.
|
|
461
439
|
*
|
|
462
|
-
*
|
|
463
|
-
* const debounced = new Debouncer({ delay: 200 });
|
|
464
|
-
* // Called rapidly three times — only the last fn runs.
|
|
465
|
-
* const [a, b, c] = await Promise.all([
|
|
466
|
-
* debounced.do(() => fetch("/api/search?q=h")),
|
|
467
|
-
* debounced.do(() => fetch("/api/search?q=he")),
|
|
468
|
-
* debounced.do(() => fetch("/api/search?q=hel")),
|
|
469
|
-
* ]);
|
|
470
|
-
* // a.status === "ok" and a.value is the result of the third fetch.
|
|
471
|
-
* // b and c share the same result as a.
|
|
440
|
+
* Accepts the same `capacity` and `yieldMode` options as Mutex, plus `slots`.
|
|
472
441
|
*/
|
|
473
|
-
declare class
|
|
474
|
-
private
|
|
475
|
-
private
|
|
476
|
-
private
|
|
477
|
-
private
|
|
478
|
-
private
|
|
479
|
-
|
|
480
|
-
constructor(options?: DebouncerOptions);
|
|
442
|
+
declare class Semaphore {
|
|
443
|
+
private _slots;
|
|
444
|
+
private _available;
|
|
445
|
+
private _capacity;
|
|
446
|
+
private _yieldMode;
|
|
447
|
+
private waiters;
|
|
448
|
+
constructor(options?: SemaphoreOptions);
|
|
481
449
|
/**
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
* All callers within the same quiet window share the same result — the
|
|
485
|
-
* function that actually runs is the *last* one enqueued before the delay
|
|
486
|
-
* expires. Use this when you need the return value of the debounced call.
|
|
487
|
-
*
|
|
488
|
-
* For fire-and-forget use (void fns, event handlers), prefer `fire()` to
|
|
489
|
-
* avoid unhandled-promise-rejection warnings and make intent explicit.
|
|
450
|
+
* Acquires one slot. If all slots are taken, waits until one is released.
|
|
490
451
|
*
|
|
491
|
-
* @param
|
|
492
|
-
* @
|
|
452
|
+
* @param timeout - Optional maximum wait time in milliseconds.
|
|
453
|
+
* @throws {TimeoutError} If a slot cannot be acquired within the timeout.
|
|
454
|
+
* @throws {Error} If the wait queue is full.
|
|
493
455
|
*/
|
|
494
|
-
|
|
456
|
+
acquire(timeout?: number): Promise<void>;
|
|
495
457
|
/**
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
*
|
|
458
|
+
* Attempts to acquire a slot without waiting.
|
|
459
|
+
* @returns `true` if a slot was acquired, `false` otherwise.
|
|
460
|
+
*/
|
|
461
|
+
tryAcquire(): boolean;
|
|
462
|
+
/**
|
|
463
|
+
* Releases one slot. If waiters are queued, the next one is scheduled
|
|
464
|
+
* according to yieldMode.
|
|
502
465
|
*
|
|
503
|
-
* @
|
|
466
|
+
* @throws {Error} If no slot is currently held (release without acquire).
|
|
504
467
|
*/
|
|
505
|
-
|
|
468
|
+
release(): void;
|
|
506
469
|
/**
|
|
507
|
-
*
|
|
470
|
+
* Runs a function with one acquired slot, releasing it when done.
|
|
471
|
+
* Convenience wrapper — prefer this over manual acquire/release.
|
|
472
|
+
*/
|
|
473
|
+
run<T>(fn: () => Promise<T> | T, timeout?: number): Promise<T>;
|
|
474
|
+
/** Number of slots currently free. */
|
|
475
|
+
available(): number;
|
|
476
|
+
/** Number of callers waiting for a slot. */
|
|
477
|
+
pending(): number;
|
|
478
|
+
/** Total slot count (as configured). */
|
|
479
|
+
slots(): number;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
type SerializerResult<T> = {
|
|
483
|
+
value: T | null;
|
|
484
|
+
error?: unknown;
|
|
485
|
+
};
|
|
486
|
+
interface SerializerOptions {
|
|
487
|
+
/**
|
|
488
|
+
* Max items in queue. If full, .do() returns an error immediately.
|
|
489
|
+
* @default 1000
|
|
490
|
+
*/
|
|
491
|
+
capacity?: number;
|
|
492
|
+
/**
|
|
493
|
+
* Yield mode for the internal mutex. Defaults to "macrotask" for
|
|
494
|
+
* coarse-grained serializers. Use "microtask" for fine-grained
|
|
495
|
+
* latency-sensitive serializers.
|
|
496
|
+
*/
|
|
497
|
+
yieldMode?: "macrotask" | "microtask";
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Ensures tasks are executed sequentially (FIFO).
|
|
501
|
+
* Maintains the result of the last successful execution.
|
|
502
|
+
* Includes backpressure protection via configurable queue capacity.
|
|
503
|
+
*/
|
|
504
|
+
declare class Serializer<T = void> {
|
|
505
|
+
private mutex;
|
|
506
|
+
private _done;
|
|
507
|
+
private _lastValue;
|
|
508
|
+
private _lastError;
|
|
509
|
+
private _hasRun;
|
|
510
|
+
constructor(options?: SerializerOptions);
|
|
511
|
+
/**
|
|
512
|
+
* Enqueue a function to be executed after all previous tasks complete.
|
|
508
513
|
*
|
|
514
|
+
* @param fn - The function to execute.
|
|
515
|
+
* @param timeout - Max time to wait to acquire the lock.
|
|
516
|
+
* @returns Object containing the value or error.
|
|
509
517
|
*/
|
|
510
|
-
|
|
518
|
+
do(fn: () => Promise<T> | T, timeout?: number): Promise<SerializerResult<T | null>>;
|
|
511
519
|
/**
|
|
512
|
-
*
|
|
513
|
-
*
|
|
520
|
+
* Returns the result of the last execution.
|
|
521
|
+
*
|
|
522
|
+
* Returns `{ value: null, error: undefined }` both when the serializer has
|
|
523
|
+
* never run and when it ran and returned null — use `hasRun()` to distinguish
|
|
524
|
+
* these two cases.
|
|
514
525
|
*/
|
|
515
|
-
|
|
526
|
+
peek(): SerializerResult<T | null>;
|
|
516
527
|
/**
|
|
517
|
-
*
|
|
518
|
-
* All waiting callers receive the result.
|
|
528
|
+
* Returns true if at least one task has been executed (successfully or not).
|
|
519
529
|
*/
|
|
520
|
-
|
|
521
|
-
/** Returns true if a debounced call is currently pending. */
|
|
522
|
-
pending(): boolean;
|
|
530
|
+
hasRun(): boolean;
|
|
523
531
|
/**
|
|
524
|
-
*
|
|
532
|
+
* Permanently closes the serializer.
|
|
533
|
+
* Subsequent calls to `do()` will fail immediately with SerializerExecutionDone.
|
|
525
534
|
*/
|
|
526
|
-
|
|
535
|
+
close(): void;
|
|
536
|
+
/** Returns the number of tasks currently waiting. */
|
|
537
|
+
pending(): number;
|
|
538
|
+
/** Returns true if a task is currently executing. */
|
|
539
|
+
running(): boolean;
|
|
527
540
|
}
|
|
528
541
|
|
|
529
|
-
export { Debouncer, type DebouncerCancelled, type DebouncerError, type DebouncerOk, type DebouncerOptions, type DebouncerResult, Latch, Mutex, type MutexOptions, Once, type OnceResult, RWMutex, type RWMutexOptions, Semaphore, type SemaphoreOptions, Serializer, type SerializerOptions, type SerializerResult };
|
|
542
|
+
export { Debouncer, type DebouncerCancelled, type DebouncerError, type DebouncerOk, type DebouncerOptions, type DebouncerResult, Latch, Mutex, type MutexOptions, Once, OnceExecutionConflict, type OnceResult, RWMutex, type RWMutexOptions, Semaphore, type SemaphoreOptions, Serializer, SerializerExecutionDone, type SerializerOptions, type SerializerResult, SyncError, TimeoutError };
|