@dmop/puru 0.1.4 → 0.1.5

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/serialize.ts","../src/configure.ts","../src/runtime.ts","../src/adapters/node.ts","../src/bootstrap.ts","../src/adapters/bun.ts","../src/channel.ts","../src/adapters/inline.ts","../src/pool.ts","../src/spawn.ts","../src/waitgroup.ts","../src/errgroup.ts","../src/mutex.ts","../src/once.ts","../src/select.ts","../src/after.ts","../src/ticker.ts","../src/registry.ts"],"sourcesContent":["export { spawn } from './spawn.js'\nexport { chan } from './channel.js'\nexport type { Channel } from './channel.js'\nexport { WaitGroup } from './waitgroup.js'\nexport { ErrGroup } from './errgroup.js'\nexport { Mutex } from './mutex.js'\nexport { Once } from './once.js'\nexport { select } from './select.js'\nexport type { SelectOptions } from './select.js'\nexport { after } from './after.js'\nexport { Ticker, ticker } from './ticker.js'\nexport { register, run } from './registry.js'\nexport { configure } from './configure.js'\nexport { stats, resize } from './pool.js'\nexport type { PoolStats } from './pool.js'\nexport { detectRuntime, detectCapability } from './runtime.js'\nexport type { Runtime, Capability } from './runtime.js'\nexport type { SpawnResult, PuruConfig } from './types.js'\n","const NATIVE_CODE_RE = /\\[native code\\]/\nconst METHOD_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*\\s*\\(/\n\n// A valid serialized function must start with one of these patterns.\n// This guards against prototype pollution on Function.prototype.toString\n// returning arbitrary strings.\nconst VALID_FN_START_RE = /^(?:function\\b|async\\s+function\\b|async\\s*\\(|\\(|[a-zA-Z_$][a-zA-Z0-9_$]*\\s*=>|async\\s+[a-zA-Z_$])/\n\nexport function serializeFunction(fn: Function): string {\n if (typeof fn !== 'function') {\n throw new TypeError('Expected a function')\n }\n\n const str = fn.toString()\n\n if (typeof str !== 'string' || str.length === 0) {\n throw new TypeError(\n 'Function serialization returned an invalid result. ' +\n 'This may indicate Function.prototype.toString has been tampered with.',\n )\n }\n\n if (NATIVE_CODE_RE.test(str)) {\n throw new TypeError(\n 'Native functions cannot be serialized. Use an arrow function wrapper instead.',\n )\n }\n\n if (!VALID_FN_START_RE.test(str)) {\n throw new TypeError(\n 'Function serialization produced unexpected output. ' +\n 'Only arrow functions, function expressions, and async functions are supported.',\n )\n }\n\n // Detect class methods like \"method() { ... }\" — not valid standalone functions\n if (\n METHOD_RE.test(str) &&\n !str.startsWith('function') &&\n !str.startsWith('async function') &&\n !str.startsWith('async (') &&\n !str.startsWith('async=') &&\n !str.startsWith('(') &&\n !str.includes('=>')\n ) {\n throw new TypeError(\n 'Class methods cannot be serialized. Use an arrow function wrapper instead.',\n )\n }\n\n return str\n}\n","import { availableParallelism } from 'node:os'\nimport type { PuruConfig } from './types.js'\n\nconst DEFAULT_CONFIG: PuruConfig = {\n maxThreads: availableParallelism?.() ?? 4,\n strategy: 'fifo',\n idleTimeout: 30_000,\n adapter: 'auto',\n concurrency: 64,\n}\n\nlet currentConfig: PuruConfig = { ...DEFAULT_CONFIG }\nlet configLocked = false\n\nexport function configure(opts: Partial<PuruConfig>): void {\n if (configLocked) {\n throw new Error(\n 'configure() must be called before the first spawn(). The worker pool has already been initialized.',\n )\n }\n currentConfig = { ...currentConfig, ...opts }\n}\n\nexport function getConfig(): PuruConfig {\n configLocked = true\n return { ...currentConfig }\n}\n\n/** @internal For testing only */\nexport function resetConfig(): void {\n currentConfig = { ...DEFAULT_CONFIG }\n configLocked = false\n}\n","export type Runtime = 'node' | 'deno' | 'bun' | 'browser'\nexport type Capability = 'full-threads' | 'single-thread'\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function detectRuntime(): Runtime {\n if (typeof (globalThis as any).Bun !== 'undefined') return 'bun'\n if (typeof (globalThis as any).Deno !== 'undefined') return 'deno'\n if (\n typeof globalThis.process !== 'undefined' &&\n globalThis.process.versions?.node\n )\n return 'node'\n return 'browser'\n}\n\nexport function detectCapability(): Capability {\n const runtime = detectRuntime()\n if (runtime === 'node' || runtime === 'bun') return 'full-threads'\n if (typeof (globalThis as any).Worker !== 'undefined') return 'full-threads'\n return 'single-thread'\n}\n","import { Worker } from 'node:worker_threads'\nimport { NODE_BOOTSTRAP_CODE } from '../bootstrap.js'\nimport type { ManagedWorker, WorkerAdapter } from './base.js'\n\nclass NodeManagedWorker implements ManagedWorker {\n private worker: Worker\n\n constructor() {\n this.worker = new Worker(NODE_BOOTSTRAP_CODE, { eval: true })\n }\n\n get id(): number {\n return this.worker.threadId\n }\n\n postMessage(data: unknown): void {\n this.worker.postMessage(data)\n }\n\n terminate(): Promise<number> {\n return this.worker.terminate()\n }\n\n on(event: 'message', handler: (data: unknown) => void): void\n on(event: 'error', handler: (err: Error) => void): void\n on(event: 'exit', handler: (code: number) => void): void\n on(event: string, handler: (...args: any[]) => void): void {\n this.worker.on(event, handler)\n }\n\n unref(): void {\n this.worker.unref()\n }\n\n ref(): void {\n this.worker.ref()\n }\n}\n\nexport class NodeWorkerAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new NodeManagedWorker()\n }\n}\n","/**\n * Channel proxy code shared between Node and Web bootstraps.\n * Injected at the top of the worker, inert unless channels are passed.\n */\nconst CHANNEL_PROXY_CODE = `\nconst __chCallbacks = new Map();\nlet __chRpcId = 0;\n\nclass __ChannelProxy {\n constructor(id) {\n this._id = id;\n }\n\n _rpc(op, value) {\n const correlationId = ++__chRpcId;\n return new Promise((resolve, reject) => {\n __chCallbacks.set(correlationId, { resolve, reject });\n __postMsg({\n type: 'channel-op',\n channelId: this._id,\n op,\n correlationId,\n value\n });\n });\n }\n\n send(value) {\n return this._rpc('send', value);\n }\n\n recv() {\n return this._rpc('recv', undefined);\n }\n\n close() {\n __postMsg({\n type: 'channel-op',\n channelId: this._id,\n op: 'close',\n correlationId: ++__chRpcId\n });\n }\n\n [Symbol.asyncIterator]() {\n const proxy = this;\n return {\n async next() {\n const value = await proxy.recv();\n if (value === null) return { done: true, value: undefined };\n return { done: false, value };\n }\n };\n }\n}\n\nfunction __handleChannelResult(msg) {\n if (msg.type === 'channel-result') {\n const cb = __chCallbacks.get(msg.correlationId);\n if (cb) {\n __chCallbacks.delete(msg.correlationId);\n if (msg.error) {\n cb.reject(new Error(msg.error));\n } else {\n cb.resolve(msg.value);\n }\n }\n }\n}\n\nfunction __buildChannelProxies(channels) {\n if (!channels) return undefined;\n const proxies = {};\n for (const name of Object.keys(channels)) {\n proxies[name] = new __ChannelProxy(channels[name]);\n }\n return proxies;\n}\n\nfunction __execFn(fnStr, channels) {\n if (channels) {\n const __ch = __buildChannelProxies(channels);\n const fn = new Function('__ch', 'return (' + fnStr + ')(__ch)');\n return fn(__ch);\n } else {\n const fn = new Function('return (' + fnStr + ')()');\n return fn();\n }\n}\n`\n\n/** Bootstrap code for Node.js workers (eval: true, CJS context) */\nexport const NODE_BOOTSTRAP_CODE = `\n'use strict';\nconst { parentPort } = require('worker_threads');\n\nconst __postMsg = (d) => parentPort.postMessage(d);\n\n${CHANNEL_PROXY_CODE}\n\nconst cancelledTasks = new Set();\n\nparentPort.on('message', (msg) => {\n __handleChannelResult(msg);\n});\n\nparentPort.on('message', async (msg) => {\n if (msg.type === 'execute') {\n if (msg.concurrent) {\n (async () => {\n if (cancelledTasks.has(msg.taskId)) {\n cancelledTasks.delete(msg.taskId);\n return;\n }\n try {\n const result = await __execFn(msg.fnStr, msg.channels);\n if (!cancelledTasks.has(msg.taskId)) {\n parentPort.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n }\n } catch (error) {\n if (!cancelledTasks.has(msg.taskId)) {\n parentPort.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n } finally {\n cancelledTasks.delete(msg.taskId);\n }\n })();\n } else {\n try {\n const result = await __execFn(msg.fnStr, msg.channels);\n parentPort.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n } catch (error) {\n parentPort.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n } else if (msg.type === 'cancel') {\n cancelledTasks.add(msg.taskId);\n } else if (msg.type === 'shutdown') {\n process.exit(0);\n }\n});\n\nparentPort.postMessage({ type: 'ready' });\n`\n\n/** Bootstrap code for Bun/Web Workers (file-based, Web Worker API) */\nexport const WEB_BOOTSTRAP_CODE = `\nconst __postMsg = (d) => self.postMessage(d);\n\n${CHANNEL_PROXY_CODE}\n\nconst cancelledTasks = new Set();\n\nself.addEventListener('message', (event) => {\n __handleChannelResult(event.data);\n});\n\nself.onmessage = async (event) => {\n const msg = event.data;\n if (msg.type === 'execute') {\n if (msg.concurrent) {\n (async () => {\n if (cancelledTasks.has(msg.taskId)) {\n cancelledTasks.delete(msg.taskId);\n return;\n }\n try {\n const result = await __execFn(msg.fnStr, msg.channels);\n if (!cancelledTasks.has(msg.taskId)) {\n self.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n }\n } catch (error) {\n if (!cancelledTasks.has(msg.taskId)) {\n self.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n } finally {\n cancelledTasks.delete(msg.taskId);\n }\n })();\n } else {\n try {\n const result = await __execFn(msg.fnStr, msg.channels);\n self.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n } catch (error) {\n self.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n } else if (msg.type === 'cancel') {\n cancelledTasks.add(msg.taskId);\n } else if (msg.type === 'shutdown') {\n self.close();\n }\n};\n\nself.postMessage({ type: 'ready' });\n`\n\n/** @deprecated Use NODE_BOOTSTRAP_CODE instead */\nexport const BOOTSTRAP_CODE = NODE_BOOTSTRAP_CODE\n","import { WEB_BOOTSTRAP_CODE } from '../bootstrap.js'\nimport type { ManagedWorker, WorkerAdapter } from './base.js'\nimport { writeFileSync, unlinkSync, mkdtempSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { tmpdir } from 'node:os'\n\nlet workerIdCounter = 0\nlet bootstrapFile: string | null = null\n\n/**\n * Returns the path to a temporary JS file containing the bootstrap code.\n * Bun's Blob URL workers break when the URL is revoked before the worker\n * fully initializes its message handler, so we use a file-based worker instead.\n */\nfunction getBootstrapFile(): string {\n if (!bootstrapFile) {\n const dir = mkdtempSync(join(tmpdir(), 'puru-'))\n bootstrapFile = join(dir, 'worker.js')\n writeFileSync(bootstrapFile, WEB_BOOTSTRAP_CODE)\n }\n return bootstrapFile\n}\n\nclass BunManagedWorker implements ManagedWorker {\n private worker: Worker\n readonly id: number\n\n constructor() {\n this.id = ++workerIdCounter\n this.worker = new Worker(getBootstrapFile())\n }\n\n postMessage(data: unknown): void {\n this.worker.postMessage(data)\n }\n\n terminate(): Promise<number> {\n this.worker.terminate()\n // Web Worker terminate() is synchronous and void; return resolved 0\n return Promise.resolve(0)\n }\n\n on(event: 'message', handler: (data: unknown) => void): void\n on(event: 'error', handler: (err: Error) => void): void\n on(event: 'exit', handler: (code: number) => void): void\n on(event: string, handler: (...args: any[]) => void): void {\n if (event === 'message') {\n this.worker.addEventListener('message', (e: MessageEvent) => {\n handler(e.data)\n })\n } else if (event === 'error') {\n this.worker.addEventListener('error', (e: ErrorEvent) => {\n handler(e.error ?? new Error(e.message))\n })\n } else if (event === 'exit') {\n // Bun emits 'close' on worker termination\n this.worker.addEventListener('close', (e: CloseEvent) => {\n handler((e as any).code ?? 0)\n })\n }\n }\n\n unref(): void {\n // Bun Workers support unref()\n if ('unref' in this.worker && typeof this.worker.unref === 'function') {\n ;(this.worker as any).unref()\n }\n }\n\n ref(): void {\n // Bun Workers support ref()\n if ('ref' in this.worker && typeof this.worker.ref === 'function') {\n ;(this.worker as any).ref()\n }\n }\n}\n\nexport class BunWorkerAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new BunManagedWorker()\n }\n}\n\n/** Clean up the temporary bootstrap file. Called during pool drain. */\nexport function cleanupBootstrapFile(): void {\n if (bootstrapFile) {\n try { unlinkSync(bootstrapFile) } catch {}\n bootstrapFile = null\n }\n}\n","export interface Channel<T> {\n send(value: T): Promise<void>\n recv(): Promise<T | null>\n close(): void\n [Symbol.asyncIterator](): AsyncIterator<T>\n}\n\ninterface PendingRecv<T> {\n resolve: (value: T | null) => void\n}\n\ninterface PendingSend<T> {\n value: T\n resolve: () => void\n reject: (reason: unknown) => void\n}\n\nlet channelIdCounter = 0\nconst channelRegistry = new Map<string, ChannelImpl<unknown>>()\n\nclass ChannelImpl<T> implements Channel<T> {\n /** @internal */\n readonly _id: string\n private buffer: T[] = []\n private capacity: number\n private closed = false\n private recvQueue: PendingRecv<T>[] = []\n private sendQueue: PendingSend<T>[] = []\n\n constructor(capacity: number) {\n this._id = `__ch_${++channelIdCounter}`\n this.capacity = capacity\n channelRegistry.set(this._id, this as ChannelImpl<unknown>)\n }\n\n send(value: T): Promise<void> {\n if (this.closed) {\n return Promise.reject(new Error('send on closed channel'))\n }\n\n // If there's a waiting receiver, deliver directly\n const receiver = this.recvQueue.shift()\n if (receiver) {\n receiver.resolve(value)\n return Promise.resolve()\n }\n\n // If buffer has room, buffer it\n if (this.buffer.length < this.capacity) {\n this.buffer.push(value)\n return Promise.resolve()\n }\n\n // Block until a receiver is ready\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ value, resolve, reject })\n })\n }\n\n recv(): Promise<T | null> {\n // If buffer has a value, take it and unblock a pending sender\n if (this.buffer.length > 0) {\n const value = this.buffer.shift()!\n const sender = this.sendQueue.shift()\n if (sender) {\n this.buffer.push(sender.value)\n sender.resolve()\n }\n return Promise.resolve(value)\n }\n\n // If there's a pending sender (unbuffered or buffer was empty), take directly\n const sender = this.sendQueue.shift()\n if (sender) {\n sender.resolve()\n return Promise.resolve(sender.value)\n }\n\n // If closed, return null\n if (this.closed) {\n return Promise.resolve(null)\n }\n\n // Block until a sender provides a value or channel closes\n return new Promise<T | null>((resolve) => {\n this.recvQueue.push({ resolve })\n })\n }\n\n close(): void {\n if (this.closed) return\n this.closed = true\n\n // Resolve all pending receivers with null\n for (const receiver of this.recvQueue) {\n receiver.resolve(null)\n }\n this.recvQueue = []\n\n // Reject all pending senders\n for (const sender of this.sendQueue) {\n sender.reject(new Error('send on closed channel'))\n }\n this.sendQueue = []\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n while (true) {\n const value = await this.recv()\n if (value === null) return\n yield value\n }\n }\n}\n\nexport function chan<T>(capacity: number = 0): Channel<T> {\n if (capacity < 0 || !Number.isInteger(capacity)) {\n throw new RangeError('Channel capacity must be a non-negative integer')\n }\n return new ChannelImpl<T>(capacity)\n}\n\n/** @internal */\nexport function getChannelById(id: string): Channel<unknown> | undefined {\n return channelRegistry.get(id)\n}\n\n/** @internal */\nexport function resetChannelRegistry(): void {\n channelRegistry.clear()\n channelIdCounter = 0\n}\n","import type { ManagedWorker, WorkerAdapter } from './base.js'\nimport { getChannelById } from '../channel.js'\n\nlet inlineIdCounter = 0\n\ntype MessageHandler = (data: unknown) => void\ntype ErrorHandler = (err: Error) => void\ntype ExitHandler = (code: number) => void\n\nclass InlineManagedWorker implements ManagedWorker {\n readonly id: number\n private messageHandlers: MessageHandler[] = []\n private errorHandlers: ErrorHandler[] = []\n private exitHandlers: ExitHandler[] = []\n private terminated = false\n private cancelledTasks = new Set<string>()\n\n constructor() {\n this.id = ++inlineIdCounter\n // Emit ready on next microtask (matches real worker timing)\n queueMicrotask(() => {\n this.emit('message', { type: 'ready' })\n })\n }\n\n postMessage(data: unknown): void {\n if (this.terminated) return\n\n const msg = data as { type: string; taskId?: string; fnStr?: string; concurrent?: boolean; channels?: Record<string, string>; correlationId?: number; value?: unknown; error?: string }\n if (msg.type === 'execute') {\n this.executeTask(msg.taskId!, msg.fnStr!, msg.concurrent ?? false, msg.channels)\n } else if (msg.type === 'cancel') {\n this.cancelledTasks.add(msg.taskId!)\n } else if (msg.type === 'channel-result') {\n // Route channel results back to pending RPC callbacks\n this.emit('message', msg)\n } else if (msg.type === 'shutdown') {\n this.terminated = true\n this.emit('exit', 0)\n }\n }\n\n terminate(): Promise<number> {\n this.terminated = true\n this.emit('exit', 1)\n return Promise.resolve(1)\n }\n\n on(event: 'message', handler: MessageHandler): void\n on(event: 'error', handler: ErrorHandler): void\n on(event: 'exit', handler: ExitHandler): void\n on(event: string, handler: (...args: any[]) => void): void {\n if (event === 'message') this.messageHandlers.push(handler as MessageHandler)\n else if (event === 'error') this.errorHandlers.push(handler as ErrorHandler)\n else if (event === 'exit') this.exitHandlers.push(handler as ExitHandler)\n }\n\n unref(): void {}\n ref(): void {}\n\n private emit(event: 'message', data: unknown): void\n private emit(event: 'error', err: Error): void\n private emit(event: 'exit', code: number): void\n private emit(event: string, value: unknown): void {\n if (event === 'message') {\n for (const h of this.messageHandlers) h(value)\n } else if (event === 'error') {\n for (const h of this.errorHandlers) h(value as Error)\n } else if (event === 'exit') {\n for (const h of this.exitHandlers) h(value as number)\n }\n }\n\n private buildChannelProxies(channels: Record<string, string>): Record<string, unknown> {\n const self = this\n const proxies: Record<string, unknown> = {}\n for (const [name, channelId] of Object.entries(channels)) {\n proxies[name] = {\n _id: channelId,\n async send(value: unknown) {\n const ch = getChannelById(channelId)\n if (!ch) throw new Error(`Channel ${channelId} not found`)\n await ch.send(value)\n },\n async recv() {\n const ch = getChannelById(channelId)\n if (!ch) throw new Error(`Channel ${channelId} not found`)\n return ch.recv()\n },\n close() {\n const ch = getChannelById(channelId)\n if (ch) ch.close()\n },\n [Symbol.asyncIterator]() {\n const ch = getChannelById(channelId) as any\n if (!ch) throw new Error(`Channel ${channelId} not found`)\n return {\n async next() {\n const value = await ch.recv()\n if (value === null) return { done: true, value: undefined }\n return { done: false, value }\n }\n }\n }\n }\n }\n return proxies\n }\n\n private executeTask(taskId: string, fnStr: string, concurrent: boolean, channels?: Record<string, string>): void {\n // Run on next microtask to simulate async worker behavior\n queueMicrotask(async () => {\n if (this.terminated) return\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId)\n return\n }\n try {\n let result: unknown\n if (channels) {\n const proxies = this.buildChannelProxies(channels)\n const fn = new Function('__ch', 'return (' + fnStr + ')(__ch)') as (ch: unknown) => unknown\n result = await fn(proxies)\n } else {\n const fn = new Function('return (' + fnStr + ')()') as () => unknown\n result = await fn()\n }\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId)\n return\n }\n this.emit('message', { type: 'result', taskId, value: result })\n } catch (error) {\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId)\n return\n }\n this.emit('message', {\n type: 'error',\n taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n })\n }\n })\n }\n}\n\nexport class InlineAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new InlineManagedWorker()\n }\n}\n","import type { ManagedWorker, WorkerAdapter } from './adapters/base.js'\nimport type { PuruConfig, Task, WorkerMessage, WorkerResponse } from './types.js'\nimport { getConfig } from './configure.js'\nimport { detectRuntime, detectCapability } from './runtime.js'\nimport { NodeWorkerAdapter } from './adapters/node.js'\nimport { BunWorkerAdapter } from './adapters/bun.js'\nimport { InlineAdapter } from './adapters/inline.js'\nimport { getChannelById } from './channel.js'\n\nexport class WorkerPool {\n private config: PuruConfig\n private adapter: WorkerAdapter\n private idleWorkers: ManagedWorker[] = []\n private exclusiveWorkers = new Map<string, ManagedWorker>()\n private sharedWorkers = new Map<ManagedWorker, Set<string>>()\n private queues = {\n high: [] as Task[],\n normal: [] as Task[],\n low: [] as Task[],\n }\n private concurrentQueues = {\n high: [] as Task[],\n normal: [] as Task[],\n low: [] as Task[],\n }\n private allWorkers = new Set<ManagedWorker>()\n private idleTimers = new Map<ManagedWorker, ReturnType<typeof setTimeout>>()\n private pendingWorkerCount = 0\n private pendingTasksForWorkers: Task[] = []\n private draining = false\n private totalCompleted = 0\n private totalFailed = 0\n private taskMap = new Map<string, Task>()\n\n constructor(config: PuruConfig, adapter: WorkerAdapter) {\n this.config = config\n this.adapter = adapter\n }\n\n // --- Queue helpers ---\n\n private enqueue(task: Task): void {\n this.queues[task.priority].push(task)\n }\n\n private dequeue(): Task | undefined {\n return (\n this.queues.high.shift() ??\n this.queues.normal.shift() ??\n this.queues.low.shift()\n )\n }\n\n private enqueueConcurrent(task: Task): void {\n this.concurrentQueues[task.priority].push(task)\n }\n\n private dequeueConcurrent(): Task | undefined {\n return (\n this.concurrentQueues.high.shift() ??\n this.concurrentQueues.normal.shift() ??\n this.concurrentQueues.low.shift()\n )\n }\n\n private removeFromQueue(taskId: string): Task | undefined {\n for (const priority of ['high', 'normal', 'low'] as const) {\n const queue = this.queues[priority]\n const idx = queue.findIndex((t) => t.id === taskId)\n if (idx !== -1) {\n return queue.splice(idx, 1)[0]\n }\n }\n return undefined\n }\n\n private removeFromConcurrentQueue(taskId: string): Task | undefined {\n for (const priority of ['high', 'normal', 'low'] as const) {\n const queue = this.concurrentQueues[priority]\n const idx = queue.findIndex((t) => t.id === taskId)\n if (idx !== -1) {\n return queue.splice(idx, 1)[0]\n }\n }\n return undefined\n }\n\n // --- Submit ---\n\n submit(task: Task): void {\n if (this.draining) {\n task.reject(new Error('Pool is shutting down'))\n return\n }\n\n if (task.concurrent) {\n this.submitConcurrent(task)\n } else {\n this.submitExclusive(task)\n }\n }\n\n private submitExclusive(task: Task): void {\n // Try to assign to an idle worker\n const worker = this.idleWorkers.pop()\n if (worker) {\n this.dispatch(worker, task)\n return\n }\n\n // Try to create a new worker\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount\n if (totalWorkers < this.config.maxThreads) {\n this.pendingWorkerCount++\n this.pendingTasksForWorkers.push(task)\n this.createAndReadyWorker()\n return\n }\n\n // Queue the task by priority\n this.enqueue(task)\n }\n\n private submitConcurrent(task: Task): void {\n // 1. Find a shared worker under the concurrency limit\n for (const [worker, tasks] of this.sharedWorkers) {\n if (tasks.size < this.config.concurrency) {\n this.dispatchConcurrent(worker, task)\n return\n }\n }\n\n // 2. Grab an idle worker and convert to shared mode\n const idleWorker = this.idleWorkers.pop()\n if (idleWorker) {\n this.dispatchConcurrent(idleWorker, task)\n return\n }\n\n // 3. Spin up a new worker if under limit\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount\n if (totalWorkers < this.config.maxThreads) {\n this.pendingWorkerCount++\n this.pendingTasksForWorkers.push(task)\n this.createAndReadyWorker()\n return\n }\n\n // 4. All workers busy/saturated — queue it\n this.enqueueConcurrent(task)\n }\n\n // --- Dispatch ---\n\n private dispatch(worker: ManagedWorker, task: Task): void {\n const timer = this.idleTimers.get(worker)\n if (timer) {\n clearTimeout(timer)\n this.idleTimers.delete(worker)\n }\n\n worker.ref()\n this.exclusiveWorkers.set(task.id, worker)\n this.taskMap.set(task.id, task)\n\n const msg: WorkerMessage = {\n type: 'execute',\n taskId: task.id,\n fnStr: task.fnStr,\n concurrent: false,\n channels: task.channels,\n }\n worker.postMessage(msg)\n }\n\n private dispatchConcurrent(worker: ManagedWorker, task: Task): void {\n const timer = this.idleTimers.get(worker)\n if (timer) {\n clearTimeout(timer)\n this.idleTimers.delete(worker)\n }\n\n worker.ref()\n\n if (!this.sharedWorkers.has(worker)) {\n this.sharedWorkers.set(worker, new Set())\n }\n this.sharedWorkers.get(worker)!.add(task.id)\n this.taskMap.set(task.id, task)\n\n const msg: WorkerMessage = {\n type: 'execute',\n taskId: task.id,\n fnStr: task.fnStr,\n concurrent: true,\n channels: task.channels,\n }\n worker.postMessage(msg)\n }\n\n // --- Task completion ---\n\n private handleWorkerMessage(worker: ManagedWorker, response: WorkerResponse): void {\n if (response.type === 'channel-op') {\n this.handleChannelOp(worker, response)\n return\n }\n\n if (response.type === 'result') {\n const taskId = response.taskId\n this.resolveTask(taskId, response.value)\n\n if (this.exclusiveWorkers.has(taskId)) {\n this.exclusiveWorkers.delete(taskId)\n this.assignNextOrIdle(worker)\n } else {\n const taskSet = this.sharedWorkers.get(worker)\n if (taskSet) {\n taskSet.delete(taskId)\n this.assignNextConcurrentOrIdle(worker)\n }\n }\n } else if (response.type === 'error') {\n const taskId = response.taskId\n const err = new Error(response.message)\n if (response.stack) err.stack = response.stack\n this.rejectTask(taskId, err)\n\n if (this.exclusiveWorkers.has(taskId)) {\n this.exclusiveWorkers.delete(taskId)\n this.assignNextOrIdle(worker)\n } else {\n const taskSet = this.sharedWorkers.get(worker)\n if (taskSet) {\n taskSet.delete(taskId)\n this.assignNextConcurrentOrIdle(worker)\n }\n }\n }\n }\n\n private assignNextOrIdle(worker: ManagedWorker): void {\n if (!this.allWorkers.has(worker)) return\n\n // Try exclusive queue first\n const next = this.dequeue()\n if (next) {\n this.dispatch(worker, next)\n return\n }\n\n // Then try concurrent queue\n const concurrentNext = this.dequeueConcurrent()\n if (concurrentNext) {\n this.dispatchConcurrent(worker, concurrentNext)\n return\n }\n\n this.makeIdle(worker)\n }\n\n private assignNextConcurrentOrIdle(worker: ManagedWorker): void {\n if (!this.allWorkers.has(worker)) return\n\n const taskSet = this.sharedWorkers.get(worker)\n const currentCount = taskSet?.size ?? 0\n\n // Fill up to concurrency limit from concurrent queue\n let filled = currentCount\n while (filled < this.config.concurrency) {\n const next = this.dequeueConcurrent()\n if (!next) break\n this.dispatchConcurrent(worker, next)\n filled++\n }\n\n // If no tasks remain, transition back\n const updatedSet = this.sharedWorkers.get(worker)\n if (!updatedSet || updatedSet.size === 0) {\n this.sharedWorkers.delete(worker)\n // Try exclusive queue before going idle\n const exclusiveTask = this.dequeue()\n if (exclusiveTask) {\n this.dispatch(worker, exclusiveTask)\n } else {\n this.makeIdle(worker)\n }\n }\n }\n\n private makeIdle(worker: ManagedWorker): void {\n worker.unref()\n this.idleWorkers.push(worker)\n\n if (this.config.idleTimeout > 0) {\n const timer = setTimeout(() => {\n this.idleTimers.delete(worker)\n const idx = this.idleWorkers.indexOf(worker)\n if (idx !== -1) {\n this.idleWorkers.splice(idx, 1)\n }\n this.allWorkers.delete(worker)\n worker.terminate()\n }, this.config.idleTimeout)\n\n // Don't let the idle timer prevent process exit\n if (timer.unref) timer.unref()\n this.idleTimers.set(worker, timer)\n }\n }\n\n // --- Channel RPC ---\n\n private async handleChannelOp(\n worker: ManagedWorker,\n msg: { channelId: string; op: 'send' | 'recv' | 'close'; correlationId: number; value?: unknown },\n ): Promise<void> {\n const channel = getChannelById(msg.channelId)\n\n if (!channel) {\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n error: `Channel ${msg.channelId} not found`,\n })\n return\n }\n\n try {\n if (msg.op === 'send') {\n await channel.send(msg.value)\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n })\n } else if (msg.op === 'recv') {\n const value = await channel.recv()\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n value,\n })\n } else if (msg.op === 'close') {\n channel.close()\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n })\n }\n } catch (err) {\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n // --- Task resolution ---\n\n private resolveTask(taskId: string, value: unknown): void {\n const task = this.taskMap.get(taskId)\n if (task) {\n this.taskMap.delete(taskId)\n this.totalCompleted++\n task.resolve(value)\n }\n }\n\n private rejectTask(taskId: string, reason: unknown): void {\n const task = this.taskMap.get(taskId)\n if (task) {\n this.taskMap.delete(taskId)\n this.totalFailed++\n task.reject(reason)\n }\n }\n\n // --- Cancellation ---\n\n cancelTask(taskId: string): void {\n // 1. Check exclusive queues\n const removed = this.removeFromQueue(taskId)\n if (removed) {\n removed.reject(new DOMException('Task was cancelled', 'AbortError'))\n return\n }\n\n // 2. Check concurrent queues\n const removedConcurrent = this.removeFromConcurrentQueue(taskId)\n if (removedConcurrent) {\n removedConcurrent.reject(new DOMException('Task was cancelled', 'AbortError'))\n return\n }\n\n // 3. Check exclusive workers — terminate the worker (existing behavior)\n const exclusiveWorker = this.exclusiveWorkers.get(taskId)\n if (exclusiveWorker) {\n this.exclusiveWorkers.delete(taskId)\n this.allWorkers.delete(exclusiveWorker)\n this.taskMap.delete(taskId)\n exclusiveWorker.terminate()\n return\n }\n\n // 4. Check shared workers — send cancel message, do NOT terminate\n for (const [worker, taskSet] of this.sharedWorkers) {\n if (taskSet.has(taskId)) {\n taskSet.delete(taskId)\n this.taskMap.delete(taskId)\n worker.postMessage({ type: 'cancel', taskId })\n if (taskSet.size === 0) {\n this.sharedWorkers.delete(worker)\n this.assignNextConcurrentOrIdle(worker)\n }\n return\n }\n }\n }\n\n // --- Lifecycle ---\n\n async drain(): Promise<void> {\n this.draining = true\n\n // Reject all queued exclusive tasks\n for (const priority of ['high', 'normal', 'low'] as const) {\n for (const task of this.queues[priority]) {\n task.reject(new Error('Pool is shutting down'))\n }\n this.queues[priority] = []\n }\n\n // Reject all queued concurrent tasks\n for (const priority of ['high', 'normal', 'low'] as const) {\n for (const task of this.concurrentQueues[priority]) {\n task.reject(new Error('Pool is shutting down'))\n }\n this.concurrentQueues[priority] = []\n }\n\n // Clear in-flight concurrent tasks — their workers are about to be terminated.\n // We don't reject them here because the caller may not be listening, which\n // would cause unhandled rejection errors. The promises will simply never settle.\n for (const [, taskSet] of this.sharedWorkers) {\n for (const taskId of taskSet) {\n this.taskMap.delete(taskId)\n }\n }\n\n // Terminate all workers\n const terminatePromises: Promise<number>[] = []\n for (const worker of this.allWorkers) {\n const timer = this.idleTimers.get(worker)\n if (timer) clearTimeout(timer)\n terminatePromises.push(worker.terminate())\n }\n\n await Promise.all(terminatePromises)\n\n this.idleWorkers = []\n this.exclusiveWorkers.clear()\n this.sharedWorkers.clear()\n this.allWorkers.clear()\n this.idleTimers.clear()\n }\n\n resize(maxThreads: number): void {\n this.config = { ...this.config, maxThreads }\n\n // If we now have capacity, dequeue tasks and spin up workers\n while (true) {\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount\n if (totalWorkers >= maxThreads) break\n // Try exclusive queue first, then concurrent\n const task = this.dequeue() ?? this.dequeueConcurrent()\n if (!task) break\n this.pendingWorkerCount++\n this.pendingTasksForWorkers.push(task)\n this.createAndReadyWorker()\n }\n\n // If pool is now oversized, terminate excess idle workers\n while (this.allWorkers.size > maxThreads && this.idleWorkers.length > 0) {\n const worker = this.idleWorkers.pop()!\n const timer = this.idleTimers.get(worker)\n if (timer) {\n clearTimeout(timer)\n this.idleTimers.delete(worker)\n }\n this.allWorkers.delete(worker)\n worker.terminate()\n }\n }\n\n // --- Worker creation ---\n\n private createAndReadyWorker(): void {\n const worker = this.adapter.createWorker()\n\n const onReady = () => {\n this.pendingWorkerCount--\n this.allWorkers.add(worker)\n\n const task = this.pendingTasksForWorkers.shift()\n if (task) {\n if (task.concurrent) {\n this.dispatchConcurrent(worker, task)\n } else {\n this.dispatch(worker, task)\n }\n } else {\n this.makeIdle(worker)\n }\n }\n\n worker.on('message', (msg: unknown) => {\n const response = msg as WorkerResponse\n if (response.type === 'ready') {\n onReady()\n return\n }\n this.handleWorkerMessage(worker, response)\n })\n\n worker.on('error', (err: Error) => {\n // Clean up exclusive task on this worker\n for (const [taskId, w] of this.exclusiveWorkers) {\n if (w === worker) {\n this.exclusiveWorkers.delete(taskId)\n break\n }\n }\n // Clean up concurrent tasks on this worker\n const taskSet = this.sharedWorkers.get(worker)\n if (taskSet) {\n for (const taskId of taskSet) {\n this.rejectTask(taskId, err)\n }\n this.sharedWorkers.delete(worker)\n }\n })\n\n worker.on('exit', (_code: number) => {\n this.allWorkers.delete(worker)\n const timer = this.idleTimers.get(worker)\n if (timer) {\n clearTimeout(timer)\n this.idleTimers.delete(worker)\n }\n\n // Remove from idle if present\n const idleIdx = this.idleWorkers.indexOf(worker)\n if (idleIdx !== -1) {\n this.idleWorkers.splice(idleIdx, 1)\n }\n\n // Clean up exclusive task\n for (const [taskId, w] of this.exclusiveWorkers) {\n if (w === worker) {\n this.exclusiveWorkers.delete(taskId)\n break\n }\n }\n\n // Clean up concurrent tasks\n const taskSet = this.sharedWorkers.get(worker)\n if (taskSet) {\n for (const taskId of taskSet) {\n this.rejectTask(taskId, new Error('Worker exited unexpectedly'))\n }\n this.sharedWorkers.delete(worker)\n }\n })\n }\n\n // --- Stats ---\n\n stats(): PoolStats {\n let concurrentTasks = 0\n for (const taskSet of this.sharedWorkers.values()) {\n concurrentTasks += taskSet.size\n }\n\n return {\n totalWorkers: this.allWorkers.size,\n idleWorkers: this.idleWorkers.length,\n busyWorkers: this.exclusiveWorkers.size,\n sharedWorkers: this.sharedWorkers.size,\n concurrentTasks,\n pendingWorkers: this.pendingWorkerCount,\n queuedTasks: {\n high: this.queues.high.length,\n normal: this.queues.normal.length,\n low: this.queues.low.length,\n total:\n this.queues.high.length +\n this.queues.normal.length +\n this.queues.low.length,\n },\n queuedConcurrentTasks: {\n high: this.concurrentQueues.high.length,\n normal: this.concurrentQueues.normal.length,\n low: this.concurrentQueues.low.length,\n total:\n this.concurrentQueues.high.length +\n this.concurrentQueues.normal.length +\n this.concurrentQueues.low.length,\n },\n totalCompleted: this.totalCompleted,\n totalFailed: this.totalFailed,\n maxThreads: this.config.maxThreads,\n concurrency: this.config.concurrency,\n }\n }\n}\n\nexport interface PoolStats {\n totalWorkers: number\n idleWorkers: number\n busyWorkers: number\n sharedWorkers: number\n concurrentTasks: number\n pendingWorkers: number\n queuedTasks: {\n high: number\n normal: number\n low: number\n total: number\n }\n queuedConcurrentTasks: {\n high: number\n normal: number\n low: number\n total: number\n }\n totalCompleted: number\n totalFailed: number\n maxThreads: number\n concurrency: number\n}\n\n// Pool singleton\nlet poolInstance: WorkerPool | null = null\n\nfunction createAdapter(adapterConfig: string): WorkerAdapter {\n if (adapterConfig === 'inline') return new InlineAdapter()\n if (adapterConfig === 'node') return new NodeWorkerAdapter()\n if (adapterConfig === 'bun') return new BunWorkerAdapter()\n\n // auto — detect runtime\n const capability = detectCapability()\n if (capability === 'single-thread') {\n throw new Error(\n 'puru requires a runtime with thread support (Node.js or Bun). ' +\n 'Current runtime does not support worker threads.',\n )\n }\n const runtime = detectRuntime()\n if (runtime === 'bun') return new BunWorkerAdapter()\n return new NodeWorkerAdapter()\n}\n\nexport function getPool(): WorkerPool {\n if (!poolInstance) {\n const config = getConfig()\n poolInstance = new WorkerPool(config, createAdapter(config.adapter))\n }\n return poolInstance\n}\n\nexport function stats(): PoolStats {\n return getPool().stats()\n}\n\nexport function resize(maxThreads: number): void {\n getPool().resize(maxThreads)\n}\n\nexport async function resetPool(): Promise<void> {\n if (poolInstance) {\n await poolInstance.drain()\n poolInstance = null\n }\n}\n","import { serializeFunction } from './serialize.js'\nimport { getPool } from './pool.js'\nimport type { SpawnResult, Task } from './types.js'\nimport type { Channel } from './channel.js'\n\nlet taskCounter = 0\n\nexport function spawn<T>(\n fn: (() => T | Promise<T>) | ((channels: Record<string, Channel<unknown>>) => T | Promise<T>),\n opts?: {\n priority?: 'low' | 'normal' | 'high'\n concurrent?: boolean\n channels?: Record<string, Channel<unknown>>\n },\n): SpawnResult<T> {\n const fnStr = serializeFunction(fn)\n const taskId = String(++taskCounter)\n\n // Capture the call site stack for better error reporting\n const spawnStack = new Error().stack\n\n let resolveFn!: (value: T) => void\n let rejectFn!: (reason: unknown) => void\n let settled = false\n\n const result = new Promise<T>((resolve, reject) => {\n resolveFn = resolve\n rejectFn = reject\n })\n\n // Extract channel IDs if channels are provided\n let channelMap: Record<string, string> | undefined\n if (opts?.channels) {\n channelMap = {}\n for (const [name, ch] of Object.entries(opts.channels)) {\n const impl = ch as unknown as { _id: string }\n if (!impl._id) {\n throw new Error(`Channel \"${name}\" is not a valid puru channel`)\n }\n channelMap[name] = impl._id\n }\n }\n\n const task: Task = {\n id: taskId,\n fnStr,\n priority: opts?.priority ?? 'normal',\n concurrent: opts?.concurrent ?? false,\n channels: channelMap,\n resolve: (value) => {\n if (!settled) {\n settled = true\n resolveFn(value as T)\n }\n },\n reject: (reason) => {\n if (!settled) {\n settled = true\n // Enrich worker errors with the spawn() call site\n if (reason instanceof Error && spawnStack) {\n const callerLine = spawnStack\n .split('\\n')\n .slice(2)\n .join('\\n')\n reason.stack =\n (reason.stack ?? reason.message) +\n '\\n --- spawned at ---\\n' +\n callerLine\n }\n rejectFn(reason)\n }\n },\n }\n\n getPool().submit(task)\n\n const cancel = () => {\n if (settled) return\n settled = true\n getPool().cancelTask(taskId)\n rejectFn(new DOMException('Task was cancelled', 'AbortError'))\n }\n\n return { result, cancel }\n}\n\n/** @internal For testing only */\nexport function resetTaskCounter(): void {\n taskCounter = 0\n}\n","import { spawn } from './spawn.js'\nimport type { SpawnResult } from './types.js'\nimport type { Channel } from './channel.js'\n\nexport class WaitGroup {\n private tasks: SpawnResult<unknown>[] = []\n private controller = new AbortController()\n\n get signal(): AbortSignal {\n return this.controller.signal\n }\n\n spawn(\n fn: (() => unknown) | ((channels: Record<string, Channel<unknown>>) => unknown),\n opts?: { concurrent?: boolean; channels?: Record<string, Channel<unknown>> },\n ): void {\n if (this.controller.signal.aborted) {\n throw new Error('WaitGroup has been cancelled')\n }\n const handle = spawn(fn, opts)\n this.tasks.push(handle)\n }\n\n async wait(): Promise<unknown[]> {\n return Promise.all(this.tasks.map((t) => t.result))\n }\n\n async waitSettled(): Promise<PromiseSettledResult<unknown>[]> {\n return Promise.allSettled(this.tasks.map((t) => t.result))\n }\n\n cancel(): void {\n this.controller.abort()\n for (const task of this.tasks) {\n task.cancel()\n }\n }\n}\n","import { spawn } from './spawn.js'\nimport type { SpawnResult } from './types.js'\n\nexport class ErrGroup {\n private tasks: SpawnResult<unknown>[] = []\n private controller = new AbortController()\n private firstError: unknown = undefined\n private hasError = false\n\n get signal(): AbortSignal {\n return this.controller.signal\n }\n\n spawn(fn: () => unknown, opts?: { concurrent?: boolean }): void {\n if (this.controller.signal.aborted) {\n throw new Error('ErrGroup has been cancelled')\n }\n const handle = spawn(fn, opts)\n\n // Watch for errors and cancel all tasks on first failure\n handle.result.catch((err) => {\n if (!this.hasError) {\n this.hasError = true\n this.firstError = err\n this.cancel()\n }\n })\n\n this.tasks.push(handle)\n }\n\n async wait(): Promise<unknown[]> {\n const settled = await Promise.allSettled(this.tasks.map((t) => t.result))\n\n if (this.hasError) {\n throw this.firstError\n }\n\n return settled.map((r) => {\n if (r.status === 'fulfilled') return r.value\n throw r.reason\n })\n }\n\n cancel(): void {\n this.controller.abort()\n for (const task of this.tasks) {\n task.cancel()\n }\n }\n}\n","export class Mutex {\n private queue: (() => void)[] = []\n private locked = false\n\n async lock(): Promise<void> {\n if (!this.locked) {\n this.locked = true\n return\n }\n return new Promise<void>((resolve) => {\n this.queue.push(resolve)\n })\n }\n\n unlock(): void {\n if (!this.locked) {\n throw new Error('Cannot unlock a mutex that is not locked')\n }\n const next = this.queue.shift()\n if (next) {\n next()\n } else {\n this.locked = false\n }\n }\n\n async withLock<T>(fn: () => T | Promise<T>): Promise<T> {\n await this.lock()\n try {\n return await fn()\n } finally {\n this.unlock()\n }\n }\n\n get isLocked(): boolean {\n return this.locked\n }\n}\n","export class Once<T = void> {\n private promise: Promise<T> | null = null\n private called = false\n\n async do(fn: () => T | Promise<T>): Promise<T> {\n if (!this.called) {\n this.called = true\n this.promise = Promise.resolve(fn())\n }\n return this.promise!\n }\n\n get done(): boolean {\n return this.called\n }\n\n reset(): void {\n this.called = false\n this.promise = null\n }\n}\n","type SelectCase<T = unknown> = [Promise<T>, (value: T) => void]\n\nexport interface SelectOptions {\n default?: () => void\n}\n\nexport function select(\n cases: SelectCase[],\n opts?: SelectOptions,\n): Promise<void> {\n if (cases.length === 0) {\n if (opts?.default) {\n opts.default()\n }\n return Promise.resolve()\n }\n\n // Non-blocking: if default is provided, check if any promise is already settled\n if (opts?.default) {\n // Race a microtask against the promises to check if any is immediately ready\n return new Promise<void>((resolve, reject) => {\n let settled = false\n\n // Check all promises for immediate resolution\n for (const [promise, handler] of cases) {\n Promise.resolve(promise).then(\n (value) => {\n if (settled) return\n settled = true\n try {\n handler(value)\n resolve()\n } catch (err) {\n reject(err)\n }\n },\n (err) => {\n if (settled) return\n settled = true\n reject(err)\n },\n )\n }\n\n // Schedule default on the next microtask — if no promise resolved synchronously,\n // default wins\n queueMicrotask(() => {\n if (settled) return\n settled = true\n try {\n opts.default!()\n resolve()\n } catch (err) {\n reject(err)\n }\n })\n })\n }\n\n // Blocking: wait for the first promise to settle\n return new Promise<void>((resolve, reject) => {\n let settled = false\n\n cases.forEach(([promise, handler]) => {\n promise.then(\n (value) => {\n if (settled) return\n settled = true\n try {\n handler(value)\n resolve()\n } catch (err) {\n reject(err)\n }\n },\n (err) => {\n if (settled) return\n settled = true\n reject(err)\n },\n )\n })\n })\n}\n","export function after(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","export class Ticker {\n private interval: ReturnType<typeof setInterval> | null = null\n private resolve: (() => void) | null = null\n private stopped = false\n private ms: number\n\n constructor(ms: number) {\n this.ms = ms\n this.interval = setInterval(() => {\n if (this.resolve) {\n const r = this.resolve\n this.resolve = null\n r()\n }\n }, ms)\n if (this.interval.unref) this.interval.unref()\n }\n\n async tick(): Promise<boolean> {\n if (this.stopped) return false\n return new Promise<boolean>((resolve) => {\n this.resolve = () => resolve(true)\n })\n }\n\n stop(): void {\n this.stopped = true\n if (this.interval) {\n clearInterval(this.interval)\n this.interval = null\n }\n if (this.resolve) {\n const r = this.resolve\n this.resolve = null\n r()\n }\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<void> {\n while (await this.tick()) {\n yield\n }\n }\n}\n\nexport function ticker(ms: number): Ticker {\n return new Ticker(ms)\n}\n","import { getPool } from './pool.js'\nimport { serializeFunction } from './serialize.js'\nimport type { SpawnResult, Task } from './types.js'\n\ntype TaskFn = (...args: unknown[]) => unknown\n\nconst registry = new Map<string, TaskFn>()\nlet taskCounter = 0\n\nexport function register(name: string, fn: TaskFn): void {\n if (registry.has(name)) {\n throw new Error(`Task \"${name}\" is already registered`)\n }\n registry.set(name, fn)\n}\n\nexport function run<T = unknown>(\n name: string,\n ...args: unknown[]\n): Promise<T> {\n const fn = registry.get(name)\n if (!fn) {\n throw new Error(`Task \"${name}\" is not registered. Call register() first.`)\n }\n\n // Serialize the function and JSON-encode args into a self-contained string\n // that the worker can execute without any closures.\n const fnStr = serializeFunction(fn)\n const serializedArgs = args.map((a) => {\n const json = JSON.stringify(a)\n if (json === undefined) {\n throw new TypeError(\n `Argument of type ${typeof a} is not JSON-serializable. ` +\n 'run() args must be JSON-serializable (no undefined, functions, symbols, or BigInt).',\n )\n }\n return json\n })\n const wrapperStr = `() => (${fnStr})(${serializedArgs.join(', ')})`\n\n const taskId = `reg_${++taskCounter}`\n const spawnStack = new Error().stack\n\n let resolveFn!: (value: T) => void\n let rejectFn!: (reason: unknown) => void\n\n const result = new Promise<T>((resolve, reject) => {\n resolveFn = resolve\n rejectFn = reject\n })\n\n const task: Task = {\n id: taskId,\n fnStr: wrapperStr,\n priority: 'normal',\n concurrent: false,\n resolve: (value) => resolveFn(value as T),\n reject: (reason) => {\n if (reason instanceof Error && spawnStack) {\n const callerLine = spawnStack.split('\\n').slice(2).join('\\n')\n reason.stack =\n (reason.stack ?? reason.message) +\n '\\n --- spawned at ---\\n' +\n callerLine\n }\n rejectFn(reason)\n },\n }\n\n getPool().submit(task)\n\n return result\n}\n\n/** @internal For testing only */\nexport function clearRegistry(): void {\n registry.clear()\n taskCounter = 0\n}\n"],"mappings":"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","names":["import_node_os","sender","taskCounter"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/serialize.ts","../src/configure.ts","../src/runtime.ts","../src/adapters/node.ts","../src/bootstrap.ts","../src/adapters/bun.ts","../src/channel.ts","../src/adapters/inline.ts","../src/pool.ts","../src/spawn.ts","../src/waitgroup.ts","../src/errgroup.ts","../src/mutex.ts","../src/once.ts","../src/select.ts","../src/after.ts","../src/ticker.ts","../src/registry.ts"],"sourcesContent":["export { spawn } from './spawn.js'\nexport { chan } from './channel.js'\nexport type { Channel } from './channel.js'\nexport { WaitGroup } from './waitgroup.js'\nexport { ErrGroup } from './errgroup.js'\nexport { Mutex } from './mutex.js'\nexport { Once } from './once.js'\nexport { select } from './select.js'\nexport type { SelectOptions } from './select.js'\nexport { after } from './after.js'\nexport { Ticker, ticker } from './ticker.js'\nexport { task } from './registry.js'\nexport { configure } from './configure.js'\nexport { stats, resize, shutdown } from './pool.js'\nexport type { PoolStats } from './pool.js'\nexport { detectRuntime, detectCapability } from './runtime.js'\nexport type { Runtime, Capability } from './runtime.js'\nexport type { SpawnResult, PuruConfig } from './types.js'\n","const NATIVE_CODE_RE = /\\[native code\\]/\nconst METHOD_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*\\s*\\(/\n\n// A valid serialized function must start with one of these patterns.\n// This guards against prototype pollution on Function.prototype.toString\n// returning arbitrary strings.\nconst VALID_FN_START_RE = /^(?:function\\b|async\\s+function\\b|async\\s*\\(|\\(|[a-zA-Z_$][a-zA-Z0-9_$]*\\s*=>|async\\s+[a-zA-Z_$])/\n\nexport function serializeFunction(fn: Function): string {\n if (typeof fn !== 'function') {\n throw new TypeError('Expected a function')\n }\n\n const str = fn.toString()\n\n if (typeof str !== 'string' || str.length === 0) {\n throw new TypeError(\n 'Function serialization returned an invalid result. ' +\n 'This may indicate Function.prototype.toString has been tampered with.',\n )\n }\n\n if (NATIVE_CODE_RE.test(str)) {\n throw new TypeError(\n 'Native functions cannot be serialized. Use an arrow function wrapper instead.',\n )\n }\n\n if (!VALID_FN_START_RE.test(str)) {\n throw new TypeError(\n 'Function serialization produced unexpected output. ' +\n 'Only arrow functions, function expressions, and async functions are supported.',\n )\n }\n\n // Detect class methods like \"method() { ... }\" — not valid standalone functions\n if (\n METHOD_RE.test(str) &&\n !str.startsWith('function') &&\n !str.startsWith('async function') &&\n !str.startsWith('async (') &&\n !str.startsWith('async=') &&\n !str.startsWith('(') &&\n !str.includes('=>')\n ) {\n throw new TypeError(\n 'Class methods cannot be serialized. Use an arrow function wrapper instead.',\n )\n }\n\n return str\n}\n","import { availableParallelism } from 'node:os'\nimport type { PuruConfig } from './types.js'\n\nconst DEFAULT_CONFIG: PuruConfig = {\n maxThreads: availableParallelism?.() ?? 4,\n strategy: 'fifo',\n idleTimeout: 30_000,\n adapter: 'auto',\n concurrency: 64,\n}\n\nlet currentConfig: PuruConfig = { ...DEFAULT_CONFIG }\nlet configLocked = false\n\n/**\n * Configure the global thread pool. **Must be called before the first `spawn()`.**\n *\n * After the pool is initialized, calling `configure()` throws. Call it once at\n * application startup or in test setup.\n *\n * @example\n * configure({\n * maxThreads: 4, // default: os.availableParallelism()\n * concurrency: 64, // max concurrent tasks per shared worker (default: 64)\n * idleTimeout: 30_000, // kill idle workers after 30s (default: 30_000)\n * adapter: 'auto', // 'auto' | 'node' | 'bun' | 'inline' (default: 'auto')\n * })\n *\n * @example\n * // In tests: run tasks on the main thread with no real workers\n * configure({ adapter: 'inline' })\n */\nexport function configure(opts: Partial<PuruConfig>): void {\n if (configLocked) {\n throw new Error(\n 'configure() must be called before the first spawn(). The worker pool has already been initialized.',\n )\n }\n currentConfig = { ...currentConfig, ...opts }\n}\n\nexport function getConfig(): PuruConfig {\n configLocked = true\n return { ...currentConfig }\n}\n\n/** @internal For testing only */\nexport function resetConfig(): void {\n currentConfig = { ...DEFAULT_CONFIG }\n configLocked = false\n}\n","export type Runtime = 'node' | 'deno' | 'bun' | 'browser'\nexport type Capability = 'full-threads' | 'single-thread'\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function detectRuntime(): Runtime {\n if (typeof (globalThis as any).Bun !== 'undefined') return 'bun'\n if (typeof (globalThis as any).Deno !== 'undefined') return 'deno'\n if (\n typeof globalThis.process !== 'undefined' &&\n globalThis.process.versions?.node\n )\n return 'node'\n return 'browser'\n}\n\nexport function detectCapability(): Capability {\n const runtime = detectRuntime()\n if (runtime === 'node' || runtime === 'bun') return 'full-threads'\n if (typeof (globalThis as any).Worker !== 'undefined') return 'full-threads'\n return 'single-thread'\n}\n","import { Worker } from 'node:worker_threads'\nimport { NODE_BOOTSTRAP_CODE } from '../bootstrap.js'\nimport type { ManagedWorker, WorkerAdapter } from './base.js'\n\nclass NodeManagedWorker implements ManagedWorker {\n private worker: Worker\n\n constructor() {\n this.worker = new Worker(NODE_BOOTSTRAP_CODE, { eval: true })\n }\n\n get id(): number {\n return this.worker.threadId\n }\n\n postMessage(data: unknown): void {\n this.worker.postMessage(data)\n }\n\n terminate(): Promise<number> {\n return this.worker.terminate()\n }\n\n on(event: 'message', handler: (data: unknown) => void): void\n on(event: 'error', handler: (err: Error) => void): void\n on(event: 'exit', handler: (code: number) => void): void\n on(event: string, handler: (...args: any[]) => void): void {\n this.worker.on(event, handler)\n }\n\n unref(): void {\n this.worker.unref()\n }\n\n ref(): void {\n this.worker.ref()\n }\n}\n\nexport class NodeWorkerAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new NodeManagedWorker()\n }\n}\n","/**\n * Channel proxy code shared between Node and Web bootstraps.\n * Injected at the top of the worker, inert unless channels are passed.\n */\nconst CHANNEL_PROXY_CODE = `\nconst __chCallbacks = new Map();\nlet __chRpcId = 0;\n\nclass __ChannelProxy {\n constructor(id) {\n this._id = id;\n }\n\n _rpc(op, value) {\n const correlationId = ++__chRpcId;\n return new Promise((resolve, reject) => {\n __chCallbacks.set(correlationId, { resolve, reject });\n __postMsg({\n type: 'channel-op',\n channelId: this._id,\n op,\n correlationId,\n value\n });\n });\n }\n\n send(value) {\n return this._rpc('send', value);\n }\n\n recv() {\n return this._rpc('recv', undefined);\n }\n\n close() {\n __postMsg({\n type: 'channel-op',\n channelId: this._id,\n op: 'close',\n correlationId: ++__chRpcId\n });\n }\n\n [Symbol.asyncIterator]() {\n const proxy = this;\n return {\n async next() {\n const value = await proxy.recv();\n if (value === null) return { done: true, value: undefined };\n return { done: false, value };\n }\n };\n }\n}\n\nfunction __handleChannelResult(msg) {\n if (msg.type === 'channel-result') {\n const cb = __chCallbacks.get(msg.correlationId);\n if (cb) {\n __chCallbacks.delete(msg.correlationId);\n if (msg.error) {\n cb.reject(new Error(msg.error));\n } else {\n cb.resolve(msg.value);\n }\n }\n }\n}\n\nfunction __buildChannelProxies(channels) {\n if (!channels) return undefined;\n const proxies = {};\n for (const name of Object.keys(channels)) {\n proxies[name] = new __ChannelProxy(channels[name]);\n }\n return proxies;\n}\n\nfunction __execFn(fnStr, channels) {\n if (channels) {\n const __ch = __buildChannelProxies(channels);\n const fn = new Function('__ch', 'return (' + fnStr + ')(__ch)');\n return fn(__ch);\n } else {\n const fn = new Function('return (' + fnStr + ')()');\n return fn();\n }\n}\n`\n\n/** Bootstrap code for Node.js workers (eval: true, CJS context) */\nexport const NODE_BOOTSTRAP_CODE = `\n'use strict';\nconst { parentPort } = require('worker_threads');\n\nconst __postMsg = (d) => parentPort.postMessage(d);\n\n${CHANNEL_PROXY_CODE}\n\nconst cancelledTasks = new Set();\n\nparentPort.on('message', (msg) => {\n __handleChannelResult(msg);\n});\n\nparentPort.on('message', async (msg) => {\n if (msg.type === 'execute') {\n if (msg.concurrent) {\n (async () => {\n if (cancelledTasks.has(msg.taskId)) {\n cancelledTasks.delete(msg.taskId);\n return;\n }\n try {\n const result = await __execFn(msg.fnStr, msg.channels);\n if (!cancelledTasks.has(msg.taskId)) {\n parentPort.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n }\n } catch (error) {\n if (!cancelledTasks.has(msg.taskId)) {\n parentPort.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n } finally {\n cancelledTasks.delete(msg.taskId);\n }\n })();\n } else {\n try {\n const result = await __execFn(msg.fnStr, msg.channels);\n parentPort.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n } catch (error) {\n parentPort.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n } else if (msg.type === 'cancel') {\n cancelledTasks.add(msg.taskId);\n } else if (msg.type === 'shutdown') {\n process.exit(0);\n }\n});\n\nparentPort.postMessage({ type: 'ready' });\n`\n\n/** Bootstrap code for Bun/Web Workers (file-based, Web Worker API) */\nexport const WEB_BOOTSTRAP_CODE = `\nconst __postMsg = (d) => self.postMessage(d);\n\n${CHANNEL_PROXY_CODE}\n\nconst cancelledTasks = new Set();\n\nself.addEventListener('message', (event) => {\n __handleChannelResult(event.data);\n});\n\nself.onmessage = async (event) => {\n const msg = event.data;\n if (msg.type === 'execute') {\n if (msg.concurrent) {\n (async () => {\n if (cancelledTasks.has(msg.taskId)) {\n cancelledTasks.delete(msg.taskId);\n return;\n }\n try {\n const result = await __execFn(msg.fnStr, msg.channels);\n if (!cancelledTasks.has(msg.taskId)) {\n self.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n }\n } catch (error) {\n if (!cancelledTasks.has(msg.taskId)) {\n self.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n } finally {\n cancelledTasks.delete(msg.taskId);\n }\n })();\n } else {\n try {\n const result = await __execFn(msg.fnStr, msg.channels);\n self.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n } catch (error) {\n self.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n } else if (msg.type === 'cancel') {\n cancelledTasks.add(msg.taskId);\n } else if (msg.type === 'shutdown') {\n self.close();\n }\n};\n\nself.postMessage({ type: 'ready' });\n`\n\n/** @deprecated Use NODE_BOOTSTRAP_CODE instead */\nexport const BOOTSTRAP_CODE = NODE_BOOTSTRAP_CODE\n","import { WEB_BOOTSTRAP_CODE } from '../bootstrap.js'\nimport type { ManagedWorker, WorkerAdapter } from './base.js'\nimport { writeFileSync, unlinkSync, mkdtempSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { tmpdir } from 'node:os'\n\nlet workerIdCounter = 0\nlet bootstrapFile: string | null = null\n\n/**\n * Returns the path to a temporary JS file containing the bootstrap code.\n * Bun's Blob URL workers break when the URL is revoked before the worker\n * fully initializes its message handler, so we use a file-based worker instead.\n */\nfunction getBootstrapFile(): string {\n if (!bootstrapFile) {\n const dir = mkdtempSync(join(tmpdir(), 'puru-'))\n bootstrapFile = join(dir, 'worker.js')\n writeFileSync(bootstrapFile, WEB_BOOTSTRAP_CODE)\n }\n return bootstrapFile\n}\n\nclass BunManagedWorker implements ManagedWorker {\n private worker: Worker\n readonly id: number\n\n constructor() {\n this.id = ++workerIdCounter\n this.worker = new Worker(getBootstrapFile())\n }\n\n postMessage(data: unknown): void {\n this.worker.postMessage(data)\n }\n\n terminate(): Promise<number> {\n this.worker.terminate()\n // Web Worker terminate() is synchronous and void; return resolved 0\n return Promise.resolve(0)\n }\n\n on(event: 'message', handler: (data: unknown) => void): void\n on(event: 'error', handler: (err: Error) => void): void\n on(event: 'exit', handler: (code: number) => void): void\n on(event: string, handler: (...args: any[]) => void): void {\n if (event === 'message') {\n this.worker.addEventListener('message', (e: MessageEvent) => {\n handler(e.data)\n })\n } else if (event === 'error') {\n this.worker.addEventListener('error', (e: ErrorEvent) => {\n handler(e.error ?? new Error(e.message))\n })\n } else if (event === 'exit') {\n // Bun emits 'close' on worker termination\n this.worker.addEventListener('close', (e: CloseEvent) => {\n handler((e as any).code ?? 0)\n })\n }\n }\n\n unref(): void {\n // Bun Workers support unref()\n if ('unref' in this.worker && typeof this.worker.unref === 'function') {\n ;(this.worker as any).unref()\n }\n }\n\n ref(): void {\n // Bun Workers support ref()\n if ('ref' in this.worker && typeof this.worker.ref === 'function') {\n ;(this.worker as any).ref()\n }\n }\n}\n\nexport class BunWorkerAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new BunManagedWorker()\n }\n}\n\n/** Clean up the temporary bootstrap file. Called during pool drain. */\nexport function cleanupBootstrapFile(): void {\n if (bootstrapFile) {\n try { unlinkSync(bootstrapFile) } catch {}\n bootstrapFile = null\n }\n}\n","// Internal sentinel used to signal channel closure.\n// Using a symbol instead of null means null is a valid value to send through a channel\n// at the implementation level, and avoids silent failures if someone attempts to send null.\n// The public recv() API still returns null for a closed channel — the symbol is not leaked.\nconst CLOSED = Symbol('puru.channel.closed')\n\n/**\n * A Go-style channel for communicating between async tasks and across worker threads.\n *\n * Use `chan<T>(capacity?)` to create a channel. Values must be structured-cloneable\n * (no functions, symbols, or WeakRefs). `null` cannot be sent — `recv()` returns\n * `null` only when the channel is closed.\n *\n * @example\n * const ch = chan<number>(10)\n * await ch.send(42)\n * const value = await ch.recv() // 42\n * ch.close()\n * await ch.recv() // null — channel closed\n *\n * @example\n * // Async iteration ends automatically when the channel is closed\n * for await (const item of ch) {\n * process(item)\n * }\n */\nexport interface Channel<T> {\n send(value: T): Promise<void>\n /** Resolves with the next value, or `null` if the channel is closed. */\n recv(): Promise<T | null>\n close(): void\n [Symbol.asyncIterator](): AsyncIterator<T>\n}\n\ninterface PendingRecv<T> {\n resolve: (value: T | typeof CLOSED) => void\n}\n\ninterface PendingSend<T> {\n value: T\n resolve: () => void\n reject: (reason: unknown) => void\n}\n\nlet channelIdCounter = 0\nconst channelRegistry = new Map<string, ChannelImpl<NonNullable<unknown>>>()\n\nclass ChannelImpl<T extends NonNullable<unknown>> implements Channel<T> { // constraint: can't create channels of nullable type\n /** @internal */\n readonly _id: string\n private buffer: T[] = []\n private capacity: number\n private closed = false\n private recvQueue: PendingRecv<T>[] = []\n private sendQueue: PendingSend<T>[] = []\n\n constructor(capacity: number) {\n this._id = `__ch_${++channelIdCounter}`\n this.capacity = capacity\n channelRegistry.set(this._id, this as unknown as ChannelImpl<NonNullable<unknown>>)\n }\n\n send(value: T): Promise<void> {\n if (this.closed) {\n return Promise.reject(new Error('send on closed channel'))\n }\n\n // If there's a waiting receiver, deliver directly\n const receiver = this.recvQueue.shift()\n if (receiver) {\n receiver.resolve(value)\n return Promise.resolve()\n }\n\n // If buffer has room, buffer it\n if (this.buffer.length < this.capacity) {\n this.buffer.push(value)\n return Promise.resolve()\n }\n\n // Block until a receiver is ready\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ value, resolve, reject })\n })\n }\n\n recv(): Promise<T | null> {\n // If buffer has a value, take it and unblock a pending sender\n if (this.buffer.length > 0) {\n const value = this.buffer.shift()!\n const sender = this.sendQueue.shift()\n if (sender) {\n this.buffer.push(sender.value)\n sender.resolve()\n }\n return Promise.resolve(value)\n }\n\n // If there's a pending sender (unbuffered or buffer was empty), take directly\n const sender = this.sendQueue.shift()\n if (sender) {\n sender.resolve()\n return Promise.resolve(sender.value)\n }\n\n // If closed, return null\n if (this.closed) {\n return Promise.resolve(null)\n }\n\n // Block until a sender provides a value or channel closes\n return new Promise<T | null>((resolve) => {\n this.recvQueue.push({\n resolve: (v) => resolve(v === CLOSED ? null : (v as T)),\n })\n })\n }\n\n close(): void {\n if (this.closed) return\n this.closed = true\n\n // Resolve all pending receivers with the CLOSED sentinel (converted to null at the public boundary)\n for (const receiver of this.recvQueue) {\n receiver.resolve(CLOSED)\n }\n this.recvQueue = []\n\n // Reject all pending senders\n for (const sender of this.sendQueue) {\n sender.reject(new Error('send on closed channel'))\n }\n this.sendQueue = []\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n while (true) {\n const value = await this.recv()\n if (value === null) return\n yield value\n }\n }\n}\n\n/**\n * Create a Go-style channel for communicating between tasks and across worker threads.\n *\n * Provides backpressure: `send()` blocks when the buffer is full,\n * `recv()` blocks when the buffer is empty. Channel values must be structured-cloneable\n * (no functions, symbols, or WeakRefs). `null` cannot be sent — it signals closure.\n *\n * @param capacity Buffer size. `0` (default) = unbuffered: each `send()` blocks until a `recv()` is ready.\n *\n * @example\n * const ch = chan<string>(5) // buffered channel, capacity 5\n * await ch.send('hello')\n * const msg = await ch.recv() // 'hello'\n * ch.close()\n *\n * @example\n * // Fan-out: multiple workers pulling from the same channel\n * const input = chan<Job>(50)\n * const output = chan<Result>(50)\n *\n * for (let i = 0; i < 4; i++) {\n * spawn(async ({ input, output }) => {\n * for await (const job of input) {\n * await output.send(processJob(job))\n * }\n * }, { channels: { input, output } })\n * }\n */\nexport function chan<T extends NonNullable<unknown>>(capacity: number = 0): Channel<T> {\n if (capacity < 0 || !Number.isInteger(capacity)) {\n throw new RangeError('Channel capacity must be a non-negative integer')\n }\n return new ChannelImpl<T>(capacity)\n}\n\n/** @internal */\nexport function getChannelById(id: string): Channel<NonNullable<unknown>> | undefined {\n return channelRegistry.get(id)\n}\n\n/** @internal */\nexport function resetChannelRegistry(): void {\n channelRegistry.clear()\n channelIdCounter = 0\n}\n","import type { ManagedWorker, WorkerAdapter } from './base.js'\nimport { getChannelById } from '../channel.js'\n\nlet inlineIdCounter = 0\n\ntype MessageHandler = (data: unknown) => void\ntype ErrorHandler = (err: Error) => void\ntype ExitHandler = (code: number) => void\n\nclass InlineManagedWorker implements ManagedWorker {\n readonly id: number\n private messageHandlers: MessageHandler[] = []\n private errorHandlers: ErrorHandler[] = []\n private exitHandlers: ExitHandler[] = []\n private terminated = false\n private cancelledTasks = new Set<string>()\n\n constructor() {\n this.id = ++inlineIdCounter\n // Emit ready on next microtask (matches real worker timing)\n queueMicrotask(() => {\n this.emit('message', { type: 'ready' })\n })\n }\n\n postMessage(data: unknown): void {\n if (this.terminated) return\n\n const msg = data as { type: string; taskId?: string; fnStr?: string; concurrent?: boolean; channels?: Record<string, string>; correlationId?: number; value?: unknown; error?: string }\n if (msg.type === 'execute') {\n this.executeTask(msg.taskId!, msg.fnStr!, msg.concurrent ?? false, msg.channels)\n } else if (msg.type === 'cancel') {\n this.cancelledTasks.add(msg.taskId!)\n } else if (msg.type === 'channel-result') {\n // Route channel results back to pending RPC callbacks\n this.emit('message', msg)\n } else if (msg.type === 'shutdown') {\n this.terminated = true\n this.emit('exit', 0)\n }\n }\n\n terminate(): Promise<number> {\n this.terminated = true\n this.emit('exit', 1)\n return Promise.resolve(1)\n }\n\n on(event: 'message', handler: MessageHandler): void\n on(event: 'error', handler: ErrorHandler): void\n on(event: 'exit', handler: ExitHandler): void\n on(event: string, handler: (...args: any[]) => void): void {\n if (event === 'message') this.messageHandlers.push(handler as MessageHandler)\n else if (event === 'error') this.errorHandlers.push(handler as ErrorHandler)\n else if (event === 'exit') this.exitHandlers.push(handler as ExitHandler)\n }\n\n unref(): void {}\n ref(): void {}\n\n private emit(event: 'message', data: unknown): void\n private emit(event: 'error', err: Error): void\n private emit(event: 'exit', code: number): void\n private emit(event: string, value: unknown): void {\n if (event === 'message') {\n for (const h of this.messageHandlers) h(value)\n } else if (event === 'error') {\n for (const h of this.errorHandlers) h(value as Error)\n } else if (event === 'exit') {\n for (const h of this.exitHandlers) h(value as number)\n }\n }\n\n private buildChannelProxies(channels: Record<string, string>): Record<string, unknown> {\n const self = this\n const proxies: Record<string, unknown> = {}\n for (const [name, channelId] of Object.entries(channels)) {\n proxies[name] = {\n _id: channelId,\n async send(value: unknown) {\n const ch = getChannelById(channelId)\n if (!ch) throw new Error(`Channel ${channelId} not found`)\n await ch.send(value)\n },\n async recv() {\n const ch = getChannelById(channelId)\n if (!ch) throw new Error(`Channel ${channelId} not found`)\n return ch.recv()\n },\n close() {\n const ch = getChannelById(channelId)\n if (ch) ch.close()\n },\n [Symbol.asyncIterator]() {\n const ch = getChannelById(channelId) as any\n if (!ch) throw new Error(`Channel ${channelId} not found`)\n return {\n async next() {\n const value = await ch.recv()\n if (value === null) return { done: true, value: undefined }\n return { done: false, value }\n }\n }\n }\n }\n }\n return proxies\n }\n\n private executeTask(taskId: string, fnStr: string, concurrent: boolean, channels?: Record<string, string>): void {\n // Run on next microtask to simulate async worker behavior\n queueMicrotask(async () => {\n if (this.terminated) return\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId)\n return\n }\n try {\n let result: unknown\n if (channels) {\n const proxies = this.buildChannelProxies(channels)\n const fn = new Function('__ch', 'return (' + fnStr + ')(__ch)') as (ch: unknown) => unknown\n result = await fn(proxies)\n } else {\n const fn = new Function('return (' + fnStr + ')()') as () => unknown\n result = await fn()\n }\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId)\n return\n }\n this.emit('message', { type: 'result', taskId, value: result })\n } catch (error) {\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId)\n return\n }\n this.emit('message', {\n type: 'error',\n taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n })\n }\n })\n }\n}\n\nexport class InlineAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new InlineManagedWorker()\n }\n}\n","import type { ManagedWorker, WorkerAdapter } from './adapters/base.js'\nimport type { PuruConfig, Task, WorkerMessage, WorkerResponse } from './types.js'\nimport { getConfig } from './configure.js'\nimport { detectRuntime, detectCapability } from './runtime.js'\nimport { NodeWorkerAdapter } from './adapters/node.js'\nimport { BunWorkerAdapter } from './adapters/bun.js'\nimport { InlineAdapter } from './adapters/inline.js'\nimport { getChannelById } from './channel.js'\n\nexport class WorkerPool {\n private config: PuruConfig\n private adapter: WorkerAdapter\n private idleWorkers: ManagedWorker[] = []\n private exclusiveWorkers = new Map<string, ManagedWorker>()\n private sharedWorkers = new Map<ManagedWorker, Set<string>>()\n private queues = {\n high: [] as Task[],\n normal: [] as Task[],\n low: [] as Task[],\n }\n private concurrentQueues = {\n high: [] as Task[],\n normal: [] as Task[],\n low: [] as Task[],\n }\n private allWorkers = new Set<ManagedWorker>()\n private idleTimers = new Map<ManagedWorker, ReturnType<typeof setTimeout>>()\n private pendingWorkerCount = 0\n private pendingTasksForWorkers: Task[] = []\n private draining = false\n private totalCompleted = 0\n private totalFailed = 0\n private taskMap = new Map<string, Task>()\n\n constructor(config: PuruConfig, adapter: WorkerAdapter) {\n this.config = config\n this.adapter = adapter\n }\n\n // --- Queue helpers ---\n\n private enqueue(task: Task): void {\n this.queues[task.priority].push(task)\n }\n\n private dequeue(): Task | undefined {\n return (\n this.queues.high.shift() ??\n this.queues.normal.shift() ??\n this.queues.low.shift()\n )\n }\n\n private enqueueConcurrent(task: Task): void {\n this.concurrentQueues[task.priority].push(task)\n }\n\n private dequeueConcurrent(): Task | undefined {\n return (\n this.concurrentQueues.high.shift() ??\n this.concurrentQueues.normal.shift() ??\n this.concurrentQueues.low.shift()\n )\n }\n\n private removeFromQueue(taskId: string): Task | undefined {\n for (const priority of ['high', 'normal', 'low'] as const) {\n const queue = this.queues[priority]\n const idx = queue.findIndex((t) => t.id === taskId)\n if (idx !== -1) {\n return queue.splice(idx, 1)[0]\n }\n }\n return undefined\n }\n\n private removeFromConcurrentQueue(taskId: string): Task | undefined {\n for (const priority of ['high', 'normal', 'low'] as const) {\n const queue = this.concurrentQueues[priority]\n const idx = queue.findIndex((t) => t.id === taskId)\n if (idx !== -1) {\n return queue.splice(idx, 1)[0]\n }\n }\n return undefined\n }\n\n // --- Submit ---\n\n submit(task: Task): void {\n if (this.draining) {\n task.reject(new Error('Pool is shutting down'))\n return\n }\n\n if (task.concurrent) {\n this.submitConcurrent(task)\n } else {\n this.submitExclusive(task)\n }\n }\n\n private submitExclusive(task: Task): void {\n // Try to assign to an idle worker\n const worker = this.idleWorkers.pop()\n if (worker) {\n this.dispatch(worker, task)\n return\n }\n\n // Try to create a new worker\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount\n if (totalWorkers < this.config.maxThreads) {\n this.pendingWorkerCount++\n this.pendingTasksForWorkers.push(task)\n this.createAndReadyWorker()\n return\n }\n\n // Queue the task by priority\n this.enqueue(task)\n }\n\n private submitConcurrent(task: Task): void {\n // 1. Find a shared worker under the concurrency limit\n for (const [worker, tasks] of this.sharedWorkers) {\n if (tasks.size < this.config.concurrency) {\n this.dispatchConcurrent(worker, task)\n return\n }\n }\n\n // 2. Grab an idle worker and convert to shared mode\n const idleWorker = this.idleWorkers.pop()\n if (idleWorker) {\n this.dispatchConcurrent(idleWorker, task)\n return\n }\n\n // 3. Spin up a new worker if under limit\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount\n if (totalWorkers < this.config.maxThreads) {\n this.pendingWorkerCount++\n this.pendingTasksForWorkers.push(task)\n this.createAndReadyWorker()\n return\n }\n\n // 4. All workers busy/saturated — queue it\n this.enqueueConcurrent(task)\n }\n\n // --- Dispatch ---\n\n private dispatch(worker: ManagedWorker, task: Task): void {\n const timer = this.idleTimers.get(worker)\n if (timer) {\n clearTimeout(timer)\n this.idleTimers.delete(worker)\n }\n\n worker.ref()\n this.exclusiveWorkers.set(task.id, worker)\n this.taskMap.set(task.id, task)\n\n const msg: WorkerMessage = {\n type: 'execute',\n taskId: task.id,\n fnStr: task.fnStr,\n concurrent: false,\n channels: task.channels,\n }\n worker.postMessage(msg)\n }\n\n private dispatchConcurrent(worker: ManagedWorker, task: Task): void {\n const timer = this.idleTimers.get(worker)\n if (timer) {\n clearTimeout(timer)\n this.idleTimers.delete(worker)\n }\n\n worker.ref()\n\n if (!this.sharedWorkers.has(worker)) {\n this.sharedWorkers.set(worker, new Set())\n }\n this.sharedWorkers.get(worker)!.add(task.id)\n this.taskMap.set(task.id, task)\n\n const msg: WorkerMessage = {\n type: 'execute',\n taskId: task.id,\n fnStr: task.fnStr,\n concurrent: true,\n channels: task.channels,\n }\n worker.postMessage(msg)\n }\n\n // --- Task completion ---\n\n private handleWorkerMessage(worker: ManagedWorker, response: WorkerResponse): void {\n if (response.type === 'channel-op') {\n this.handleChannelOp(worker, response)\n return\n }\n\n if (response.type === 'result') {\n const taskId = response.taskId\n this.resolveTask(taskId, response.value)\n\n if (this.exclusiveWorkers.has(taskId)) {\n this.exclusiveWorkers.delete(taskId)\n this.assignNextOrIdle(worker)\n } else {\n const taskSet = this.sharedWorkers.get(worker)\n if (taskSet) {\n taskSet.delete(taskId)\n this.assignNextConcurrentOrIdle(worker)\n }\n }\n } else if (response.type === 'error') {\n const taskId = response.taskId\n const err = new Error(response.message)\n if (response.stack) err.stack = response.stack\n // ReferenceError inside a worker almost always means the function captured\n // a variable from the enclosing scope. Surface a clear message rather than\n // a cryptic worker-internal stack trace.\n if (response.message.match(/^ReferenceError:/) || response.message.match(/ is not defined$/)) {\n err.message +=\n '\\n Hint: functions passed to spawn() cannot access variables from the enclosing scope. ' +\n 'Inline all required values directly in the function body, or pass them via the channels option.'\n }\n this.rejectTask(taskId, err)\n\n if (this.exclusiveWorkers.has(taskId)) {\n this.exclusiveWorkers.delete(taskId)\n this.assignNextOrIdle(worker)\n } else {\n const taskSet = this.sharedWorkers.get(worker)\n if (taskSet) {\n taskSet.delete(taskId)\n this.assignNextConcurrentOrIdle(worker)\n }\n }\n }\n }\n\n private assignNextOrIdle(worker: ManagedWorker): void {\n if (!this.allWorkers.has(worker)) return\n\n // Try exclusive queue first\n const next = this.dequeue()\n if (next) {\n this.dispatch(worker, next)\n return\n }\n\n // Then try concurrent queue\n const concurrentNext = this.dequeueConcurrent()\n if (concurrentNext) {\n this.dispatchConcurrent(worker, concurrentNext)\n return\n }\n\n this.makeIdle(worker)\n }\n\n private assignNextConcurrentOrIdle(worker: ManagedWorker): void {\n if (!this.allWorkers.has(worker)) return\n\n const taskSet = this.sharedWorkers.get(worker)\n const currentCount = taskSet?.size ?? 0\n\n // Fill up to concurrency limit from concurrent queue\n let filled = currentCount\n while (filled < this.config.concurrency) {\n const next = this.dequeueConcurrent()\n if (!next) break\n this.dispatchConcurrent(worker, next)\n filled++\n }\n\n // If no tasks remain, transition back\n const updatedSet = this.sharedWorkers.get(worker)\n if (!updatedSet || updatedSet.size === 0) {\n this.sharedWorkers.delete(worker)\n // Try exclusive queue before going idle\n const exclusiveTask = this.dequeue()\n if (exclusiveTask) {\n this.dispatch(worker, exclusiveTask)\n } else {\n this.makeIdle(worker)\n }\n }\n }\n\n private makeIdle(worker: ManagedWorker): void {\n worker.unref()\n this.idleWorkers.push(worker)\n\n if (this.config.idleTimeout > 0) {\n const timer = setTimeout(() => {\n this.idleTimers.delete(worker)\n const idx = this.idleWorkers.indexOf(worker)\n if (idx !== -1) {\n this.idleWorkers.splice(idx, 1)\n }\n this.allWorkers.delete(worker)\n worker.terminate()\n }, this.config.idleTimeout)\n\n // Don't let the idle timer prevent process exit\n if (timer.unref) timer.unref()\n this.idleTimers.set(worker, timer)\n }\n }\n\n // --- Channel RPC ---\n\n private async handleChannelOp(\n worker: ManagedWorker,\n msg: { channelId: string; op: 'send' | 'recv' | 'close'; correlationId: number; value?: unknown },\n ): Promise<void> {\n const channel = getChannelById(msg.channelId)\n\n if (!channel) {\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n error: `Channel ${msg.channelId} not found`,\n })\n return\n }\n\n try {\n if (msg.op === 'send') {\n await channel.send(msg.value as NonNullable<unknown>)\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n })\n } else if (msg.op === 'recv') {\n const value = await channel.recv()\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n value,\n })\n } else if (msg.op === 'close') {\n channel.close()\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n })\n }\n } catch (err) {\n worker.postMessage({\n type: 'channel-result',\n correlationId: msg.correlationId,\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n // --- Task resolution ---\n\n private resolveTask(taskId: string, value: unknown): void {\n const task = this.taskMap.get(taskId)\n if (task) {\n this.taskMap.delete(taskId)\n this.totalCompleted++\n task.resolve(value)\n }\n }\n\n private rejectTask(taskId: string, reason: unknown): void {\n const task = this.taskMap.get(taskId)\n if (task) {\n this.taskMap.delete(taskId)\n this.totalFailed++\n task.reject(reason)\n }\n }\n\n // --- Cancellation ---\n\n cancelTask(taskId: string): void {\n // 1. Check exclusive queues\n const removed = this.removeFromQueue(taskId)\n if (removed) {\n removed.reject(new DOMException('Task was cancelled', 'AbortError'))\n return\n }\n\n // 2. Check concurrent queues\n const removedConcurrent = this.removeFromConcurrentQueue(taskId)\n if (removedConcurrent) {\n removedConcurrent.reject(new DOMException('Task was cancelled', 'AbortError'))\n return\n }\n\n // 3. Check exclusive workers — terminate the worker (existing behavior)\n const exclusiveWorker = this.exclusiveWorkers.get(taskId)\n if (exclusiveWorker) {\n this.exclusiveWorkers.delete(taskId)\n this.allWorkers.delete(exclusiveWorker)\n this.taskMap.delete(taskId)\n exclusiveWorker.terminate()\n return\n }\n\n // 4. Check shared workers — send cancel message, do NOT terminate\n for (const [worker, taskSet] of this.sharedWorkers) {\n if (taskSet.has(taskId)) {\n taskSet.delete(taskId)\n this.taskMap.delete(taskId)\n worker.postMessage({ type: 'cancel', taskId })\n if (taskSet.size === 0) {\n this.sharedWorkers.delete(worker)\n this.assignNextConcurrentOrIdle(worker)\n }\n return\n }\n }\n }\n\n // --- Lifecycle ---\n\n async drain(): Promise<void> {\n this.draining = true\n\n // Reject all queued exclusive tasks\n for (const priority of ['high', 'normal', 'low'] as const) {\n for (const task of this.queues[priority]) {\n task.reject(new Error('Pool is shutting down'))\n }\n this.queues[priority] = []\n }\n\n // Reject all queued concurrent tasks\n for (const priority of ['high', 'normal', 'low'] as const) {\n for (const task of this.concurrentQueues[priority]) {\n task.reject(new Error('Pool is shutting down'))\n }\n this.concurrentQueues[priority] = []\n }\n\n // Clear in-flight concurrent tasks — their workers are about to be terminated.\n // We don't reject them here because the caller may not be listening, which\n // would cause unhandled rejection errors. The promises will simply never settle.\n for (const [, taskSet] of this.sharedWorkers) {\n for (const taskId of taskSet) {\n this.taskMap.delete(taskId)\n }\n }\n\n // Terminate all workers\n const terminatePromises: Promise<number>[] = []\n for (const worker of this.allWorkers) {\n const timer = this.idleTimers.get(worker)\n if (timer) clearTimeout(timer)\n terminatePromises.push(worker.terminate())\n }\n\n await Promise.all(terminatePromises)\n\n this.idleWorkers = []\n this.exclusiveWorkers.clear()\n this.sharedWorkers.clear()\n this.allWorkers.clear()\n this.idleTimers.clear()\n }\n\n resize(maxThreads: number): void {\n this.config = { ...this.config, maxThreads }\n\n // If we now have capacity, dequeue tasks and spin up workers\n while (true) {\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount\n if (totalWorkers >= maxThreads) break\n // Try exclusive queue first, then concurrent\n const task = this.dequeue() ?? this.dequeueConcurrent()\n if (!task) break\n this.pendingWorkerCount++\n this.pendingTasksForWorkers.push(task)\n this.createAndReadyWorker()\n }\n\n // If pool is now oversized, terminate excess idle workers\n while (this.allWorkers.size > maxThreads && this.idleWorkers.length > 0) {\n const worker = this.idleWorkers.pop()!\n const timer = this.idleTimers.get(worker)\n if (timer) {\n clearTimeout(timer)\n this.idleTimers.delete(worker)\n }\n this.allWorkers.delete(worker)\n worker.terminate()\n }\n }\n\n // --- Worker creation ---\n\n private createAndReadyWorker(): void {\n const worker = this.adapter.createWorker()\n\n const onReady = () => {\n this.pendingWorkerCount--\n this.allWorkers.add(worker)\n\n const task = this.pendingTasksForWorkers.shift()\n if (task) {\n if (task.concurrent) {\n this.dispatchConcurrent(worker, task)\n } else {\n this.dispatch(worker, task)\n }\n } else {\n this.makeIdle(worker)\n }\n }\n\n worker.on('message', (msg: unknown) => {\n const response = msg as WorkerResponse\n if (response.type === 'ready') {\n onReady()\n return\n }\n this.handleWorkerMessage(worker, response)\n })\n\n worker.on('error', (err: Error) => {\n // Clean up exclusive task on this worker\n for (const [taskId, w] of this.exclusiveWorkers) {\n if (w === worker) {\n this.exclusiveWorkers.delete(taskId)\n break\n }\n }\n // Clean up concurrent tasks on this worker\n const taskSet = this.sharedWorkers.get(worker)\n if (taskSet) {\n for (const taskId of taskSet) {\n this.rejectTask(taskId, err)\n }\n this.sharedWorkers.delete(worker)\n }\n })\n\n worker.on('exit', (_code: number) => {\n this.allWorkers.delete(worker)\n const timer = this.idleTimers.get(worker)\n if (timer) {\n clearTimeout(timer)\n this.idleTimers.delete(worker)\n }\n\n // Remove from idle if present\n const idleIdx = this.idleWorkers.indexOf(worker)\n if (idleIdx !== -1) {\n this.idleWorkers.splice(idleIdx, 1)\n }\n\n // Clean up exclusive task\n for (const [taskId, w] of this.exclusiveWorkers) {\n if (w === worker) {\n this.exclusiveWorkers.delete(taskId)\n break\n }\n }\n\n // Clean up concurrent tasks\n const taskSet = this.sharedWorkers.get(worker)\n if (taskSet) {\n for (const taskId of taskSet) {\n this.rejectTask(taskId, new Error('Worker exited unexpectedly'))\n }\n this.sharedWorkers.delete(worker)\n }\n })\n }\n\n // --- Stats ---\n\n stats(): PoolStats {\n let concurrentTasks = 0\n for (const taskSet of this.sharedWorkers.values()) {\n concurrentTasks += taskSet.size\n }\n\n return {\n totalWorkers: this.allWorkers.size,\n idleWorkers: this.idleWorkers.length,\n busyWorkers: this.exclusiveWorkers.size,\n sharedWorkers: this.sharedWorkers.size,\n concurrentTasks,\n pendingWorkers: this.pendingWorkerCount,\n queuedTasks: {\n high: this.queues.high.length,\n normal: this.queues.normal.length,\n low: this.queues.low.length,\n total:\n this.queues.high.length +\n this.queues.normal.length +\n this.queues.low.length,\n },\n queuedConcurrentTasks: {\n high: this.concurrentQueues.high.length,\n normal: this.concurrentQueues.normal.length,\n low: this.concurrentQueues.low.length,\n total:\n this.concurrentQueues.high.length +\n this.concurrentQueues.normal.length +\n this.concurrentQueues.low.length,\n },\n totalCompleted: this.totalCompleted,\n totalFailed: this.totalFailed,\n maxThreads: this.config.maxThreads,\n concurrency: this.config.concurrency,\n }\n }\n}\n\nexport interface PoolStats {\n totalWorkers: number\n idleWorkers: number\n busyWorkers: number\n sharedWorkers: number\n concurrentTasks: number\n pendingWorkers: number\n queuedTasks: {\n high: number\n normal: number\n low: number\n total: number\n }\n queuedConcurrentTasks: {\n high: number\n normal: number\n low: number\n total: number\n }\n totalCompleted: number\n totalFailed: number\n maxThreads: number\n concurrency: number\n}\n\n// Pool singleton\nlet poolInstance: WorkerPool | null = null\n\nfunction createAdapter(adapterConfig: string): WorkerAdapter {\n if (adapterConfig === 'inline') return new InlineAdapter()\n if (adapterConfig === 'node') return new NodeWorkerAdapter()\n if (adapterConfig === 'bun') return new BunWorkerAdapter()\n\n // auto — detect runtime\n const capability = detectCapability()\n if (capability === 'single-thread') {\n throw new Error(\n 'puru requires a runtime with thread support (Node.js or Bun). ' +\n 'Current runtime does not support worker threads.',\n )\n }\n const runtime = detectRuntime()\n if (runtime === 'bun') return new BunWorkerAdapter()\n return new NodeWorkerAdapter()\n}\n\nexport function getPool(): WorkerPool {\n if (!poolInstance) {\n const config = getConfig()\n poolInstance = new WorkerPool(config, createAdapter(config.adapter))\n }\n return poolInstance\n}\n\nexport function stats(): PoolStats {\n return getPool().stats()\n}\n\nexport function resize(maxThreads: number): void {\n getPool().resize(maxThreads)\n}\n\n/**\n * Gracefully shut down the thread pool.\n *\n * Rejects all queued tasks, waits for all workers to terminate, then clears\n * the pool. Safe to call at process exit or at the end of a test suite.\n *\n * ```ts\n * process.on('SIGTERM', async () => {\n * await shutdown()\n * process.exit(0)\n * })\n * ```\n */\nexport async function shutdown(): Promise<void> {\n if (poolInstance) {\n await poolInstance.drain()\n poolInstance = null\n }\n}\n\n/** @internal For testing only */\nexport async function resetPool(): Promise<void> {\n await shutdown()\n}\n","import { serializeFunction } from './serialize.js'\nimport { getPool } from './pool.js'\nimport type { SpawnResult, Task } from './types.js'\nimport type { Channel } from './channel.js'\n\nlet taskCounter = 0\n\n/**\n * Run a function in a worker thread. Returns a handle with the result promise and a cancel function.\n *\n * **Functions must be self-contained** — they are serialized via `.toString()` and sent to a\n * worker thread, so they cannot capture variables from the enclosing scope. Define everything\n * you need inside the function body, or use `task()` to pass arguments.\n *\n * **Two modes:**\n * - Default (exclusive): the function gets a dedicated thread. Best for CPU-bound work (> 5ms).\n * - `{ concurrent: true }`: many tasks share a thread's event loop. Best for async/I/O work.\n *\n * @example\n * // CPU-bound work — define helpers inside the function body\n * const { result } = spawn(() => {\n * function fibonacci(n: number): number {\n * if (n <= 1) return n\n * return fibonacci(n - 1) + fibonacci(n - 2)\n * }\n * return fibonacci(40)\n * })\n * console.log(await result)\n *\n * @example\n * // I/O-bound work — concurrent mode shares threads efficiently\n * const { result } = spawn(() => fetch('https://api.example.com').then(r => r.json()), {\n * concurrent: true,\n * })\n *\n * @example\n * // Cancel a long-running task\n * const { result, cancel } = spawn(() => longRunningTask())\n * setTimeout(cancel, 5000)\n *\n * @example\n * // Cross-thread channels — pass channels via opts.channels\n * const ch = chan<number>(10)\n * spawn(async ({ ch }) => {\n * for (let i = 0; i < 100; i++) await ch.send(i)\n * ch.close()\n * }, { channels: { ch } })\n */\nexport function spawn<T>(\n fn: (() => T | Promise<T>) | ((channels: Record<string, Channel<unknown>>) => T | Promise<T>),\n opts?: {\n priority?: 'low' | 'normal' | 'high'\n concurrent?: boolean\n channels?: Record<string, Channel<unknown>>\n },\n): SpawnResult<T> {\n const fnStr = serializeFunction(fn)\n const taskId = String(++taskCounter)\n\n // Capture the call site stack for better error reporting\n const spawnStack = new Error().stack\n\n let resolveFn!: (value: T) => void\n let rejectFn!: (reason: unknown) => void\n let settled = false\n\n const result = new Promise<T>((resolve, reject) => {\n resolveFn = resolve\n rejectFn = reject\n })\n\n // Extract channel IDs if channels are provided\n let channelMap: Record<string, string> | undefined\n if (opts?.channels) {\n channelMap = {}\n for (const [name, ch] of Object.entries(opts.channels)) {\n const impl = ch as unknown as { _id: string }\n if (!impl._id) {\n throw new Error(`Channel \"${name}\" is not a valid puru channel`)\n }\n channelMap[name] = impl._id\n }\n }\n\n const task: Task = {\n id: taskId,\n fnStr,\n priority: opts?.priority ?? 'normal',\n concurrent: opts?.concurrent ?? false,\n channels: channelMap,\n resolve: (value) => {\n if (!settled) {\n settled = true\n resolveFn(value as T)\n }\n },\n reject: (reason) => {\n if (!settled) {\n settled = true\n // Enrich worker errors with the spawn() call site\n if (reason instanceof Error && spawnStack) {\n const callerLine = spawnStack\n .split('\\n')\n .slice(2)\n .join('\\n')\n reason.stack =\n (reason.stack ?? reason.message) +\n '\\n --- spawned at ---\\n' +\n callerLine\n }\n rejectFn(reason)\n }\n },\n }\n\n getPool().submit(task)\n\n const cancel = () => {\n if (settled) return\n settled = true\n getPool().cancelTask(taskId)\n rejectFn(new DOMException('Task was cancelled', 'AbortError'))\n }\n\n return { result, cancel }\n}\n\n/** @internal For testing only */\nexport function resetTaskCounter(): void {\n taskCounter = 0\n}\n","import { spawn } from './spawn.js'\nimport type { SpawnResult } from './types.js'\nimport type { Channel } from './channel.js'\n\n/**\n * Structured concurrency: spawn multiple tasks and wait for all to complete.\n *\n * Like `Promise.all`, but tasks run in worker threads across CPU cores. Results are\n * returned in the order tasks were spawned. A shared `AbortSignal` lets long-running\n * tasks observe cooperative cancellation via `cancel()`.\n *\n * For fail-fast behavior (cancel all on first error), use `ErrGroup` instead.\n *\n * @example\n * // CPU-bound parallel work\n * const wg = new WaitGroup()\n * wg.spawn(() => { /* define helpers inside — no closure captures *\\/ })\n * wg.spawn(() => { /* another CPU task *\\/ })\n * const [r1, r2] = await wg.wait()\n *\n * @example\n * // Mixed CPU + I/O\n * wg.spawn(() => crunchNumbers(), )\n * wg.spawn(() => fetch('https://api.example.com').then(r => r.json()), { concurrent: true })\n * const results = await wg.wait()\n *\n * @example\n * // Tolerate partial failures with waitSettled\n * const settled = await wg.waitSettled()\n * for (const r of settled) {\n * if (r.status === 'fulfilled') use(r.value)\n * else console.error(r.reason)\n * }\n */\nexport class WaitGroup {\n private tasks: SpawnResult<unknown>[] = []\n private controller = new AbortController()\n\n /**\n * An `AbortSignal` shared across all tasks in this group.\n * Pass it into spawned functions so they can stop early when `cancel()` is called.\n */\n get signal(): AbortSignal {\n return this.controller.signal\n }\n\n /**\n * Spawns a function on a worker thread and adds it to the group.\n *\n * @throws If the group has already been cancelled.\n */\n spawn(\n fn: (() => unknown) | ((channels: Record<string, Channel<unknown>>) => unknown),\n opts?: { concurrent?: boolean; channels?: Record<string, Channel<unknown>> },\n ): void {\n if (this.controller.signal.aborted) {\n throw new Error('WaitGroup has been cancelled')\n }\n const handle = spawn(fn, opts)\n this.tasks.push(handle)\n }\n\n /**\n * Waits for all tasks to complete successfully.\n * Rejects as soon as any task throws.\n */\n async wait(): Promise<unknown[]> {\n return Promise.all(this.tasks.map((t) => t.result))\n }\n\n /**\n * Waits for all tasks to settle (fulfilled or rejected) and returns each outcome.\n * Never rejects — inspect each `PromiseSettledResult` to handle failures individually.\n */\n async waitSettled(): Promise<PromiseSettledResult<unknown>[]> {\n return Promise.allSettled(this.tasks.map((t) => t.result))\n }\n\n /**\n * Cancels all tasks in the group and signals the shared `AbortSignal`.\n * Already-settled tasks are unaffected.\n */\n cancel(): void {\n this.controller.abort()\n for (const task of this.tasks) {\n task.cancel()\n }\n }\n}\n","import { spawn } from './spawn.js'\nimport type { SpawnResult } from './types.js'\nimport type { Channel } from './channel.js'\n\n/**\n * Like `WaitGroup`, but cancels all remaining tasks on the first error.\n *\n * Modeled after Go's `golang.org/x/sync/errgroup`. Use when partial results are useless —\n * if any task fails, there is no point waiting for the rest. Benchmarks show ~3.7x faster\n * failure handling than waiting for all tasks to settle.\n *\n * For \"wait for everything regardless of failures\", use `WaitGroup` with `waitSettled()`.\n *\n * @example\n * const eg = new ErrGroup()\n * eg.spawn(() => run('fetchUser', userId))\n * eg.spawn(() => run('fetchOrders', userId))\n * eg.spawn(() => run('fetchAnalytics', userId))\n *\n * try {\n * const [user, orders, analytics] = await eg.wait()\n * } catch (err) {\n * // First failure cancelled the rest — no partial data to clean up\n * }\n *\n * @example\n * // Observe cancellation inside a task via the shared signal\n * const eg = new ErrGroup()\n * eg.spawn(() => {\n * // eg.signal is not directly available inside the worker —\n * // use task() with register() and check a channel or AbortSignal instead\n * })\n */\nexport class ErrGroup {\n private tasks: SpawnResult<unknown>[] = []\n private controller = new AbortController()\n private firstError: unknown = undefined\n private hasError = false\n\n get signal(): AbortSignal {\n return this.controller.signal\n }\n\n spawn(\n fn: (() => unknown) | ((channels: Record<string, Channel<unknown>>) => unknown),\n opts?: { concurrent?: boolean; channels?: Record<string, Channel<unknown>> },\n ): void {\n if (this.controller.signal.aborted) {\n throw new Error('ErrGroup has been cancelled')\n }\n const handle = spawn(fn, opts)\n\n // Watch for errors and cancel all tasks on first failure\n handle.result.catch((err) => {\n if (!this.hasError) {\n this.hasError = true\n this.firstError = err\n this.cancel()\n }\n })\n\n this.tasks.push(handle)\n }\n\n async wait(): Promise<unknown[]> {\n const settled = await Promise.allSettled(this.tasks.map((t) => t.result))\n\n if (this.hasError) {\n throw this.firstError\n }\n\n return settled.map((r) => {\n if (r.status === 'fulfilled') return r.value\n throw r.reason\n })\n }\n\n cancel(): void {\n this.controller.abort()\n for (const task of this.tasks) {\n task.cancel()\n }\n }\n}\n","/**\n * Async mutual exclusion. Serializes access to shared state under concurrency.\n *\n * Prefer `withLock()` over manual `lock()`/`unlock()` — it automatically releases\n * the lock even if the callback throws.\n *\n * Note: `Mutex` operates on the main thread (or whichever thread creates it).\n * Worker threads do not share memory, so this is not useful for cross-thread locking.\n * For cross-thread coordination, use channels instead.\n *\n * @example\n * const mu = new Mutex()\n *\n * // withLock — recommended (auto-unlocks on error)\n * const result = await mu.withLock(async () => {\n * const current = await db.get('counter')\n * await db.set('counter', current + 1)\n * return current + 1\n * })\n *\n * @example\n * // Manual lock/unlock (use withLock instead when possible)\n * await mu.lock()\n * try {\n * // critical section\n * } finally {\n * mu.unlock()\n * }\n */\nexport class Mutex {\n private queue: (() => void)[] = []\n private locked = false\n\n async lock(): Promise<void> {\n if (!this.locked) {\n this.locked = true\n return\n }\n return new Promise<void>((resolve) => {\n this.queue.push(resolve)\n })\n }\n\n unlock(): void {\n if (!this.locked) {\n throw new Error('Cannot unlock a mutex that is not locked')\n }\n const next = this.queue.shift()\n if (next) {\n next()\n } else {\n this.locked = false\n }\n }\n\n async withLock<T>(fn: () => T | Promise<T>): Promise<T> {\n await this.lock()\n try {\n return await fn()\n } finally {\n this.unlock()\n }\n }\n\n get isLocked(): boolean {\n return this.locked\n }\n}\n","/**\n * Run a function exactly once, even if called concurrently.\n * All callers await the same promise and receive the same result.\n *\n * Use for lazy, one-time initialization of expensive resources (DB pools, ML models,\n * config, etc.) that must be initialized at most once regardless of concurrent demand.\n *\n * @example\n * const initDB = new Once<DBPool>()\n *\n * async function getDB() {\n * return initDB.do(() => createPool({ max: 10 }))\n * }\n *\n * // Safe under concurrent load — pool is created exactly once\n * const [db1, db2] = await Promise.all([getDB(), getDB()])\n * // db1 === db2 (same pool instance)\n *\n * @example\n * // Check if initialization has already run\n * if (!initDB.done) {\n * console.log('not yet initialized')\n * }\n */\nexport class Once<T = void> {\n private promise: Promise<T> | null = null\n private called = false\n\n async do(fn: () => T | Promise<T>): Promise<T> {\n if (!this.called) {\n this.called = true\n this.promise = Promise.resolve(fn())\n }\n return this.promise!\n }\n\n get done(): boolean {\n return this.called\n }\n\n reset(): void {\n this.called = false\n this.promise = null\n }\n}\n","type SelectCase<T = unknown> = [Promise<T>, (value: T) => void]\n\n/**\n * Options for `select()`.\n *\n * `default` makes the call non-blocking: if no case is immediately ready,\n * the default handler runs instead of waiting. This mirrors Go's `select { default: ... }`.\n */\nexport interface SelectOptions {\n default?: () => void\n}\n\n/**\n * Wait for the first of multiple promises to resolve, like Go's `select`.\n *\n * Each case is a `[promise, handler]` tuple. The handler for the first settled\n * promise is called with its value. All other handlers are ignored.\n *\n * If `opts.default` is provided, `select` becomes non-blocking: if no promise\n * is already resolved, the default runs immediately (Go's `select { default: ... }`).\n *\n * Commonly used with `ch.recv()`, `after()`, and `spawn().result`.\n *\n * @example\n * // Block until a channel message arrives or timeout after 5s\n * await select([\n * [ch.recv(), (value) => console.log('received', value)],\n * [after(5000), () => console.log('timed out')],\n * ])\n *\n * @example\n * // Non-blocking: check a channel without waiting\n * await select(\n * [[ch.recv(), (value) => process(value)]],\n * { default: () => console.log('channel empty — doing other work') },\n * )\n *\n * @example\n * // Race two worker results against a deadline\n * const { result: fast } = spawn(() => quickSearch(query))\n * const { result: deep } = spawn(() => deepSearch(query))\n *\n * let response: Result\n * await select([\n * [fast, (r) => { response = r }],\n * [after(200), () => { response = { partial: true } }],\n * ])\n */\nexport function select(\n cases: SelectCase[],\n opts?: SelectOptions,\n): Promise<void> {\n if (cases.length === 0) {\n if (opts?.default) {\n opts.default()\n }\n return Promise.resolve()\n }\n\n // Non-blocking: if default is provided, check if any promise is already settled\n if (opts?.default) {\n // Race a microtask against the promises to check if any is immediately ready\n return new Promise<void>((resolve, reject) => {\n let settled = false\n\n // Check all promises for immediate resolution\n for (const [promise, handler] of cases) {\n Promise.resolve(promise).then(\n (value) => {\n if (settled) return\n settled = true\n try {\n handler(value)\n resolve()\n } catch (err) {\n reject(err)\n }\n },\n (err) => {\n if (settled) return\n settled = true\n reject(err)\n },\n )\n }\n\n // Schedule default on the next microtask — if no promise resolved synchronously,\n // default wins\n queueMicrotask(() => {\n if (settled) return\n settled = true\n try {\n opts.default!()\n resolve()\n } catch (err) {\n reject(err)\n }\n })\n })\n }\n\n // Blocking: wait for the first promise to settle\n return new Promise<void>((resolve, reject) => {\n let settled = false\n\n cases.forEach(([promise, handler]) => {\n promise.then(\n (value) => {\n if (settled) return\n settled = true\n try {\n handler(value)\n resolve()\n } catch (err) {\n reject(err)\n }\n },\n (err) => {\n if (settled) return\n settled = true\n reject(err)\n },\n )\n })\n })\n}\n","/**\n * Returns a promise that resolves after `ms` milliseconds.\n *\n * Designed for use with `select()` to add timeouts to channel operations or\n * race a deadline against worker results. Also works as a simple async delay.\n *\n * @example\n * // Timeout a channel receive after 2 seconds\n * await select([\n * [ch.recv(), (value) => handle(value)],\n * [after(2000), () => handleTimeout()],\n * ])\n *\n * @example\n * // Simple delay\n * await after(500)\n * console.log('500ms later')\n */\nexport function after(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","/**\n * A repeating timer that ticks at a fixed interval.\n *\n * Implements `AsyncIterable<void>` — use `for await...of` to run work on each tick.\n * Call `stop()` to cancel the ticker and end the iteration.\n *\n * Create with the `ticker(ms)` factory function.\n *\n * @example\n * const t = ticker(1000) // tick every second\n * for await (const _ of t) {\n * await doWork()\n * if (shouldStop) t.stop() // ends the for-await loop\n * }\n *\n * @example\n * // Use with select() to process work on each tick with a timeout\n * const t = ticker(5000)\n * for await (const _ of t) {\n * await select([\n * [spawn(() => checkHealth()).result, (ok) => report(ok)],\n * [after(4000), () => report('timeout')],\n * ])\n * }\n */\nexport class Ticker {\n private interval: ReturnType<typeof setInterval> | null = null\n private resolve: ((value: boolean) => void) | null = null\n private stopped = false\n private ms: number\n\n constructor(ms: number) {\n this.ms = ms\n this.interval = setInterval(() => {\n if (this.resolve) {\n const r = this.resolve\n this.resolve = null\n r(true)\n }\n }, ms)\n if (this.interval.unref) this.interval.unref()\n }\n\n async tick(): Promise<boolean> {\n if (this.stopped) return false\n return new Promise<boolean>((resolve) => {\n this.resolve = resolve\n // Re-check after assignment: stop() may have been called between\n // the guard above and here, in which case this.resolve was never\n // seen by stop() and the promise would hang.\n if (this.stopped) {\n this.resolve = null\n resolve(false)\n }\n })\n }\n\n stop(): void {\n this.stopped = true\n if (this.interval) {\n clearInterval(this.interval)\n this.interval = null\n }\n if (this.resolve) {\n const r = this.resolve\n this.resolve = null\n r(false) // resolve pending tick with false — the ticker has stopped\n }\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<void> {\n while (await this.tick()) {\n yield\n }\n }\n}\n\n/**\n * Create a `Ticker` that fires every `ms` milliseconds.\n *\n * @example\n * const t = ticker(500)\n * for await (const _ of t) {\n * console.log('tick')\n * if (done) t.stop()\n * }\n */\nexport function ticker(ms: number): Ticker {\n return new Ticker(ms)\n}\n","import { getPool } from './pool.js'\nimport { serializeFunction } from './serialize.js'\nimport type { Task } from './types.js'\n\nlet taskCounter = 0\n\n/**\n * Define a reusable task that runs in a worker thread.\n *\n * Returns a typed async function — call it like a regular async function,\n * and it dispatches to the thread pool each time.\n *\n * Use task() when you have the same function to call many times with\n * different arguments. For one-off work, use spawn() instead.\n *\n * Arguments must be JSON-serializable (no functions, symbols, undefined, or BigInt).\n * The function itself must be self-contained — it cannot capture enclosing scope variables.\n *\n * @example\n * const resizeImage = task((src: string, width: number, height: number) => {\n * // runs in a worker thread\n * return processPixels(src, width, height)\n * })\n *\n * const result = await resizeImage('photo.jpg', 800, 600)\n * const [a, b] = await Promise.all([resizeImage('a.jpg', 400, 300), resizeImage('b.jpg', 800, 600)])\n */\nexport function task<TArgs extends unknown[], TReturn>(\n fn: (...args: TArgs) => TReturn | Promise<TReturn>,\n): (...args: TArgs) => Promise<TReturn> {\n return (...args: TArgs): Promise<TReturn> => {\n const fnStr = serializeFunction(fn)\n const serializedArgs = args.map((a) => {\n const json = JSON.stringify(a)\n if (json === undefined) {\n throw new TypeError(\n `Argument of type ${typeof a} is not JSON-serializable. ` +\n 'task() args must be JSON-serializable (no undefined, functions, symbols, or BigInt).',\n )\n }\n return json\n })\n const wrapperStr = `() => (${fnStr})(${serializedArgs.join(', ')})`\n\n const taskId = `task_${++taskCounter}`\n const spawnStack = new Error().stack\n\n let resolveFn!: (value: TReturn) => void\n let rejectFn!: (reason: unknown) => void\n\n const result = new Promise<TReturn>((resolve, reject) => {\n resolveFn = resolve\n rejectFn = reject\n })\n\n const taskObj: Task = {\n id: taskId,\n fnStr: wrapperStr,\n priority: 'normal',\n concurrent: false,\n resolve: (value) => resolveFn(value as TReturn),\n reject: (reason) => {\n if (reason instanceof Error && spawnStack) {\n const callerLine = spawnStack.split('\\n').slice(2).join('\\n')\n reason.stack =\n (reason.stack ?? reason.message) +\n '\\n --- spawned at ---\\n' +\n callerLine\n }\n rejectFn(reason)\n },\n }\n\n getPool().submit(taskObj)\n\n return result\n }\n}\n\n/** @internal For testing only */\nexport function resetTaskCounter(): void {\n taskCounter = 0\n}\n"],"mappings":"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","names":["import_node_os","sender","task","task","task","task","taskCounter"]}