@vielzeug/familiar 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/dist/_pool-core.cjs +2 -0
- package/dist/_pool-core.cjs.map +1 -0
- package/dist/_pool-core.d.ts +40 -0
- package/dist/_pool-core.d.ts.map +1 -0
- package/dist/_pool-core.js +105 -0
- package/dist/_pool-core.js.map +1 -0
- package/dist/_pool.cjs +1 -1
- package/dist/_pool.cjs.map +1 -1
- package/dist/_pool.d.ts +4 -8
- package/dist/_pool.d.ts.map +1 -1
- package/dist/_pool.js +75 -129
- package/dist/_pool.js.map +1 -1
- package/dist/_stream-pool.cjs +1 -1
- package/dist/_stream-pool.cjs.map +1 -1
- package/dist/_stream-pool.d.ts +1 -1
- package/dist/_stream-pool.d.ts.map +1 -1
- package/dist/_stream-pool.js +64 -118
- package/dist/_stream-pool.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +0 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -4
- package/dist/errors.js.map +1 -1
- package/dist/familiar.cjs +1 -1
- package/dist/familiar.cjs.map +1 -1
- package/dist/familiar.iife.js +1 -1
- package/dist/familiar.iife.js.map +1 -1
- package/dist/familiar.js +1 -1
- package/dist/familiar.js.map +1 -1
- package/dist/types.d.ts +5 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./_timers.cjs"),t=require("./errors.cjs");let n=require("@vielzeug/arsenal/async");function r(r){let i=new AbortController,a=[],o=[],s=0,c=0,l=0,u,d=!1;function f(){if(r.isIdle())for(let e of a.splice(0))e.timer&&clearTimeout(e.timer),e.resolve()}function p(n){return r.isIdle()?Promise.resolve():new Promise((r,i)=>{let o={reject:i,resolve:r};n.timeout!==void 0&&(o.timer=setTimeout(()=>{let e=a.indexOf(o);e!==-1&&a.splice(e,1),i(new t.FamiliarTimeoutError(n.timeout))},n.timeout),e.unrefTimer(o.timer)),a.push(o)})}function m(){o.shift()?.resolve()}function h(e){for(let t of o.splice(0))t.reject(e)}function g(e){return e?.aborted?Promise.reject((0,n.abortError)(e)):new Promise((t,r)=>{let i=!1,a={cleanup(){e?.removeEventListener(`abort`,s)},reject(e){if(i)return;i=!0,a.cleanup();let t=o.indexOf(a);t!==-1&&o.splice(t,1),r(e)},resolve(){i||(i=!0,a.cleanup(),t())}},s=()=>a.reject((0,n.abortError)(e));e?.addEventListener(`abort`,s,{once:!0}),o.push(a)})}function _(){d||(d=!0,i.abort(),r.onDispose(),h(new t.FamiliarTerminatedError),f())}function v(e){return d?Promise.resolve():u||(r.onDrainStart(),h(new t.FamiliarTerminatedError(`Worker is draining`)),u=p(e).then(()=>_(),e=>{throw _(),e}),u)}function y(e){return Promise.all(e.map(e=>e.prime())).then(()=>void 0)}function b(e){s+=e}function x(){c+=1}function S(){l+=1}function C(e){return{active:s,completed:c,failed:l,queued:e}}function w(){return d?`terminated`:s===0?`idle`:`running`}return{disposalSignal:i.signal,dispose:_,get disposed(){return d},drain:v,get drainPromise(){return u},isIdle:r.isIdle,prime:y,rejectCapacity:h,releaseCapacity:m,settleIdle:f,stats:C,status:w,trackActive:b,trackCompleted:x,trackFailed:S,waitForCapacity:g,waitForIdle:p}}exports.createPoolCore=r;
|
|
2
|
+
//# sourceMappingURL=_pool-core.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_pool-core.cjs","names":[],"sources":["../src/_pool-core.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\nimport { unrefTimer } from './_timers';\nimport { FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type { DrainOptions, WorkerStats, WorkerStatus } from './types';\n\nexport type PoolOptions = {\n concurrency: number;\n defaultTimeout: number | undefined;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n};\n\ntype IdleWaiter = {\n reject: (reason: unknown) => void;\n resolve: () => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\nexport interface PoolCore {\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n drain(options: DrainOptions): Promise<void>;\n readonly drainPromise: Promise<void> | undefined;\n isIdle(): boolean;\n prime(slots: readonly { prime(): Promise<void> }[]): Promise<void>;\n rejectCapacity(reason: unknown): void;\n releaseCapacity(): void;\n settleIdle(): void;\n stats(queued: number): WorkerStats;\n status(): WorkerStatus;\n trackActive(delta: number): void;\n trackCompleted(): void;\n trackFailed(): void;\n waitForCapacity(signal: AbortSignal | undefined): Promise<void>;\n waitForIdle(options: DrainOptions): Promise<void>;\n}\n\n/**\n * Shared disposal controller, idle/capacity waiters, drain, and stats tracking\n * used by both the single-result pool (`_pool.ts`) and the stream pool\n * (`_stream-pool.ts`). Each pool provides its own `isIdle` predicate and\n * `onDispose`/`onDrainStart` hooks to flush pool-specific pending work.\n */\nexport function createPoolCore(options: {\n isIdle: () => boolean;\n onDispose: () => void;\n onDrainStart: () => void;\n}): PoolCore {\n const disposalController = new AbortController();\n const idleWaiters: IdleWaiter[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let drainPromise: Promise<void> | undefined;\n let terminated = false;\n\n function settleIdle(): void {\n if (!options.isIdle()) return;\n\n for (const waiter of idleWaiters.splice(0)) {\n if (waiter.timer) clearTimeout(waiter.timer);\n\n waiter.resolve();\n }\n }\n\n function waitForIdle(drainOptions: DrainOptions): Promise<void> {\n if (options.isIdle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n const waiter: IdleWaiter = { reject, resolve };\n\n if (drainOptions.timeout !== undefined) {\n waiter.timer = setTimeout(() => {\n const index = idleWaiters.indexOf(waiter);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(drainOptions.timeout!));\n }, drainOptions.timeout);\n unrefTimer(waiter.timer);\n }\n\n idleWaiters.push(waiter);\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n options.onDispose();\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n options.onDrainStart();\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n function prime(slots: readonly { prime(): Promise<void> }[]): Promise<void> {\n return Promise.all(slots.map((slot) => slot.prime())).then(() => undefined);\n }\n\n function trackActive(delta: number): void {\n active += delta;\n }\n\n function trackCompleted(): void {\n completed += 1;\n }\n\n function trackFailed(): void {\n failed += 1;\n }\n\n function stats(queued: number): WorkerStats {\n return { active, completed, failed, queued };\n }\n\n function status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n }\n\n return {\n disposalSignal: disposalController.signal,\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n get drainPromise() {\n return drainPromise;\n },\n isIdle: options.isIdle,\n prime,\n rejectCapacity,\n releaseCapacity,\n settleIdle,\n stats,\n status,\n trackActive,\n trackCompleted,\n trackFailed,\n waitForCapacity,\n waitForIdle,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { DrainOptions, WorkerStats, WorkerStatus } from './types';
|
|
2
|
+
export type PoolOptions = {
|
|
3
|
+
concurrency: number;
|
|
4
|
+
defaultTimeout: number | undefined;
|
|
5
|
+
maxQueue: number | undefined;
|
|
6
|
+
onFull: 'reject' | 'wait';
|
|
7
|
+
};
|
|
8
|
+
export interface PoolCore {
|
|
9
|
+
readonly disposalSignal: AbortSignal;
|
|
10
|
+
dispose(): void;
|
|
11
|
+
readonly disposed: boolean;
|
|
12
|
+
drain(options: DrainOptions): Promise<void>;
|
|
13
|
+
readonly drainPromise: Promise<void> | undefined;
|
|
14
|
+
isIdle(): boolean;
|
|
15
|
+
prime(slots: readonly {
|
|
16
|
+
prime(): Promise<void>;
|
|
17
|
+
}[]): Promise<void>;
|
|
18
|
+
rejectCapacity(reason: unknown): void;
|
|
19
|
+
releaseCapacity(): void;
|
|
20
|
+
settleIdle(): void;
|
|
21
|
+
stats(queued: number): WorkerStats;
|
|
22
|
+
status(): WorkerStatus;
|
|
23
|
+
trackActive(delta: number): void;
|
|
24
|
+
trackCompleted(): void;
|
|
25
|
+
trackFailed(): void;
|
|
26
|
+
waitForCapacity(signal: AbortSignal | undefined): Promise<void>;
|
|
27
|
+
waitForIdle(options: DrainOptions): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Shared disposal controller, idle/capacity waiters, drain, and stats tracking
|
|
31
|
+
* used by both the single-result pool (`_pool.ts`) and the stream pool
|
|
32
|
+
* (`_stream-pool.ts`). Each pool provides its own `isIdle` predicate and
|
|
33
|
+
* `onDispose`/`onDrainStart` hooks to flush pool-specific pending work.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createPoolCore(options: {
|
|
36
|
+
isIdle: () => boolean;
|
|
37
|
+
onDispose: () => void;
|
|
38
|
+
onDrainStart: () => void;
|
|
39
|
+
}): PoolCore;
|
|
40
|
+
//# sourceMappingURL=_pool-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_pool-core.d.ts","sourceRoot":"","sources":["../src/_pool-core.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvE,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;CAC3B,CAAC;AAcF,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACjD,MAAM,IAAI,OAAO,CAAC;IAClB,KAAK,CAAC,KAAK,EAAE,SAAS;QAAE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACtC,eAAe,IAAI,IAAI,CAAC;IACxB,UAAU,IAAI,IAAI,CAAC;IACnB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IACnC,MAAM,IAAI,YAAY,CAAC;IACvB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,IAAI,IAAI,CAAC;IACvB,WAAW,IAAI,IAAI,CAAC;IACpB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,GAAG,QAAQ,CAkKX"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { unrefTimer as e } from "./_timers.js";
|
|
2
|
+
import { FamiliarTerminatedError as t, FamiliarTimeoutError as n } from "./errors.js";
|
|
3
|
+
import { abortError as r } from "@vielzeug/arsenal/async";
|
|
4
|
+
//#region src/_pool-core.ts
|
|
5
|
+
function i(i) {
|
|
6
|
+
let a = new AbortController(), o = [], s = [], c = 0, l = 0, u = 0, d, f = !1;
|
|
7
|
+
function p() {
|
|
8
|
+
if (i.isIdle()) for (let e of o.splice(0)) e.timer && clearTimeout(e.timer), e.resolve();
|
|
9
|
+
}
|
|
10
|
+
function m(t) {
|
|
11
|
+
return i.isIdle() ? Promise.resolve() : new Promise((r, i) => {
|
|
12
|
+
let a = {
|
|
13
|
+
reject: i,
|
|
14
|
+
resolve: r
|
|
15
|
+
};
|
|
16
|
+
t.timeout !== void 0 && (a.timer = setTimeout(() => {
|
|
17
|
+
let e = o.indexOf(a);
|
|
18
|
+
e !== -1 && o.splice(e, 1), i(new n(t.timeout));
|
|
19
|
+
}, t.timeout), e(a.timer)), o.push(a);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function h() {
|
|
23
|
+
s.shift()?.resolve();
|
|
24
|
+
}
|
|
25
|
+
function g(e) {
|
|
26
|
+
for (let t of s.splice(0)) t.reject(e);
|
|
27
|
+
}
|
|
28
|
+
function _(e) {
|
|
29
|
+
return e?.aborted ? Promise.reject(r(e)) : new Promise((t, n) => {
|
|
30
|
+
let i = !1, a = {
|
|
31
|
+
cleanup() {
|
|
32
|
+
e?.removeEventListener("abort", o);
|
|
33
|
+
},
|
|
34
|
+
reject(e) {
|
|
35
|
+
if (i) return;
|
|
36
|
+
i = !0, a.cleanup();
|
|
37
|
+
let t = s.indexOf(a);
|
|
38
|
+
t !== -1 && s.splice(t, 1), n(e);
|
|
39
|
+
},
|
|
40
|
+
resolve() {
|
|
41
|
+
i || (i = !0, a.cleanup(), t());
|
|
42
|
+
}
|
|
43
|
+
}, o = () => a.reject(r(e));
|
|
44
|
+
e?.addEventListener("abort", o, { once: !0 }), s.push(a);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function v() {
|
|
48
|
+
f || (f = !0, a.abort(), i.onDispose(), g(new t()), p());
|
|
49
|
+
}
|
|
50
|
+
function y(e) {
|
|
51
|
+
return f ? Promise.resolve() : d || (i.onDrainStart(), g(new t("Worker is draining")), d = m(e).then(() => v(), (e) => {
|
|
52
|
+
throw v(), e;
|
|
53
|
+
}), d);
|
|
54
|
+
}
|
|
55
|
+
function b(e) {
|
|
56
|
+
return Promise.all(e.map((e) => e.prime())).then(() => void 0);
|
|
57
|
+
}
|
|
58
|
+
function x(e) {
|
|
59
|
+
c += e;
|
|
60
|
+
}
|
|
61
|
+
function S() {
|
|
62
|
+
l += 1;
|
|
63
|
+
}
|
|
64
|
+
function C() {
|
|
65
|
+
u += 1;
|
|
66
|
+
}
|
|
67
|
+
function w(e) {
|
|
68
|
+
return {
|
|
69
|
+
active: c,
|
|
70
|
+
completed: l,
|
|
71
|
+
failed: u,
|
|
72
|
+
queued: e
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function T() {
|
|
76
|
+
return f ? "terminated" : c === 0 ? "idle" : "running";
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
disposalSignal: a.signal,
|
|
80
|
+
dispose: v,
|
|
81
|
+
get disposed() {
|
|
82
|
+
return f;
|
|
83
|
+
},
|
|
84
|
+
drain: y,
|
|
85
|
+
get drainPromise() {
|
|
86
|
+
return d;
|
|
87
|
+
},
|
|
88
|
+
isIdle: i.isIdle,
|
|
89
|
+
prime: b,
|
|
90
|
+
rejectCapacity: g,
|
|
91
|
+
releaseCapacity: h,
|
|
92
|
+
settleIdle: p,
|
|
93
|
+
stats: w,
|
|
94
|
+
status: T,
|
|
95
|
+
trackActive: x,
|
|
96
|
+
trackCompleted: S,
|
|
97
|
+
trackFailed: C,
|
|
98
|
+
waitForCapacity: _,
|
|
99
|
+
waitForIdle: m
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { i as createPoolCore };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=_pool-core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_pool-core.js","names":[],"sources":["../src/_pool-core.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\nimport { unrefTimer } from './_timers';\nimport { FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type { DrainOptions, WorkerStats, WorkerStatus } from './types';\n\nexport type PoolOptions = {\n concurrency: number;\n defaultTimeout: number | undefined;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n};\n\ntype IdleWaiter = {\n reject: (reason: unknown) => void;\n resolve: () => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\nexport interface PoolCore {\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n drain(options: DrainOptions): Promise<void>;\n readonly drainPromise: Promise<void> | undefined;\n isIdle(): boolean;\n prime(slots: readonly { prime(): Promise<void> }[]): Promise<void>;\n rejectCapacity(reason: unknown): void;\n releaseCapacity(): void;\n settleIdle(): void;\n stats(queued: number): WorkerStats;\n status(): WorkerStatus;\n trackActive(delta: number): void;\n trackCompleted(): void;\n trackFailed(): void;\n waitForCapacity(signal: AbortSignal | undefined): Promise<void>;\n waitForIdle(options: DrainOptions): Promise<void>;\n}\n\n/**\n * Shared disposal controller, idle/capacity waiters, drain, and stats tracking\n * used by both the single-result pool (`_pool.ts`) and the stream pool\n * (`_stream-pool.ts`). Each pool provides its own `isIdle` predicate and\n * `onDispose`/`onDrainStart` hooks to flush pool-specific pending work.\n */\nexport function createPoolCore(options: {\n isIdle: () => boolean;\n onDispose: () => void;\n onDrainStart: () => void;\n}): PoolCore {\n const disposalController = new AbortController();\n const idleWaiters: IdleWaiter[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let drainPromise: Promise<void> | undefined;\n let terminated = false;\n\n function settleIdle(): void {\n if (!options.isIdle()) return;\n\n for (const waiter of idleWaiters.splice(0)) {\n if (waiter.timer) clearTimeout(waiter.timer);\n\n waiter.resolve();\n }\n }\n\n function waitForIdle(drainOptions: DrainOptions): Promise<void> {\n if (options.isIdle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n const waiter: IdleWaiter = { reject, resolve };\n\n if (drainOptions.timeout !== undefined) {\n waiter.timer = setTimeout(() => {\n const index = idleWaiters.indexOf(waiter);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(drainOptions.timeout!));\n }, drainOptions.timeout);\n unrefTimer(waiter.timer);\n }\n\n idleWaiters.push(waiter);\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n options.onDispose();\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n options.onDrainStart();\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n function prime(slots: readonly { prime(): Promise<void> }[]): Promise<void> {\n return Promise.all(slots.map((slot) => slot.prime())).then(() => undefined);\n }\n\n function trackActive(delta: number): void {\n active += delta;\n }\n\n function trackCompleted(): void {\n completed += 1;\n }\n\n function trackFailed(): void {\n failed += 1;\n }\n\n function stats(queued: number): WorkerStats {\n return { active, completed, failed, queued };\n }\n\n function status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n }\n\n return {\n disposalSignal: disposalController.signal,\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n get drainPromise() {\n return drainPromise;\n },\n isIdle: options.isIdle,\n prime,\n rejectCapacity,\n releaseCapacity,\n settleIdle,\n stats,\n status,\n trackActive,\n trackCompleted,\n trackFailed,\n waitForCapacity,\n waitForIdle,\n };\n}\n"],"mappings":"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"}
|
package/dist/_pool.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_pool-core.cjs"),n=require("./_queue.cjs");let r=require("@vielzeug/arsenal/async");function i(i,a){let o=[...i],s=new n.TaskQueue,c=!1,l=t.createPoolCore({isIdle:()=>o.length===i.length&&s.size===0,onDispose(){for(let e of i)e.terminate();for(;s.size>0;){let t=s.shift();if(!t)break;t.cleanupAbort?.(),t.reject(new e.FamiliarTerminatedError)}},onDrainStart(){}});function u(){for(;s.size>0;){let e=s.shift();if(!e)break;if(e.signal?.aborted){e.cleanupAbort?.(),e.reject((0,r.abortError)(e.signal)),l.releaseCapacity();continue}return e}l.settleIdle()}function d(){if(!(c||l.disposed)){for(c=!0;!l.disposed&&o.length>0&&s.size>0;){let i=u();if(!i)break;let s=i,c=o.pop(),f=s.timeout??a.defaultTimeout;l.trackActive(1),l.releaseCapacity();let p=()=>c.cancel((0,r.abortError)(s.signal));s.cleanupAbort=()=>{s.signal?.removeEventListener(`abort`,p),s.cleanupAbort=void 0},s.signal?.addEventListener(`abort`,p,{once:!0}),c.run(s.input,s.transferables,f).then(e=>t(e),e=>n(e));function t(e){s.cleanupAbort?.(),o.push(c),l.trackActive(-1),l.trackCompleted(),s.resolve(e),d(),l.settleIdle()}function n(t){s.cleanupAbort?.(),o.push(c),l.trackActive(-1),!(t instanceof e.FamiliarTerminatedError)&&t instanceof Error&&t.name!==`AbortError`&&l.trackFailed(),s.reject(t),d(),l.settleIdle()}}c=!1}}async function f(t,n={}){let{priority:i=0,signal:o,timeout:c,transferables:u=[]}=n;if(l.disposed)throw new e.FamiliarTerminatedError;if(l.drainPromise)throw new e.FamiliarTerminatedError(`Worker is draining`);if(o?.aborted)throw(0,r.abortError)(o);for(;a.onFull===`wait`&&a.maxQueue!==void 0&&s.size>=a.maxQueue;){if(await l.waitForCapacity(o),l.disposed)throw new e.FamiliarTerminatedError;if(l.drainPromise)throw new e.FamiliarTerminatedError(`Worker is draining`);if(o?.aborted)throw(0,r.abortError)(o)}let f,p,m=new Promise((e,t)=>{f=e,p=t}),h={input:t,priority:i,reject:p,resolve:f,signal:o,timeout:c,transferables:u};if(!s.enqueue(h,a.onFull===`wait`?void 0:a.maxQueue))throw new e.FamiliarQueueFullError(a.maxQueue);if(o){let e=()=>{s.remove(h)&&(h.cleanupAbort?.(),p((0,r.abortError)(o)),l.releaseCapacity(),l.settleIdle())};h.cleanupAbort=()=>{o.removeEventListener(`abort`,e),h.cleanupAbort=void 0},o.addEventListener(`abort`,e,{once:!0})}return d(),m}return{get disposalSignal(){return l.disposalSignal},dispose:l.dispose,get disposed(){return l.disposed},drain:l.drain,async prime(){await l.prime(i)},run:f,get stats(){return l.stats(s.size)},get status(){return l.status()},[Symbol.asyncDispose]:()=>l.drain({}),[Symbol.dispose]:l.dispose}}async function*a(e,t,n={}){let r=new AbortController,i=()=>r.abort(n.signal?.reason);n.signal?.addEventListener(`abort`,i,{once:!0});let a=t.map(t=>e.run(t,{...n,signal:r.signal}));try{for(let e of a)yield await e}catch(e){throw r.abort(e),await Promise.allSettled(a),e}finally{n.signal?.removeEventListener(`abort`,i),r.abort(),await Promise.allSettled(a)}}function o(e,t=void 0,n={}){let r=new AbortController,i=new Set,a=0;return n.signal?.addEventListener(`abort`,()=>r.abort(n.signal?.reason),{once:!0}),{abort(e){r.abort(e)},async drain(){return Promise.allSettled([...i])},get name(){return t},get pending(){return i.size},run(t,n={}){let o=e.run(t,{...n,signal:r.signal});return a+=1,i.add(o),o.finally(()=>i.delete(o)),o},get size(){return a}}}exports.batch=a,exports.createPool=i,exports.createTaskGroup=o;
|
|
2
2
|
//# sourceMappingURL=_pool.cjs.map
|
package/dist/_pool.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_pool.cjs","names":[],"sources":["../src/_pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\nimport { type QueueItem, TaskQueue } from './_queue';\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type {\n BatchOptions,\n DrainOptions,\n RunOptions,\n SlotStrategy,\n TaskGroup,\n TaskGroupOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\n\nexport type PoolOptions = {\n concurrency: number;\n defaultTimeout: number | undefined;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n};\n\ntype IdleWaiter = {\n reject: (reason: unknown) => void;\n resolve: () => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\nexport function createPool<TInput, TOutput>(\n slots: SlotStrategy<TInput, TOutput>[],\n options: PoolOptions,\n): WorkerPool<TInput, TOutput> {\n const freeSlots = [...slots];\n const queue = new TaskQueue<TInput, TOutput>();\n const disposalController = new AbortController();\n const idleWaiters: IdleWaiter[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let drainPromise: Promise<void> | undefined;\n let draining = false;\n let terminated = false;\n\n function isIdle(): boolean {\n return active === 0 && queue.size === 0;\n }\n\n function settleIdle(): void {\n if (!isIdle()) return;\n\n for (const waiter of idleWaiters.splice(0)) {\n if (waiter.timer) clearTimeout(waiter.timer);\n\n waiter.resolve();\n }\n }\n\n function waitForIdle(drainOptions: DrainOptions = {}): Promise<void> {\n if (isIdle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n const waiter: IdleWaiter = { reject, resolve };\n\n if (drainOptions.timeout !== undefined) {\n waiter.timer = setTimeout(() => {\n const index = idleWaiters.indexOf(waiter);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(drainOptions.timeout!));\n }, drainOptions.timeout);\n unrefTimer(waiter.timer);\n }\n\n idleWaiters.push(waiter);\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function nextItem(): QueueItem<TInput, TOutput> | undefined {\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n if (item.signal?.aborted) {\n item.cleanupAbort?.();\n item.reject(abortError(item.signal));\n releaseCapacity();\n continue;\n }\n\n return item;\n }\n\n settleIdle();\n\n return undefined;\n }\n\n function drainQueue(): void {\n if (draining || terminated) return;\n\n draining = true;\n\n while (!terminated && freeSlots.length > 0 && queue.size > 0) {\n const next = nextItem();\n\n if (!next) break;\n\n const item = next;\n const slot = freeSlots.pop()!;\n const timeout = item.timeout ?? options.defaultTimeout;\n\n active += 1;\n releaseCapacity();\n\n const onAbort = () => slot.cancel(abortError(item.signal!));\n\n item.cleanupAbort = () => {\n item.signal?.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n item.signal?.addEventListener('abort', onAbort, { once: true });\n\n slot.run(item.input, item.transferables, timeout).then(\n (value) => finish(value),\n (error: unknown) => fail(error),\n );\n\n function finish(value: TOutput): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n active -= 1;\n completed += 1;\n item.resolve(value);\n drainQueue();\n settleIdle();\n }\n\n function fail(error: unknown): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n active -= 1;\n\n if (!(error instanceof FamiliarTerminatedError) && error?.constructor?.name !== 'AbortError') failed += 1;\n\n item.reject(error);\n drainQueue();\n settleIdle();\n }\n }\n\n draining = false;\n }\n\n async function run(input: TInput, runOptions: RunOptions = {}): Promise<TOutput> {\n const { priority = 0, signal, timeout, transferables = [] } = runOptions;\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n\n while (options.onFull === 'wait' && options.maxQueue !== undefined && queue.size >= options.maxQueue) {\n await waitForCapacity(signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n }\n\n let resolve!: (value: TOutput) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<TOutput>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const item: QueueItem<TInput, TOutput> = { input, priority, reject, resolve, signal, timeout, transferables };\n\n if (!queue.enqueue(item, options.onFull === 'wait' ? undefined : options.maxQueue)) {\n throw new FamiliarQueueFullError(options.maxQueue!);\n }\n\n if (signal) {\n const onAbort = () => {\n if (!queue.remove(item)) return;\n\n item.cleanupAbort?.();\n reject(abortError(signal));\n releaseCapacity();\n settleIdle();\n };\n\n item.cleanupAbort = () => {\n signal.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n\n drainQueue();\n\n return promise;\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n for (const slot of slots) slot.terminate();\n\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n item.cleanupAbort?.();\n item.reject(new FamiliarTerminatedError());\n }\n\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions = {}): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n return {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n async prime(): Promise<void> {\n await Promise.all(slots.map((slot) => slot.prime()));\n },\n run,\n get stats(): WorkerStats {\n return { active, completed, failed, queued: queue.size };\n },\n get status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n },\n [Symbol.asyncDispose]: () => drain(),\n [Symbol.dispose]: dispose,\n };\n}\n\nexport async function* batch<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n inputs: readonly TInput[],\n options: BatchOptions = {},\n): AsyncIterable<TOutput> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n const tasks = inputs.map((input) => pool.run(input, { ...options, signal: controller.signal }));\n\n try {\n for (const task of tasks) yield await task;\n } catch (error) {\n controller.abort(error);\n await Promise.allSettled(tasks);\n throw error;\n } finally {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort();\n await Promise.allSettled(tasks);\n }\n}\n\nexport function createTaskGroup<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n name: string | undefined = undefined,\n options: TaskGroupOptions = {},\n): TaskGroup<TInput, TOutput> {\n const controller = new AbortController();\n const tasks = new Set<Promise<TOutput>>();\n let size = 0;\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n abort(reason?: unknown): void {\n controller.abort(reason);\n },\n async drain(): Promise<PromiseSettledResult<TOutput>[]> {\n return Promise.allSettled([...tasks]);\n },\n get name() {\n return name;\n },\n get pending() {\n return tasks.size;\n },\n run(input, runOptions = {}): Promise<TOutput> {\n const task = pool.run(input, { ...runOptions, signal: controller.signal });\n\n size += 1;\n tasks.add(task);\n void task.finally(() => tasks.delete(task));\n\n return task;\n },\n get size() {\n return size;\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"_pool.cjs","names":[],"sources":["../src/_pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\nimport { createPoolCore, type PoolCore, type PoolOptions } from './_pool-core';\nimport { type QueueItem, TaskQueue } from './_queue';\nimport { FamiliarQueueFullError, FamiliarTerminatedError } from './errors';\nimport type { RunOptions, SlotStrategy, TaskGroup, TaskGroupOptions, WorkerPool } from './types';\n\nexport type { PoolOptions } from './_pool-core';\n\nexport function createPool<TInput, TOutput>(\n slots: SlotStrategy<TInput, TOutput>[],\n options: PoolOptions,\n): WorkerPool<TInput, TOutput> {\n const freeSlots = [...slots];\n const queue = new TaskQueue<TInput, TOutput>();\n let draining = false;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && queue.size === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n item.cleanupAbort?.();\n item.reject(new FamiliarTerminatedError());\n }\n },\n onDrainStart() {\n // No pending waiters to reject for the queue-based pool; capacity waiters\n // are rejected by the core's drain().\n },\n });\n\n function nextItem(): QueueItem<TInput, TOutput> | undefined {\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n if (item.signal?.aborted) {\n item.cleanupAbort?.();\n item.reject(abortError(item.signal));\n core.releaseCapacity();\n continue;\n }\n\n return item;\n }\n\n core.settleIdle();\n\n return undefined;\n }\n\n function drainQueue(): void {\n if (draining || core.disposed) return;\n\n draining = true;\n\n while (!core.disposed && freeSlots.length > 0 && queue.size > 0) {\n const next = nextItem();\n\n if (!next) break;\n\n const item = next;\n const slot = freeSlots.pop()!;\n const timeout = item.timeout ?? options.defaultTimeout;\n\n core.trackActive(1);\n core.releaseCapacity();\n\n const onAbort = () => slot.cancel(abortError(item.signal!));\n\n item.cleanupAbort = () => {\n item.signal?.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n item.signal?.addEventListener('abort', onAbort, { once: true });\n\n slot.run(item.input, item.transferables, timeout).then(\n (value) => finish(value),\n (error: unknown) => fail(error),\n );\n\n function finish(value: TOutput): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n core.trackActive(-1);\n core.trackCompleted();\n item.resolve(value);\n drainQueue();\n core.settleIdle();\n }\n\n function fail(error: unknown): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n core.trackActive(-1);\n\n if (!(error instanceof FamiliarTerminatedError) && error instanceof Error && error.name !== 'AbortError')\n core.trackFailed();\n\n item.reject(error);\n drainQueue();\n core.settleIdle();\n }\n }\n\n draining = false;\n }\n\n async function run(input: TInput, runOptions: RunOptions = {}): Promise<TOutput> {\n const { priority = 0, signal, timeout, transferables = [] } = runOptions;\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n\n while (options.onFull === 'wait' && options.maxQueue !== undefined && queue.size >= options.maxQueue) {\n await core.waitForCapacity(signal);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n }\n\n let resolve!: (value: TOutput) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<TOutput>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const item: QueueItem<TInput, TOutput> = { input, priority, reject, resolve, signal, timeout, transferables };\n\n if (!queue.enqueue(item, options.onFull === 'wait' ? undefined : options.maxQueue)) {\n throw new FamiliarQueueFullError(options.maxQueue!);\n }\n\n if (signal) {\n const onAbort = () => {\n if (!queue.remove(item)) return;\n\n item.cleanupAbort?.();\n reject(abortError(signal));\n core.releaseCapacity();\n core.settleIdle();\n };\n\n item.cleanupAbort = () => {\n signal.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n\n drainQueue();\n\n return promise;\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n async prime(): Promise<void> {\n await core.prime(slots);\n },\n run,\n get stats() {\n return core.stats(queue.size);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n\nexport async function* batch<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n inputs: readonly TInput[],\n options: RunOptions = {},\n): AsyncIterable<TOutput> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n const tasks = inputs.map((input) => pool.run(input, { ...options, signal: controller.signal }));\n\n try {\n for (const task of tasks) yield await task;\n } catch (error) {\n controller.abort(error);\n await Promise.allSettled(tasks);\n throw error;\n } finally {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort();\n await Promise.allSettled(tasks);\n }\n}\n\nexport function createTaskGroup<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n name: string | undefined = undefined,\n options: TaskGroupOptions = {},\n): TaskGroup<TInput, TOutput> {\n const controller = new AbortController();\n const tasks = new Set<Promise<TOutput>>();\n let size = 0;\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n abort(reason?: unknown): void {\n controller.abort(reason);\n },\n async drain(): Promise<PromiseSettledResult<TOutput>[]> {\n return Promise.allSettled([...tasks]);\n },\n get name() {\n return name;\n },\n get pending() {\n return tasks.size;\n },\n run(input, runOptions = {}): Promise<TOutput> {\n const task = pool.run(input, { ...runOptions, signal: controller.signal });\n\n size += 1;\n tasks.add(task);\n void task.finally(() => tasks.delete(task));\n\n return task;\n },\n get size() {\n return size;\n },\n };\n}\n"],"mappings":"iIAQA,SAAgB,EACd,EACA,EAC6B,CAC7B,IAAM,EAAY,CAAC,GAAG,CAAK,EACrB,EAAQ,IAAI,EAAA,UACd,EAAW,GAIT,EAAiB,EAAA,eAAe,CACpC,WAH4B,EAAU,SAAW,EAAM,QAAU,EAAM,OAAS,EAIhF,WAAY,CACV,IAAK,IAAM,KAAQ,EAAO,EAAK,UAAU,EAEzC,KAAO,EAAM,KAAO,GAAG,CACrB,IAAM,EAAO,EAAM,MAAM,EAEzB,GAAI,CAAC,EAAM,MAEX,EAAK,eAAe,EACpB,EAAK,OAAO,IAAI,EAAA,uBAAyB,CAC3C,CACF,EACA,cAAe,CAGf,CACF,CAAC,EAED,SAAS,GAAmD,CAC1D,KAAO,EAAM,KAAO,GAAG,CACrB,IAAM,EAAO,EAAM,MAAM,EAEzB,GAAI,CAAC,EAAM,MAEX,GAAI,EAAK,QAAQ,QAAS,CACxB,EAAK,eAAe,EACpB,EAAK,QAAA,EAAO,EAAA,WAAA,CAAW,EAAK,MAAM,CAAC,EACnC,EAAK,gBAAgB,EACrB,QACF,CAEA,OAAO,CACT,CAEA,EAAK,WAAW,CAGlB,CAEA,SAAS,GAAmB,CACtB,QAAY,EAAK,UAIrB,KAFA,EAAW,GAEJ,CAAC,EAAK,UAAY,EAAU,OAAS,GAAK,EAAM,KAAO,GAAG,CAC/D,IAAM,EAAO,EAAS,EAEtB,GAAI,CAAC,EAAM,MAEX,IAAM,EAAO,EACP,EAAO,EAAU,IAAI,EACrB,EAAU,EAAK,SAAW,EAAQ,eAExC,EAAK,YAAY,CAAC,EAClB,EAAK,gBAAgB,EAErB,IAAM,MAAgB,EAAK,QAAA,EAAO,EAAA,WAAA,CAAW,EAAK,MAAO,CAAC,EAE1D,EAAK,iBAAqB,CACxB,EAAK,QAAQ,oBAAoB,QAAS,CAAO,EACjD,EAAK,aAAe,IAAA,EACtB,EACA,EAAK,QAAQ,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,EAE9D,EAAK,IAAI,EAAK,MAAO,EAAK,cAAe,CAAO,CAAC,CAAC,KAC/C,GAAU,EAAO,CAAK,EACtB,GAAmB,EAAK,CAAK,CAChC,EAEA,SAAS,EAAO,EAAsB,CACpC,EAAK,eAAe,EACpB,EAAU,KAAK,CAAI,EACnB,EAAK,YAAY,EAAE,EACnB,EAAK,eAAe,EACpB,EAAK,QAAQ,CAAK,EAClB,EAAW,EACX,EAAK,WAAW,CAClB,CAEA,SAAS,EAAK,EAAsB,CAClC,EAAK,eAAe,EACpB,EAAU,KAAK,CAAI,EACnB,EAAK,YAAY,EAAE,EAEf,EAAE,aAAiB,EAAA,0BAA4B,aAAiB,OAAS,EAAM,OAAS,cAC1F,EAAK,YAAY,EAEnB,EAAK,OAAO,CAAK,EACjB,EAAW,EACX,EAAK,WAAW,CAClB,CACF,CAEA,EAAW,EAFX,CAGF,CAEA,eAAe,EAAI,EAAe,EAAyB,CAAC,EAAqB,CAC/E,GAAM,CAAE,WAAW,EAAG,SAAQ,UAAS,gBAAgB,CAAC,GAAM,EAE9D,GAAI,EAAK,SAAU,MAAM,IAAI,EAAA,wBAE7B,GAAI,EAAK,aAAc,MAAM,IAAI,EAAA,wBAAwB,oBAAoB,EAE7E,GAAI,GAAQ,QAAS,MAAA,EAAM,EAAA,WAAA,CAAW,CAAM,EAE5C,KAAO,EAAQ,SAAW,QAAU,EAAQ,WAAa,IAAA,IAAa,EAAM,MAAQ,EAAQ,UAAU,CAGpG,GAFA,MAAM,EAAK,gBAAgB,CAAM,EAE7B,EAAK,SAAU,MAAM,IAAI,EAAA,wBAE7B,GAAI,EAAK,aAAc,MAAM,IAAI,EAAA,wBAAwB,oBAAoB,EAE7E,GAAI,GAAQ,QAAS,MAAA,EAAM,EAAA,WAAA,CAAW,CAAM,CAC9C,CAEA,IAAI,EACA,EACE,EAAU,IAAI,SAAkB,EAAK,IAAQ,CACjD,EAAU,EACV,EAAS,CACX,CAAC,EACK,EAAmC,CAAE,QAAO,WAAU,SAAQ,UAAS,SAAQ,UAAS,eAAc,EAE5G,GAAI,CAAC,EAAM,QAAQ,EAAM,EAAQ,SAAW,OAAS,IAAA,GAAY,EAAQ,QAAQ,EAC/E,MAAM,IAAI,EAAA,uBAAuB,EAAQ,QAAS,EAGpD,GAAI,EAAQ,CACV,IAAM,MAAgB,CACf,EAAM,OAAO,CAAI,IAEtB,EAAK,eAAe,EACpB,GAAA,EAAO,EAAA,WAAA,CAAW,CAAM,CAAC,EACzB,EAAK,gBAAgB,EACrB,EAAK,WAAW,EAClB,EAEA,EAAK,iBAAqB,CACxB,EAAO,oBAAoB,QAAS,CAAO,EAC3C,EAAK,aAAe,IAAA,EACtB,EACA,EAAO,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,CAC1D,CAIA,OAFA,EAAW,EAEJ,CACT,CAEA,MAAO,CACL,IAAI,gBAAiB,CACnB,OAAO,EAAK,cACd,EACA,QAAS,EAAK,QACd,IAAI,UAAW,CACb,OAAO,EAAK,QACd,EACA,MAAO,EAAK,MACZ,MAAM,OAAuB,CAC3B,MAAM,EAAK,MAAM,CAAK,CACxB,EACA,MACA,IAAI,OAAQ,CACV,OAAO,EAAK,MAAM,EAAM,IAAI,CAC9B,EACA,IAAI,QAAS,CACX,OAAO,EAAK,OAAO,CACrB,GACC,OAAO,kBAAqB,EAAK,MAAM,CAAC,CAAC,GACzC,OAAO,SAAU,EAAK,OACzB,CACF,CAEA,eAAuB,EACrB,EACA,EACA,EAAsB,CAAC,EACC,CACxB,IAAM,EAAa,IAAI,gBACjB,MAAgB,EAAW,MAAM,EAAQ,QAAQ,MAAM,EAE7D,EAAQ,QAAQ,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,EAEjE,IAAM,EAAQ,EAAO,IAAK,GAAU,EAAK,IAAI,EAAO,CAAE,GAAG,EAAS,OAAQ,EAAW,MAAO,CAAC,CAAC,EAE9F,GAAI,CACF,IAAK,IAAM,KAAQ,EAAO,MAAM,MAAM,CACxC,OAAS,EAAO,CAGd,MAFA,EAAW,MAAM,CAAK,EACtB,MAAM,QAAQ,WAAW,CAAK,EACxB,CACR,QAAU,CACR,EAAQ,QAAQ,oBAAoB,QAAS,CAAO,EACpD,EAAW,MAAM,EACjB,MAAM,QAAQ,WAAW,CAAK,CAChC,CACF,CAEA,SAAgB,EACd,EACA,EAA2B,IAAA,GAC3B,EAA4B,CAAC,EACD,CAC5B,IAAM,EAAa,IAAI,gBACjB,EAAQ,IAAI,IACd,EAAO,EAKX,OAFA,EAAQ,QAAQ,iBAAiB,YAFX,EAAW,MAAM,EAAQ,QAAQ,MAAM,EAEV,CAAE,KAAM,EAAK,CAAC,EAE1D,CACL,MAAM,EAAwB,CAC5B,EAAW,MAAM,CAAM,CACzB,EACA,MAAM,OAAkD,CACtD,OAAO,QAAQ,WAAW,CAAC,GAAG,CAAK,CAAC,CACtC,EACA,IAAI,MAAO,CACT,OAAO,CACT,EACA,IAAI,SAAU,CACZ,OAAO,EAAM,IACf,EACA,IAAI,EAAO,EAAa,CAAC,EAAqB,CAC5C,IAAM,EAAO,EAAK,IAAI,EAAO,CAAE,GAAG,EAAY,OAAQ,EAAW,MAAO,CAAC,EAMzE,MAJA,IAAQ,EACR,EAAM,IAAI,CAAI,EACd,EAAU,YAAc,EAAM,OAAO,CAAI,CAAC,EAEnC,CACT,EACA,IAAI,MAAO,CACT,OAAO,CACT,CACF,CACF"}
|
package/dist/_pool.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
defaultTimeout: number | undefined;
|
|
5
|
-
maxQueue: number | undefined;
|
|
6
|
-
onFull: 'reject' | 'wait';
|
|
7
|
-
};
|
|
1
|
+
import { type PoolOptions } from './_pool-core';
|
|
2
|
+
import type { RunOptions, SlotStrategy, TaskGroup, TaskGroupOptions, WorkerPool } from './types';
|
|
3
|
+
export type { PoolOptions } from './_pool-core';
|
|
8
4
|
export declare function createPool<TInput, TOutput>(slots: SlotStrategy<TInput, TOutput>[], options: PoolOptions): WorkerPool<TInput, TOutput>;
|
|
9
|
-
export declare function batch<TInput, TOutput>(pool: WorkerPool<TInput, TOutput>, inputs: readonly TInput[], options?:
|
|
5
|
+
export declare function batch<TInput, TOutput>(pool: WorkerPool<TInput, TOutput>, inputs: readonly TInput[], options?: RunOptions): AsyncIterable<TOutput>;
|
|
10
6
|
export declare function createTaskGroup<TInput, TOutput>(pool: WorkerPool<TInput, TOutput>, name?: string | undefined, options?: TaskGroupOptions): TaskGroup<TInput, TOutput>;
|
|
11
7
|
//# sourceMappingURL=_pool.d.ts.map
|
package/dist/_pool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_pool.d.ts","sourceRoot":"","sources":["../src/_pool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"_pool.d.ts","sourceRoot":"","sources":["../src/_pool.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAG/E,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEjG,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EACxC,KAAK,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACtC,OAAO,EAAE,WAAW,GACnB,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAoL7B;AAED,wBAAuB,KAAK,CAAC,MAAM,EAAE,OAAO,EAC1C,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,OAAO,GAAE,UAAe,GACvB,aAAa,CAAC,OAAO,CAAC,CAmBxB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAC7C,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,IAAI,GAAE,MAAM,GAAG,SAAqB,EACpC,OAAO,GAAE,gBAAqB,GAC7B,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAkC5B"}
|
package/dist/_pool.js
CHANGED
|
@@ -1,164 +1,110 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { abortError as
|
|
1
|
+
import { FamiliarQueueFullError as e, FamiliarTerminatedError as t } from "./errors.js";
|
|
2
|
+
import { createPoolCore as n } from "./_pool-core.js";
|
|
3
|
+
import { TaskQueue as r } from "./_queue.js";
|
|
4
|
+
import { abortError as i } from "@vielzeug/arsenal/async";
|
|
5
5
|
//#region src/_pool.ts
|
|
6
|
-
function
|
|
7
|
-
let
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
t !== -1 && d.splice(t, 1), r(new i(e.timeout));
|
|
23
|
-
}, e.timeout), t(a.timer)), d.push(a);
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
function S() {
|
|
27
|
-
f.shift()?.resolve();
|
|
28
|
-
}
|
|
29
|
-
function C(e) {
|
|
30
|
-
for (let t of f.splice(0)) t.reject(e);
|
|
31
|
-
}
|
|
32
|
-
function w(e) {
|
|
33
|
-
return e?.aborted ? Promise.reject(a(e)) : new Promise((t, n) => {
|
|
34
|
-
let r = !1, i = {
|
|
35
|
-
cleanup() {
|
|
36
|
-
e?.removeEventListener("abort", o);
|
|
37
|
-
},
|
|
38
|
-
reject(e) {
|
|
39
|
-
if (r) return;
|
|
40
|
-
r = !0, i.cleanup();
|
|
41
|
-
let t = f.indexOf(i);
|
|
42
|
-
t !== -1 && f.splice(t, 1), n(e);
|
|
43
|
-
},
|
|
44
|
-
resolve() {
|
|
45
|
-
r || (r = !0, i.cleanup(), t());
|
|
46
|
-
}
|
|
47
|
-
}, o = () => i.reject(a(e));
|
|
48
|
-
e?.addEventListener("abort", o, { once: !0 }), f.push(i);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
function T() {
|
|
52
|
-
for (; l.size > 0;) {
|
|
53
|
-
let e = l.shift();
|
|
6
|
+
function a(a, o) {
|
|
7
|
+
let s = [...a], c = new r(), l = !1, u = n({
|
|
8
|
+
isIdle: () => s.length === a.length && c.size === 0,
|
|
9
|
+
onDispose() {
|
|
10
|
+
for (let e of a) e.terminate();
|
|
11
|
+
for (; c.size > 0;) {
|
|
12
|
+
let e = c.shift();
|
|
13
|
+
if (!e) break;
|
|
14
|
+
e.cleanupAbort?.(), e.reject(new t());
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
onDrainStart() {}
|
|
18
|
+
});
|
|
19
|
+
function d() {
|
|
20
|
+
for (; c.size > 0;) {
|
|
21
|
+
let e = c.shift();
|
|
54
22
|
if (!e) break;
|
|
55
23
|
if (e.signal?.aborted) {
|
|
56
|
-
e.cleanupAbort?.(), e.reject(
|
|
24
|
+
e.cleanupAbort?.(), e.reject(i(e.signal)), u.releaseCapacity();
|
|
57
25
|
continue;
|
|
58
26
|
}
|
|
59
27
|
return e;
|
|
60
28
|
}
|
|
61
|
-
|
|
29
|
+
u.settleIdle();
|
|
62
30
|
}
|
|
63
|
-
function
|
|
64
|
-
if (!(
|
|
65
|
-
for (
|
|
66
|
-
let e =
|
|
31
|
+
function f() {
|
|
32
|
+
if (!(l || u.disposed)) {
|
|
33
|
+
for (l = !0; !u.disposed && s.length > 0 && c.size > 0;) {
|
|
34
|
+
let e = d();
|
|
67
35
|
if (!e) break;
|
|
68
|
-
let
|
|
69
|
-
|
|
70
|
-
let
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
36
|
+
let n = e, r = s.pop(), a = n.timeout ?? o.defaultTimeout;
|
|
37
|
+
u.trackActive(1), u.releaseCapacity();
|
|
38
|
+
let c = () => r.cancel(i(n.signal));
|
|
39
|
+
n.cleanupAbort = () => {
|
|
40
|
+
n.signal?.removeEventListener("abort", c), n.cleanupAbort = void 0;
|
|
41
|
+
}, n.signal?.addEventListener("abort", c, { once: !0 }), r.run(n.input, n.transferables, a).then((e) => l(e), (e) => p(e));
|
|
74
42
|
function l(e) {
|
|
75
|
-
|
|
43
|
+
n.cleanupAbort?.(), s.push(r), u.trackActive(-1), u.trackCompleted(), n.resolve(e), f(), u.settleIdle();
|
|
76
44
|
}
|
|
77
|
-
function
|
|
78
|
-
|
|
45
|
+
function p(e) {
|
|
46
|
+
n.cleanupAbort?.(), s.push(r), u.trackActive(-1), !(e instanceof t) && e instanceof Error && e.name !== "AbortError" && u.trackFailed(), n.reject(e), f(), u.settleIdle();
|
|
79
47
|
}
|
|
80
48
|
}
|
|
81
|
-
|
|
49
|
+
l = !1;
|
|
82
50
|
}
|
|
83
51
|
}
|
|
84
|
-
async function
|
|
85
|
-
let { priority:
|
|
86
|
-
if (
|
|
87
|
-
if (
|
|
88
|
-
if (
|
|
89
|
-
for (;
|
|
90
|
-
if (await
|
|
91
|
-
if (
|
|
92
|
-
if (
|
|
52
|
+
async function p(n, r = {}) {
|
|
53
|
+
let { priority: a = 0, signal: s, timeout: l, transferables: d = [] } = r;
|
|
54
|
+
if (u.disposed) throw new t();
|
|
55
|
+
if (u.drainPromise) throw new t("Worker is draining");
|
|
56
|
+
if (s?.aborted) throw i(s);
|
|
57
|
+
for (; o.onFull === "wait" && o.maxQueue !== void 0 && c.size >= o.maxQueue;) {
|
|
58
|
+
if (await u.waitForCapacity(s), u.disposed) throw new t();
|
|
59
|
+
if (u.drainPromise) throw new t("Worker is draining");
|
|
60
|
+
if (s?.aborted) throw i(s);
|
|
93
61
|
}
|
|
94
|
-
let
|
|
95
|
-
|
|
96
|
-
}),
|
|
97
|
-
input:
|
|
98
|
-
priority:
|
|
99
|
-
reject:
|
|
100
|
-
resolve:
|
|
101
|
-
signal:
|
|
102
|
-
timeout:
|
|
103
|
-
transferables:
|
|
62
|
+
let p, m, h = new Promise((e, t) => {
|
|
63
|
+
p = e, m = t;
|
|
64
|
+
}), g = {
|
|
65
|
+
input: n,
|
|
66
|
+
priority: a,
|
|
67
|
+
reject: m,
|
|
68
|
+
resolve: p,
|
|
69
|
+
signal: s,
|
|
70
|
+
timeout: l,
|
|
71
|
+
transferables: d
|
|
104
72
|
};
|
|
105
|
-
if (!
|
|
106
|
-
if (
|
|
73
|
+
if (!c.enqueue(g, o.onFull === "wait" ? void 0 : o.maxQueue)) throw new e(o.maxQueue);
|
|
74
|
+
if (s) {
|
|
107
75
|
let e = () => {
|
|
108
|
-
|
|
76
|
+
c.remove(g) && (g.cleanupAbort?.(), m(i(s)), u.releaseCapacity(), u.settleIdle());
|
|
109
77
|
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
},
|
|
113
|
-
}
|
|
114
|
-
return E(), p;
|
|
115
|
-
}
|
|
116
|
-
function O() {
|
|
117
|
-
if (!v) {
|
|
118
|
-
v = !0, u.abort();
|
|
119
|
-
for (let e of o) e.terminate();
|
|
120
|
-
for (; l.size > 0;) {
|
|
121
|
-
let e = l.shift();
|
|
122
|
-
if (!e) break;
|
|
123
|
-
e.cleanupAbort?.(), e.reject(new r());
|
|
124
|
-
}
|
|
125
|
-
C(new r()), b();
|
|
78
|
+
g.cleanupAbort = () => {
|
|
79
|
+
s.removeEventListener("abort", e), g.cleanupAbort = void 0;
|
|
80
|
+
}, s.addEventListener("abort", e, { once: !0 });
|
|
126
81
|
}
|
|
127
|
-
|
|
128
|
-
function k(e = {}) {
|
|
129
|
-
return v ? Promise.resolve() : g || (C(new r("Worker is draining")), g = x(e).then(() => O(), (e) => {
|
|
130
|
-
throw O(), e;
|
|
131
|
-
}), g);
|
|
82
|
+
return f(), h;
|
|
132
83
|
}
|
|
133
84
|
return {
|
|
134
85
|
get disposalSignal() {
|
|
135
|
-
return u.
|
|
86
|
+
return u.disposalSignal;
|
|
136
87
|
},
|
|
137
|
-
dispose:
|
|
88
|
+
dispose: u.dispose,
|
|
138
89
|
get disposed() {
|
|
139
|
-
return
|
|
90
|
+
return u.disposed;
|
|
140
91
|
},
|
|
141
|
-
drain:
|
|
92
|
+
drain: u.drain,
|
|
142
93
|
async prime() {
|
|
143
|
-
await
|
|
94
|
+
await u.prime(a);
|
|
144
95
|
},
|
|
145
|
-
run:
|
|
96
|
+
run: p,
|
|
146
97
|
get stats() {
|
|
147
|
-
return
|
|
148
|
-
active: p,
|
|
149
|
-
completed: m,
|
|
150
|
-
failed: h,
|
|
151
|
-
queued: l.size
|
|
152
|
-
};
|
|
98
|
+
return u.stats(c.size);
|
|
153
99
|
},
|
|
154
100
|
get status() {
|
|
155
|
-
return
|
|
101
|
+
return u.status();
|
|
156
102
|
},
|
|
157
|
-
[Symbol.asyncDispose]: () =>
|
|
158
|
-
[Symbol.dispose]:
|
|
103
|
+
[Symbol.asyncDispose]: () => u.drain({}),
|
|
104
|
+
[Symbol.dispose]: u.dispose
|
|
159
105
|
};
|
|
160
106
|
}
|
|
161
|
-
async function*
|
|
107
|
+
async function* o(e, t, n = {}) {
|
|
162
108
|
let r = new AbortController(), i = () => r.abort(n.signal?.reason);
|
|
163
109
|
n.signal?.addEventListener("abort", i, { once: !0 });
|
|
164
110
|
let a = t.map((t) => e.run(t, {
|
|
@@ -173,7 +119,7 @@ async function* s(e, t, n = {}) {
|
|
|
173
119
|
n.signal?.removeEventListener("abort", i), r.abort(), await Promise.allSettled(a);
|
|
174
120
|
}
|
|
175
121
|
}
|
|
176
|
-
function
|
|
122
|
+
function s(e, t = void 0, n = {}) {
|
|
177
123
|
let r = new AbortController(), i = /* @__PURE__ */ new Set(), a = 0;
|
|
178
124
|
return n.signal?.addEventListener("abort", () => r.abort(n.signal?.reason), { once: !0 }), {
|
|
179
125
|
abort(e) {
|
|
@@ -201,6 +147,6 @@ function c(e, t = void 0, n = {}) {
|
|
|
201
147
|
};
|
|
202
148
|
}
|
|
203
149
|
//#endregion
|
|
204
|
-
export {
|
|
150
|
+
export { o as batch, a as createPool, s as createTaskGroup };
|
|
205
151
|
|
|
206
152
|
//# sourceMappingURL=_pool.js.map
|