@vielzeug/familiar 2.0.0 → 2.0.1

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.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./_queue.cjs"),n=require("./_timers.cjs");let r=require("@vielzeug/arsenal/async");function i(i,a){let o=[...i],s=new t.TaskQueue,c=new AbortController,l=[],u=[],d=0,f=0,p=0,m,h=!1,g=!1;function _(){return d===0&&s.size===0}function v(){if(_())for(let e of l.splice(0))e.timer&&clearTimeout(e.timer),e.resolve()}function y(t={}){return _()?Promise.resolve():new Promise((r,i)=>{let a={reject:i,resolve:r};t.timeout!==void 0&&(a.timer=setTimeout(()=>{let n=l.indexOf(a);n!==-1&&l.splice(n,1),i(new e.FamiliarTimeoutError(t.timeout))},t.timeout),n.unrefTimer(a.timer)),l.push(a)})}function b(){u.shift()?.resolve()}function x(e){for(let t of u.splice(0))t.reject(e)}function S(e){return e?.aborted?Promise.reject((0,r.abortError)(e)):new Promise((t,n)=>{let i=!1,a={cleanup(){e?.removeEventListener(`abort`,o)},reject(e){if(i)return;i=!0,a.cleanup();let t=u.indexOf(a);t!==-1&&u.splice(t,1),n(e)},resolve(){i||(i=!0,a.cleanup(),t())}},o=()=>a.reject((0,r.abortError)(e));e?.addEventListener(`abort`,o,{once:!0}),u.push(a)})}function C(){for(;s.size>0;){let e=s.shift();if(!e)break;if(e.signal?.aborted){e.cleanupAbort?.(),e.reject((0,r.abortError)(e.signal)),b();continue}return e}v()}function w(){if(!(h||g)){for(h=!0;!g&&o.length>0&&s.size>0;){let i=C();if(!i)break;let s=i,c=o.pop(),l=s.timeout??a.defaultTimeout;d+=1,b();let u=()=>c.cancel((0,r.abortError)(s.signal));s.cleanupAbort=()=>{s.signal?.removeEventListener(`abort`,u),s.cleanupAbort=void 0},s.signal?.addEventListener(`abort`,u,{once:!0}),c.run(s.input,s.transferables,l).then(e=>t(e),e=>n(e));function t(e){s.cleanupAbort?.(),o.push(c),--d,f+=1,s.resolve(e),w(),v()}function n(t){s.cleanupAbort?.(),o.push(c),--d,!(t instanceof e.FamiliarTerminatedError)&&t?.constructor?.name!==`AbortError`&&(p+=1),s.reject(t),w(),v()}}h=!1}}async function T(t,n={}){let{priority:i=0,signal:o,timeout:c,transferables:l=[]}=n;if(g)throw new e.FamiliarTerminatedError;if(m)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 S(o),g)throw new e.FamiliarTerminatedError;if(m)throw new e.FamiliarTerminatedError(`Worker is draining`);if(o?.aborted)throw(0,r.abortError)(o)}let u,d,f=new Promise((e,t)=>{u=e,d=t}),p={input:t,priority:i,reject:d,resolve:u,signal:o,timeout:c,transferables:l};if(!s.enqueue(p,a.onFull===`wait`?void 0:a.maxQueue))throw new e.FamiliarQueueFullError(a.maxQueue);if(o){let e=()=>{s.remove(p)&&(p.cleanupAbort?.(),d((0,r.abortError)(o)),b(),v())};p.cleanupAbort=()=>{o.removeEventListener(`abort`,e),p.cleanupAbort=void 0},o.addEventListener(`abort`,e,{once:!0})}return w(),f}function E(){if(!g){g=!0,c.abort();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)}x(new e.FamiliarTerminatedError),v()}}function D(t={}){return g?Promise.resolve():m||(x(new e.FamiliarTerminatedError(`Worker is draining`)),m=y(t).then(()=>E(),e=>{throw E(),e}),m)}return{get disposalSignal(){return c.signal},dispose:E,get disposed(){return g},drain:D,async prime(){await Promise.all(i.map(e=>e.prime()))},run:T,get stats(){return{active:d,completed:f,failed:p,queued:s.size}},get status(){return g?`terminated`:d===0?`idle`:`running`},[Symbol.asyncDispose]:()=>D(),[Symbol.dispose]:E}}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;
1
+ const e=require("./_queue.cjs"),t=require("./_timers.cjs"),n=require("./errors.cjs");let r=require("@vielzeug/arsenal/async");function i(i,a){let o=[...i],s=new e.TaskQueue,c=new AbortController,l=[],u=[],d=0,f=0,p=0,m,h=!1,g=!1;function _(){return d===0&&s.size===0}function v(){if(_())for(let e of l.splice(0))e.timer&&clearTimeout(e.timer),e.resolve()}function y(e={}){return _()?Promise.resolve():new Promise((r,i)=>{let a={reject:i,resolve:r};e.timeout!==void 0&&(a.timer=setTimeout(()=>{let t=l.indexOf(a);t!==-1&&l.splice(t,1),i(new n.FamiliarTimeoutError(e.timeout))},e.timeout),t.unrefTimer(a.timer)),l.push(a)})}function b(){u.shift()?.resolve()}function x(e){for(let t of u.splice(0))t.reject(e)}function S(e){return e?.aborted?Promise.reject((0,r.abortError)(e)):new Promise((t,n)=>{let i=!1,a={cleanup(){e?.removeEventListener(`abort`,o)},reject(e){if(i)return;i=!0,a.cleanup();let t=u.indexOf(a);t!==-1&&u.splice(t,1),n(e)},resolve(){i||(i=!0,a.cleanup(),t())}},o=()=>a.reject((0,r.abortError)(e));e?.addEventListener(`abort`,o,{once:!0}),u.push(a)})}function C(){for(;s.size>0;){let e=s.shift();if(!e)break;if(e.signal?.aborted){e.cleanupAbort?.(),e.reject((0,r.abortError)(e.signal)),b();continue}return e}v()}function w(){if(!(h||g)){for(h=!0;!g&&o.length>0&&s.size>0;){let i=C();if(!i)break;let s=i,c=o.pop(),l=s.timeout??a.defaultTimeout;d+=1,b();let u=()=>c.cancel((0,r.abortError)(s.signal));s.cleanupAbort=()=>{s.signal?.removeEventListener(`abort`,u),s.cleanupAbort=void 0},s.signal?.addEventListener(`abort`,u,{once:!0}),c.run(s.input,s.transferables,l).then(t=>e(t),e=>t(e));function e(e){s.cleanupAbort?.(),o.push(c),--d,f+=1,s.resolve(e),w(),v()}function t(e){s.cleanupAbort?.(),o.push(c),--d,!(e instanceof n.FamiliarTerminatedError)&&e?.constructor?.name!==`AbortError`&&(p+=1),s.reject(e),w(),v()}}h=!1}}async function T(e,t={}){let{priority:i=0,signal:o,timeout:c,transferables:l=[]}=t;if(g)throw new n.FamiliarTerminatedError;if(m)throw new n.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 S(o),g)throw new n.FamiliarTerminatedError;if(m)throw new n.FamiliarTerminatedError(`Worker is draining`);if(o?.aborted)throw(0,r.abortError)(o)}let u,d,f=new Promise((e,t)=>{u=e,d=t}),p={input:e,priority:i,reject:d,resolve:u,signal:o,timeout:c,transferables:l};if(!s.enqueue(p,a.onFull===`wait`?void 0:a.maxQueue))throw new n.FamiliarQueueFullError(a.maxQueue);if(o){let e=()=>{s.remove(p)&&(p.cleanupAbort?.(),d((0,r.abortError)(o)),b(),v())};p.cleanupAbort=()=>{o.removeEventListener(`abort`,e),p.cleanupAbort=void 0},o.addEventListener(`abort`,e,{once:!0})}return w(),f}function E(){if(!g){g=!0,c.abort();for(let e of i)e.terminate();for(;s.size>0;){let e=s.shift();if(!e)break;e.cleanupAbort?.(),e.reject(new n.FamiliarTerminatedError)}x(new n.FamiliarTerminatedError),v()}}function D(e={}){return g?Promise.resolve():m||(x(new n.FamiliarTerminatedError(`Worker is draining`)),m=y(e).then(()=>E(),e=>{throw E(),e}),m)}return{get disposalSignal(){return c.signal},dispose:E,get disposed(){return g},drain:D,async prime(){await Promise.all(i.map(e=>e.prime()))},run:T,get stats(){return{active:d,completed:f,failed:p,queued:s.size}},get status(){return g?`terminated`:d===0?`idle`:`running`},[Symbol.asyncDispose]:()=>D(),[Symbol.dispose]:E}}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
@@ -1 +1 @@
1
- {"version":3,"file":"_pool.cjs","names":[],"sources":["../src/_pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type {\n BatchOptions,\n DrainOptions,\n RunOptions,\n SlotStrategy,\n TaskGroup,\n TaskGroupOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\n\nimport { type QueueItem, TaskQueue } from './_queue';\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\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 { 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 +1 @@
1
- {"version":3,"file":"_pool.d.ts","sourceRoot":"","sources":["../src/_pool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EAGZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,UAAU,EAGX,MAAM,SAAS,CAAC;AAMjB,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,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,CA2R7B;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,YAAiB,GACzB,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"}
1
+ {"version":3,"file":"_pool.d.ts","sourceRoot":"","sources":["../src/_pool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EAGZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,UAAU,EAGX,MAAM,SAAS,CAAC;AAEjB,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,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,CA2R7B;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,YAAiB,GACzB,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,10 +1,10 @@
1
- import { FamiliarQueueFullError as e, FamiliarTerminatedError as t, FamiliarTimeoutError as n } from "./errors.js";
2
- import { TaskQueue as r } from "./_queue.js";
3
- import { unrefTimer as i } from "./_timers.js";
1
+ import { TaskQueue as e } from "./_queue.js";
2
+ import { unrefTimer as t } from "./_timers.js";
3
+ import { FamiliarQueueFullError as n, FamiliarTerminatedError as r, FamiliarTimeoutError as i } from "./errors.js";
4
4
  import { abortError as a } from "@vielzeug/arsenal/async";
5
5
  //#region src/_pool.ts
6
6
  function o(o, s) {
7
- let c = [...o], l = new r(), u = new AbortController(), d = [], f = [], p = 0, m = 0, h = 0, g, _ = !1, v = !1;
7
+ let c = [...o], l = new e(), u = new AbortController(), d = [], f = [], p = 0, m = 0, h = 0, g, _ = !1, v = !1;
8
8
  function y() {
9
9
  return p === 0 && l.size === 0;
10
10
  }
@@ -12,15 +12,15 @@ function o(o, s) {
12
12
  if (y()) for (let e of d.splice(0)) e.timer && clearTimeout(e.timer), e.resolve();
13
13
  }
14
14
  function x(e = {}) {
15
- return y() ? Promise.resolve() : new Promise((t, r) => {
15
+ return y() ? Promise.resolve() : new Promise((n, r) => {
16
16
  let a = {
17
17
  reject: r,
18
- resolve: t
18
+ resolve: n
19
19
  };
20
20
  e.timeout !== void 0 && (a.timer = setTimeout(() => {
21
21
  let t = d.indexOf(a);
22
- t !== -1 && d.splice(t, 1), r(new n(e.timeout));
23
- }, e.timeout), i(a.timer)), d.push(a);
22
+ t !== -1 && d.splice(t, 1), r(new i(e.timeout));
23
+ }, e.timeout), t(a.timer)), d.push(a);
24
24
  });
25
25
  }
26
26
  function S() {
@@ -65,36 +65,36 @@ function o(o, s) {
65
65
  for (_ = !0; !v && c.length > 0 && l.size > 0;) {
66
66
  let e = T();
67
67
  if (!e) break;
68
- let n = e, r = c.pop(), i = n.timeout ?? s.defaultTimeout;
68
+ let t = e, n = c.pop(), i = t.timeout ?? s.defaultTimeout;
69
69
  p += 1, S();
70
- let o = () => r.cancel(a(n.signal));
71
- n.cleanupAbort = () => {
72
- n.signal?.removeEventListener("abort", o), n.cleanupAbort = void 0;
73
- }, n.signal?.addEventListener("abort", o, { once: !0 }), r.run(n.input, n.transferables, i).then((e) => l(e), (e) => u(e));
70
+ let o = () => n.cancel(a(t.signal));
71
+ t.cleanupAbort = () => {
72
+ t.signal?.removeEventListener("abort", o), t.cleanupAbort = void 0;
73
+ }, t.signal?.addEventListener("abort", o, { once: !0 }), n.run(t.input, t.transferables, i).then((e) => l(e), (e) => u(e));
74
74
  function l(e) {
75
- n.cleanupAbort?.(), c.push(r), --p, m += 1, n.resolve(e), E(), b();
75
+ t.cleanupAbort?.(), c.push(n), --p, m += 1, t.resolve(e), E(), b();
76
76
  }
77
77
  function u(e) {
78
- n.cleanupAbort?.(), c.push(r), --p, !(e instanceof t) && e?.constructor?.name !== "AbortError" && (h += 1), n.reject(e), E(), b();
78
+ t.cleanupAbort?.(), c.push(n), --p, !(e instanceof r) && e?.constructor?.name !== "AbortError" && (h += 1), t.reject(e), E(), b();
79
79
  }
80
80
  }
81
81
  _ = !1;
82
82
  }
83
83
  }
84
- async function D(n, r = {}) {
85
- let { priority: i = 0, signal: o, timeout: c, transferables: u = [] } = r;
86
- if (v) throw new t();
87
- if (g) throw new t("Worker is draining");
84
+ async function D(e, t = {}) {
85
+ let { priority: i = 0, signal: o, timeout: c, transferables: u = [] } = t;
86
+ if (v) throw new r();
87
+ if (g) throw new r("Worker is draining");
88
88
  if (o?.aborted) throw a(o);
89
89
  for (; s.onFull === "wait" && s.maxQueue !== void 0 && l.size >= s.maxQueue;) {
90
- if (await w(o), v) throw new t();
91
- if (g) throw new t("Worker is draining");
90
+ if (await w(o), v) throw new r();
91
+ if (g) throw new r("Worker is draining");
92
92
  if (o?.aborted) throw a(o);
93
93
  }
94
94
  let d, f, p = new Promise((e, t) => {
95
95
  d = e, f = t;
96
96
  }), m = {
97
- input: n,
97
+ input: e,
98
98
  priority: i,
99
99
  reject: f,
100
100
  resolve: d,
@@ -102,7 +102,7 @@ function o(o, s) {
102
102
  timeout: c,
103
103
  transferables: u
104
104
  };
105
- if (!l.enqueue(m, s.onFull === "wait" ? void 0 : s.maxQueue)) throw new e(s.maxQueue);
105
+ if (!l.enqueue(m, s.onFull === "wait" ? void 0 : s.maxQueue)) throw new n(s.maxQueue);
106
106
  if (o) {
107
107
  let e = () => {
108
108
  l.remove(m) && (m.cleanupAbort?.(), f(a(o)), S(), b());
@@ -120,13 +120,13 @@ function o(o, s) {
120
120
  for (; l.size > 0;) {
121
121
  let e = l.shift();
122
122
  if (!e) break;
123
- e.cleanupAbort?.(), e.reject(new t());
123
+ e.cleanupAbort?.(), e.reject(new r());
124
124
  }
125
- C(new t()), b();
125
+ C(new r()), b();
126
126
  }
127
127
  }
128
128
  function k(e = {}) {
129
- return v ? Promise.resolve() : g || (C(new t("Worker is draining")), g = x(e).then(() => O(), (e) => {
129
+ return v ? Promise.resolve() : g || (C(new r("Worker is draining")), g = x(e).then(() => O(), (e) => {
130
130
  throw O(), e;
131
131
  }), g);
132
132
  }
@@ -159,7 +159,7 @@ function o(o, s) {
159
159
  };
160
160
  }
161
161
  async function* s(e, t, n = {}) {
162
- let r = new AbortController(), i = () => r.abort(n.signal.reason);
162
+ let r = new AbortController(), i = () => r.abort(n.signal?.reason);
163
163
  n.signal?.addEventListener("abort", i, { once: !0 });
164
164
  let a = t.map((t) => e.run(t, {
165
165
  ...n,
@@ -175,7 +175,7 @@ async function* s(e, t, n = {}) {
175
175
  }
176
176
  function c(e, t = void 0, n = {}) {
177
177
  let r = new AbortController(), i = /* @__PURE__ */ new Set(), a = 0;
178
- return n.signal?.addEventListener("abort", () => r.abort(n.signal.reason), { once: !0 }), {
178
+ return n.signal?.addEventListener("abort", () => r.abort(n.signal?.reason), { once: !0 }), {
179
179
  abort(e) {
180
180
  r.abort(e);
181
181
  },
package/dist/_pool.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"_pool.js","names":[],"sources":["../src/_pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type {\n BatchOptions,\n DrainOptions,\n RunOptions,\n SlotStrategy,\n TaskGroup,\n TaskGroupOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\n\nimport { type QueueItem, TaskQueue } from './_queue';\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\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.js","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,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./_timers.cjs");let n=require("@vielzeug/arsenal/async");function r(r,i){let a=[...r],o=[],s=[],c=new AbortController,l=[],u=0,d=0,f=0,p=0,m=!1,h;function g(){return u===0&&o.length===0}function _(){if(g())for(let e of l.splice(0))e()}function v(n){return g()?Promise.resolve():new Promise((r,i)=>{if(l.push(r),n.timeout!==void 0){let a=setTimeout(()=>{let t=l.indexOf(r);t!==-1&&l.splice(t,1),i(new e.FamiliarTimeoutError(n.timeout))},n.timeout);t.unrefTimer(a)}})}function y(){s.shift()?.resolve()}function b(e){for(let t of s.splice(0))t.reject(e)}function x(e){return e?.aborted?Promise.reject((0,n.abortError)(e)):new Promise((t,r)=>{let i=!1,a={cleanup(){e?.removeEventListener(`abort`,o)},reject(e){if(i)return;i=!0,a.cleanup();let t=s.indexOf(a);t!==-1&&s.splice(t,1),r(e)},resolve(){i||(i=!0,a.cleanup(),t())}},o=()=>a.reject((0,n.abortError)(e));e?.addEventListener(`abort`,o,{once:!0}),s.push(a)})}function S(e){let t=o.shift();t?(t.resolve(e),y()):a.push(e)}async function C(t){if(m)throw new e.FamiliarTerminatedError;if(h)throw new e.FamiliarTerminatedError(`Worker is draining`);if(t.signal?.aborted)throw(0,n.abortError)(t.signal);for(;i.maxQueue!==void 0&&o.length>=i.maxQueue;){if(i.onFull===`reject`)throw new e.FamiliarQueueFullError(i.maxQueue);if(await x(t.signal),m)throw new e.FamiliarTerminatedError;if(h)throw new e.FamiliarTerminatedError(`Worker is draining`);if(t.signal?.aborted)throw(0,n.abortError)(t.signal)}return a.pop()||new Promise((e,r)=>{let i={cleanup(){i.signal?.removeEventListener(`abort`,a)},priority:t.priority??0,reject(e){i.cleanup();let t=o.indexOf(i);t!==-1&&(o.splice(t,1),y()),r(e),_()},resolve(t){i.cleanup(),e(t)},sequence:p++,signal:t.signal},a=()=>i.reject((0,n.abortError)(i.signal));i.signal?.addEventListener(`abort`,a,{once:!0}),o.push(i),o.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}function w(){if(!m){m=!0,c.abort();for(let e of r)e.terminate();for(let t of o.splice(0))t.reject(new e.FamiliarTerminatedError);b(new e.FamiliarTerminatedError),_()}}function T(t={}){if(m)return Promise.resolve();if(h)return h;for(let t of o.splice(0))t.reject(new e.FamiliarTerminatedError(`Worker is draining`));return b(new e.FamiliarTerminatedError(`Worker is draining`)),h=v(t).then(()=>w(),e=>{throw w(),e}),h}return{get disposalSignal(){return c.signal},dispose:w,get disposed(){return m},drain:T,async prime(){await Promise.all(r.map(e=>e.prime()))},runStream(t,r={}){let a=new AbortController,o=()=>a.abort(r.signal.reason);return r.signal?.addEventListener(`abort`,o,{once:!0}),{[Symbol.asyncIterator]:async function*(){let s,c;try{s=await C({...r,signal:a.signal}),u+=1,c=()=>s?.cancel((0,n.abortError)(a.signal)),a.signal.addEventListener(`abort`,c,{once:!0});let e=s.stream(t,{...r,signal:a.signal,timeout:r.timeout??i.defaultTimeout});for await(let t of e.iterable)yield t;await e.done,d+=1}catch(t){throw t?.constructor?.name!==`AbortError`&&!(t instanceof e.FamiliarTerminatedError)&&(f+=1),t}finally{r.signal?.removeEventListener(`abort`,o),s&&(c&&a.signal.removeEventListener(`abort`,c),--u,S(s),_())}}}},get stats(){return{active:u,completed:d,failed:f,queued:o.length}},get status(){return m?`terminated`:u===0?`idle`:`running`},[Symbol.asyncDispose]:()=>T(),[Symbol.dispose]:w}}exports.createStreamPool=r;
1
+ const e=require("./_timers.cjs"),t=require("./errors.cjs");let n=require("@vielzeug/arsenal/async");function r(r,i){let a=[...r],o=[],s=[],c=new AbortController,l=[],u=0,d=0,f=0,p=0,m=!1,h;function g(){return u===0&&o.length===0}function _(){if(g())for(let e of l.splice(0))e()}function v(n){return g()?Promise.resolve():new Promise((r,i)=>{if(l.push(r),n.timeout!==void 0){let a=setTimeout(()=>{let e=l.indexOf(r);e!==-1&&l.splice(e,1),i(new t.FamiliarTimeoutError(n.timeout))},n.timeout);e.unrefTimer(a)}})}function y(){s.shift()?.resolve()}function b(e){for(let t of s.splice(0))t.reject(e)}function x(e){return e?.aborted?Promise.reject((0,n.abortError)(e)):new Promise((t,r)=>{let i=!1,a={cleanup(){e?.removeEventListener(`abort`,o)},reject(e){if(i)return;i=!0,a.cleanup();let t=s.indexOf(a);t!==-1&&s.splice(t,1),r(e)},resolve(){i||(i=!0,a.cleanup(),t())}},o=()=>a.reject((0,n.abortError)(e));e?.addEventListener(`abort`,o,{once:!0}),s.push(a)})}function S(e){let t=o.shift();t?(t.resolve(e),y()):a.push(e)}async function C(e){if(m)throw new t.FamiliarTerminatedError;if(h)throw new t.FamiliarTerminatedError(`Worker is draining`);if(e.signal?.aborted)throw(0,n.abortError)(e.signal);for(;i.maxQueue!==void 0&&o.length>=i.maxQueue;){if(i.onFull===`reject`)throw new t.FamiliarQueueFullError(i.maxQueue);if(await x(e.signal),m)throw new t.FamiliarTerminatedError;if(h)throw new t.FamiliarTerminatedError(`Worker is draining`);if(e.signal?.aborted)throw(0,n.abortError)(e.signal)}return a.pop()||new Promise((t,r)=>{let i={cleanup(){i.signal?.removeEventListener(`abort`,a)},priority:e.priority??0,reject(e){i.cleanup();let t=o.indexOf(i);t!==-1&&(o.splice(t,1),y()),r(e),_()},resolve(e){i.cleanup(),t(e)},sequence:p++,signal:e.signal},a=()=>i.reject((0,n.abortError)(i.signal));i.signal?.addEventListener(`abort`,a,{once:!0}),o.push(i),o.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}function w(){if(!m){m=!0,c.abort();for(let e of r)e.terminate();for(let e of o.splice(0))e.reject(new t.FamiliarTerminatedError);b(new t.FamiliarTerminatedError),_()}}function T(e={}){if(m)return Promise.resolve();if(h)return h;for(let e of o.splice(0))e.reject(new t.FamiliarTerminatedError(`Worker is draining`));return b(new t.FamiliarTerminatedError(`Worker is draining`)),h=v(e).then(()=>w(),e=>{throw w(),e}),h}return{get disposalSignal(){return c.signal},dispose:w,get disposed(){return m},drain:T,async prime(){await Promise.all(r.map(e=>e.prime()))},runStream(e,r={}){let a=new AbortController,o=()=>a.abort(r.signal?.reason);return r.signal?.addEventListener(`abort`,o,{once:!0}),{[Symbol.asyncIterator]:async function*(){let s,c;try{s=await C({...r,signal:a.signal}),u+=1,c=()=>s?.cancel((0,n.abortError)(a.signal)),a.signal.addEventListener(`abort`,c,{once:!0});let t=s.stream(e,{...r,signal:a.signal,timeout:r.timeout??i.defaultTimeout});for await(let e of t.iterable)yield e;await t.done,d+=1}catch(e){throw e?.constructor?.name!==`AbortError`&&!(e instanceof t.FamiliarTerminatedError)&&(f+=1),e}finally{r.signal?.removeEventListener(`abort`,o),s&&(c&&a.signal.removeEventListener(`abort`,c),--u,S(s),_())}}}},get stats(){return{active:u,completed:d,failed:f,queued:o.length}},get status(){return m?`terminated`:u===0?`idle`:`running`},[Symbol.asyncDispose]:()=>T(),[Symbol.dispose]:w}}exports.createStreamPool=r;
2
2
  //# sourceMappingURL=_stream-pool.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"_stream-pool.cjs","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type { PoolOptions } from './_pool';\nimport type { DrainOptions, RunOptions, StreamWorkerPool, WorkerStats, WorkerStatus } from './types';\nimport type { RunningStream } from './worker';\n\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n prime(): Promise<void>;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const disposalController = new AbortController();\n const idleWaiters: Array<() => void> = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let sequence = 0;\n let terminated = false;\n let drainPromise: Promise<void> | undefined;\n\n function idle(): boolean {\n return active === 0 && waiters.length === 0;\n }\n\n function settleIdle(): void {\n if (!idle()) return;\n\n for (const resolve of idleWaiters.splice(0)) resolve();\n }\n\n function waitForIdle(options: DrainOptions): Promise<void> {\n if (idle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n idleWaiters.push(resolve);\n\n if (options.timeout !== undefined) {\n const timer = setTimeout(() => {\n const index = idleWaiters.indexOf(resolve);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(options.timeout!));\n }, options.timeout);\n\n unrefTimer(timer);\n }\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 release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(runOptions.signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n releaseCapacity();\n }\n\n reject(reason);\n settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\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 for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\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 for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\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 runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(runOptions.signal!.reason);\n\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n [Symbol.asyncIterator]: async function* () {\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n try {\n slot = await acquire({ ...runOptions, signal: controller.signal });\n active += 1;\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, {\n ...runOptions,\n signal: controller.signal,\n timeout: runOptions.timeout ?? options.defaultTimeout,\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n completed += 1;\n } catch (error) {\n if (error?.constructor?.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError)) failed += 1;\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n active -= 1;\n release(slot);\n settleIdle();\n }\n }\n },\n };\n },\n get stats(): WorkerStats {\n return { active, completed, failed, queued: waiters.length };\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"],"mappings":"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"}
1
+ {"version":3,"file":"_stream-pool.cjs","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type { PoolOptions } from './_pool';\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type { DrainOptions, RunOptions, StreamWorkerPool, WorkerStats, WorkerStatus } from './types';\nimport type { RunningStream } from './worker';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n prime(): Promise<void>;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const disposalController = new AbortController();\n const idleWaiters: Array<() => void> = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let sequence = 0;\n let terminated = false;\n let drainPromise: Promise<void> | undefined;\n\n function idle(): boolean {\n return active === 0 && waiters.length === 0;\n }\n\n function settleIdle(): void {\n if (!idle()) return;\n\n for (const resolve of idleWaiters.splice(0)) resolve();\n }\n\n function waitForIdle(options: DrainOptions): Promise<void> {\n if (idle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n idleWaiters.push(resolve);\n\n if (options.timeout !== undefined) {\n const timer = setTimeout(() => {\n const index = idleWaiters.indexOf(resolve);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(options.timeout!));\n }, options.timeout);\n\n unrefTimer(timer);\n }\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 release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(runOptions.signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n releaseCapacity();\n }\n\n reject(reason);\n settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\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 for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\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 for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\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 runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(runOptions.signal?.reason);\n\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n [Symbol.asyncIterator]: async function* () {\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n try {\n slot = await acquire({ ...runOptions, signal: controller.signal });\n active += 1;\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, {\n ...runOptions,\n signal: controller.signal,\n timeout: runOptions.timeout ?? options.defaultTimeout,\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n completed += 1;\n } catch (error) {\n if (error?.constructor?.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError)) failed += 1;\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n active -= 1;\n release(slot);\n settleIdle();\n }\n }\n },\n };\n },\n get stats(): WorkerStats {\n return { active, completed, failed, queued: waiters.length };\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"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"_stream-pool.d.ts","sourceRoot":"","sources":["../src/_stream-pool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAgB,UAAU,EAAE,gBAAgB,EAA6B,MAAM,SAAS,CAAC;AACrG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAK9C,MAAM,MAAM,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI;IACvC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClE,SAAS,IAAI,IAAI,CAAC;CACnB,CAAC;AAiBF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAC7C,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EACnC,OAAO,EAAE,WAAW,GACnB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CA2PlC"}
1
+ {"version":3,"file":"_stream-pool.d.ts","sourceRoot":"","sources":["../src/_stream-pool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,OAAO,KAAK,EAAgB,UAAU,EAAE,gBAAgB,EAA6B,MAAM,SAAS,CAAC;AACrG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,MAAM,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI;IACvC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClE,SAAS,IAAI,IAAI,CAAC;CACnB,CAAC;AAiBF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAC7C,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EACnC,OAAO,EAAE,WAAW,GACnB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CA2PlC"}
@@ -1,5 +1,5 @@
1
- import { FamiliarQueueFullError as e, FamiliarTerminatedError as t, FamiliarTimeoutError as n } from "./errors.js";
2
- import { unrefTimer as r } from "./_timers.js";
1
+ import { unrefTimer as e } from "./_timers.js";
2
+ import { FamiliarQueueFullError as t, FamiliarTerminatedError as n, FamiliarTimeoutError as r } from "./errors.js";
3
3
  import { abortError as i } from "@vielzeug/arsenal/async";
4
4
  //#region src/_stream-pool.ts
5
5
  function a(a, o) {
@@ -10,14 +10,14 @@ function a(a, o) {
10
10
  function y() {
11
11
  if (v()) for (let e of d.splice(0)) e();
12
12
  }
13
- function b(e) {
14
- return v() ? Promise.resolve() : new Promise((t, i) => {
15
- if (d.push(t), e.timeout !== void 0) {
13
+ function b(t) {
14
+ return v() ? Promise.resolve() : new Promise((n, i) => {
15
+ if (d.push(n), t.timeout !== void 0) {
16
16
  let a = setTimeout(() => {
17
- let r = d.indexOf(t);
18
- r !== -1 && d.splice(r, 1), i(new n(e.timeout));
19
- }, e.timeout);
20
- r(a);
17
+ let e = d.indexOf(n);
18
+ e !== -1 && d.splice(e, 1), i(new r(t.timeout));
19
+ }, t.timeout);
20
+ e(a);
21
21
  }
22
22
  });
23
23
  }
@@ -50,32 +50,32 @@ function a(a, o) {
50
50
  let t = c.shift();
51
51
  t ? (t.resolve(e), x()) : s.push(e);
52
52
  }
53
- async function T(n) {
54
- if (g) throw new t();
55
- if (_) throw new t("Worker is draining");
56
- if (n.signal?.aborted) throw i(n.signal);
53
+ async function T(e) {
54
+ if (g) throw new n();
55
+ if (_) throw new n("Worker is draining");
56
+ if (e.signal?.aborted) throw i(e.signal);
57
57
  for (; o.maxQueue !== void 0 && c.length >= o.maxQueue;) {
58
- if (o.onFull === "reject") throw new e(o.maxQueue);
59
- if (await C(n.signal), g) throw new t();
60
- if (_) throw new t("Worker is draining");
61
- if (n.signal?.aborted) throw i(n.signal);
58
+ if (o.onFull === "reject") throw new t(o.maxQueue);
59
+ if (await C(e.signal), g) throw new n();
60
+ if (_) throw new n("Worker is draining");
61
+ if (e.signal?.aborted) throw i(e.signal);
62
62
  }
63
- return s.pop() || new Promise((e, t) => {
63
+ return s.pop() || new Promise((t, n) => {
64
64
  let r = {
65
65
  cleanup() {
66
66
  r.signal?.removeEventListener("abort", a);
67
67
  },
68
- priority: n.priority ?? 0,
68
+ priority: e.priority ?? 0,
69
69
  reject(e) {
70
70
  r.cleanup();
71
- let n = c.indexOf(r);
72
- n !== -1 && (c.splice(n, 1), x()), t(e), y();
71
+ let t = c.indexOf(r);
72
+ t !== -1 && (c.splice(t, 1), x()), n(e), y();
73
73
  },
74
- resolve(t) {
75
- r.cleanup(), e(t);
74
+ resolve(e) {
75
+ r.cleanup(), t(e);
76
76
  },
77
77
  sequence: h++,
78
- signal: n.signal
78
+ signal: e.signal
79
79
  }, a = () => r.reject(i(r.signal));
80
80
  r.signal?.addEventListener("abort", a, { once: !0 }), c.push(r), c.sort((e, t) => t.priority - e.priority || e.sequence - t.sequence);
81
81
  });
@@ -84,15 +84,15 @@ function a(a, o) {
84
84
  if (!g) {
85
85
  g = !0, u.abort();
86
86
  for (let e of a) e.terminate();
87
- for (let e of c.splice(0)) e.reject(new t());
88
- S(new t()), y();
87
+ for (let e of c.splice(0)) e.reject(new n());
88
+ S(new n()), y();
89
89
  }
90
90
  }
91
91
  function D(e = {}) {
92
92
  if (g) return Promise.resolve();
93
93
  if (_) return _;
94
- for (let e of c.splice(0)) e.reject(new t("Worker is draining"));
95
- return S(new t("Worker is draining")), _ = b(e).then(() => E(), (e) => {
94
+ for (let e of c.splice(0)) e.reject(new n("Worker is draining"));
95
+ return S(new n("Worker is draining")), _ = b(e).then(() => E(), (e) => {
96
96
  throw E(), e;
97
97
  }), _;
98
98
  }
@@ -108,26 +108,26 @@ function a(a, o) {
108
108
  async prime() {
109
109
  await Promise.all(a.map((e) => e.prime()));
110
110
  },
111
- runStream(e, n = {}) {
112
- let r = new AbortController(), a = () => r.abort(n.signal.reason);
113
- return n.signal?.addEventListener("abort", a, { once: !0 }), { [Symbol.asyncIterator]: async function* () {
111
+ runStream(e, t = {}) {
112
+ let r = new AbortController(), a = () => r.abort(t.signal?.reason);
113
+ return t.signal?.addEventListener("abort", a, { once: !0 }), { [Symbol.asyncIterator]: async function* () {
114
114
  let s, c;
115
115
  try {
116
116
  s = await T({
117
- ...n,
117
+ ...t,
118
118
  signal: r.signal
119
119
  }), f += 1, c = () => s?.cancel(i(r.signal)), r.signal.addEventListener("abort", c, { once: !0 });
120
- let t = s.stream(e, {
121
- ...n,
120
+ let n = s.stream(e, {
121
+ ...t,
122
122
  signal: r.signal,
123
- timeout: n.timeout ?? o.defaultTimeout
123
+ timeout: t.timeout ?? o.defaultTimeout
124
124
  });
125
- for await (let e of t.iterable) yield e;
126
- await t.done, p += 1;
125
+ for await (let e of n.iterable) yield e;
126
+ await n.done, p += 1;
127
127
  } catch (e) {
128
- throw e?.constructor?.name !== "AbortError" && !(e instanceof t) && (m += 1), e;
128
+ throw e?.constructor?.name !== "AbortError" && !(e instanceof n) && (m += 1), e;
129
129
  } finally {
130
- n.signal?.removeEventListener("abort", a), s && (c && r.signal.removeEventListener("abort", c), --f, w(s), y());
130
+ t.signal?.removeEventListener("abort", a), s && (c && r.signal.removeEventListener("abort", c), --f, w(s), y());
131
131
  }
132
132
  } };
133
133
  },
@@ -1 +1 @@
1
- {"version":3,"file":"_stream-pool.js","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type { PoolOptions } from './_pool';\nimport type { DrainOptions, RunOptions, StreamWorkerPool, WorkerStats, WorkerStatus } from './types';\nimport type { RunningStream } from './worker';\n\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n prime(): Promise<void>;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const disposalController = new AbortController();\n const idleWaiters: Array<() => void> = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let sequence = 0;\n let terminated = false;\n let drainPromise: Promise<void> | undefined;\n\n function idle(): boolean {\n return active === 0 && waiters.length === 0;\n }\n\n function settleIdle(): void {\n if (!idle()) return;\n\n for (const resolve of idleWaiters.splice(0)) resolve();\n }\n\n function waitForIdle(options: DrainOptions): Promise<void> {\n if (idle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n idleWaiters.push(resolve);\n\n if (options.timeout !== undefined) {\n const timer = setTimeout(() => {\n const index = idleWaiters.indexOf(resolve);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(options.timeout!));\n }, options.timeout);\n\n unrefTimer(timer);\n }\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 release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(runOptions.signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n releaseCapacity();\n }\n\n reject(reason);\n settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\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 for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\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 for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\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 runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(runOptions.signal!.reason);\n\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n [Symbol.asyncIterator]: async function* () {\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n try {\n slot = await acquire({ ...runOptions, signal: controller.signal });\n active += 1;\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, {\n ...runOptions,\n signal: controller.signal,\n timeout: runOptions.timeout ?? options.defaultTimeout,\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n completed += 1;\n } catch (error) {\n if (error?.constructor?.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError)) failed += 1;\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n active -= 1;\n release(slot);\n settleIdle();\n }\n }\n },\n };\n },\n get stats(): WorkerStats {\n return { active, completed, failed, queued: waiters.length };\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"],"mappings":"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"}
1
+ {"version":3,"file":"_stream-pool.js","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type { PoolOptions } from './_pool';\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type { DrainOptions, RunOptions, StreamWorkerPool, WorkerStats, WorkerStatus } from './types';\nimport type { RunningStream } from './worker';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n prime(): Promise<void>;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const disposalController = new AbortController();\n const idleWaiters: Array<() => void> = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let sequence = 0;\n let terminated = false;\n let drainPromise: Promise<void> | undefined;\n\n function idle(): boolean {\n return active === 0 && waiters.length === 0;\n }\n\n function settleIdle(): void {\n if (!idle()) return;\n\n for (const resolve of idleWaiters.splice(0)) resolve();\n }\n\n function waitForIdle(options: DrainOptions): Promise<void> {\n if (idle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n idleWaiters.push(resolve);\n\n if (options.timeout !== undefined) {\n const timer = setTimeout(() => {\n const index = idleWaiters.indexOf(resolve);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(options.timeout!));\n }, options.timeout);\n\n unrefTimer(timer);\n }\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 release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(runOptions.signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n releaseCapacity();\n }\n\n reject(reason);\n settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\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 for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\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 for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\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 runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(runOptions.signal?.reason);\n\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n [Symbol.asyncIterator]: async function* () {\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n try {\n slot = await acquire({ ...runOptions, signal: controller.signal });\n active += 1;\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, {\n ...runOptions,\n signal: controller.signal,\n timeout: runOptions.timeout ?? options.defaultTimeout,\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n completed += 1;\n } catch (error) {\n if (error?.constructor?.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError)) failed += 1;\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n active -= 1;\n release(slot);\n settleIdle();\n }\n }\n },\n };\n },\n get stats(): WorkerStats {\n return { active, completed, failed, queued: waiters.length };\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"],"mappings":"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"}