@vielzeug/familiar 26.10.14 → 26.10.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_pool-core.cjs.map +1 -1
- package/dist/_pool-core.js +171 -1
- package/dist/_pool-core.js.map +1 -1
- package/dist/_pool.cjs.map +1 -1
- package/dist/_pool.js +111 -1
- package/dist/_pool.js.map +1 -1
- package/dist/_stream-pool.cjs.map +1 -1
- package/dist/_stream-pool.js +77 -1
- package/dist/_stream-pool.js.map +1 -1
- package/dist/_timers.cjs.map +1 -1
- package/dist/_timers.js +7 -1
- package/dist/_timers.js.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.js +23 -1
- 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 +528 -1
- package/dist/familiar.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.js +78 -1
- package/dist/protocol.js.map +1 -1
- package/dist/testing/testing.cjs.map +1 -1
- package/dist/testing/testing.js +75 -1
- package/dist/testing/testing.js.map +1 -1
- package/dist/testing.js +3 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.js +166 -1
- package/dist/worker.js.map +1 -1
- package/package.json +5 -5
package/dist/worker.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.cjs","names":[],"sources":["../src/worker.ts"],"sourcesContent":["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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"}
|
|
1
|
+
{"version":3,"file":"worker.cjs","names":["FamiliarInvalidOptionsError","FamiliarRuntimeError","FamiliarTaskError","FamiliarTerminatedError","FamiliarTimeoutError","createPool","createStreamPool","require__timers","require_errors","require__pool_core","require__pool","require__stream_pool","options","resolvedConcurrency","concurrency","maxQueue","onFull","timeout","value","response","cause","error","#url","url","#pending","#stopWorker","#settlePending","reason","#dispatch","input","transferables","chunks","waiters","done","waiter","result","resolve","reject","#disposed","worker","#ensureWorker","id","#taskId","pending","#worker","#onMessage","event","#failWorker","message","kind","resolvedUrl","resolved"],"sources":["../src/worker.ts"],"sourcesContent":["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/worker.js
CHANGED
|
@@ -1,2 +1,167 @@
|
|
|
1
|
-
import{unrefTimer as e
|
|
1
|
+
import { unrefTimer as e } from "./_timers.js";
|
|
2
|
+
import { FamiliarInvalidOptionsError as t, FamiliarRuntimeError as n, FamiliarTaskError as r, FamiliarTerminatedError as i, FamiliarTimeoutError as a } from "./errors.js";
|
|
3
|
+
import { validateTimeout as o } from "./_pool-core.js";
|
|
4
|
+
import { createPool as s } from "./_pool.js";
|
|
5
|
+
import { createStreamPool as c } from "./_stream-pool.js";
|
|
6
|
+
import "./protocol.js";
|
|
7
|
+
//#region src/worker.ts
|
|
8
|
+
function resolveOptions(e = {}) {
|
|
9
|
+
let { concurrency: n = 1, maxQueue: r, onFull: i = "reject", timeout: a } = e, s = n === "auto" ? Math.min(512, Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1)) : n;
|
|
10
|
+
if (!Number.isInteger(s) || s < 1 || s > 512) throw new t("`concurrency` must be a positive integer ≤ 512 or \"auto\"");
|
|
11
|
+
if (r !== void 0 && (!Number.isInteger(r) || r < 1)) throw new t("`maxQueue` must be a positive integer");
|
|
12
|
+
if (i !== "reject" && i !== "wait") throw new t("`onFull` must be \"reject\" or \"wait\"");
|
|
13
|
+
return o(a), {
|
|
14
|
+
concurrency: s,
|
|
15
|
+
maxQueue: r,
|
|
16
|
+
onFull: i,
|
|
17
|
+
timeout: a
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function isWorkerResponse(e) {
|
|
21
|
+
if (typeof e != "object" || !e) return !1;
|
|
22
|
+
let t = e;
|
|
23
|
+
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");
|
|
24
|
+
}
|
|
25
|
+
function responseError(e) {
|
|
26
|
+
let t = Error(e.message);
|
|
27
|
+
return t.name = e.name, t.stack = e.stack, e.category === "protocol" ? new n(e.message, { cause: t }) : new r(e.message, { cause: t });
|
|
28
|
+
}
|
|
29
|
+
var Slot = class {
|
|
30
|
+
#e;
|
|
31
|
+
#t = !1;
|
|
32
|
+
#n;
|
|
33
|
+
#r = 0;
|
|
34
|
+
#i;
|
|
35
|
+
notify = void 0;
|
|
36
|
+
constructor(e) {
|
|
37
|
+
this.#e = e;
|
|
38
|
+
}
|
|
39
|
+
cancel(e) {
|
|
40
|
+
this.#n && (this.#s(), this.#u("reject", e));
|
|
41
|
+
}
|
|
42
|
+
run(e, t, n) {
|
|
43
|
+
return this.#a(e, t, n, "run");
|
|
44
|
+
}
|
|
45
|
+
stream(e, t) {
|
|
46
|
+
let stop = () => this.cancel(new i("Stream consumer stopped")), n = [], r = [], a = !1, o, emit = (e) => {
|
|
47
|
+
let t = r.shift();
|
|
48
|
+
t ? t({
|
|
49
|
+
done: !1,
|
|
50
|
+
value: e
|
|
51
|
+
}) : n.push(e);
|
|
52
|
+
}, finish = (e) => {
|
|
53
|
+
for (a = !0, o = e; r.length > 0;) r.shift()(e === void 0 ? {
|
|
54
|
+
done: !0,
|
|
55
|
+
value: void 0
|
|
56
|
+
} : Promise.reject(e));
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
done: this.#a(e, [...t.transferables ?? []], t.timeout, "stream", emit).then(() => finish(), (e) => finish(e)),
|
|
60
|
+
iterable: { [Symbol.asyncIterator]: () => ({
|
|
61
|
+
async next() {
|
|
62
|
+
if (n.length > 0) return {
|
|
63
|
+
done: !1,
|
|
64
|
+
value: n.shift()
|
|
65
|
+
};
|
|
66
|
+
if (o !== void 0) throw o;
|
|
67
|
+
return a ? {
|
|
68
|
+
done: !0,
|
|
69
|
+
value: void 0
|
|
70
|
+
} : new Promise((e, t) => {
|
|
71
|
+
r.push((n) => {
|
|
72
|
+
n instanceof Promise ? n.then(e, t) : e(n);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
async return() {
|
|
77
|
+
return stop(), {
|
|
78
|
+
done: !0,
|
|
79
|
+
value: void 0
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}) }
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
terminate() {
|
|
86
|
+
this.#t = !0, this.#s(), this.#u("reject", new i());
|
|
87
|
+
}
|
|
88
|
+
#a(t, r, o, s, c) {
|
|
89
|
+
if (this.#t) return Promise.reject(new i());
|
|
90
|
+
if (this.#n) return Promise.reject(new n("Worker slot is already busy"));
|
|
91
|
+
try {
|
|
92
|
+
let i = this.#o(), l = this.#r;
|
|
93
|
+
return this.#r = l === 2 ** 53 - 1 ? 0 : l + 1, new Promise((u, d) => {
|
|
94
|
+
let f = {
|
|
95
|
+
emit: c,
|
|
96
|
+
id: l,
|
|
97
|
+
kind: s,
|
|
98
|
+
reject: d,
|
|
99
|
+
resolve: u
|
|
100
|
+
};
|
|
101
|
+
this.#n = f, o !== void 0 && (f.timer = setTimeout(() => this.cancel(new a(o)), o), e(f.timer));
|
|
102
|
+
try {
|
|
103
|
+
i.postMessage({
|
|
104
|
+
id: l,
|
|
105
|
+
input: t,
|
|
106
|
+
kind: s,
|
|
107
|
+
version: 1
|
|
108
|
+
}, r);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
this.cancel(new n("Failed to post message to worker", { cause: e }));
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
} catch (e) {
|
|
114
|
+
return Promise.reject(e);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
#o() {
|
|
118
|
+
if (this.#i) return this.#i;
|
|
119
|
+
if (typeof Worker > "u") throw new n("Worker API is unavailable in this runtime");
|
|
120
|
+
try {
|
|
121
|
+
let e = new Worker(this.#e, { type: "module" });
|
|
122
|
+
return e.onmessage = (t) => {
|
|
123
|
+
this.#i === e && this.#l(t.data);
|
|
124
|
+
}, e.onerror = (t) => this.#c(e, new n(t.message || "Worker failed")), e.onmessageerror = () => this.#c(e, new n("Worker response could not be deserialized")), this.#i = e, e;
|
|
125
|
+
} catch (e) {
|
|
126
|
+
throw new n("Failed to create Worker", { cause: e });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
#s() {
|
|
130
|
+
let e = this.#i;
|
|
131
|
+
this.#i = void 0, e && (e.onmessage = null, e.onerror = null, e.onmessageerror = null, e.terminate());
|
|
132
|
+
}
|
|
133
|
+
#c(e, t) {
|
|
134
|
+
this.#i === e && (this.#s(), this.#u("reject", t), this.notify?.(t));
|
|
135
|
+
}
|
|
136
|
+
#l(e) {
|
|
137
|
+
this.#n && (!isWorkerResponse(e) || e.id !== this.#n.id || this.#n.kind === "run" && e.kind === "chunk" ? this.cancel(new n("Worker returned an incompatible protocol response")) : e.kind === "chunk" ? this.#n.emit?.(e.value) : e.kind === "error" ? this.#u("reject", responseError(e.error)) : this.#u("resolve", e.value));
|
|
138
|
+
}
|
|
139
|
+
#u(e, t) {
|
|
140
|
+
let n = this.#n;
|
|
141
|
+
n && (this.#n = void 0, n.timer && clearTimeout(n.timer), e === "resolve" ? n.resolve(t) : n.reject(t));
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
function slots(e, t) {
|
|
145
|
+
let n = typeof e == "string" ? e : e.href;
|
|
146
|
+
return Array.from({ length: t.concurrency }, () => new Slot(n));
|
|
147
|
+
}
|
|
148
|
+
function createWorker(e, t = {}) {
|
|
149
|
+
let n = resolveOptions(t);
|
|
150
|
+
return s(slots(e, n), {
|
|
151
|
+
defaultTimeout: n.timeout,
|
|
152
|
+
maxQueue: n.maxQueue,
|
|
153
|
+
onFull: n.onFull
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function createStreamWorker(e, t = {}) {
|
|
157
|
+
let n = resolveOptions(t);
|
|
158
|
+
return c(slots(e, n), {
|
|
159
|
+
defaultTimeout: n.timeout,
|
|
160
|
+
maxQueue: n.maxQueue,
|
|
161
|
+
onFull: n.onFull
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
export { createStreamWorker, createWorker };
|
|
166
|
+
|
|
2
167
|
//# sourceMappingURL=worker.js.map
|
package/dist/worker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","names":[],"sources":["../src/worker.ts"],"sourcesContent":["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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"}
|
|
1
|
+
{"version":3,"file":"worker.js","names":["options","resolvedConcurrency","concurrency","FamiliarInvalidOptionsError","maxQueue","onFull","validateTimeout","timeout","value","response","cause","error","FamiliarRuntimeError","FamiliarTaskError","#url","url","#pending","#stopWorker","#settlePending","reason","#dispatch","input","transferables","FamiliarTerminatedError","chunks","waiters","done","waiter","result","resolve","reject","#disposed","worker","#ensureWorker","id","#taskId","pending","FamiliarTimeoutError","unrefTimer","#worker","#onMessage","event","#failWorker","message","kind","resolvedUrl","resolved","createPool","createStreamPool"],"sources":["../src/worker.ts"],"sourcesContent":["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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vielzeug/familiar",
|
|
3
|
-
"version": "26.10.
|
|
3
|
+
"version": "26.10.16",
|
|
4
4
|
"description": "Web Worker pool with tasks, timeouts, cancellation",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
"verify:exports": "node verify-exports.mjs"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@vielzeug/arsenal": "26.10.
|
|
65
|
+
"@vielzeug/arsenal": "26.10.16"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@types/node": "^26.6.
|
|
68
|
+
"@types/node": "^26.6.5",
|
|
69
69
|
"typescript": "^6.0.3",
|
|
70
|
-
"vite": "^8.3.
|
|
71
|
-
"vitest": "^5.0.
|
|
70
|
+
"vite": "^8.3.4",
|
|
71
|
+
"vitest": "^5.0.5"
|
|
72
72
|
}
|
|
73
73
|
}
|