@vielzeug/familiar 2.2.0 → 26.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -11
- package/dist/_pool-core.cjs +1 -1
- package/dist/_pool-core.cjs.map +1 -1
- package/dist/_pool-core.d.ts +43 -22
- package/dist/_pool-core.d.ts.map +1 -1
- package/dist/_pool-core.js +1 -104
- package/dist/_pool-core.js.map +1 -1
- package/dist/_pool.cjs +1 -1
- package/dist/_pool.cjs.map +1 -1
- package/dist/_pool.d.ts +9 -6
- package/dist/_pool.d.ts.map +1 -1
- package/dist/_pool.js +1 -151
- package/dist/_pool.js.map +1 -1
- package/dist/_stream-pool.cjs +1 -1
- package/dist/_stream-pool.cjs.map +1 -1
- package/dist/_stream-pool.d.ts +10 -6
- package/dist/_stream-pool.d.ts.map +1 -1
- package/dist/_stream-pool.js +1 -97
- package/dist/_stream-pool.js.map +1 -1
- package/dist/_timers.cjs +1 -1
- package/dist/_timers.cjs.map +1 -1
- package/dist/_timers.js +1 -7
- package/dist/_timers.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -23
- package/dist/errors.js.map +1 -1
- package/dist/familiar.cjs +1 -1
- package/dist/familiar.cjs.map +1 -1
- package/dist/familiar.iife.js +1 -1
- package/dist/familiar.iife.js.map +1 -1
- package/dist/familiar.js +1 -1
- package/dist/familiar.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -4
- package/dist/protocol.cjs +1 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.ts +1 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +1 -67
- package/dist/protocol.js.map +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/testing.cjs +1 -1
- package/dist/testing/testing.cjs.map +1 -1
- package/dist/testing/testing.d.ts +4 -4
- package/dist/testing/testing.d.ts.map +1 -1
- package/dist/testing/testing.js +1 -75
- package/dist/testing/testing.js.map +1 -1
- package/dist/testing.js +1 -3
- package/dist/types.d.ts +18 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.ts +1 -8
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +1 -178
- package/dist/worker.js.map +1 -1
- package/package.json +11 -9
- package/dist/_dev.d.ts +0 -2
- package/dist/_dev.d.ts.map +0 -1
- package/dist/_queue.cjs +0 -2
- package/dist/_queue.cjs.map +0 -1
- package/dist/_queue.d.ts +0 -19
- package/dist/_queue.d.ts.map +0 -1
- package/dist/_queue.js +0 -51
- package/dist/_queue.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"familiar.iife.js","names":["#heap","#live","#sequence","#siftUp","#extract","#siftDown","#before","#onSlotError","#url","#worker","#settlePending","#disposed","#ensureWorker","#dispatch","#pending","#taskId","#onMessage"],"sources":["../../arsenal/dist/async/abortError.js","../src/_timers.ts","../src/errors.ts","../src/_pool-core.ts","../src/_queue.ts","../src/_pool.ts","../src/_stream-pool.ts","../src/worker.ts"],"sourcesContent":["//#region src/async/abortError.ts\nfunction e(e) {\n\treturn e?.reason ?? new DOMException(\"Aborted\", \"AbortError\");\n}\n//#endregion\nexport { e as abortError };\n\n//# sourceMappingURL=abortError.js.map","/**\n * Node compatibility helper: `unref()`s a timer so a pending per-task timeout/watchdog does not\n * keep a Node event loop (e.g. a Worker polyfill) alive. Browsers return a plain number from\n * `setTimeout`/`setInterval`, so this is a no-op there.\n *\n * Not part of the public API surface.\n */\nexport function unrefTimer(timer: ReturnType<typeof setTimeout> | ReturnType<typeof setInterval>): void {\n if (typeof timer === 'object' && timer !== null && 'unref' in timer) {\n (timer as { unref(): void }).unref();\n }\n}\n","/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when invalid options are passed to a Familiar pool factory. */\nexport class FamiliarInvalidOptionsError extends FamiliarError {}\n\n/** Thrown when run() is called and the queue is full (`onFull='reject'`). */\nexport class FamiliarQueueFullError extends FamiliarError {\n /** The configured `maxQueue` value. */\n readonly maxQueue: number;\n\n constructor(maxQueue: number) {\n super(`Queue is full (maxQueue=${maxQueue})`);\n this.maxQueue = maxQueue;\n }\n}\n\n/** Thrown when the task function throws. The original error is available as `.cause`. */\nexport class FamiliarTaskError extends FamiliarError {}\n\n/** Thrown when a task or operation is rejected because the worker was terminated. */\nexport class FamiliarTerminatedError extends FamiliarError {\n constructor(message = 'Worker was terminated') {\n super(message);\n }\n}\n\n/** Thrown when a task exceeds its timeout or `drain()` times out. */\nexport class FamiliarTimeoutError extends FamiliarError {\n /** The configured timeout in milliseconds. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number) {\n super(`Task timed out after ${timeoutMs}ms`);\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */\nexport class FamiliarRuntimeError extends FamiliarError {}\n","import { abortError } from '@vielzeug/arsenal/async';\nimport { unrefTimer } from './_timers';\nimport { FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type { DrainOptions, WorkerStats, WorkerStatus } from './types';\n\nexport type PoolOptions = {\n concurrency: number;\n defaultTimeout: number | undefined;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n};\n\ntype IdleWaiter = {\n reject: (reason: unknown) => void;\n resolve: () => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\nexport interface PoolCore {\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n drain(options: DrainOptions): Promise<void>;\n readonly drainPromise: Promise<void> | undefined;\n isIdle(): boolean;\n prime(slots: readonly { prime(): Promise<void> }[]): Promise<void>;\n rejectCapacity(reason: unknown): void;\n releaseCapacity(): void;\n settleIdle(): void;\n stats(queued: number): WorkerStats;\n status(): WorkerStatus;\n trackActive(delta: number): void;\n trackCompleted(): void;\n trackFailed(): void;\n waitForCapacity(signal: AbortSignal | undefined): Promise<void>;\n waitForIdle(options: DrainOptions): Promise<void>;\n}\n\n/**\n * Shared disposal controller, idle/capacity waiters, drain, and stats tracking\n * used by both the single-result pool (`_pool.ts`) and the stream pool\n * (`_stream-pool.ts`). Each pool provides its own `isIdle` predicate and\n * `onDispose`/`onDrainStart` hooks to flush pool-specific pending work.\n */\nexport function createPoolCore(options: {\n isIdle: () => boolean;\n onDispose: () => void;\n onDrainStart: () => void;\n}): PoolCore {\n const disposalController = new AbortController();\n const idleWaiters: IdleWaiter[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let drainPromise: Promise<void> | undefined;\n let terminated = false;\n\n function settleIdle(): void {\n if (!options.isIdle()) return;\n\n for (const waiter of idleWaiters.splice(0)) {\n if (waiter.timer) clearTimeout(waiter.timer);\n\n waiter.resolve();\n }\n }\n\n function waitForIdle(drainOptions: DrainOptions): Promise<void> {\n if (options.isIdle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n const waiter: IdleWaiter = { reject, resolve };\n\n if (drainOptions.timeout !== undefined) {\n waiter.timer = setTimeout(() => {\n const index = idleWaiters.indexOf(waiter);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(drainOptions.timeout!));\n }, drainOptions.timeout);\n unrefTimer(waiter.timer);\n }\n\n idleWaiters.push(waiter);\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n options.onDispose();\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n options.onDrainStart();\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n function prime(slots: readonly { prime(): Promise<void> }[]): Promise<void> {\n return Promise.all(slots.map((slot) => slot.prime())).then(() => undefined);\n }\n\n function trackActive(delta: number): void {\n active += delta;\n }\n\n function trackCompleted(): void {\n completed += 1;\n }\n\n function trackFailed(): void {\n failed += 1;\n }\n\n function stats(queued: number): WorkerStats {\n return { active, completed, failed, queued };\n }\n\n function status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n }\n\n return {\n disposalSignal: disposalController.signal,\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n get drainPromise() {\n return drainPromise;\n },\n isIdle: options.isIdle,\n prime,\n rejectCapacity,\n releaseCapacity,\n settleIdle,\n stats,\n status,\n trackActive,\n trackCompleted,\n trackFailed,\n waitForCapacity,\n waitForIdle,\n };\n}\n","export type QueueItem<TInput, TOutput> = {\n cancelled?: boolean;\n cleanupAbort?: () => void;\n input: TInput;\n priority: number;\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n signal?: AbortSignal;\n timeout?: number;\n transferables: Transferable[];\n};\n\ntype Entry<TInput, TOutput> = { readonly item: QueueItem<TInput, TOutput>; readonly sequence: number };\n\nexport class TaskQueue<TInput, TOutput> {\n readonly #heap: Entry<TInput, TOutput>[] = [];\n #live = 0;\n #sequence = 0;\n\n get size(): number {\n return this.#live;\n }\n\n enqueue(item: QueueItem<TInput, TOutput>, maxSize: number | undefined): boolean {\n if (maxSize !== undefined && this.#live >= maxSize) return false;\n\n this.#heap.push({ item, sequence: this.#sequence++ });\n this.#siftUp(this.#heap.length - 1);\n this.#live += 1;\n\n return true;\n }\n\n remove(item: QueueItem<TInput, TOutput>): boolean {\n if (item.cancelled) return false;\n\n for (const entry of this.#heap) {\n if (entry.item === item) {\n item.cancelled = true;\n this.#live -= 1;\n\n return true;\n }\n }\n\n return false;\n }\n\n shift(): QueueItem<TInput, TOutput> | undefined {\n while (this.#heap.length > 0) {\n const item = this.#extract().item;\n\n if (!item.cancelled) {\n this.#live -= 1;\n\n return item;\n }\n }\n\n return undefined;\n }\n\n #extract(): Entry<TInput, TOutput> {\n const top = this.#heap[0]!;\n const last = this.#heap.pop()!;\n\n if (this.#heap.length > 0) {\n this.#heap[0] = last;\n this.#siftDown(0);\n }\n\n return top;\n }\n\n #before(a: Entry<TInput, TOutput>, b: Entry<TInput, TOutput>): boolean {\n return a.item.priority === b.item.priority ? a.sequence < b.sequence : a.item.priority > b.item.priority;\n }\n\n #siftUp(index: number): void {\n while (index > 0) {\n const parent = (index - 1) >> 1;\n\n if (!this.#before(this.#heap[index]!, this.#heap[parent]!)) return;\n\n [this.#heap[index], this.#heap[parent]] = [this.#heap[parent]!, this.#heap[index]!];\n index = parent;\n }\n }\n\n #siftDown(index: number): void {\n for (;;) {\n const left = index * 2 + 1;\n const right = left + 1;\n let next = index;\n\n if (left < this.#heap.length && this.#before(this.#heap[left]!, this.#heap[next]!)) next = left;\n\n if (right < this.#heap.length && this.#before(this.#heap[right]!, this.#heap[next]!)) next = right;\n\n if (next === index) return;\n\n [this.#heap[index], this.#heap[next]] = [this.#heap[next]!, this.#heap[index]!];\n index = next;\n }\n }\n}\n","import { abortError } from '@vielzeug/arsenal/async';\nimport { createPoolCore, type PoolCore, type PoolOptions } from './_pool-core';\nimport { type QueueItem, TaskQueue } from './_queue';\nimport { FamiliarQueueFullError, FamiliarTerminatedError } from './errors';\nimport type { RunOptions, SlotStrategy, TaskGroup, TaskGroupOptions, WorkerPool } from './types';\n\nexport type { PoolOptions } from './_pool-core';\n\nexport function createPool<TInput, TOutput>(\n slots: SlotStrategy<TInput, TOutput>[],\n options: PoolOptions,\n): WorkerPool<TInput, TOutput> {\n const freeSlots = [...slots];\n const queue = new TaskQueue<TInput, TOutput>();\n let draining = false;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && queue.size === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n item.cleanupAbort?.();\n item.reject(new FamiliarTerminatedError());\n }\n },\n onDrainStart() {\n // No pending waiters to reject for the queue-based pool; capacity waiters\n // are rejected by the core's drain().\n },\n });\n\n function nextItem(): QueueItem<TInput, TOutput> | undefined {\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n if (item.signal?.aborted) {\n item.cleanupAbort?.();\n item.reject(abortError(item.signal));\n core.releaseCapacity();\n continue;\n }\n\n return item;\n }\n\n core.settleIdle();\n\n return undefined;\n }\n\n function drainQueue(): void {\n if (draining || core.disposed) return;\n\n draining = true;\n\n while (!core.disposed && freeSlots.length > 0 && queue.size > 0) {\n const next = nextItem();\n\n if (!next) break;\n\n const item = next;\n const slot = freeSlots.pop()!;\n const timeout = item.timeout ?? options.defaultTimeout;\n\n core.trackActive(1);\n core.releaseCapacity();\n\n const onAbort = () => slot.cancel(abortError(item.signal!));\n\n item.cleanupAbort = () => {\n item.signal?.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n item.signal?.addEventListener('abort', onAbort, { once: true });\n\n slot.run(item.input, item.transferables, timeout).then(\n (value) => finish(value),\n (error: unknown) => fail(error),\n );\n\n function finish(value: TOutput): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n core.trackActive(-1);\n core.trackCompleted();\n item.resolve(value);\n drainQueue();\n core.settleIdle();\n }\n\n function fail(error: unknown): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n core.trackActive(-1);\n\n if (!(error instanceof FamiliarTerminatedError) && error instanceof Error && error.name !== 'AbortError')\n core.trackFailed();\n\n item.reject(error);\n drainQueue();\n core.settleIdle();\n }\n }\n\n draining = false;\n }\n\n async function run(input: TInput, runOptions: RunOptions = {}): Promise<TOutput> {\n const { priority = 0, signal, timeout, transferables = [] } = runOptions;\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n\n while (options.onFull === 'wait' && options.maxQueue !== undefined && queue.size >= options.maxQueue) {\n await core.waitForCapacity(signal);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n }\n\n let resolve!: (value: TOutput) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<TOutput>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const item: QueueItem<TInput, TOutput> = { input, priority, reject, resolve, signal, timeout, transferables };\n\n if (!queue.enqueue(item, options.onFull === 'wait' ? undefined : options.maxQueue)) {\n throw new FamiliarQueueFullError(options.maxQueue!);\n }\n\n if (signal) {\n const onAbort = () => {\n if (!queue.remove(item)) return;\n\n item.cleanupAbort?.();\n reject(abortError(signal));\n core.releaseCapacity();\n core.settleIdle();\n };\n\n item.cleanupAbort = () => {\n signal.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n\n drainQueue();\n\n return promise;\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n async prime(): Promise<void> {\n await core.prime(slots);\n },\n run,\n get stats() {\n return core.stats(queue.size);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n\nexport async function* batch<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n inputs: readonly TInput[],\n options: RunOptions = {},\n): AsyncIterable<TOutput> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n const tasks = inputs.map((input) => pool.run(input, { ...options, signal: controller.signal }));\n\n try {\n for (const task of tasks) yield await task;\n } catch (error) {\n controller.abort(error);\n await Promise.allSettled(tasks);\n throw error;\n } finally {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort();\n await Promise.allSettled(tasks);\n }\n}\n\nexport function createTaskGroup<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n name: string | undefined = undefined,\n options: TaskGroupOptions = {},\n): TaskGroup<TInput, TOutput> {\n const controller = new AbortController();\n const tasks = new Set<Promise<TOutput>>();\n let size = 0;\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n abort(reason?: unknown): void {\n controller.abort(reason);\n },\n async drain(): Promise<PromiseSettledResult<TOutput>[]> {\n return Promise.allSettled([...tasks]);\n },\n get name() {\n return name;\n },\n get pending() {\n return tasks.size;\n },\n run(input, runOptions = {}): Promise<TOutput> {\n const task = pool.run(input, { ...runOptions, signal: controller.signal });\n\n size += 1;\n tasks.add(task);\n void task.finally(() => tasks.delete(task));\n\n return task;\n },\n get size() {\n return size;\n },\n };\n}\n","import { abortError } from '@vielzeug/arsenal/async';\n\nimport { createPoolCore, type PoolCore, type PoolOptions } from './_pool-core';\nimport { FamiliarQueueFullError, FamiliarTerminatedError } from './errors';\nimport type { RunOptions, StreamWorkerPool } 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 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 let sequence = 0;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && waiters.length === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n },\n onDrainStart() {\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\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 core.releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.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 core.waitForCapacity(runOptions.signal);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.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 core.releaseCapacity();\n }\n\n reject(reason);\n core.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 return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n async prime(): Promise<void> {\n await core.prime(slots);\n },\n 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 core.trackActive(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 core.trackCompleted();\n } catch (error) {\n if (error instanceof Error && error.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError))\n core.trackFailed();\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 core.trackActive(-1);\n release(slot);\n core.settleIdle();\n }\n }\n },\n };\n },\n get stats() {\n return core.stats(waiters.length);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n","export { batch, createTaskGroup } from './_pool';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nexport type {\n DrainOptions,\n PoolBase,\n RunOptions,\n StreamWorkerPool,\n TaskGroup,\n TaskGroupOptions,\n WorkerOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\n\nimport { createPool } from './_pool';\nimport { createStreamPool, type StreamSlot } from './_stream-pool';\nimport { unrefTimer } from './_timers';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nimport type { SerializedError, WorkerResponse } from './protocol';\nimport { PROTOCOL_VERSION } from './protocol';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } from './types';\n\nconst MAX_CONCURRENCY = 512;\n\ntype ResolvedOptions = {\n concurrency: number;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n onSlotError: WorkerOptions['onSlotError'];\n timeout: number | undefined;\n};\n\ntype Pending<TOutput> = {\n emit?: (value: TOutput) => void;\n id: number;\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\nexport type RunningStream<TChunk> = {\n done: Promise<void>;\n iterable: AsyncIterable<TChunk>;\n};\n\nfunction resolveOptions(options: WorkerOptions = {}): ResolvedOptions {\n const { concurrency = 1, maxQueue, onFull = 'reject', onSlotError, timeout } = options;\n const resolvedConcurrency =\n concurrency === 'auto' ? Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1) : concurrency;\n\n if (!Number.isInteger(resolvedConcurrency) || resolvedConcurrency < 1 || resolvedConcurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY} or \"auto\"`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0)) {\n throw new FamiliarInvalidOptionsError('`timeout` must be a finite number greater than 0');\n }\n\n return { concurrency: resolvedConcurrency, maxQueue, onFull, onSlotError, timeout };\n}\n\nfunction isWorkerResponse<TOutput>(value: unknown): value is WorkerResponse<TOutput> {\n if (typeof value !== 'object' || value === null) return false;\n\n const response = value as Partial<WorkerResponse<TOutput>>;\n\n return (\n response.version === PROTOCOL_VERSION &&\n typeof response.id === 'number' &&\n (response.kind === 'chunk' || response.kind === 'error' || response.kind === 'result')\n );\n}\n\nfunction taskError(error: SerializedError): FamiliarTaskError {\n const cause = new Error(error.message);\n\n cause.name = error.name;\n cause.stack = error.stack;\n\n return new FamiliarTaskError(error.message, { cause });\n}\n\nclass Slot<TInput, TOutput> implements SlotStrategy<TInput, TOutput>, StreamSlot<TInput, TOutput> {\n readonly #onSlotError: WorkerOptions['onSlotError'];\n readonly #url: URL | string;\n #disposed = false;\n #pending: Pending<TOutput> | undefined;\n #taskId = 0;\n #worker: Worker | undefined;\n\n constructor(url: URL | string, onSlotError: WorkerOptions['onSlotError']) {\n this.#url = url;\n this.#onSlotError = onSlotError;\n }\n\n cancel(reason: unknown): void {\n this.#worker?.terminate();\n this.#worker = undefined;\n this.#settlePending('reject', reason);\n }\n\n prime(): Promise<void> {\n if (!this.#disposed) this.#ensureWorker();\n\n return Promise.resolve();\n }\n\n run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput> {\n return this.#dispatch(input, transferables, timeout, 'run') as Promise<TOutput>;\n }\n\n stream(input: TInput, options: RunOptions): RunningStream<TOutput> {\n const stop = () => this.cancel(new FamiliarTerminatedError('Stream consumer stopped'));\n const chunks: TOutput[] = [];\n const waiters: Array<(result: IteratorResult<TOutput>) => void> = [];\n let done = false;\n let error: unknown;\n const emit = (value: TOutput) => {\n const waiter = waiters.shift();\n\n if (waiter) waiter({ done: false, value });\n else chunks.push(value);\n };\n const finish = (reason?: unknown) => {\n done = true;\n error = reason;\n\n while (waiters.length > 0) {\n const waiter = waiters.shift()!;\n\n if (reason !== undefined) waiter(Promise.reject(reason) as never);\n else waiter({ done: true, value: undefined as never });\n }\n };\n const donePromise = this.#dispatch(input, options.transferables ?? [], options.timeout, 'stream', emit).then(\n () => finish(),\n (reason: unknown) => finish(reason),\n );\n\n return {\n done: donePromise,\n iterable: {\n [Symbol.asyncIterator]: () => ({\n async next(): Promise<IteratorResult<TOutput>> {\n if (chunks.length > 0) return { done: false, value: chunks.shift()! };\n\n if (error !== undefined) throw error;\n\n if (done) return { done: true, value: undefined as never };\n\n return new Promise<IteratorResult<TOutput>>((resolve, reject) => {\n waiters.push((result) => {\n if (result instanceof Promise) void result.then(resolve, reject);\n else resolve(result);\n });\n });\n },\n async return(): Promise<IteratorResult<TOutput>> {\n stop();\n\n return { done: true, value: undefined as never };\n },\n }),\n },\n };\n }\n\n terminate(): void {\n this.#disposed = true;\n this.cancel(new FamiliarTerminatedError());\n }\n\n #dispatch(\n input: TInput,\n transferables: Transferable[],\n timeout: number | undefined,\n kind: 'run' | 'stream',\n emit?: (value: TOutput) => void,\n ): Promise<TOutput> {\n if (this.#disposed) return Promise.reject(new FamiliarTerminatedError());\n\n if (this.#pending) return Promise.reject(new FamiliarRuntimeError('Worker slot is already busy'));\n\n try {\n const worker = this.#ensureWorker();\n const id = this.#taskId++;\n\n return new Promise<TOutput>((resolve, reject) => {\n const pending: Pending<TOutput> = { emit, id, reject, resolve };\n\n this.#pending = pending;\n\n if (timeout !== undefined) {\n pending.timer = setTimeout(() => this.cancel(new FamiliarTimeoutError(timeout)), timeout);\n unrefTimer(pending.timer);\n }\n\n try {\n worker.postMessage({ id, input, kind, version: PROTOCOL_VERSION }, transferables);\n } catch (error) {\n this.cancel(new FamiliarRuntimeError('Failed to post message to worker', { cause: error }));\n }\n });\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #ensureWorker(): Worker {\n if (this.#worker) return this.#worker;\n\n if (typeof Worker === 'undefined') throw new FamiliarRuntimeError('Worker API is unavailable in this runtime');\n\n try {\n const worker = new Worker(this.#url, { type: 'module' });\n\n worker.onmessage = (event: MessageEvent<unknown>) => this.#onMessage(event.data);\n worker.onerror = (event) => {\n const error = new FamiliarRuntimeError(event.message || 'Worker failed');\n\n this.#worker = undefined;\n this.#onSlotError?.(error);\n this.#settlePending('reject', error);\n };\n this.#worker = worker;\n\n return worker;\n } catch (error) {\n throw new FamiliarRuntimeError('Failed to create Worker', { cause: error });\n }\n }\n\n #onMessage(message: unknown): void {\n if (!this.#pending) return;\n\n if (!isWorkerResponse<TOutput>(message) || message.id !== this.#pending.id) {\n this.cancel(new FamiliarRuntimeError('Worker returned an incompatible protocol response'));\n\n return;\n }\n\n if (message.kind === 'chunk') {\n this.#pending.emit?.(message.value);\n\n return;\n }\n\n if (message.kind === 'error') {\n this.#settlePending('reject', taskError(message.error));\n\n return;\n }\n\n this.#settlePending('resolve', message.value);\n }\n\n #settlePending(kind: 'resolve' | 'reject', value: unknown): void {\n const pending = this.#pending;\n\n if (!pending) return;\n\n this.#pending = undefined;\n\n if (pending.timer) clearTimeout(pending.timer);\n\n if (kind === 'resolve') pending.resolve(value as TOutput);\n else pending.reject(value);\n }\n}\n\nfunction slots<TInput, TOutput>(url: URL | string, options: ResolvedOptions): Slot<TInput, TOutput>[] {\n return Array.from({ length: options.concurrency }, () => new Slot<TInput, TOutput>(url, options.onSlotError));\n}\n\n/** Create a pool backed by an ES module worker registered with exposeTask(). */\nexport function createWorker<TInput, TOutput>(\n url: URL | string,\n options: WorkerOptions = {},\n): WorkerPool<TInput, TOutput> {\n const resolved = resolveOptions(options);\n\n return createPool(slots<TInput, TOutput>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n\n/** Create a stream-only pool backed by an ES module worker registered with exposeStream(). */\nexport function createStreamWorker<TInput, TChunk>(\n url: URL | string,\n options: WorkerOptions = {},\n): StreamWorkerPool<TInput, TChunk> {\n const resolved = resolveOptions(options);\n\n return createStreamPool(slots<TInput, TChunk>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"familiar.iife.js","names":[],"sources":["../src/_timers.ts","../src/errors.ts","../src/_pool-core.ts","../src/_pool.ts","../src/_stream-pool.ts","../src/worker.ts"],"sourcesContent":["/**\n * Node compatibility helper: `unref()`s a timer so a pending per-task timeout/watchdog does not\n * keep a Node event loop (e.g. a Worker polyfill) alive. Browsers return a plain number from\n * `setTimeout`/`setInterval`, so this is a no-op there.\n *\n * Not part of the public API surface.\n */\nexport function unrefTimer(timer: ReturnType<typeof setTimeout> | ReturnType<typeof setInterval>): void {\n if (typeof timer === 'object' && timer !== null && 'unref' in timer) {\n (timer as { unref(): void }).unref();\n }\n}\n","/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when invalid options are passed to a Familiar pool factory. */\nexport class FamiliarInvalidOptionsError extends FamiliarError {}\n\n/** Thrown when run() is called and the queue is full (`onFull='reject'`). */\nexport class FamiliarQueueFullError extends FamiliarError {\n /** The configured `maxQueue` value. */\n readonly maxQueue: number;\n\n constructor(maxQueue: number) {\n super(`Queue is full (maxQueue=${maxQueue})`);\n this.maxQueue = maxQueue;\n }\n}\n\n/** Thrown when the task function throws. The original error is available as `.cause`. */\nexport class FamiliarTaskError extends FamiliarError {}\n\n/** Thrown when a task or operation is rejected because the worker was terminated. */\nexport class FamiliarTerminatedError extends FamiliarError {\n constructor(message = 'Worker was terminated') {\n super(message);\n }\n}\n\n/** Thrown when a task exceeds its timeout or `drain()` times out. */\nexport class FamiliarTimeoutError extends FamiliarError {\n /** The configured timeout in milliseconds. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, operation = 'Task') {\n super(`${operation} timed out after ${timeoutMs}ms`);\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */\nexport class FamiliarRuntimeError extends FamiliarError {}\n","import { abortError, tapper } from '@vielzeug/arsenal';\nimport { unrefTimer } from './_timers.js';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n type FamiliarRuntimeError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors.js';\nimport type { DrainOptions, FamiliarTapEvent, WorkerStats, WorkerStatus } from './types.js';\n\nexport const MAX_CONCURRENCY = 512;\nexport const MAX_TIMEOUT = 2_147_483_647;\n\nexport function validatePriority(priority: number): number {\n if (!Number.isFinite(priority)) throw new FamiliarInvalidOptionsError('`priority` must be a finite number');\n return priority;\n}\n\nexport function validateTimeout(timeout: number | undefined, name = 'timeout'): number | undefined {\n if (timeout !== undefined && (!Number.isInteger(timeout) || timeout < 1 || timeout > MAX_TIMEOUT)) {\n throw new FamiliarInvalidOptionsError(`\\`${name}\\` must be an integer from 1 through ${MAX_TIMEOUT}`);\n }\n return timeout;\n}\n\nexport type PoolOptions = {\n defaultTimeout: number | undefined;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n};\n\nexport type AcquireOptions = {\n priority: number;\n signal?: AbortSignal;\n};\n\n/**\n * A pool slot: tearable on disposal, with an optional channel for reporting\n * unhandled runtime errors. Pool factories wire `notify` to the core's tap so\n * slot owners can emit without holding a pool reference.\n */\nexport type PoolSlot = {\n notify?(error: FamiliarRuntimeError): void;\n terminate(): void;\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 priority: number;\n reject(reason: unknown): void;\n resolve(): void;\n sequence: number;\n};\n\ntype SlotWaiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n start(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport interface PoolCore<TSlot> {\n /**\n * Acquire a free slot and hand it to `fn`, which runs the acquired work.\n * `fn` is invoked synchronously both for an immediately free slot and when\n * a release hands the next waiter its slot, so dispatch never lags a\n * release by a microtask. Honors priority, FIFO order, abort, and `maxQueue`\n * admission; failures surface as a rejected promise. Without `fn`, resolves\n * with the slot instead.\n */\n acquire(options: AcquireOptions): Promise<TSlot>;\n acquire<R>(options: AcquireOptions, fn: (slot: TSlot) => R | Promise<R>): Promise<R>;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n drain(options?: DrainOptions): Promise<void>;\n readonly drainPromise: Promise<void> | undefined;\n emitTap(event: FamiliarTapEvent): void;\n /** Return a slot to the pool, handing it to the highest-priority waiter if any. */\n release(slot: TSlot): void;\n settleIdle(): void;\n stats(): WorkerStats;\n status(): WorkerStatus;\n tap(handler: (event: FamiliarTapEvent) => void, options?: { readonly signal?: AbortSignal }): () => void;\n trackActive(delta: number): void;\n trackCompleted(): void;\n trackFailed(): void;\n}\n\n/**\n * The single slot scheduler shared by the result pool and the stream pool:\n * free-slot fast path, priority/FIFO waiter queue, `maxQueue` admission with\n * capacity waiters, idle/drain tracking, stats, disposal, and tap observation.\n * The two pools differ only in what they do with an acquired slot.\n */\nexport function createPoolCore<TSlot extends PoolSlot>(slots: readonly TSlot[], options: PoolOptions): PoolCore<TSlot> {\n const freeSlots = [...slots];\n const waiters: SlotWaiter<TSlot>[] = [];\n const idleWaiters: IdleWaiter[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const tappers = tapper<FamiliarTapEvent>();\n const disposalController = new AbortController();\n let active = 0;\n let waiterSequence = 0;\n let capacitySequence = 0;\n let completed = 0;\n let failed = 0;\n let drainPromise: Promise<void> | undefined;\n let terminated = false;\n\n function isIdle(): boolean {\n return freeSlots.length === slots.length && waiters.length === 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!, 'Drain'));\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, priority: number): 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 priority,\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 sequence: capacitySequence++,\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n capacityWaiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\n }\n\n function acquire<R>(acquireOptions: AcquireOptions, fn?: (slot: TSlot) => R | Promise<R>): Promise<R | TSlot> {\n const { priority, signal } = acquireOptions;\n\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return (async () => {\n for (;;) {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (options.maxQueue === undefined || waiters.length < options.maxQueue) {\n return admit(acquireOptions, (fn ?? ((slot) => slot)) as (slot: TSlot) => R | Promise<R>);\n }\n\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(signal, priority);\n\n if (signal?.aborted) {\n releaseCapacity();\n throw abortError(signal);\n }\n }\n })();\n }\n\n function admit<R>(acquireOptions: AcquireOptions, fn: (slot: TSlot) => R | Promise<R>): Promise<R> {\n const { priority, signal } = acquireOptions;\n\n const free = freeSlots.pop();\n\n if (free) {\n try {\n return Promise.resolve(fn(free));\n } catch (error) {\n // A synchronous throw must not strand the slot: idle would never settle.\n release(free);\n settleIdle();\n\n return Promise.reject(error);\n }\n }\n\n return new Promise<R>((resolve, reject) => {\n const waiter: SlotWaiter<TSlot> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority,\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 sequence: waiterSequence++,\n signal,\n start(slot) {\n waiter.cleanup();\n\n try {\n resolve(fn(slot));\n } catch (error) {\n release(slot);\n settleIdle();\n reject(error);\n }\n },\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 release(slot: TSlot): void {\n const next = waiters.shift();\n\n if (next) {\n next.start(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n\n for (const slot of slots) slot.terminate();\n\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n tappers.emit({ type: 'dispose' });\n tappers.clear();\n }\n\n function drain(drainOptions: DrainOptions = {}): Promise<void> {\n if (terminated) return Promise.resolve();\n try {\n validateTimeout(drainOptions.timeout, 'drain.timeout');\n } catch (error) {\n return Promise.reject(error);\n }\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 acquire,\n disposalSignal: disposalController.signal,\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n get drainPromise() {\n return drainPromise;\n },\n emitTap(event) {\n tappers.emit(event);\n },\n release,\n settleIdle,\n stats() {\n return { active, completed, failed, queued: waiters.length + capacityWaiters.length };\n },\n status() {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n },\n tap(handler, tapOptions) {\n if (terminated) return () => undefined;\n\n return tappers.tap(handler, tapOptions);\n },\n trackActive(delta: number) {\n active += delta;\n },\n trackCompleted() {\n completed += 1;\n },\n trackFailed() {\n failed += 1;\n },\n };\n}\n","import { abortError } from '@vielzeug/arsenal';\nimport { createPoolCore, type PoolCore, type PoolOptions, validatePriority, validateTimeout } from './_pool-core.js';\nimport { FamiliarRuntimeError, FamiliarTerminatedError } from './errors.js';\nimport type { RunOptions, SlotStrategy, WorkerPool } from './types.js';\n\nexport type { PoolOptions } from './_pool-core.js';\n\nexport function createPool<TInput, TOutput>(\n slots: readonly SlotStrategy<TInput, TOutput>[],\n options: PoolOptions,\n): WorkerPool<TInput, TOutput> {\n const core: PoolCore<SlotStrategy<TInput, TOutput>> = createPoolCore(slots, options);\n\n for (const slot of slots) slot.notify = (error) => core.emitTap({ error, type: 'worker-error' });\n\n function run(input: TInput, runOptions: RunOptions = {}): Promise<TOutput> {\n let priority: number;\n let timeout: number | undefined;\n let transferables: Transferable[];\n\n try {\n priority = validatePriority(runOptions.priority ?? 0);\n timeout = validateTimeout(runOptions.timeout) ?? options.defaultTimeout;\n transferables = [...(runOptions.transferables ?? [])];\n } catch (error) {\n return Promise.reject(error);\n }\n\n return core.acquire({ priority, signal: runOptions.signal }, (slot) => {\n core.trackActive(1);\n\n const onAbort = () => slot.cancel(abortError(runOptions.signal!));\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n const finish = async (): Promise<TOutput> => {\n try {\n const value = await slot.run(input, transferables, timeout);\n\n core.trackCompleted();\n\n return value;\n } catch (error) {\n if (!runOptions.signal?.aborted && !(error instanceof FamiliarTerminatedError)) core.trackFailed();\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n core.trackActive(-1);\n core.release(slot);\n core.settleIdle();\n }\n };\n\n return finish();\n });\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n run,\n get stats() {\n return core.stats();\n },\n get status() {\n return core.status();\n },\n tap: core.tap,\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n\nexport type BatchOptions<TInput> = Pick<RunOptions, 'priority' | 'signal' | 'timeout'> & {\n getTransferables?: (input: TInput, index: number) => readonly Transferable[];\n};\n\n/** Run related tasks concurrently and yield their results in input order. */\nexport function runBatch<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n inputs: readonly TInput[],\n options: BatchOptions<TInput> = {},\n): AsyncIterable<TOutput> {\n let owner: object | undefined;\n\n const iterate = async function* (controller: AbortController): AsyncGenerator<TOutput> {\n const tasks: Promise<TOutput>[] = [];\n const onAbort = () => controller.abort(options.signal?.reason);\n\n if (options.signal?.aborted) controller.abort(options.signal.reason);\n else options.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n for (const [index, input] of inputs.entries()) {\n const task = pool\n .run(input, {\n priority: options.priority,\n signal: controller.signal,\n timeout: options.timeout,\n transferables: options.getTransferables?.(input, index),\n })\n .catch((error: unknown) => {\n controller.abort(error);\n throw error;\n });\n\n void task.catch(() => undefined);\n tasks.push(task);\n }\n\n if (tasks.length === 0 && controller.signal.aborted) throw abortError(controller.signal);\n for (const task of tasks) {\n if (controller.signal.aborted) throw abortError(controller.signal);\n const value = await task;\n if (controller.signal.aborted) throw abortError(controller.signal);\n yield value;\n }\n } catch (error) {\n controller.abort(error);\n throw error;\n } finally {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort(new DOMException('Batch consumer stopped', 'AbortError'));\n await Promise.allSettled(tasks);\n }\n };\n\n return {\n [Symbol.asyncIterator]() {\n const token = {};\n const controller = new AbortController();\n let iterator: AsyncGenerator<TOutput> | undefined;\n const start = (): AsyncGenerator<TOutput> | undefined => {\n owner ??= token;\n if (owner !== token) return undefined;\n iterator ??= iterate(controller);\n return iterator;\n };\n\n return {\n next: () =>\n start()?.next() ?? Promise.reject(new FamiliarRuntimeError('Worker batches can only be consumed once')),\n return: async (value?: unknown) => {\n if (!owner || owner !== token) return { done: true, value: value as TOutput };\n controller.abort(new FamiliarTerminatedError('Batch consumer stopped'));\n return iterator?.return(value as TOutput) ?? { done: true, value: value as TOutput };\n },\n throw: async (error?: unknown) => {\n const active = start();\n if (!active) throw new FamiliarRuntimeError('Worker batches can only be consumed once');\n controller.abort(error);\n return active.throw(error);\n },\n };\n },\n };\n}\n","import { abortError } from '@vielzeug/arsenal';\nimport { createPoolCore, type PoolCore, type PoolOptions, validatePriority, validateTimeout } from './_pool-core.js';\nimport { FamiliarRuntimeError, FamiliarTerminatedError } from './errors.js';\nimport type { RunOptions, StreamWorkerPool } from './types.js';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n /** Wired by the pool factory to report unhandled worker runtime errors through `tap()`. */\n notify?(error: FamiliarRuntimeError): void;\n stream(input: TInput, options: RunOptions): { done: Promise<void>; iterable: AsyncIterable<TChunk> };\n terminate(): void;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: readonly StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const core: PoolCore<StreamSlot<TInput, TChunk>> = createPoolCore(slots, options);\n\n for (const slot of slots) slot.notify = (error) => core.emitTap({ error, type: 'worker-error' });\n\n function runStream(input: TInput, runOptions: RunOptions = {}): AsyncIterable<TChunk> {\n const priority = validatePriority(runOptions.priority ?? 0);\n const timeout = validateTimeout(runOptions.timeout) ?? options.defaultTimeout;\n const transferables = [...(runOptions.transferables ?? [])];\n let owner: object | undefined;\n\n const iterate = async function* (controller: AbortController): AsyncGenerator<TChunk> {\n const onAbort = () => controller.abort(runOptions.signal?.reason);\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n if (runOptions.signal?.aborted) controller.abort(runOptions.signal.reason);\n else runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const running = await core.acquire({ priority, signal: controller.signal }, (acquired) => {\n slot = acquired;\n core.trackActive(1);\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n return acquired.stream(input, { priority, signal: controller.signal, timeout, transferables });\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n core.trackCompleted();\n } catch (error) {\n if (slot && !controller.signal.aborted && !(error instanceof FamiliarTerminatedError)) core.trackFailed();\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 core.trackActive(-1);\n core.release(slot);\n core.settleIdle();\n }\n }\n };\n\n return {\n [Symbol.asyncIterator]() {\n const token = {};\n const controller = new AbortController();\n let iterator: AsyncGenerator<TChunk> | undefined;\n const start = (): AsyncGenerator<TChunk> | undefined => {\n owner ??= token;\n if (owner !== token) return undefined;\n iterator ??= iterate(controller);\n return iterator;\n };\n\n return {\n next: () =>\n start()?.next() ?? Promise.reject(new FamiliarRuntimeError('Worker streams can only be consumed once')),\n return: async (value?: unknown) => {\n if (!owner || owner !== token) return { done: true, value: value as TChunk };\n controller.abort(new FamiliarTerminatedError('Stream consumer stopped'));\n return iterator?.return(value as TChunk) ?? { done: true, value: value as TChunk };\n },\n throw: async (error?: unknown) => {\n const active = start();\n if (!active) throw new FamiliarRuntimeError('Worker streams can only be consumed once');\n controller.abort(error);\n return active.throw(error);\n },\n };\n },\n };\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n runStream,\n get stats() {\n return core.stats();\n },\n get status() {\n return core.status();\n },\n tap: core.tap,\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n","import { createPool } from './_pool.js';\nimport { MAX_CONCURRENCY, validateTimeout } from './_pool-core.js';\nimport { createStreamPool, type StreamSlot } from './_stream-pool.js';\nimport { unrefTimer } from './_timers.js';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors.js';\nimport type { SerializedError, WorkerResponse } from './protocol.js';\nimport { PROTOCOL_VERSION } from './protocol.js';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } from './types.js';\n\ntype ResolvedOptions = {\n concurrency: number;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n timeout: number | undefined;\n};\n\ntype Pending<TOutput> = {\n emit?: (value: TOutput) => void;\n id: number;\n kind: 'run' | 'stream';\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\ntype RunningStream<TChunk> = {\n done: Promise<void>;\n iterable: AsyncIterable<TChunk>;\n};\n\nfunction resolveOptions(options: WorkerOptions = {}): ResolvedOptions {\n const { concurrency = 1, maxQueue, onFull = 'reject', timeout } = options;\n const resolvedConcurrency =\n concurrency === 'auto'\n ? Math.min(MAX_CONCURRENCY, Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1))\n : concurrency;\n\n if (!Number.isInteger(resolvedConcurrency) || resolvedConcurrency < 1 || resolvedConcurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY} or \"auto\"`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (onFull !== 'reject' && onFull !== 'wait') {\n throw new FamiliarInvalidOptionsError('`onFull` must be \"reject\" or \"wait\"');\n }\n\n validateTimeout(timeout);\n\n return { concurrency: resolvedConcurrency, maxQueue, onFull, timeout };\n}\n\nfunction isWorkerResponse<TOutput>(value: unknown): value is WorkerResponse<TOutput> {\n if (typeof value !== 'object' || value === null) return false;\n\n const response = value as Partial<WorkerResponse<TOutput>>;\n if (\n response.version !== PROTOCOL_VERSION ||\n typeof response.id !== 'number' ||\n !Number.isSafeInteger(response.id) ||\n response.id < 0\n )\n return false;\n\n if (response.kind === 'chunk' || response.kind === 'result') return 'value' in response;\n if (response.kind !== 'error' || typeof response.error !== 'object' || response.error === null) return false;\n\n return (\n (response.error.category === undefined || response.error.category === 'protocol') &&\n typeof response.error.message === 'string' &&\n typeof response.error.name === 'string' &&\n (response.error.stack === undefined || typeof response.error.stack === 'string')\n );\n}\n\nfunction responseError(error: SerializedError): FamiliarRuntimeError | FamiliarTaskError {\n const cause = new Error(error.message);\n\n cause.name = error.name;\n cause.stack = error.stack;\n\n return error.category === 'protocol'\n ? new FamiliarRuntimeError(error.message, { cause })\n : new FamiliarTaskError(error.message, { cause });\n}\n\nclass Slot<TInput, TOutput> implements SlotStrategy<TInput, TOutput>, StreamSlot<TInput, TOutput> {\n readonly #url: URL | string;\n #disposed = false;\n #pending: Pending<TOutput> | undefined;\n #taskId = 0;\n #worker: Worker | undefined;\n\n /** Wired by the pool factory to report unhandled worker runtime errors through `tap()`. */\n notify: ((error: FamiliarRuntimeError) => void) | undefined = undefined;\n\n constructor(url: URL | string) {\n this.#url = url;\n }\n\n cancel(reason: unknown): void {\n if (!this.#pending) return;\n this.#stopWorker();\n this.#settlePending('reject', reason);\n }\n\n run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput> {\n return this.#dispatch(input, transferables, timeout, 'run') as Promise<TOutput>;\n }\n\n stream(input: TInput, options: RunOptions): RunningStream<TOutput> {\n const stop = () => this.cancel(new FamiliarTerminatedError('Stream consumer stopped'));\n const chunks: TOutput[] = [];\n const waiters: Array<(result: IteratorResult<TOutput>) => void> = [];\n let done = false;\n let error: unknown;\n const emit = (value: TOutput) => {\n const waiter = waiters.shift();\n\n if (waiter) waiter({ done: false, value });\n else chunks.push(value);\n };\n const finish = (reason?: unknown) => {\n done = true;\n error = reason;\n\n while (waiters.length > 0) {\n const waiter = waiters.shift()!;\n\n if (reason !== undefined) waiter(Promise.reject(reason) as never);\n else waiter({ done: true, value: undefined as never });\n }\n };\n const donePromise = this.#dispatch(input, [...(options.transferables ?? [])], options.timeout, 'stream', emit).then(\n () => finish(),\n (reason: unknown) => finish(reason),\n );\n\n return {\n done: donePromise,\n iterable: {\n [Symbol.asyncIterator]: () => ({\n async next(): Promise<IteratorResult<TOutput>> {\n if (chunks.length > 0) return { done: false, value: chunks.shift()! };\n\n if (error !== undefined) throw error;\n\n if (done) return { done: true, value: undefined as never };\n\n return new Promise<IteratorResult<TOutput>>((resolve, reject) => {\n waiters.push((result) => {\n if (result instanceof Promise) void result.then(resolve, reject);\n else resolve(result);\n });\n });\n },\n async return(): Promise<IteratorResult<TOutput>> {\n stop();\n\n return { done: true, value: undefined as never };\n },\n }),\n },\n };\n }\n\n terminate(): void {\n this.#disposed = true;\n this.#stopWorker();\n this.#settlePending('reject', new FamiliarTerminatedError());\n }\n\n #dispatch(\n input: TInput,\n transferables: Transferable[],\n timeout: number | undefined,\n kind: 'run' | 'stream',\n emit?: (value: TOutput) => void,\n ): Promise<TOutput> {\n if (this.#disposed) return Promise.reject(new FamiliarTerminatedError());\n\n if (this.#pending) return Promise.reject(new FamiliarRuntimeError('Worker slot is already busy'));\n\n try {\n const worker = this.#ensureWorker();\n const id = this.#taskId;\n this.#taskId = id === Number.MAX_SAFE_INTEGER ? 0 : id + 1;\n\n return new Promise<TOutput>((resolve, reject) => {\n const pending: Pending<TOutput> = { emit, id, kind, reject, resolve };\n\n this.#pending = pending;\n\n if (timeout !== undefined) {\n pending.timer = setTimeout(() => this.cancel(new FamiliarTimeoutError(timeout)), timeout);\n unrefTimer(pending.timer);\n }\n\n try {\n worker.postMessage({ id, input, kind, version: PROTOCOL_VERSION }, transferables);\n } catch (error) {\n this.cancel(new FamiliarRuntimeError('Failed to post message to worker', { cause: error }));\n }\n });\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #ensureWorker(): Worker {\n if (this.#worker) return this.#worker;\n\n if (typeof Worker === 'undefined') throw new FamiliarRuntimeError('Worker API is unavailable in this runtime');\n\n try {\n const worker = new Worker(this.#url, { type: 'module' });\n\n worker.onmessage = (event: MessageEvent<unknown>) => {\n if (this.#worker === worker) this.#onMessage(event.data);\n };\n worker.onerror = (event) => this.#failWorker(worker, new FamiliarRuntimeError(event.message || 'Worker failed'));\n worker.onmessageerror = () =>\n this.#failWorker(worker, new FamiliarRuntimeError('Worker response could not be deserialized'));\n this.#worker = worker;\n\n return worker;\n } catch (error) {\n throw new FamiliarRuntimeError('Failed to create Worker', { cause: error });\n }\n }\n\n #stopWorker(): void {\n const worker = this.#worker;\n this.#worker = undefined;\n if (!worker) return;\n\n worker.onmessage = null;\n worker.onerror = null;\n worker.onmessageerror = null;\n worker.terminate();\n }\n\n #failWorker(worker: Worker, error: FamiliarRuntimeError): void {\n if (this.#worker !== worker) return;\n\n this.#stopWorker();\n this.#settlePending('reject', error);\n this.notify?.(error);\n }\n\n #onMessage(message: unknown): void {\n if (!this.#pending) return;\n\n if (\n !isWorkerResponse<TOutput>(message) ||\n message.id !== this.#pending.id ||\n (this.#pending.kind === 'run' && message.kind === 'chunk')\n ) {\n this.cancel(new FamiliarRuntimeError('Worker returned an incompatible protocol response'));\n\n return;\n }\n\n if (message.kind === 'chunk') {\n this.#pending.emit?.(message.value);\n\n return;\n }\n\n if (message.kind === 'error') {\n this.#settlePending('reject', responseError(message.error));\n\n return;\n }\n\n this.#settlePending('resolve', message.value);\n }\n\n #settlePending(kind: 'resolve' | 'reject', value: unknown): void {\n const pending = this.#pending;\n\n if (!pending) return;\n\n this.#pending = undefined;\n\n if (pending.timer) clearTimeout(pending.timer);\n\n if (kind === 'resolve') pending.resolve(value as TOutput);\n else pending.reject(value);\n }\n}\n\nfunction slots<TInput, TOutput>(url: URL | string, options: ResolvedOptions): Slot<TInput, TOutput>[] {\n const resolvedUrl = typeof url === 'string' ? url : url.href;\n return Array.from({ length: options.concurrency }, () => new Slot<TInput, TOutput>(resolvedUrl));\n}\n\n/** Create a pool backed by an ES module worker registered with exposeTask(). */\nexport function createWorker<TInput, TOutput>(\n url: URL | string,\n options: WorkerOptions = {},\n): WorkerPool<TInput, TOutput> {\n const resolved = resolveOptions(options);\n\n return createPool(slots<TInput, TOutput>(url, resolved), {\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n\n/** Create a stream-only pool backed by an ES module worker registered with exposeStream(). */\nexport function createStreamWorker<TInput, TChunk>(\n url: URL | string,\n options: WorkerOptions = {},\n): StreamWorkerPool<TInput, TChunk> {\n const resolved = resolveOptions(options);\n\n return createStreamPool(slots<TInput, TChunk>(url, resolved), {\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n"],"mappings":"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"}
|
package/dist/familiar.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(e){return e?.reason??new DOMException(`Aborted`,`AbortError`)}function t(e){typeof e==`object`&&e&&`unref`in e&&e.unref()}var n=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},r=class extends n{},i=class extends n{maxQueue;constructor(e){super(`Queue is full (maxQueue=${e})`),this.maxQueue=e}},a=class extends n{},o=class extends n{constructor(e=`Worker was terminated`){super(e)}},s=class extends n{timeoutMs;constructor(e){super(`Task timed out after ${e}ms`),this.timeoutMs=e}},c=class extends n{};function l(n){let r=new AbortController,i=[],a=[],c=0,l=0,u=0,d,f=!1;function p(){if(n.isIdle())for(let e of i.splice(0))e.timer&&clearTimeout(e.timer),e.resolve()}function m(e){return n.isIdle()?Promise.resolve():new Promise((n,r)=>{let a={reject:r,resolve:n};e.timeout!==void 0&&(a.timer=setTimeout(()=>{let t=i.indexOf(a);t!==-1&&i.splice(t,1),r(new s(e.timeout))},e.timeout),t(a.timer)),i.push(a)})}function h(){a.shift()?.resolve()}function g(e){for(let t of a.splice(0))t.reject(e)}function _(t){return t?.aborted?Promise.reject(e(t)):new Promise((n,r)=>{let i=!1,o={cleanup(){t?.removeEventListener(`abort`,s)},reject(e){if(i)return;i=!0,o.cleanup();let t=a.indexOf(o);t!==-1&&a.splice(t,1),r(e)},resolve(){i||(i=!0,o.cleanup(),n())}},s=()=>o.reject(e(t));t?.addEventListener(`abort`,s,{once:!0}),a.push(o)})}function v(){f||(f=!0,r.abort(),n.onDispose(),g(new o),p())}function y(e){return f?Promise.resolve():d||(n.onDrainStart(),g(new o(`Worker is draining`)),d=m(e).then(()=>v(),e=>{throw v(),e}),d)}function b(e){return Promise.all(e.map(e=>e.prime())).then(()=>void 0)}function x(e){c+=e}function S(){l+=1}function C(){u+=1}function w(e){return{active:c,completed:l,failed:u,queued:e}}function T(){return f?`terminated`:c===0?`idle`:`running`}return{disposalSignal:r.signal,dispose:v,get disposed(){return f},drain:y,get drainPromise(){return d},isIdle:n.isIdle,prime:b,rejectCapacity:g,releaseCapacity:h,settleIdle:p,stats:w,status:T,trackActive:x,trackCompleted:S,trackFailed:C,waitForCapacity:_,waitForIdle:m}}var u=class{#e=[];#t=0;#n=0;get size(){return this.#t}enqueue(e,t){return t!==void 0&&this.#t>=t?!1:(this.#e.push({item:e,sequence:this.#n++}),this.#a(this.#e.length-1),this.#t+=1,!0)}remove(e){if(e.cancelled)return!1;for(let t of this.#e)if(t.item===e)return e.cancelled=!0,--this.#t,!0;return!1}shift(){for(;this.#e.length>0;){let e=this.#r().item;if(!e.cancelled)return--this.#t,e}}#r(){let e=this.#e[0],t=this.#e.pop();return this.#e.length>0&&(this.#e[0]=t,this.#o(0)),e}#i(e,t){return e.item.priority===t.item.priority?e.sequence<t.sequence:e.item.priority>t.item.priority}#a(e){for(;e>0;){let t=e-1>>1;if(!this.#i(this.#e[e],this.#e[t]))return;[this.#e[e],this.#e[t]]=[this.#e[t],this.#e[e]],e=t}}#o(e){for(;;){let t=e*2+1,n=t+1,r=e;if(t<this.#e.length&&this.#i(this.#e[t],this.#e[r])&&(r=t),n<this.#e.length&&this.#i(this.#e[n],this.#e[r])&&(r=n),r===e)return;[this.#e[e],this.#e[r]]=[this.#e[r],this.#e[e]],e=r}}};function d(t,n){let r=[...t],a=new u,s=!1,c=l({isIdle:()=>r.length===t.length&&a.size===0,onDispose(){for(let e of t)e.terminate();for(;a.size>0;){let e=a.shift();if(!e)break;e.cleanupAbort?.(),e.reject(new o)}},onDrainStart(){}});function d(){for(;a.size>0;){let t=a.shift();if(!t)break;if(t.signal?.aborted){t.cleanupAbort?.(),t.reject(e(t.signal)),c.releaseCapacity();continue}return t}c.settleIdle()}function f(){if(!(s||c.disposed)){for(s=!0;!c.disposed&&r.length>0&&a.size>0;){let t=d();if(!t)break;let i=t,a=r.pop(),s=i.timeout??n.defaultTimeout;c.trackActive(1),c.releaseCapacity();let l=()=>a.cancel(e(i.signal));i.cleanupAbort=()=>{i.signal?.removeEventListener(`abort`,l),i.cleanupAbort=void 0},i.signal?.addEventListener(`abort`,l,{once:!0}),a.run(i.input,i.transferables,s).then(e=>u(e),e=>p(e));function u(e){i.cleanupAbort?.(),r.push(a),c.trackActive(-1),c.trackCompleted(),i.resolve(e),f(),c.settleIdle()}function p(e){i.cleanupAbort?.(),r.push(a),c.trackActive(-1),!(e instanceof o)&&e instanceof Error&&e.name!==`AbortError`&&c.trackFailed(),i.reject(e),f(),c.settleIdle()}}s=!1}}async function p(t,r={}){let{priority:s=0,signal:l,timeout:u,transferables:d=[]}=r;if(c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(l?.aborted)throw e(l);for(;n.onFull===`wait`&&n.maxQueue!==void 0&&a.size>=n.maxQueue;){if(await c.waitForCapacity(l),c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(l?.aborted)throw e(l)}let p,m,h=new Promise((e,t)=>{p=e,m=t}),g={input:t,priority:s,reject:m,resolve:p,signal:l,timeout:u,transferables:d};if(!a.enqueue(g,n.onFull===`wait`?void 0:n.maxQueue))throw new i(n.maxQueue);if(l){let t=()=>{a.remove(g)&&(g.cleanupAbort?.(),m(e(l)),c.releaseCapacity(),c.settleIdle())};g.cleanupAbort=()=>{l.removeEventListener(`abort`,t),g.cleanupAbort=void 0},l.addEventListener(`abort`,t,{once:!0})}return f(),h}return{get disposalSignal(){return c.disposalSignal},dispose:c.dispose,get disposed(){return c.disposed},drain:c.drain,async prime(){await c.prime(t)},run:p,get stats(){return c.stats(a.size)},get status(){return c.status()},[Symbol.asyncDispose]:()=>c.drain({}),[Symbol.dispose]:c.dispose}}async function*f(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 p(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}}}function m(t,n){let r=[...t],a=[],s=0,c=l({isIdle:()=>r.length===t.length&&a.length===0,onDispose(){for(let e of t)e.terminate();for(let e of a.splice(0))e.reject(new o)},onDrainStart(){for(let e of a.splice(0))e.reject(new o(`Worker is draining`))}});function u(e){let t=a.shift();t?(t.resolve(e),c.releaseCapacity()):r.push(e)}async function d(t){if(c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(t.signal?.aborted)throw e(t.signal);for(;n.maxQueue!==void 0&&a.length>=n.maxQueue;){if(n.onFull===`reject`)throw new i(n.maxQueue);if(await c.waitForCapacity(t.signal),c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(t.signal?.aborted)throw e(t.signal)}return r.pop()||new Promise((n,r)=>{let i={cleanup(){i.signal?.removeEventListener(`abort`,o)},priority:t.priority??0,reject(e){i.cleanup();let t=a.indexOf(i);t!==-1&&(a.splice(t,1),c.releaseCapacity()),r(e),c.settleIdle()},resolve(e){i.cleanup(),n(e)},sequence:s++,signal:t.signal},o=()=>i.reject(e(i.signal));i.signal?.addEventListener(`abort`,o,{once:!0}),a.push(i),a.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}return{get disposalSignal(){return c.disposalSignal},dispose:c.dispose,get disposed(){return c.disposed},drain:c.drain,async prime(){await c.prime(t)},runStream(t,r={}){let i=new AbortController,a=()=>i.abort(r.signal?.reason);return r.signal?.addEventListener(`abort`,a,{once:!0}),{[Symbol.asyncIterator]:async function*(){let s,l;try{s=await d({...r,signal:i.signal}),c.trackActive(1),l=()=>s?.cancel(e(i.signal)),i.signal.addEventListener(`abort`,l,{once:!0});let a=s.stream(t,{...r,signal:i.signal,timeout:r.timeout??n.defaultTimeout});for await(let e of a.iterable)yield e;await a.done,c.trackCompleted()}catch(e){throw e instanceof Error&&e.name!==`AbortError`&&!(e instanceof o)&&c.trackFailed(),e}finally{r.signal?.removeEventListener(`abort`,a),s&&(l&&i.signal.removeEventListener(`abort`,l),c.trackActive(-1),u(s),c.settleIdle())}}}},get stats(){return c.stats(a.length)},get status(){return c.status()},[Symbol.asyncDispose]:()=>c.drain({}),[Symbol.dispose]:c.dispose}}var h=512;function g(e={}){let{concurrency:t=1,maxQueue:n,onFull:i=`reject`,onSlotError:a,timeout:o}=e,s=t===`auto`?Math.max(1,globalThis.navigator?.hardwareConcurrency??1):t;if(!Number.isInteger(s)||s<1||s>h)throw new r(`\`concurrency\` must be a positive integer ≤ ${h} or "auto"`);if(n!==void 0&&(!Number.isInteger(n)||n<1))throw new r("`maxQueue` must be a positive integer");if(o!==void 0&&(!Number.isFinite(o)||o<=0))throw new r("`timeout` must be a finite number greater than 0");return{concurrency:s,maxQueue:n,onFull:i,onSlotError:a,timeout:o}}function _(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.version===1&&typeof t.id==`number`&&(t.kind===`chunk`||t.kind===`error`||t.kind===`result`)}function v(e){let t=Error(e.message);return t.name=e.name,t.stack=e.stack,new a(e.message,{cause:t})}var y=class{#e;#t;#n=!1;#r;#i=0;#a;constructor(e,t){this.#t=e,this.#e=t}cancel(e){this.#a?.terminate(),this.#a=void 0,this.#l(`reject`,e)}prime(){return this.#n||this.#s(),Promise.resolve()}run(e,t,n){return this.#o(e,t,n,`run`)}stream(e,t){let n=()=>this.cancel(new o(`Stream consumer stopped`)),r=[],i=[],a=!1,s,c=e=>{let t=i.shift();t?t({done:!1,value:e}):r.push(e)},l=e=>{for(a=!0,s=e;i.length>0;)i.shift()(e===void 0?{done:!0,value:void 0}:Promise.reject(e))};return{done:this.#o(e,t.transferables??[],t.timeout,`stream`,c).then(()=>l(),e=>l(e)),iterable:{[Symbol.asyncIterator]:()=>({async next(){if(r.length>0)return{done:!1,value:r.shift()};if(s!==void 0)throw s;return a?{done:!0,value:void 0}:new Promise((e,t)=>{i.push(n=>{n instanceof Promise?n.then(e,t):e(n)})})},async return(){return n(),{done:!0,value:void 0}}})}}}terminate(){this.#n=!0,this.cancel(new o)}#o(e,n,r,i,a){if(this.#n)return Promise.reject(new o);if(this.#r)return Promise.reject(new c(`Worker slot is already busy`));try{let o=this.#s(),l=this.#i++;return new Promise((u,d)=>{let f={emit:a,id:l,reject:d,resolve:u};this.#r=f,r!==void 0&&(f.timer=setTimeout(()=>this.cancel(new s(r)),r),t(f.timer));try{o.postMessage({id:l,input:e,kind:i,version:1},n)}catch(e){this.cancel(new c(`Failed to post message to worker`,{cause:e}))}})}catch(e){return Promise.reject(e)}}#s(){if(this.#a)return this.#a;if(typeof Worker>`u`)throw new c(`Worker API is unavailable in this runtime`);try{let e=new Worker(this.#t,{type:`module`});return e.onmessage=e=>this.#c(e.data),e.onerror=e=>{let t=new c(e.message||`Worker failed`);this.#a=void 0,this.#e?.(t),this.#l(`reject`,t)},this.#a=e,e}catch(e){throw new c(`Failed to create Worker`,{cause:e})}}#c(e){if(this.#r){if(!_(e)||e.id!==this.#r.id){this.cancel(new c(`Worker returned an incompatible protocol response`));return}if(e.kind===`chunk`){this.#r.emit?.(e.value);return}if(e.kind===`error`){this.#l(`reject`,v(e.error));return}this.#l(`resolve`,e.value)}}#l(e,t){let n=this.#r;n&&(this.#r=void 0,n.timer&&clearTimeout(n.timer),e===`resolve`?n.resolve(t):n.reject(t))}};function b(e,t){return Array.from({length:t.concurrency},()=>new y(e,t.onSlotError))}function x(e,t={}){let n=g(t);return d(b(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}function S(e,t={}){let n=g(t);return m(b(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}export{n as FamiliarError,r as FamiliarInvalidOptionsError,i as FamiliarQueueFullError,c as FamiliarRuntimeError,a as FamiliarTaskError,o as FamiliarTerminatedError,s as FamiliarTimeoutError,f as batch,S as createStreamWorker,p as createTaskGroup,x as createWorker};
|
|
1
|
+
import{abortError as e,tapper as t}from"@vielzeug/arsenal";function unrefTimer(e){typeof e==`object`&&e&&`unref`in e&&e.unref()}var FamiliarError=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},FamiliarInvalidOptionsError=class extends FamiliarError{},FamiliarQueueFullError=class extends FamiliarError{maxQueue;constructor(e){super(`Queue is full (maxQueue=${e})`),this.maxQueue=e}},FamiliarTaskError=class extends FamiliarError{},FamiliarTerminatedError=class extends FamiliarError{constructor(e=`Worker was terminated`){super(e)}},FamiliarTimeoutError=class extends FamiliarError{timeoutMs;constructor(e,t=`Task`){super(`${t} timed out after ${e}ms`),this.timeoutMs=e}},FamiliarRuntimeError=class extends FamiliarError{},n=2147483647;function validatePriority(e){if(!Number.isFinite(e))throw new FamiliarInvalidOptionsError("`priority` must be a finite number");return e}function validateTimeout(e,t=`timeout`){if(e!==void 0&&(!Number.isInteger(e)||e<1||e>2147483647))throw new FamiliarInvalidOptionsError(`\`${t}\` must be an integer from 1 through ${n}`);return e}function createPoolCore(n,r){let i=[...n],a=[],o=[],s=[],c=t(),l=new AbortController,u=0,d=0,f=0,p=0,m=0,h,g=!1;function isIdle(){return i.length===n.length&&a.length===0}function settleIdle(){if(isIdle())for(let e of o.splice(0))e.timer&&clearTimeout(e.timer),e.resolve()}function waitForIdle(e){return isIdle()?Promise.resolve():new Promise((t,n)=>{let r={reject:n,resolve:t};e.timeout!==void 0&&(r.timer=setTimeout(()=>{let t=o.indexOf(r);t!==-1&&o.splice(t,1),n(new FamiliarTimeoutError(e.timeout,`Drain`))},e.timeout),unrefTimer(r.timer)),o.push(r)})}function releaseCapacity(){s.shift()?.resolve()}function rejectCapacity(e){for(let t of s.splice(0))t.reject(e)}function waitForCapacity(t,n){return t?.aborted?Promise.reject(e(t)):new Promise((r,i)=>{let a=!1,o={cleanup(){t?.removeEventListener(`abort`,onAbort)},priority:n,reject(e){if(a)return;a=!0,o.cleanup();let t=s.indexOf(o);t!==-1&&s.splice(t,1),i(e)},resolve(){a||(a=!0,o.cleanup(),r())},sequence:f++},onAbort=()=>o.reject(e(t));t?.addEventListener(`abort`,onAbort,{once:!0}),s.push(o),s.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}function acquire(t,n){let{priority:i,signal:o}=t;return o?.aborted?Promise.reject(e(o)):(async()=>{for(;;){if(g)throw new FamiliarTerminatedError;if(h)throw new FamiliarTerminatedError(`Worker is draining`);if(r.maxQueue===void 0||a.length<r.maxQueue)return admit(t,n??(e=>e));if(r.onFull===`reject`)throw new FamiliarQueueFullError(r.maxQueue);if(await waitForCapacity(o,i),o?.aborted)throw releaseCapacity(),e(o)}})()}function admit(t,n){let{priority:r,signal:o}=t,s=i.pop();if(s)try{return Promise.resolve(n(s))}catch(e){return release(s),settleIdle(),Promise.reject(e)}return new Promise((t,i)=>{let s={cleanup(){s.signal?.removeEventListener(`abort`,onAbort)},priority:r,reject(e){s.cleanup();let t=a.indexOf(s);t!==-1&&(a.splice(t,1),releaseCapacity()),i(e),settleIdle()},sequence:d++,signal:o,start(e){s.cleanup();try{t(n(e))}catch(t){release(e),settleIdle(),i(t)}}},onAbort=()=>s.reject(e(s.signal));s.signal?.addEventListener(`abort`,onAbort,{once:!0}),a.push(s),a.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}function release(e){let t=a.shift();t?(t.start(e),releaseCapacity()):i.push(e)}function dispose(){if(!g){g=!0,l.abort();for(let e of n)e.terminate();for(let e of a.splice(0))e.reject(new FamiliarTerminatedError);rejectCapacity(new FamiliarTerminatedError),settleIdle(),c.emit({type:`dispose`}),c.clear()}}function drain(e={}){if(g)return Promise.resolve();try{validateTimeout(e.timeout,`drain.timeout`)}catch(e){return Promise.reject(e)}return h||(rejectCapacity(new FamiliarTerminatedError(`Worker is draining`)),h=waitForIdle(e).then(()=>dispose(),e=>{throw dispose(),e}),h)}return{acquire,disposalSignal:l.signal,dispose,get disposed(){return g},drain,get drainPromise(){return h},emitTap(e){c.emit(e)},release,settleIdle,stats(){return{active:u,completed:p,failed:m,queued:a.length+s.length}},status(){return g?`terminated`:u===0?`idle`:`running`},tap(e,t){return g?()=>void 0:c.tap(e,t)},trackActive(e){u+=e},trackCompleted(){p+=1},trackFailed(){m+=1}}}function createPool(t,n){let r=createPoolCore(t,n);for(let e of t)e.notify=e=>r.emitTap({error:e,type:`worker-error`});function run(t,i={}){let a,o,s;try{a=validatePriority(i.priority??0),o=validateTimeout(i.timeout)??n.defaultTimeout,s=[...i.transferables??[]]}catch(e){return Promise.reject(e)}return r.acquire({priority:a,signal:i.signal},n=>{r.trackActive(1);let onAbort=()=>n.cancel(e(i.signal));i.signal?.addEventListener(`abort`,onAbort,{once:!0});let finish=async()=>{try{let e=await n.run(t,s,o);return r.trackCompleted(),e}catch(e){throw!i.signal?.aborted&&!(e instanceof FamiliarTerminatedError)&&r.trackFailed(),e}finally{i.signal?.removeEventListener(`abort`,onAbort),r.trackActive(-1),r.release(n),r.settleIdle()}};return finish()})}return{get disposalSignal(){return r.disposalSignal},dispose:r.dispose,get disposed(){return r.disposed},drain:r.drain,run,get stats(){return r.stats()},get status(){return r.status()},tap:r.tap,[Symbol.asyncDispose]:()=>r.drain({}),[Symbol.dispose]:r.dispose}}function runBatch(t,n,r={}){let i,iterate=async function*(i){let a=[],onAbort=()=>i.abort(r.signal?.reason);r.signal?.aborted?i.abort(r.signal.reason):r.signal?.addEventListener(`abort`,onAbort,{once:!0});try{for(let[e,o]of n.entries()){let n=t.run(o,{priority:r.priority,signal:i.signal,timeout:r.timeout,transferables:r.getTransferables?.(o,e)}).catch(e=>{throw i.abort(e),e});n.catch(()=>void 0),a.push(n)}if(a.length===0&&i.signal.aborted)throw e(i.signal);for(let t of a){if(i.signal.aborted)throw e(i.signal);let n=await t;if(i.signal.aborted)throw e(i.signal);yield n}}catch(e){throw i.abort(e),e}finally{r.signal?.removeEventListener(`abort`,onAbort),i.abort(new DOMException(`Batch consumer stopped`,`AbortError`)),await Promise.allSettled(a)}};return{[Symbol.asyncIterator](){let e={},t=new AbortController,n,start=()=>{if(i??=e,i===e)return n??=iterate(t),n};return{next:()=>start()?.next()??Promise.reject(new FamiliarRuntimeError(`Worker batches can only be consumed once`)),return:async r=>!i||i!==e?{done:!0,value:r}:(t.abort(new FamiliarTerminatedError(`Batch consumer stopped`)),n?.return(r)??{done:!0,value:r}),throw:async e=>{let n=start();if(!n)throw new FamiliarRuntimeError(`Worker batches can only be consumed once`);return t.abort(e),n.throw(e)}}}}}function createStreamPool(t,n){let r=createPoolCore(t,n);for(let e of t)e.notify=e=>r.emitTap({error:e,type:`worker-error`});function runStream(t,i={}){let a=validatePriority(i.priority??0),o=validateTimeout(i.timeout)??n.defaultTimeout,s=[...i.transferables??[]],c,iterate=async function*(n){let onAbort=()=>n.abort(i.signal?.reason),c,onCancel;i.signal?.aborted?n.abort(i.signal.reason):i.signal?.addEventListener(`abort`,onAbort,{once:!0});try{let i=await r.acquire({priority:a,signal:n.signal},i=>(c=i,r.trackActive(1),onCancel=()=>c?.cancel(e(n.signal)),n.signal.addEventListener(`abort`,onCancel,{once:!0}),i.stream(t,{priority:a,signal:n.signal,timeout:o,transferables:s})));for await(let e of i.iterable)yield e;await i.done,r.trackCompleted()}catch(e){throw c&&!n.signal.aborted&&!(e instanceof FamiliarTerminatedError)&&r.trackFailed(),e}finally{i.signal?.removeEventListener(`abort`,onAbort),c&&(onCancel&&n.signal.removeEventListener(`abort`,onCancel),r.trackActive(-1),r.release(c),r.settleIdle())}};return{[Symbol.asyncIterator](){let e={},t=new AbortController,n,start=()=>{if(c??=e,c===e)return n??=iterate(t),n};return{next:()=>start()?.next()??Promise.reject(new FamiliarRuntimeError(`Worker streams can only be consumed once`)),return:async r=>!c||c!==e?{done:!0,value:r}:(t.abort(new FamiliarTerminatedError(`Stream consumer stopped`)),n?.return(r)??{done:!0,value:r}),throw:async e=>{let n=start();if(!n)throw new FamiliarRuntimeError(`Worker streams can only be consumed once`);return t.abort(e),n.throw(e)}}}}}return{get disposalSignal(){return r.disposalSignal},dispose:r.dispose,get disposed(){return r.disposed},drain:r.drain,runStream,get stats(){return r.stats()},get status(){return r.status()},tap:r.tap,[Symbol.asyncDispose]:()=>r.drain({}),[Symbol.dispose]:r.dispose}}function resolveOptions(e={}){let{concurrency:t=1,maxQueue:n,onFull:r=`reject`,timeout:i}=e,a=t===`auto`?Math.min(512,Math.max(1,globalThis.navigator?.hardwareConcurrency??1)):t;if(!Number.isInteger(a)||a<1||a>512)throw new FamiliarInvalidOptionsError('`concurrency` must be a positive integer ≤ 512 or "auto"');if(n!==void 0&&(!Number.isInteger(n)||n<1))throw new FamiliarInvalidOptionsError("`maxQueue` must be a positive integer");if(r!==`reject`&&r!==`wait`)throw new FamiliarInvalidOptionsError('`onFull` must be "reject" or "wait"');return validateTimeout(i),{concurrency:a,maxQueue:n,onFull:r,timeout:i}}function isWorkerResponse(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.version!==1||typeof t.id!=`number`||!Number.isSafeInteger(t.id)||t.id<0?!1:t.kind===`chunk`||t.kind===`result`?`value`in t:t.kind!==`error`||typeof t.error!=`object`||t.error===null?!1:(t.error.category===void 0||t.error.category===`protocol`)&&typeof t.error.message==`string`&&typeof t.error.name==`string`&&(t.error.stack===void 0||typeof t.error.stack==`string`)}function responseError(e){let t=Error(e.message);return t.name=e.name,t.stack=e.stack,e.category===`protocol`?new FamiliarRuntimeError(e.message,{cause:t}):new FamiliarTaskError(e.message,{cause:t})}var Slot=class{#e;#t=!1;#n;#r=0;#i;notify=void 0;constructor(e){this.#e=e}cancel(e){this.#n&&(this.#s(),this.#u(`reject`,e))}run(e,t,n){return this.#a(e,t,n,`run`)}stream(e,t){let stop=()=>this.cancel(new FamiliarTerminatedError(`Stream consumer stopped`)),n=[],r=[],i=!1,a,emit=e=>{let t=r.shift();t?t({done:!1,value:e}):n.push(e)},finish=e=>{for(i=!0,a=e;r.length>0;)r.shift()(e===void 0?{done:!0,value:void 0}:Promise.reject(e))};return{done:this.#a(e,[...t.transferables??[]],t.timeout,`stream`,emit).then(()=>finish(),e=>finish(e)),iterable:{[Symbol.asyncIterator]:()=>({async next(){if(n.length>0)return{done:!1,value:n.shift()};if(a!==void 0)throw a;return i?{done:!0,value:void 0}:new Promise((e,t)=>{r.push(n=>{n instanceof Promise?n.then(e,t):e(n)})})},async return(){return stop(),{done:!0,value:void 0}}})}}}terminate(){this.#t=!0,this.#s(),this.#u(`reject`,new FamiliarTerminatedError)}#a(e,t,n,r,i){if(this.#t)return Promise.reject(new FamiliarTerminatedError);if(this.#n)return Promise.reject(new FamiliarRuntimeError(`Worker slot is already busy`));try{let a=this.#o(),o=this.#r;return this.#r=o===2**53-1?0:o+1,new Promise((s,c)=>{let l={emit:i,id:o,kind:r,reject:c,resolve:s};this.#n=l,n!==void 0&&(l.timer=setTimeout(()=>this.cancel(new FamiliarTimeoutError(n)),n),unrefTimer(l.timer));try{a.postMessage({id:o,input:e,kind:r,version:1},t)}catch(e){this.cancel(new FamiliarRuntimeError(`Failed to post message to worker`,{cause:e}))}})}catch(e){return Promise.reject(e)}}#o(){if(this.#i)return this.#i;if(typeof Worker>`u`)throw new FamiliarRuntimeError(`Worker API is unavailable in this runtime`);try{let e=new Worker(this.#e,{type:`module`});return e.onmessage=t=>{this.#i===e&&this.#l(t.data)},e.onerror=t=>this.#c(e,new FamiliarRuntimeError(t.message||`Worker failed`)),e.onmessageerror=()=>this.#c(e,new FamiliarRuntimeError(`Worker response could not be deserialized`)),this.#i=e,e}catch(e){throw new FamiliarRuntimeError(`Failed to create Worker`,{cause:e})}}#s(){let e=this.#i;this.#i=void 0,e&&(e.onmessage=null,e.onerror=null,e.onmessageerror=null,e.terminate())}#c(e,t){this.#i===e&&(this.#s(),this.#u(`reject`,t),this.notify?.(t))}#l(e){if(this.#n){if(!isWorkerResponse(e)||e.id!==this.#n.id||this.#n.kind===`run`&&e.kind===`chunk`){this.cancel(new FamiliarRuntimeError(`Worker returned an incompatible protocol response`));return}if(e.kind===`chunk`){this.#n.emit?.(e.value);return}if(e.kind===`error`){this.#u(`reject`,responseError(e.error));return}this.#u(`resolve`,e.value)}}#u(e,t){let n=this.#n;n&&(this.#n=void 0,n.timer&&clearTimeout(n.timer),e===`resolve`?n.resolve(t):n.reject(t))}};function slots(e,t){let n=typeof e==`string`?e:e.href;return Array.from({length:t.concurrency},()=>new Slot(n))}function createWorker(e,t={}){let n=resolveOptions(t);return createPool(slots(e,n),{defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}function createStreamWorker(e,t={}){let n=resolveOptions(t);return createStreamPool(slots(e,n),{defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}export{FamiliarError,FamiliarInvalidOptionsError,FamiliarQueueFullError,FamiliarRuntimeError,FamiliarTaskError,FamiliarTerminatedError,FamiliarTimeoutError,createStreamWorker,createWorker,runBatch};
|
|
2
2
|
//# sourceMappingURL=familiar.js.map
|
package/dist/familiar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"familiar.js","names":["#heap","#live","#sequence","#siftUp","#extract","#siftDown","#before","#onSlotError","#url","#worker","#settlePending","#disposed","#ensureWorker","#dispatch","#pending","#taskId","#onMessage"],"sources":["../../arsenal/dist/async/abortError.js","../src/_timers.ts","../src/errors.ts","../src/_pool-core.ts","../src/_queue.ts","../src/_pool.ts","../src/_stream-pool.ts","../src/worker.ts"],"sourcesContent":["//#region src/async/abortError.ts\nfunction e(e) {\n\treturn e?.reason ?? new DOMException(\"Aborted\", \"AbortError\");\n}\n//#endregion\nexport { e as abortError };\n\n//# sourceMappingURL=abortError.js.map","/**\n * Node compatibility helper: `unref()`s a timer so a pending per-task timeout/watchdog does not\n * keep a Node event loop (e.g. a Worker polyfill) alive. Browsers return a plain number from\n * `setTimeout`/`setInterval`, so this is a no-op there.\n *\n * Not part of the public API surface.\n */\nexport function unrefTimer(timer: ReturnType<typeof setTimeout> | ReturnType<typeof setInterval>): void {\n if (typeof timer === 'object' && timer !== null && 'unref' in timer) {\n (timer as { unref(): void }).unref();\n }\n}\n","/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when invalid options are passed to a Familiar pool factory. */\nexport class FamiliarInvalidOptionsError extends FamiliarError {}\n\n/** Thrown when run() is called and the queue is full (`onFull='reject'`). */\nexport class FamiliarQueueFullError extends FamiliarError {\n /** The configured `maxQueue` value. */\n readonly maxQueue: number;\n\n constructor(maxQueue: number) {\n super(`Queue is full (maxQueue=${maxQueue})`);\n this.maxQueue = maxQueue;\n }\n}\n\n/** Thrown when the task function throws. The original error is available as `.cause`. */\nexport class FamiliarTaskError extends FamiliarError {}\n\n/** Thrown when a task or operation is rejected because the worker was terminated. */\nexport class FamiliarTerminatedError extends FamiliarError {\n constructor(message = 'Worker was terminated') {\n super(message);\n }\n}\n\n/** Thrown when a task exceeds its timeout or `drain()` times out. */\nexport class FamiliarTimeoutError extends FamiliarError {\n /** The configured timeout in milliseconds. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number) {\n super(`Task timed out after ${timeoutMs}ms`);\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */\nexport class FamiliarRuntimeError extends FamiliarError {}\n","import { abortError } from '@vielzeug/arsenal/async';\nimport { unrefTimer } from './_timers';\nimport { FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type { DrainOptions, WorkerStats, WorkerStatus } from './types';\n\nexport type PoolOptions = {\n concurrency: number;\n defaultTimeout: number | undefined;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n};\n\ntype IdleWaiter = {\n reject: (reason: unknown) => void;\n resolve: () => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\nexport interface PoolCore {\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n drain(options: DrainOptions): Promise<void>;\n readonly drainPromise: Promise<void> | undefined;\n isIdle(): boolean;\n prime(slots: readonly { prime(): Promise<void> }[]): Promise<void>;\n rejectCapacity(reason: unknown): void;\n releaseCapacity(): void;\n settleIdle(): void;\n stats(queued: number): WorkerStats;\n status(): WorkerStatus;\n trackActive(delta: number): void;\n trackCompleted(): void;\n trackFailed(): void;\n waitForCapacity(signal: AbortSignal | undefined): Promise<void>;\n waitForIdle(options: DrainOptions): Promise<void>;\n}\n\n/**\n * Shared disposal controller, idle/capacity waiters, drain, and stats tracking\n * used by both the single-result pool (`_pool.ts`) and the stream pool\n * (`_stream-pool.ts`). Each pool provides its own `isIdle` predicate and\n * `onDispose`/`onDrainStart` hooks to flush pool-specific pending work.\n */\nexport function createPoolCore(options: {\n isIdle: () => boolean;\n onDispose: () => void;\n onDrainStart: () => void;\n}): PoolCore {\n const disposalController = new AbortController();\n const idleWaiters: IdleWaiter[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let drainPromise: Promise<void> | undefined;\n let terminated = false;\n\n function settleIdle(): void {\n if (!options.isIdle()) return;\n\n for (const waiter of idleWaiters.splice(0)) {\n if (waiter.timer) clearTimeout(waiter.timer);\n\n waiter.resolve();\n }\n }\n\n function waitForIdle(drainOptions: DrainOptions): Promise<void> {\n if (options.isIdle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n const waiter: IdleWaiter = { reject, resolve };\n\n if (drainOptions.timeout !== undefined) {\n waiter.timer = setTimeout(() => {\n const index = idleWaiters.indexOf(waiter);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(drainOptions.timeout!));\n }, drainOptions.timeout);\n unrefTimer(waiter.timer);\n }\n\n idleWaiters.push(waiter);\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n options.onDispose();\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n options.onDrainStart();\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n function prime(slots: readonly { prime(): Promise<void> }[]): Promise<void> {\n return Promise.all(slots.map((slot) => slot.prime())).then(() => undefined);\n }\n\n function trackActive(delta: number): void {\n active += delta;\n }\n\n function trackCompleted(): void {\n completed += 1;\n }\n\n function trackFailed(): void {\n failed += 1;\n }\n\n function stats(queued: number): WorkerStats {\n return { active, completed, failed, queued };\n }\n\n function status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n }\n\n return {\n disposalSignal: disposalController.signal,\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n get drainPromise() {\n return drainPromise;\n },\n isIdle: options.isIdle,\n prime,\n rejectCapacity,\n releaseCapacity,\n settleIdle,\n stats,\n status,\n trackActive,\n trackCompleted,\n trackFailed,\n waitForCapacity,\n waitForIdle,\n };\n}\n","export type QueueItem<TInput, TOutput> = {\n cancelled?: boolean;\n cleanupAbort?: () => void;\n input: TInput;\n priority: number;\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n signal?: AbortSignal;\n timeout?: number;\n transferables: Transferable[];\n};\n\ntype Entry<TInput, TOutput> = { readonly item: QueueItem<TInput, TOutput>; readonly sequence: number };\n\nexport class TaskQueue<TInput, TOutput> {\n readonly #heap: Entry<TInput, TOutput>[] = [];\n #live = 0;\n #sequence = 0;\n\n get size(): number {\n return this.#live;\n }\n\n enqueue(item: QueueItem<TInput, TOutput>, maxSize: number | undefined): boolean {\n if (maxSize !== undefined && this.#live >= maxSize) return false;\n\n this.#heap.push({ item, sequence: this.#sequence++ });\n this.#siftUp(this.#heap.length - 1);\n this.#live += 1;\n\n return true;\n }\n\n remove(item: QueueItem<TInput, TOutput>): boolean {\n if (item.cancelled) return false;\n\n for (const entry of this.#heap) {\n if (entry.item === item) {\n item.cancelled = true;\n this.#live -= 1;\n\n return true;\n }\n }\n\n return false;\n }\n\n shift(): QueueItem<TInput, TOutput> | undefined {\n while (this.#heap.length > 0) {\n const item = this.#extract().item;\n\n if (!item.cancelled) {\n this.#live -= 1;\n\n return item;\n }\n }\n\n return undefined;\n }\n\n #extract(): Entry<TInput, TOutput> {\n const top = this.#heap[0]!;\n const last = this.#heap.pop()!;\n\n if (this.#heap.length > 0) {\n this.#heap[0] = last;\n this.#siftDown(0);\n }\n\n return top;\n }\n\n #before(a: Entry<TInput, TOutput>, b: Entry<TInput, TOutput>): boolean {\n return a.item.priority === b.item.priority ? a.sequence < b.sequence : a.item.priority > b.item.priority;\n }\n\n #siftUp(index: number): void {\n while (index > 0) {\n const parent = (index - 1) >> 1;\n\n if (!this.#before(this.#heap[index]!, this.#heap[parent]!)) return;\n\n [this.#heap[index], this.#heap[parent]] = [this.#heap[parent]!, this.#heap[index]!];\n index = parent;\n }\n }\n\n #siftDown(index: number): void {\n for (;;) {\n const left = index * 2 + 1;\n const right = left + 1;\n let next = index;\n\n if (left < this.#heap.length && this.#before(this.#heap[left]!, this.#heap[next]!)) next = left;\n\n if (right < this.#heap.length && this.#before(this.#heap[right]!, this.#heap[next]!)) next = right;\n\n if (next === index) return;\n\n [this.#heap[index], this.#heap[next]] = [this.#heap[next]!, this.#heap[index]!];\n index = next;\n }\n }\n}\n","import { abortError } from '@vielzeug/arsenal/async';\nimport { createPoolCore, type PoolCore, type PoolOptions } from './_pool-core';\nimport { type QueueItem, TaskQueue } from './_queue';\nimport { FamiliarQueueFullError, FamiliarTerminatedError } from './errors';\nimport type { RunOptions, SlotStrategy, TaskGroup, TaskGroupOptions, WorkerPool } from './types';\n\nexport type { PoolOptions } from './_pool-core';\n\nexport function createPool<TInput, TOutput>(\n slots: SlotStrategy<TInput, TOutput>[],\n options: PoolOptions,\n): WorkerPool<TInput, TOutput> {\n const freeSlots = [...slots];\n const queue = new TaskQueue<TInput, TOutput>();\n let draining = false;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && queue.size === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n item.cleanupAbort?.();\n item.reject(new FamiliarTerminatedError());\n }\n },\n onDrainStart() {\n // No pending waiters to reject for the queue-based pool; capacity waiters\n // are rejected by the core's drain().\n },\n });\n\n function nextItem(): QueueItem<TInput, TOutput> | undefined {\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n if (item.signal?.aborted) {\n item.cleanupAbort?.();\n item.reject(abortError(item.signal));\n core.releaseCapacity();\n continue;\n }\n\n return item;\n }\n\n core.settleIdle();\n\n return undefined;\n }\n\n function drainQueue(): void {\n if (draining || core.disposed) return;\n\n draining = true;\n\n while (!core.disposed && freeSlots.length > 0 && queue.size > 0) {\n const next = nextItem();\n\n if (!next) break;\n\n const item = next;\n const slot = freeSlots.pop()!;\n const timeout = item.timeout ?? options.defaultTimeout;\n\n core.trackActive(1);\n core.releaseCapacity();\n\n const onAbort = () => slot.cancel(abortError(item.signal!));\n\n item.cleanupAbort = () => {\n item.signal?.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n item.signal?.addEventListener('abort', onAbort, { once: true });\n\n slot.run(item.input, item.transferables, timeout).then(\n (value) => finish(value),\n (error: unknown) => fail(error),\n );\n\n function finish(value: TOutput): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n core.trackActive(-1);\n core.trackCompleted();\n item.resolve(value);\n drainQueue();\n core.settleIdle();\n }\n\n function fail(error: unknown): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n core.trackActive(-1);\n\n if (!(error instanceof FamiliarTerminatedError) && error instanceof Error && error.name !== 'AbortError')\n core.trackFailed();\n\n item.reject(error);\n drainQueue();\n core.settleIdle();\n }\n }\n\n draining = false;\n }\n\n async function run(input: TInput, runOptions: RunOptions = {}): Promise<TOutput> {\n const { priority = 0, signal, timeout, transferables = [] } = runOptions;\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n\n while (options.onFull === 'wait' && options.maxQueue !== undefined && queue.size >= options.maxQueue) {\n await core.waitForCapacity(signal);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n }\n\n let resolve!: (value: TOutput) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<TOutput>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const item: QueueItem<TInput, TOutput> = { input, priority, reject, resolve, signal, timeout, transferables };\n\n if (!queue.enqueue(item, options.onFull === 'wait' ? undefined : options.maxQueue)) {\n throw new FamiliarQueueFullError(options.maxQueue!);\n }\n\n if (signal) {\n const onAbort = () => {\n if (!queue.remove(item)) return;\n\n item.cleanupAbort?.();\n reject(abortError(signal));\n core.releaseCapacity();\n core.settleIdle();\n };\n\n item.cleanupAbort = () => {\n signal.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n\n drainQueue();\n\n return promise;\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n async prime(): Promise<void> {\n await core.prime(slots);\n },\n run,\n get stats() {\n return core.stats(queue.size);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n\nexport async function* batch<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n inputs: readonly TInput[],\n options: RunOptions = {},\n): AsyncIterable<TOutput> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n const tasks = inputs.map((input) => pool.run(input, { ...options, signal: controller.signal }));\n\n try {\n for (const task of tasks) yield await task;\n } catch (error) {\n controller.abort(error);\n await Promise.allSettled(tasks);\n throw error;\n } finally {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort();\n await Promise.allSettled(tasks);\n }\n}\n\nexport function createTaskGroup<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n name: string | undefined = undefined,\n options: TaskGroupOptions = {},\n): TaskGroup<TInput, TOutput> {\n const controller = new AbortController();\n const tasks = new Set<Promise<TOutput>>();\n let size = 0;\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n abort(reason?: unknown): void {\n controller.abort(reason);\n },\n async drain(): Promise<PromiseSettledResult<TOutput>[]> {\n return Promise.allSettled([...tasks]);\n },\n get name() {\n return name;\n },\n get pending() {\n return tasks.size;\n },\n run(input, runOptions = {}): Promise<TOutput> {\n const task = pool.run(input, { ...runOptions, signal: controller.signal });\n\n size += 1;\n tasks.add(task);\n void task.finally(() => tasks.delete(task));\n\n return task;\n },\n get size() {\n return size;\n },\n };\n}\n","import { abortError } from '@vielzeug/arsenal/async';\n\nimport { createPoolCore, type PoolCore, type PoolOptions } from './_pool-core';\nimport { FamiliarQueueFullError, FamiliarTerminatedError } from './errors';\nimport type { RunOptions, StreamWorkerPool } 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 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 let sequence = 0;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && waiters.length === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n },\n onDrainStart() {\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\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 core.releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.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 core.waitForCapacity(runOptions.signal);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.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 core.releaseCapacity();\n }\n\n reject(reason);\n core.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 return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n async prime(): Promise<void> {\n await core.prime(slots);\n },\n 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 core.trackActive(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 core.trackCompleted();\n } catch (error) {\n if (error instanceof Error && error.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError))\n core.trackFailed();\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 core.trackActive(-1);\n release(slot);\n core.settleIdle();\n }\n }\n },\n };\n },\n get stats() {\n return core.stats(waiters.length);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n","export { batch, createTaskGroup } from './_pool';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nexport type {\n DrainOptions,\n PoolBase,\n RunOptions,\n StreamWorkerPool,\n TaskGroup,\n TaskGroupOptions,\n WorkerOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\n\nimport { createPool } from './_pool';\nimport { createStreamPool, type StreamSlot } from './_stream-pool';\nimport { unrefTimer } from './_timers';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nimport type { SerializedError, WorkerResponse } from './protocol';\nimport { PROTOCOL_VERSION } from './protocol';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } from './types';\n\nconst MAX_CONCURRENCY = 512;\n\ntype ResolvedOptions = {\n concurrency: number;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n onSlotError: WorkerOptions['onSlotError'];\n timeout: number | undefined;\n};\n\ntype Pending<TOutput> = {\n emit?: (value: TOutput) => void;\n id: number;\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\nexport type RunningStream<TChunk> = {\n done: Promise<void>;\n iterable: AsyncIterable<TChunk>;\n};\n\nfunction resolveOptions(options: WorkerOptions = {}): ResolvedOptions {\n const { concurrency = 1, maxQueue, onFull = 'reject', onSlotError, timeout } = options;\n const resolvedConcurrency =\n concurrency === 'auto' ? Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1) : concurrency;\n\n if (!Number.isInteger(resolvedConcurrency) || resolvedConcurrency < 1 || resolvedConcurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY} or \"auto\"`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0)) {\n throw new FamiliarInvalidOptionsError('`timeout` must be a finite number greater than 0');\n }\n\n return { concurrency: resolvedConcurrency, maxQueue, onFull, onSlotError, timeout };\n}\n\nfunction isWorkerResponse<TOutput>(value: unknown): value is WorkerResponse<TOutput> {\n if (typeof value !== 'object' || value === null) return false;\n\n const response = value as Partial<WorkerResponse<TOutput>>;\n\n return (\n response.version === PROTOCOL_VERSION &&\n typeof response.id === 'number' &&\n (response.kind === 'chunk' || response.kind === 'error' || response.kind === 'result')\n );\n}\n\nfunction taskError(error: SerializedError): FamiliarTaskError {\n const cause = new Error(error.message);\n\n cause.name = error.name;\n cause.stack = error.stack;\n\n return new FamiliarTaskError(error.message, { cause });\n}\n\nclass Slot<TInput, TOutput> implements SlotStrategy<TInput, TOutput>, StreamSlot<TInput, TOutput> {\n readonly #onSlotError: WorkerOptions['onSlotError'];\n readonly #url: URL | string;\n #disposed = false;\n #pending: Pending<TOutput> | undefined;\n #taskId = 0;\n #worker: Worker | undefined;\n\n constructor(url: URL | string, onSlotError: WorkerOptions['onSlotError']) {\n this.#url = url;\n this.#onSlotError = onSlotError;\n }\n\n cancel(reason: unknown): void {\n this.#worker?.terminate();\n this.#worker = undefined;\n this.#settlePending('reject', reason);\n }\n\n prime(): Promise<void> {\n if (!this.#disposed) this.#ensureWorker();\n\n return Promise.resolve();\n }\n\n run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput> {\n return this.#dispatch(input, transferables, timeout, 'run') as Promise<TOutput>;\n }\n\n stream(input: TInput, options: RunOptions): RunningStream<TOutput> {\n const stop = () => this.cancel(new FamiliarTerminatedError('Stream consumer stopped'));\n const chunks: TOutput[] = [];\n const waiters: Array<(result: IteratorResult<TOutput>) => void> = [];\n let done = false;\n let error: unknown;\n const emit = (value: TOutput) => {\n const waiter = waiters.shift();\n\n if (waiter) waiter({ done: false, value });\n else chunks.push(value);\n };\n const finish = (reason?: unknown) => {\n done = true;\n error = reason;\n\n while (waiters.length > 0) {\n const waiter = waiters.shift()!;\n\n if (reason !== undefined) waiter(Promise.reject(reason) as never);\n else waiter({ done: true, value: undefined as never });\n }\n };\n const donePromise = this.#dispatch(input, options.transferables ?? [], options.timeout, 'stream', emit).then(\n () => finish(),\n (reason: unknown) => finish(reason),\n );\n\n return {\n done: donePromise,\n iterable: {\n [Symbol.asyncIterator]: () => ({\n async next(): Promise<IteratorResult<TOutput>> {\n if (chunks.length > 0) return { done: false, value: chunks.shift()! };\n\n if (error !== undefined) throw error;\n\n if (done) return { done: true, value: undefined as never };\n\n return new Promise<IteratorResult<TOutput>>((resolve, reject) => {\n waiters.push((result) => {\n if (result instanceof Promise) void result.then(resolve, reject);\n else resolve(result);\n });\n });\n },\n async return(): Promise<IteratorResult<TOutput>> {\n stop();\n\n return { done: true, value: undefined as never };\n },\n }),\n },\n };\n }\n\n terminate(): void {\n this.#disposed = true;\n this.cancel(new FamiliarTerminatedError());\n }\n\n #dispatch(\n input: TInput,\n transferables: Transferable[],\n timeout: number | undefined,\n kind: 'run' | 'stream',\n emit?: (value: TOutput) => void,\n ): Promise<TOutput> {\n if (this.#disposed) return Promise.reject(new FamiliarTerminatedError());\n\n if (this.#pending) return Promise.reject(new FamiliarRuntimeError('Worker slot is already busy'));\n\n try {\n const worker = this.#ensureWorker();\n const id = this.#taskId++;\n\n return new Promise<TOutput>((resolve, reject) => {\n const pending: Pending<TOutput> = { emit, id, reject, resolve };\n\n this.#pending = pending;\n\n if (timeout !== undefined) {\n pending.timer = setTimeout(() => this.cancel(new FamiliarTimeoutError(timeout)), timeout);\n unrefTimer(pending.timer);\n }\n\n try {\n worker.postMessage({ id, input, kind, version: PROTOCOL_VERSION }, transferables);\n } catch (error) {\n this.cancel(new FamiliarRuntimeError('Failed to post message to worker', { cause: error }));\n }\n });\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #ensureWorker(): Worker {\n if (this.#worker) return this.#worker;\n\n if (typeof Worker === 'undefined') throw new FamiliarRuntimeError('Worker API is unavailable in this runtime');\n\n try {\n const worker = new Worker(this.#url, { type: 'module' });\n\n worker.onmessage = (event: MessageEvent<unknown>) => this.#onMessage(event.data);\n worker.onerror = (event) => {\n const error = new FamiliarRuntimeError(event.message || 'Worker failed');\n\n this.#worker = undefined;\n this.#onSlotError?.(error);\n this.#settlePending('reject', error);\n };\n this.#worker = worker;\n\n return worker;\n } catch (error) {\n throw new FamiliarRuntimeError('Failed to create Worker', { cause: error });\n }\n }\n\n #onMessage(message: unknown): void {\n if (!this.#pending) return;\n\n if (!isWorkerResponse<TOutput>(message) || message.id !== this.#pending.id) {\n this.cancel(new FamiliarRuntimeError('Worker returned an incompatible protocol response'));\n\n return;\n }\n\n if (message.kind === 'chunk') {\n this.#pending.emit?.(message.value);\n\n return;\n }\n\n if (message.kind === 'error') {\n this.#settlePending('reject', taskError(message.error));\n\n return;\n }\n\n this.#settlePending('resolve', message.value);\n }\n\n #settlePending(kind: 'resolve' | 'reject', value: unknown): void {\n const pending = this.#pending;\n\n if (!pending) return;\n\n this.#pending = undefined;\n\n if (pending.timer) clearTimeout(pending.timer);\n\n if (kind === 'resolve') pending.resolve(value as TOutput);\n else pending.reject(value);\n }\n}\n\nfunction slots<TInput, TOutput>(url: URL | string, options: ResolvedOptions): Slot<TInput, TOutput>[] {\n return Array.from({ length: options.concurrency }, () => new Slot<TInput, TOutput>(url, options.onSlotError));\n}\n\n/** Create a pool backed by an ES module worker registered with exposeTask(). */\nexport function createWorker<TInput, TOutput>(\n url: URL | string,\n options: WorkerOptions = {},\n): WorkerPool<TInput, TOutput> {\n const resolved = resolveOptions(options);\n\n return createPool(slots<TInput, TOutput>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n\n/** Create a stream-only pool backed by an ES module worker registered with exposeStream(). */\nexport function createStreamWorker<TInput, TChunk>(\n url: URL | string,\n options: WorkerOptions = {},\n): StreamWorkerPool<TInput, TChunk> {\n const resolved = resolveOptions(options);\n\n return createStreamPool(slots<TInput, TChunk>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"familiar.js","names":[],"sources":["../src/_timers.ts","../src/errors.ts","../src/_pool-core.ts","../src/_pool.ts","../src/_stream-pool.ts","../src/worker.ts"],"sourcesContent":["/**\n * Node compatibility helper: `unref()`s a timer so a pending per-task timeout/watchdog does not\n * keep a Node event loop (e.g. a Worker polyfill) alive. Browsers return a plain number from\n * `setTimeout`/`setInterval`, so this is a no-op there.\n *\n * Not part of the public API surface.\n */\nexport function unrefTimer(timer: ReturnType<typeof setTimeout> | ReturnType<typeof setInterval>): void {\n if (typeof timer === 'object' && timer !== null && 'unref' in timer) {\n (timer as { unref(): void }).unref();\n }\n}\n","/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when invalid options are passed to a Familiar pool factory. */\nexport class FamiliarInvalidOptionsError extends FamiliarError {}\n\n/** Thrown when run() is called and the queue is full (`onFull='reject'`). */\nexport class FamiliarQueueFullError extends FamiliarError {\n /** The configured `maxQueue` value. */\n readonly maxQueue: number;\n\n constructor(maxQueue: number) {\n super(`Queue is full (maxQueue=${maxQueue})`);\n this.maxQueue = maxQueue;\n }\n}\n\n/** Thrown when the task function throws. The original error is available as `.cause`. */\nexport class FamiliarTaskError extends FamiliarError {}\n\n/** Thrown when a task or operation is rejected because the worker was terminated. */\nexport class FamiliarTerminatedError extends FamiliarError {\n constructor(message = 'Worker was terminated') {\n super(message);\n }\n}\n\n/** Thrown when a task exceeds its timeout or `drain()` times out. */\nexport class FamiliarTimeoutError extends FamiliarError {\n /** The configured timeout in milliseconds. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, operation = 'Task') {\n super(`${operation} timed out after ${timeoutMs}ms`);\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */\nexport class FamiliarRuntimeError extends FamiliarError {}\n","import { abortError, tapper } from '@vielzeug/arsenal';\nimport { unrefTimer } from './_timers.js';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n type FamiliarRuntimeError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors.js';\nimport type { DrainOptions, FamiliarTapEvent, WorkerStats, WorkerStatus } from './types.js';\n\nexport const MAX_CONCURRENCY = 512;\nexport const MAX_TIMEOUT = 2_147_483_647;\n\nexport function validatePriority(priority: number): number {\n if (!Number.isFinite(priority)) throw new FamiliarInvalidOptionsError('`priority` must be a finite number');\n return priority;\n}\n\nexport function validateTimeout(timeout: number | undefined, name = 'timeout'): number | undefined {\n if (timeout !== undefined && (!Number.isInteger(timeout) || timeout < 1 || timeout > MAX_TIMEOUT)) {\n throw new FamiliarInvalidOptionsError(`\\`${name}\\` must be an integer from 1 through ${MAX_TIMEOUT}`);\n }\n return timeout;\n}\n\nexport type PoolOptions = {\n defaultTimeout: number | undefined;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n};\n\nexport type AcquireOptions = {\n priority: number;\n signal?: AbortSignal;\n};\n\n/**\n * A pool slot: tearable on disposal, with an optional channel for reporting\n * unhandled runtime errors. Pool factories wire `notify` to the core's tap so\n * slot owners can emit without holding a pool reference.\n */\nexport type PoolSlot = {\n notify?(error: FamiliarRuntimeError): void;\n terminate(): void;\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 priority: number;\n reject(reason: unknown): void;\n resolve(): void;\n sequence: number;\n};\n\ntype SlotWaiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n start(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport interface PoolCore<TSlot> {\n /**\n * Acquire a free slot and hand it to `fn`, which runs the acquired work.\n * `fn` is invoked synchronously both for an immediately free slot and when\n * a release hands the next waiter its slot, so dispatch never lags a\n * release by a microtask. Honors priority, FIFO order, abort, and `maxQueue`\n * admission; failures surface as a rejected promise. Without `fn`, resolves\n * with the slot instead.\n */\n acquire(options: AcquireOptions): Promise<TSlot>;\n acquire<R>(options: AcquireOptions, fn: (slot: TSlot) => R | Promise<R>): Promise<R>;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n drain(options?: DrainOptions): Promise<void>;\n readonly drainPromise: Promise<void> | undefined;\n emitTap(event: FamiliarTapEvent): void;\n /** Return a slot to the pool, handing it to the highest-priority waiter if any. */\n release(slot: TSlot): void;\n settleIdle(): void;\n stats(): WorkerStats;\n status(): WorkerStatus;\n tap(handler: (event: FamiliarTapEvent) => void, options?: { readonly signal?: AbortSignal }): () => void;\n trackActive(delta: number): void;\n trackCompleted(): void;\n trackFailed(): void;\n}\n\n/**\n * The single slot scheduler shared by the result pool and the stream pool:\n * free-slot fast path, priority/FIFO waiter queue, `maxQueue` admission with\n * capacity waiters, idle/drain tracking, stats, disposal, and tap observation.\n * The two pools differ only in what they do with an acquired slot.\n */\nexport function createPoolCore<TSlot extends PoolSlot>(slots: readonly TSlot[], options: PoolOptions): PoolCore<TSlot> {\n const freeSlots = [...slots];\n const waiters: SlotWaiter<TSlot>[] = [];\n const idleWaiters: IdleWaiter[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const tappers = tapper<FamiliarTapEvent>();\n const disposalController = new AbortController();\n let active = 0;\n let waiterSequence = 0;\n let capacitySequence = 0;\n let completed = 0;\n let failed = 0;\n let drainPromise: Promise<void> | undefined;\n let terminated = false;\n\n function isIdle(): boolean {\n return freeSlots.length === slots.length && waiters.length === 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!, 'Drain'));\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, priority: number): 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 priority,\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 sequence: capacitySequence++,\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n capacityWaiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\n }\n\n function acquire<R>(acquireOptions: AcquireOptions, fn?: (slot: TSlot) => R | Promise<R>): Promise<R | TSlot> {\n const { priority, signal } = acquireOptions;\n\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return (async () => {\n for (;;) {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (options.maxQueue === undefined || waiters.length < options.maxQueue) {\n return admit(acquireOptions, (fn ?? ((slot) => slot)) as (slot: TSlot) => R | Promise<R>);\n }\n\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(signal, priority);\n\n if (signal?.aborted) {\n releaseCapacity();\n throw abortError(signal);\n }\n }\n })();\n }\n\n function admit<R>(acquireOptions: AcquireOptions, fn: (slot: TSlot) => R | Promise<R>): Promise<R> {\n const { priority, signal } = acquireOptions;\n\n const free = freeSlots.pop();\n\n if (free) {\n try {\n return Promise.resolve(fn(free));\n } catch (error) {\n // A synchronous throw must not strand the slot: idle would never settle.\n release(free);\n settleIdle();\n\n return Promise.reject(error);\n }\n }\n\n return new Promise<R>((resolve, reject) => {\n const waiter: SlotWaiter<TSlot> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority,\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 sequence: waiterSequence++,\n signal,\n start(slot) {\n waiter.cleanup();\n\n try {\n resolve(fn(slot));\n } catch (error) {\n release(slot);\n settleIdle();\n reject(error);\n }\n },\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 release(slot: TSlot): void {\n const next = waiters.shift();\n\n if (next) {\n next.start(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n\n for (const slot of slots) slot.terminate();\n\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n tappers.emit({ type: 'dispose' });\n tappers.clear();\n }\n\n function drain(drainOptions: DrainOptions = {}): Promise<void> {\n if (terminated) return Promise.resolve();\n try {\n validateTimeout(drainOptions.timeout, 'drain.timeout');\n } catch (error) {\n return Promise.reject(error);\n }\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 acquire,\n disposalSignal: disposalController.signal,\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n get drainPromise() {\n return drainPromise;\n },\n emitTap(event) {\n tappers.emit(event);\n },\n release,\n settleIdle,\n stats() {\n return { active, completed, failed, queued: waiters.length + capacityWaiters.length };\n },\n status() {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n },\n tap(handler, tapOptions) {\n if (terminated) return () => undefined;\n\n return tappers.tap(handler, tapOptions);\n },\n trackActive(delta: number) {\n active += delta;\n },\n trackCompleted() {\n completed += 1;\n },\n trackFailed() {\n failed += 1;\n },\n };\n}\n","import { abortError } from '@vielzeug/arsenal';\nimport { createPoolCore, type PoolCore, type PoolOptions, validatePriority, validateTimeout } from './_pool-core.js';\nimport { FamiliarRuntimeError, FamiliarTerminatedError } from './errors.js';\nimport type { RunOptions, SlotStrategy, WorkerPool } from './types.js';\n\nexport type { PoolOptions } from './_pool-core.js';\n\nexport function createPool<TInput, TOutput>(\n slots: readonly SlotStrategy<TInput, TOutput>[],\n options: PoolOptions,\n): WorkerPool<TInput, TOutput> {\n const core: PoolCore<SlotStrategy<TInput, TOutput>> = createPoolCore(slots, options);\n\n for (const slot of slots) slot.notify = (error) => core.emitTap({ error, type: 'worker-error' });\n\n function run(input: TInput, runOptions: RunOptions = {}): Promise<TOutput> {\n let priority: number;\n let timeout: number | undefined;\n let transferables: Transferable[];\n\n try {\n priority = validatePriority(runOptions.priority ?? 0);\n timeout = validateTimeout(runOptions.timeout) ?? options.defaultTimeout;\n transferables = [...(runOptions.transferables ?? [])];\n } catch (error) {\n return Promise.reject(error);\n }\n\n return core.acquire({ priority, signal: runOptions.signal }, (slot) => {\n core.trackActive(1);\n\n const onAbort = () => slot.cancel(abortError(runOptions.signal!));\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n const finish = async (): Promise<TOutput> => {\n try {\n const value = await slot.run(input, transferables, timeout);\n\n core.trackCompleted();\n\n return value;\n } catch (error) {\n if (!runOptions.signal?.aborted && !(error instanceof FamiliarTerminatedError)) core.trackFailed();\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n core.trackActive(-1);\n core.release(slot);\n core.settleIdle();\n }\n };\n\n return finish();\n });\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n run,\n get stats() {\n return core.stats();\n },\n get status() {\n return core.status();\n },\n tap: core.tap,\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n\nexport type BatchOptions<TInput> = Pick<RunOptions, 'priority' | 'signal' | 'timeout'> & {\n getTransferables?: (input: TInput, index: number) => readonly Transferable[];\n};\n\n/** Run related tasks concurrently and yield their results in input order. */\nexport function runBatch<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n inputs: readonly TInput[],\n options: BatchOptions<TInput> = {},\n): AsyncIterable<TOutput> {\n let owner: object | undefined;\n\n const iterate = async function* (controller: AbortController): AsyncGenerator<TOutput> {\n const tasks: Promise<TOutput>[] = [];\n const onAbort = () => controller.abort(options.signal?.reason);\n\n if (options.signal?.aborted) controller.abort(options.signal.reason);\n else options.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n for (const [index, input] of inputs.entries()) {\n const task = pool\n .run(input, {\n priority: options.priority,\n signal: controller.signal,\n timeout: options.timeout,\n transferables: options.getTransferables?.(input, index),\n })\n .catch((error: unknown) => {\n controller.abort(error);\n throw error;\n });\n\n void task.catch(() => undefined);\n tasks.push(task);\n }\n\n if (tasks.length === 0 && controller.signal.aborted) throw abortError(controller.signal);\n for (const task of tasks) {\n if (controller.signal.aborted) throw abortError(controller.signal);\n const value = await task;\n if (controller.signal.aborted) throw abortError(controller.signal);\n yield value;\n }\n } catch (error) {\n controller.abort(error);\n throw error;\n } finally {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort(new DOMException('Batch consumer stopped', 'AbortError'));\n await Promise.allSettled(tasks);\n }\n };\n\n return {\n [Symbol.asyncIterator]() {\n const token = {};\n const controller = new AbortController();\n let iterator: AsyncGenerator<TOutput> | undefined;\n const start = (): AsyncGenerator<TOutput> | undefined => {\n owner ??= token;\n if (owner !== token) return undefined;\n iterator ??= iterate(controller);\n return iterator;\n };\n\n return {\n next: () =>\n start()?.next() ?? Promise.reject(new FamiliarRuntimeError('Worker batches can only be consumed once')),\n return: async (value?: unknown) => {\n if (!owner || owner !== token) return { done: true, value: value as TOutput };\n controller.abort(new FamiliarTerminatedError('Batch consumer stopped'));\n return iterator?.return(value as TOutput) ?? { done: true, value: value as TOutput };\n },\n throw: async (error?: unknown) => {\n const active = start();\n if (!active) throw new FamiliarRuntimeError('Worker batches can only be consumed once');\n controller.abort(error);\n return active.throw(error);\n },\n };\n },\n };\n}\n","import { abortError } from '@vielzeug/arsenal';\nimport { createPoolCore, type PoolCore, type PoolOptions, validatePriority, validateTimeout } from './_pool-core.js';\nimport { FamiliarRuntimeError, FamiliarTerminatedError } from './errors.js';\nimport type { RunOptions, StreamWorkerPool } from './types.js';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n /** Wired by the pool factory to report unhandled worker runtime errors through `tap()`. */\n notify?(error: FamiliarRuntimeError): void;\n stream(input: TInput, options: RunOptions): { done: Promise<void>; iterable: AsyncIterable<TChunk> };\n terminate(): void;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: readonly StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const core: PoolCore<StreamSlot<TInput, TChunk>> = createPoolCore(slots, options);\n\n for (const slot of slots) slot.notify = (error) => core.emitTap({ error, type: 'worker-error' });\n\n function runStream(input: TInput, runOptions: RunOptions = {}): AsyncIterable<TChunk> {\n const priority = validatePriority(runOptions.priority ?? 0);\n const timeout = validateTimeout(runOptions.timeout) ?? options.defaultTimeout;\n const transferables = [...(runOptions.transferables ?? [])];\n let owner: object | undefined;\n\n const iterate = async function* (controller: AbortController): AsyncGenerator<TChunk> {\n const onAbort = () => controller.abort(runOptions.signal?.reason);\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n if (runOptions.signal?.aborted) controller.abort(runOptions.signal.reason);\n else runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const running = await core.acquire({ priority, signal: controller.signal }, (acquired) => {\n slot = acquired;\n core.trackActive(1);\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n return acquired.stream(input, { priority, signal: controller.signal, timeout, transferables });\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n core.trackCompleted();\n } catch (error) {\n if (slot && !controller.signal.aborted && !(error instanceof FamiliarTerminatedError)) core.trackFailed();\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 core.trackActive(-1);\n core.release(slot);\n core.settleIdle();\n }\n }\n };\n\n return {\n [Symbol.asyncIterator]() {\n const token = {};\n const controller = new AbortController();\n let iterator: AsyncGenerator<TChunk> | undefined;\n const start = (): AsyncGenerator<TChunk> | undefined => {\n owner ??= token;\n if (owner !== token) return undefined;\n iterator ??= iterate(controller);\n return iterator;\n };\n\n return {\n next: () =>\n start()?.next() ?? Promise.reject(new FamiliarRuntimeError('Worker streams can only be consumed once')),\n return: async (value?: unknown) => {\n if (!owner || owner !== token) return { done: true, value: value as TChunk };\n controller.abort(new FamiliarTerminatedError('Stream consumer stopped'));\n return iterator?.return(value as TChunk) ?? { done: true, value: value as TChunk };\n },\n throw: async (error?: unknown) => {\n const active = start();\n if (!active) throw new FamiliarRuntimeError('Worker streams can only be consumed once');\n controller.abort(error);\n return active.throw(error);\n },\n };\n },\n };\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n runStream,\n get stats() {\n return core.stats();\n },\n get status() {\n return core.status();\n },\n tap: core.tap,\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n","import { createPool } from './_pool.js';\nimport { MAX_CONCURRENCY, validateTimeout } from './_pool-core.js';\nimport { createStreamPool, type StreamSlot } from './_stream-pool.js';\nimport { unrefTimer } from './_timers.js';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors.js';\nimport type { SerializedError, WorkerResponse } from './protocol.js';\nimport { PROTOCOL_VERSION } from './protocol.js';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } from './types.js';\n\ntype ResolvedOptions = {\n concurrency: number;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n timeout: number | undefined;\n};\n\ntype Pending<TOutput> = {\n emit?: (value: TOutput) => void;\n id: number;\n kind: 'run' | 'stream';\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\ntype RunningStream<TChunk> = {\n done: Promise<void>;\n iterable: AsyncIterable<TChunk>;\n};\n\nfunction resolveOptions(options: WorkerOptions = {}): ResolvedOptions {\n const { concurrency = 1, maxQueue, onFull = 'reject', timeout } = options;\n const resolvedConcurrency =\n concurrency === 'auto'\n ? Math.min(MAX_CONCURRENCY, Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1))\n : concurrency;\n\n if (!Number.isInteger(resolvedConcurrency) || resolvedConcurrency < 1 || resolvedConcurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY} or \"auto\"`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (onFull !== 'reject' && onFull !== 'wait') {\n throw new FamiliarInvalidOptionsError('`onFull` must be \"reject\" or \"wait\"');\n }\n\n validateTimeout(timeout);\n\n return { concurrency: resolvedConcurrency, maxQueue, onFull, timeout };\n}\n\nfunction isWorkerResponse<TOutput>(value: unknown): value is WorkerResponse<TOutput> {\n if (typeof value !== 'object' || value === null) return false;\n\n const response = value as Partial<WorkerResponse<TOutput>>;\n if (\n response.version !== PROTOCOL_VERSION ||\n typeof response.id !== 'number' ||\n !Number.isSafeInteger(response.id) ||\n response.id < 0\n )\n return false;\n\n if (response.kind === 'chunk' || response.kind === 'result') return 'value' in response;\n if (response.kind !== 'error' || typeof response.error !== 'object' || response.error === null) return false;\n\n return (\n (response.error.category === undefined || response.error.category === 'protocol') &&\n typeof response.error.message === 'string' &&\n typeof response.error.name === 'string' &&\n (response.error.stack === undefined || typeof response.error.stack === 'string')\n );\n}\n\nfunction responseError(error: SerializedError): FamiliarRuntimeError | FamiliarTaskError {\n const cause = new Error(error.message);\n\n cause.name = error.name;\n cause.stack = error.stack;\n\n return error.category === 'protocol'\n ? new FamiliarRuntimeError(error.message, { cause })\n : new FamiliarTaskError(error.message, { cause });\n}\n\nclass Slot<TInput, TOutput> implements SlotStrategy<TInput, TOutput>, StreamSlot<TInput, TOutput> {\n readonly #url: URL | string;\n #disposed = false;\n #pending: Pending<TOutput> | undefined;\n #taskId = 0;\n #worker: Worker | undefined;\n\n /** Wired by the pool factory to report unhandled worker runtime errors through `tap()`. */\n notify: ((error: FamiliarRuntimeError) => void) | undefined = undefined;\n\n constructor(url: URL | string) {\n this.#url = url;\n }\n\n cancel(reason: unknown): void {\n if (!this.#pending) return;\n this.#stopWorker();\n this.#settlePending('reject', reason);\n }\n\n run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput> {\n return this.#dispatch(input, transferables, timeout, 'run') as Promise<TOutput>;\n }\n\n stream(input: TInput, options: RunOptions): RunningStream<TOutput> {\n const stop = () => this.cancel(new FamiliarTerminatedError('Stream consumer stopped'));\n const chunks: TOutput[] = [];\n const waiters: Array<(result: IteratorResult<TOutput>) => void> = [];\n let done = false;\n let error: unknown;\n const emit = (value: TOutput) => {\n const waiter = waiters.shift();\n\n if (waiter) waiter({ done: false, value });\n else chunks.push(value);\n };\n const finish = (reason?: unknown) => {\n done = true;\n error = reason;\n\n while (waiters.length > 0) {\n const waiter = waiters.shift()!;\n\n if (reason !== undefined) waiter(Promise.reject(reason) as never);\n else waiter({ done: true, value: undefined as never });\n }\n };\n const donePromise = this.#dispatch(input, [...(options.transferables ?? [])], options.timeout, 'stream', emit).then(\n () => finish(),\n (reason: unknown) => finish(reason),\n );\n\n return {\n done: donePromise,\n iterable: {\n [Symbol.asyncIterator]: () => ({\n async next(): Promise<IteratorResult<TOutput>> {\n if (chunks.length > 0) return { done: false, value: chunks.shift()! };\n\n if (error !== undefined) throw error;\n\n if (done) return { done: true, value: undefined as never };\n\n return new Promise<IteratorResult<TOutput>>((resolve, reject) => {\n waiters.push((result) => {\n if (result instanceof Promise) void result.then(resolve, reject);\n else resolve(result);\n });\n });\n },\n async return(): Promise<IteratorResult<TOutput>> {\n stop();\n\n return { done: true, value: undefined as never };\n },\n }),\n },\n };\n }\n\n terminate(): void {\n this.#disposed = true;\n this.#stopWorker();\n this.#settlePending('reject', new FamiliarTerminatedError());\n }\n\n #dispatch(\n input: TInput,\n transferables: Transferable[],\n timeout: number | undefined,\n kind: 'run' | 'stream',\n emit?: (value: TOutput) => void,\n ): Promise<TOutput> {\n if (this.#disposed) return Promise.reject(new FamiliarTerminatedError());\n\n if (this.#pending) return Promise.reject(new FamiliarRuntimeError('Worker slot is already busy'));\n\n try {\n const worker = this.#ensureWorker();\n const id = this.#taskId;\n this.#taskId = id === Number.MAX_SAFE_INTEGER ? 0 : id + 1;\n\n return new Promise<TOutput>((resolve, reject) => {\n const pending: Pending<TOutput> = { emit, id, kind, reject, resolve };\n\n this.#pending = pending;\n\n if (timeout !== undefined) {\n pending.timer = setTimeout(() => this.cancel(new FamiliarTimeoutError(timeout)), timeout);\n unrefTimer(pending.timer);\n }\n\n try {\n worker.postMessage({ id, input, kind, version: PROTOCOL_VERSION }, transferables);\n } catch (error) {\n this.cancel(new FamiliarRuntimeError('Failed to post message to worker', { cause: error }));\n }\n });\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #ensureWorker(): Worker {\n if (this.#worker) return this.#worker;\n\n if (typeof Worker === 'undefined') throw new FamiliarRuntimeError('Worker API is unavailable in this runtime');\n\n try {\n const worker = new Worker(this.#url, { type: 'module' });\n\n worker.onmessage = (event: MessageEvent<unknown>) => {\n if (this.#worker === worker) this.#onMessage(event.data);\n };\n worker.onerror = (event) => this.#failWorker(worker, new FamiliarRuntimeError(event.message || 'Worker failed'));\n worker.onmessageerror = () =>\n this.#failWorker(worker, new FamiliarRuntimeError('Worker response could not be deserialized'));\n this.#worker = worker;\n\n return worker;\n } catch (error) {\n throw new FamiliarRuntimeError('Failed to create Worker', { cause: error });\n }\n }\n\n #stopWorker(): void {\n const worker = this.#worker;\n this.#worker = undefined;\n if (!worker) return;\n\n worker.onmessage = null;\n worker.onerror = null;\n worker.onmessageerror = null;\n worker.terminate();\n }\n\n #failWorker(worker: Worker, error: FamiliarRuntimeError): void {\n if (this.#worker !== worker) return;\n\n this.#stopWorker();\n this.#settlePending('reject', error);\n this.notify?.(error);\n }\n\n #onMessage(message: unknown): void {\n if (!this.#pending) return;\n\n if (\n !isWorkerResponse<TOutput>(message) ||\n message.id !== this.#pending.id ||\n (this.#pending.kind === 'run' && message.kind === 'chunk')\n ) {\n this.cancel(new FamiliarRuntimeError('Worker returned an incompatible protocol response'));\n\n return;\n }\n\n if (message.kind === 'chunk') {\n this.#pending.emit?.(message.value);\n\n return;\n }\n\n if (message.kind === 'error') {\n this.#settlePending('reject', responseError(message.error));\n\n return;\n }\n\n this.#settlePending('resolve', message.value);\n }\n\n #settlePending(kind: 'resolve' | 'reject', value: unknown): void {\n const pending = this.#pending;\n\n if (!pending) return;\n\n this.#pending = undefined;\n\n if (pending.timer) clearTimeout(pending.timer);\n\n if (kind === 'resolve') pending.resolve(value as TOutput);\n else pending.reject(value);\n }\n}\n\nfunction slots<TInput, TOutput>(url: URL | string, options: ResolvedOptions): Slot<TInput, TOutput>[] {\n const resolvedUrl = typeof url === 'string' ? url : url.href;\n return Array.from({ length: options.concurrency }, () => new Slot<TInput, TOutput>(resolvedUrl));\n}\n\n/** Create a pool backed by an ES module worker registered with exposeTask(). */\nexport function createWorker<TInput, TOutput>(\n url: URL | string,\n options: WorkerOptions = {},\n): WorkerPool<TInput, TOutput> {\n const resolved = resolveOptions(options);\n\n return createPool(slots<TInput, TOutput>(url, resolved), {\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n\n/** Create a stream-only pool backed by an ES module worker registered with exposeStream(). */\nexport function createStreamWorker<TInput, TChunk>(\n url: URL | string,\n options: WorkerOptions = {},\n): StreamWorkerPool<TInput, TChunk> {\n const resolved = resolveOptions(options);\n\n return createStreamPool(slots<TInput, TChunk>(url, resolved), {\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./_pool.cjs"),n=require("./worker.cjs");exports.FamiliarError=e.FamiliarError,exports.FamiliarInvalidOptionsError=e.FamiliarInvalidOptionsError,exports.FamiliarQueueFullError=e.FamiliarQueueFullError,exports.FamiliarRuntimeError=e.FamiliarRuntimeError,exports.FamiliarTaskError=e.FamiliarTaskError,exports.FamiliarTerminatedError=e.FamiliarTerminatedError,exports.FamiliarTimeoutError=e.FamiliarTimeoutError,exports.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./_pool.cjs"),n=require("./worker.cjs");exports.FamiliarError=e.FamiliarError,exports.FamiliarInvalidOptionsError=e.FamiliarInvalidOptionsError,exports.FamiliarQueueFullError=e.FamiliarQueueFullError,exports.FamiliarRuntimeError=e.FamiliarRuntimeError,exports.FamiliarTaskError=e.FamiliarTaskError,exports.FamiliarTerminatedError=e.FamiliarTerminatedError,exports.FamiliarTimeoutError=e.FamiliarTimeoutError,exports.createStreamWorker=n.createStreamWorker,exports.createWorker=n.createWorker,exports.runBatch=t.runBatch;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { type BatchOptions, runBatch } from './_pool.js';
|
|
2
|
+
export { FamiliarError, FamiliarInvalidOptionsError, FamiliarQueueFullError, FamiliarRuntimeError, FamiliarTaskError, FamiliarTerminatedError, FamiliarTimeoutError, } from './errors.js';
|
|
3
|
+
export type { DrainOptions, FamiliarTapEvent, PoolBase, RunOptions, StreamWorkerPool, WorkerOptions, WorkerPool, WorkerStats, WorkerStatus, } from './types.js';
|
|
4
|
+
export { createStreamWorker, createWorker } from './worker.js';
|
|
2
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EACL,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { batch as s, createTaskGroup as c } from "./_pool.js";
|
|
3
|
-
import { createStreamWorker as l, createWorker as u } from "./worker.js";
|
|
4
|
-
export { e as FamiliarError, t as FamiliarInvalidOptionsError, n as FamiliarQueueFullError, r as FamiliarRuntimeError, i as FamiliarTaskError, a as FamiliarTerminatedError, o as FamiliarTimeoutError, s as batch, l as createStreamWorker, c as createTaskGroup, u as createWorker };
|
|
1
|
+
import{FamiliarError as e,FamiliarInvalidOptionsError as t,FamiliarQueueFullError as n,FamiliarRuntimeError as r,FamiliarTaskError as i,FamiliarTerminatedError as a,FamiliarTimeoutError as o}from"./errors.js";import{runBatch as s}from"./_pool.js";import{createStreamWorker as c,createWorker as l}from"./worker.js";export{e as FamiliarError,t as FamiliarInvalidOptionsError,n as FamiliarQueueFullError,r as FamiliarRuntimeError,i as FamiliarTaskError,a as FamiliarTerminatedError,o as FamiliarTimeoutError,c as createStreamWorker,l as createWorker,s as runBatch};
|
package/dist/protocol.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=1;function
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=1;function serializeError(e){let t=e instanceof Error?e:Error(String(e));return{message:t.message,name:t.name,stack:t.stack}}function isRequest(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.version===1&&typeof t.id==`number`&&Number.isSafeInteger(t.id)&&t.id>=0&&(t.kind===`run`||t.kind===`stream`)&&`input`in t}function post(e){self.postMessage(e)}function postError(e,t,n){post({error:{...serializeError(t),...n&&{category:n}},id:e,kind:`error`,version:1})}function exposeTask(e){self.onmessage=async t=>{if(!isRequest(t.data))return;if(t.data.kind!==`run`){postError(t.data.id,Error(`Worker is registered for tasks, not streams`),`protocol`);return}let{id:n,input:r}=t.data;try{post({id:n,kind:`result`,value:await e(r),version:1})}catch(e){postError(n,e)}}}function exposeStream(e){self.onmessage=async t=>{if(!isRequest(t.data))return;if(t.data.kind!==`stream`){postError(t.data.id,Error(`Worker is registered for streams, not tasks`),`protocol`);return}let{id:n,input:r}=t.data;try{for await(let t of await e(r))post({id:n,kind:`chunk`,value:t,version:1});post({id:n,kind:`result`,value:void 0,version:1})}catch(e){postError(n,e)}}}exports.PROTOCOL_VERSION=e,exports.exposeStream=exposeStream,exports.exposeTask=exposeTask;
|
|
2
2
|
//# sourceMappingURL=protocol.cjs.map
|