@vielzeug/familiar 1.0.7 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -47
- package/dist/_pool.cjs +1 -1
- package/dist/_pool.cjs.map +1 -1
- package/dist/_pool.d.ts +4 -12
- package/dist/_pool.d.ts.map +1 -1
- package/dist/_pool.js +163 -222
- package/dist/_pool.js.map +1 -1
- package/dist/_queue.cjs +1 -1
- package/dist/_queue.cjs.map +1 -1
- package/dist/_queue.d.ts +3 -39
- package/dist/_queue.d.ts.map +1 -1
- package/dist/_queue.js +27 -28
- package/dist/_queue.js.map +1 -1
- package/dist/_stream-pool.cjs +2 -0
- package/dist/_stream-pool.cjs.map +1 -0
- package/dist/_stream-pool.d.ts +11 -0
- package/dist/_stream-pool.d.ts.map +1 -0
- package/dist/_stream-pool.js +152 -0
- package/dist/_stream-pool.js.map +1 -0
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/familiar.cjs +1 -27
- package/dist/familiar.cjs.map +1 -1
- package/dist/familiar.iife.js +1 -27
- package/dist/familiar.iife.js.map +1 -1
- package/dist/familiar.js +1 -27
- package/dist/familiar.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +3 -2
- package/dist/protocol.cjs +1 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.ts +40 -44
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +42 -27
- package/dist/protocol.js.map +1 -1
- package/dist/testing/testing.cjs +1 -1
- package/dist/testing/testing.cjs.map +1 -1
- package/dist/testing/testing.d.ts +15 -22
- package/dist/testing/testing.d.ts.map +1 -1
- package/dist/testing/testing.js +53 -35
- package/dist/testing/testing.js.map +1 -1
- package/dist/types.d.ts +49 -119
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.cjs +1 -27
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.ts +11 -67
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +139 -187
- package/dist/worker.js.map +1 -1
- package/package.json +13 -6
- package/dist/_dev.cjs +0 -2
- package/dist/_dev.cjs.map +0 -1
- package/dist/_dev.js +0 -6
- package/dist/_dev.js.map +0 -1
package/dist/_queue.js
CHANGED
|
@@ -1,48 +1,47 @@
|
|
|
1
1
|
//#region src/_queue.ts
|
|
2
2
|
var e = class {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
#e = [];
|
|
4
|
+
#t = 0;
|
|
5
|
+
#n = 0;
|
|
6
6
|
get size() {
|
|
7
|
-
return this
|
|
7
|
+
return this.#t;
|
|
8
8
|
}
|
|
9
9
|
enqueue(e, t) {
|
|
10
|
-
return t !== void 0 && this
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}), this
|
|
14
|
-
}
|
|
15
|
-
shift() {
|
|
16
|
-
for (; this.heap.length > 0;) {
|
|
17
|
-
let { item: e } = this.extractTop();
|
|
18
|
-
if (!e.cancelled) return this.liveCount--, e;
|
|
19
|
-
}
|
|
10
|
+
return t !== void 0 && this.#t >= t ? !1 : (this.#e.push({
|
|
11
|
+
item: e,
|
|
12
|
+
sequence: this.#n++
|
|
13
|
+
}), this.#a(this.#e.length - 1), this.#t += 1, !0);
|
|
20
14
|
}
|
|
21
15
|
remove(e) {
|
|
22
16
|
if (e.cancelled) return !1;
|
|
23
|
-
for (let t
|
|
17
|
+
for (let t of this.#e) if (t.item === e) return e.cancelled = !0, --this.#t, !0;
|
|
24
18
|
return !1;
|
|
25
19
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
shift() {
|
|
21
|
+
for (; this.#e.length > 0;) {
|
|
22
|
+
let e = this.#r().item;
|
|
23
|
+
if (!e.cancelled) return --this.#t, e;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
#r() {
|
|
27
|
+
let e = this.#e[0], t = this.#e.pop();
|
|
28
|
+
return this.#e.length > 0 && (this.#e[0] = t, this.#o(0)), e;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
return e.item.priority === t.item.priority ? e.
|
|
30
|
+
#i(e, t) {
|
|
31
|
+
return e.item.priority === t.item.priority ? e.sequence < t.sequence : e.item.priority > t.item.priority;
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
#a(e) {
|
|
34
34
|
for (; e > 0;) {
|
|
35
35
|
let t = e - 1 >> 1;
|
|
36
|
-
if (this
|
|
37
|
-
|
|
36
|
+
if (!this.#i(this.#e[e], this.#e[t])) return;
|
|
37
|
+
[this.#e[e], this.#e[t]] = [this.#e[t], this.#e[e]], e = t;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
let t = this.heap.length;
|
|
40
|
+
#o(e) {
|
|
42
41
|
for (;;) {
|
|
43
|
-
let
|
|
44
|
-
if (
|
|
45
|
-
[this
|
|
42
|
+
let t = e * 2 + 1, n = t + 1, r = e;
|
|
43
|
+
if (t < this.#e.length && this.#i(this.#e[t], this.#e[r]) && (r = t), n < this.#e.length && this.#i(this.#e[n], this.#e[r]) && (r = n), r === e) return;
|
|
44
|
+
[this.#e[e], this.#e[r]] = [this.#e[r], this.#e[e]], e = r;
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
};
|
package/dist/_queue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_queue.js","names":[],"sources":["../src/_queue.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"_queue.js","names":["#heap","#live","#sequence","#siftUp","#extract","#siftDown","#before"],"sources":["../src/_queue.ts"],"sourcesContent":["export type QueueItem<TInput, TOutput> = {\n cancelled?: boolean;\n cleanupAbort?: () => void;\n input: TInput;\n priority: number;\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n signal?: AbortSignal;\n timeout?: number;\n transferables: Transferable[];\n};\n\ntype Entry<TInput, TOutput> = { readonly item: QueueItem<TInput, TOutput>; readonly sequence: number };\n\nexport class TaskQueue<TInput, TOutput> {\n readonly #heap: Entry<TInput, TOutput>[] = [];\n #live = 0;\n #sequence = 0;\n\n get size(): number {\n return this.#live;\n }\n\n enqueue(item: QueueItem<TInput, TOutput>, maxSize: number | undefined): boolean {\n if (maxSize !== undefined && this.#live >= maxSize) return false;\n\n this.#heap.push({ item, sequence: this.#sequence++ });\n this.#siftUp(this.#heap.length - 1);\n this.#live += 1;\n\n return true;\n }\n\n remove(item: QueueItem<TInput, TOutput>): boolean {\n if (item.cancelled) return false;\n\n for (const entry of this.#heap) {\n if (entry.item === item) {\n item.cancelled = true;\n this.#live -= 1;\n\n return true;\n }\n }\n\n return false;\n }\n\n shift(): QueueItem<TInput, TOutput> | undefined {\n while (this.#heap.length > 0) {\n const item = this.#extract().item;\n\n if (!item.cancelled) {\n this.#live -= 1;\n\n return item;\n }\n }\n\n return undefined;\n }\n\n #extract(): Entry<TInput, TOutput> {\n const top = this.#heap[0]!;\n const last = this.#heap.pop()!;\n\n if (this.#heap.length > 0) {\n this.#heap[0] = last;\n this.#siftDown(0);\n }\n\n return top;\n }\n\n #before(a: Entry<TInput, TOutput>, b: Entry<TInput, TOutput>): boolean {\n return a.item.priority === b.item.priority ? a.sequence < b.sequence : a.item.priority > b.item.priority;\n }\n\n #siftUp(index: number): void {\n while (index > 0) {\n const parent = (index - 1) >> 1;\n\n if (!this.#before(this.#heap[index]!, this.#heap[parent]!)) return;\n\n [this.#heap[index], this.#heap[parent]] = [this.#heap[parent]!, this.#heap[index]!];\n index = parent;\n }\n }\n\n #siftDown(index: number): void {\n for (;;) {\n const left = index * 2 + 1;\n const right = left + 1;\n let next = index;\n\n if (left < this.#heap.length && this.#before(this.#heap[left]!, this.#heap[next]!)) next = left;\n\n if (right < this.#heap.length && this.#before(this.#heap[right]!, this.#heap[next]!)) next = right;\n\n if (next === index) return;\n\n [this.#heap[index], this.#heap[next]] = [this.#heap[next]!, this.#heap[index]!];\n index = next;\n }\n }\n}\n"],"mappings":";AAcA,IAAa,IAAb,MAAwC;CACtC,KAA2C,CAAC;CAC5C,KAAQ;CACR,KAAY;CAEZ,IAAI,OAAe;EACjB,OAAO,KAAKC;CACd;CAEA,QAAQ,GAAkC,GAAsC;EAO9E,OANI,MAAY,KAAA,KAAa,KAAKA,MAAS,IAAgB,MAE3D,KAAKD,GAAM,KAAK;GAAE;GAAM,UAAU,KAAKE;EAAY,CAAC,GACpD,KAAKC,GAAQ,KAAKH,GAAM,SAAS,CAAC,GAClC,KAAKC,MAAS,GAEP;CACT;CAEA,OAAO,GAA2C;EAChD,IAAI,EAAK,WAAW,OAAO;EAE3B,KAAK,IAAM,KAAS,KAAKD,IACvB,IAAI,EAAM,SAAS,GAIjB,OAHA,EAAK,YAAY,IACjB,OAAKC,IAEE;EAIX,OAAO;CACT;CAEA,QAAgD;EAC9C,OAAO,KAAKD,GAAM,SAAS,IAAG;GAC5B,IAAM,IAAO,KAAKI,GAAS,CAAC,CAAC;GAE7B,IAAI,CAAC,EAAK,WAGR,OAFA,OAAKH,IAEE;EAEX;CAGF;CAEA,KAAmC;EACjC,IAAM,IAAM,KAAKD,GAAM,IACjB,IAAO,KAAKA,GAAM,IAAI;EAO5B,OALI,KAAKA,GAAM,SAAS,MACtB,KAAKA,GAAM,KAAK,GAChB,KAAKK,GAAU,CAAC,IAGX;CACT;CAEA,GAAQ,GAA2B,GAAoC;EACrE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK;CAClG;CAEA,GAAQ,GAAqB;EAC3B,OAAO,IAAQ,IAAG;GAChB,IAAM,IAAU,IAAQ,KAAM;GAE9B,IAAI,CAAC,KAAKC,GAAQ,KAAKN,GAAM,IAAS,KAAKA,GAAM,EAAQ,GAAG;GAG5D,AADA,CAAC,KAAKA,GAAM,IAAQ,KAAKA,GAAM,MAAW,CAAC,KAAKA,GAAM,IAAU,KAAKA,GAAM,EAAO,GAClF,IAAQ;EACV;CACF;CAEA,GAAU,GAAqB;EAC7B,SAAS;GACP,IAAM,IAAO,IAAQ,IAAI,GACnB,IAAQ,IAAO,GACjB,IAAO;GAMX,IAJI,IAAO,KAAKA,GAAM,UAAU,KAAKM,GAAQ,KAAKN,GAAM,IAAQ,KAAKA,GAAM,EAAM,MAAG,IAAO,IAEvF,IAAQ,KAAKA,GAAM,UAAU,KAAKM,GAAQ,KAAKN,GAAM,IAAS,KAAKA,GAAM,EAAM,MAAG,IAAO,IAEzF,MAAS,GAAO;GAGpB,AADA,CAAC,KAAKA,GAAM,IAAQ,KAAKA,GAAM,MAAS,CAAC,KAAKA,GAAM,IAAQ,KAAKA,GAAM,EAAO,GAC9E,IAAQ;EACV;CACF;AACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_timers.cjs");let n=require("@vielzeug/arsenal/async");function r(r,i){let a=[...r],o=[],s=[],c=new AbortController,l=[],u=0,d=0,f=0,p=0,m=!1,h;function g(){return u===0&&o.length===0}function _(){if(g())for(let e of l.splice(0))e()}function v(n){return g()?Promise.resolve():new Promise((r,i)=>{if(l.push(r),n.timeout!==void 0){let a=setTimeout(()=>{let t=l.indexOf(r);t!==-1&&l.splice(t,1),i(new e.FamiliarTimeoutError(n.timeout))},n.timeout);t.unrefTimer(a)}})}function y(){s.shift()?.resolve()}function b(e){for(let t of s.splice(0))t.reject(e)}function x(e){return e?.aborted?Promise.reject((0,n.abortError)(e)):new Promise((t,r)=>{let i=!1,a={cleanup(){e?.removeEventListener(`abort`,o)},reject(e){if(i)return;i=!0,a.cleanup();let t=s.indexOf(a);t!==-1&&s.splice(t,1),r(e)},resolve(){i||(i=!0,a.cleanup(),t())}},o=()=>a.reject((0,n.abortError)(e));e?.addEventListener(`abort`,o,{once:!0}),s.push(a)})}function S(e){let t=o.shift();t?(t.resolve(e),y()):a.push(e)}async function C(t){if(m)throw new e.FamiliarTerminatedError;if(h)throw new e.FamiliarTerminatedError(`Worker is draining`);if(t.signal?.aborted)throw(0,n.abortError)(t.signal);for(;i.maxQueue!==void 0&&o.length>=i.maxQueue;){if(i.onFull===`reject`)throw new e.FamiliarQueueFullError(i.maxQueue);if(await x(t.signal),m)throw new e.FamiliarTerminatedError;if(h)throw new e.FamiliarTerminatedError(`Worker is draining`);if(t.signal?.aborted)throw(0,n.abortError)(t.signal)}return a.pop()||new Promise((e,r)=>{let i={cleanup(){i.signal?.removeEventListener(`abort`,a)},priority:t.priority??0,reject(e){i.cleanup();let t=o.indexOf(i);t!==-1&&(o.splice(t,1),y()),r(e),_()},resolve(t){i.cleanup(),e(t)},sequence:p++,signal:t.signal},a=()=>i.reject((0,n.abortError)(i.signal));i.signal?.addEventListener(`abort`,a,{once:!0}),o.push(i),o.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}function w(){if(!m){m=!0,c.abort();for(let e of r)e.terminate();for(let t of o.splice(0))t.reject(new e.FamiliarTerminatedError);b(new e.FamiliarTerminatedError),_()}}function T(t={}){if(m)return Promise.resolve();if(h)return h;for(let t of o.splice(0))t.reject(new e.FamiliarTerminatedError(`Worker is draining`));return b(new e.FamiliarTerminatedError(`Worker is draining`)),h=v(t).then(()=>w(),e=>{throw w(),e}),h}return{get disposalSignal(){return c.signal},dispose:w,get disposed(){return m},drain:T,async prime(){await Promise.all(r.map(e=>e.prime()))},runStream(t,r={}){let a=new AbortController,o=()=>a.abort(r.signal.reason);return r.signal?.addEventListener(`abort`,o,{once:!0}),{[Symbol.asyncIterator]:async function*(){let s,c;try{s=await C({...r,signal:a.signal}),u+=1,c=()=>s?.cancel((0,n.abortError)(a.signal)),a.signal.addEventListener(`abort`,c,{once:!0});let e=s.stream(t,{...r,signal:a.signal,timeout:r.timeout??i.defaultTimeout});for await(let t of e.iterable)yield t;await e.done,d+=1}catch(t){throw t?.constructor?.name!==`AbortError`&&!(t instanceof e.FamiliarTerminatedError)&&(f+=1),t}finally{r.signal?.removeEventListener(`abort`,o),s&&(c&&a.signal.removeEventListener(`abort`,c),--u,S(s),_())}}}},get stats(){return{active:u,completed:d,failed:f,queued:o.length}},get status(){return m?`terminated`:u===0?`idle`:`running`},[Symbol.asyncDispose]:()=>T(),[Symbol.dispose]:w}}exports.createStreamPool=r;
|
|
2
|
+
//# sourceMappingURL=_stream-pool.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_stream-pool.cjs","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type { PoolOptions } from './_pool';\nimport type { DrainOptions, RunOptions, StreamWorkerPool, WorkerStats, WorkerStatus } from './types';\nimport type { RunningStream } from './worker';\n\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n prime(): Promise<void>;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const disposalController = new AbortController();\n const idleWaiters: Array<() => void> = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let sequence = 0;\n let terminated = false;\n let drainPromise: Promise<void> | undefined;\n\n function idle(): boolean {\n return active === 0 && waiters.length === 0;\n }\n\n function settleIdle(): void {\n if (!idle()) return;\n\n for (const resolve of idleWaiters.splice(0)) resolve();\n }\n\n function waitForIdle(options: DrainOptions): Promise<void> {\n if (idle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n idleWaiters.push(resolve);\n\n if (options.timeout !== undefined) {\n const timer = setTimeout(() => {\n const index = idleWaiters.indexOf(resolve);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(options.timeout!));\n }, options.timeout);\n\n unrefTimer(timer);\n }\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(runOptions.signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n releaseCapacity();\n }\n\n reject(reason);\n settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n for (const slot of slots) slot.terminate();\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions = {}): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n return {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n async prime(): Promise<void> {\n await Promise.all(slots.map((slot) => slot.prime()));\n },\n runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(runOptions.signal!.reason);\n\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n [Symbol.asyncIterator]: async function* () {\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n try {\n slot = await acquire({ ...runOptions, signal: controller.signal });\n active += 1;\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, {\n ...runOptions,\n signal: controller.signal,\n timeout: runOptions.timeout ?? options.defaultTimeout,\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n completed += 1;\n } catch (error) {\n if (error?.constructor?.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError)) failed += 1;\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n active -= 1;\n release(slot);\n settleIdle();\n }\n }\n },\n };\n },\n get stats(): WorkerStats {\n return { active, completed, failed, queued: waiters.length };\n },\n get status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n },\n [Symbol.asyncDispose]: () => drain(),\n [Symbol.dispose]: dispose,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PoolOptions } from './_pool';
|
|
2
|
+
import type { RunOptions, StreamWorkerPool } from './types';
|
|
3
|
+
import type { RunningStream } from './worker';
|
|
4
|
+
export type StreamSlot<TInput, TChunk> = {
|
|
5
|
+
cancel(reason: unknown): void;
|
|
6
|
+
prime(): Promise<void>;
|
|
7
|
+
stream(input: TInput, options: RunOptions): RunningStream<TChunk>;
|
|
8
|
+
terminate(): void;
|
|
9
|
+
};
|
|
10
|
+
export declare function createStreamPool<TInput, TChunk>(slots: StreamSlot<TInput, TChunk>[], options: PoolOptions): StreamWorkerPool<TInput, TChunk>;
|
|
11
|
+
//# sourceMappingURL=_stream-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_stream-pool.d.ts","sourceRoot":"","sources":["../src/_stream-pool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAgB,UAAU,EAAE,gBAAgB,EAA6B,MAAM,SAAS,CAAC;AACrG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAK9C,MAAM,MAAM,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI;IACvC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClE,SAAS,IAAI,IAAI,CAAC;CACnB,CAAC;AAiBF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAC7C,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EACnC,OAAO,EAAE,WAAW,GACnB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CA2PlC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { FamiliarQueueFullError as e, FamiliarTerminatedError as t, FamiliarTimeoutError as n } from "./errors.js";
|
|
2
|
+
import { unrefTimer as r } from "./_timers.js";
|
|
3
|
+
import { abortError as i } from "@vielzeug/arsenal/async";
|
|
4
|
+
//#region src/_stream-pool.ts
|
|
5
|
+
function a(a, o) {
|
|
6
|
+
let s = [...a], c = [], l = [], u = new AbortController(), d = [], f = 0, p = 0, m = 0, h = 0, g = !1, _;
|
|
7
|
+
function v() {
|
|
8
|
+
return f === 0 && c.length === 0;
|
|
9
|
+
}
|
|
10
|
+
function y() {
|
|
11
|
+
if (v()) for (let e of d.splice(0)) e();
|
|
12
|
+
}
|
|
13
|
+
function b(e) {
|
|
14
|
+
return v() ? Promise.resolve() : new Promise((t, i) => {
|
|
15
|
+
if (d.push(t), e.timeout !== void 0) {
|
|
16
|
+
let a = setTimeout(() => {
|
|
17
|
+
let r = d.indexOf(t);
|
|
18
|
+
r !== -1 && d.splice(r, 1), i(new n(e.timeout));
|
|
19
|
+
}, e.timeout);
|
|
20
|
+
r(a);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function x() {
|
|
25
|
+
l.shift()?.resolve();
|
|
26
|
+
}
|
|
27
|
+
function S(e) {
|
|
28
|
+
for (let t of l.splice(0)) t.reject(e);
|
|
29
|
+
}
|
|
30
|
+
function C(e) {
|
|
31
|
+
return e?.aborted ? Promise.reject(i(e)) : new Promise((t, n) => {
|
|
32
|
+
let r = !1, a = {
|
|
33
|
+
cleanup() {
|
|
34
|
+
e?.removeEventListener("abort", o);
|
|
35
|
+
},
|
|
36
|
+
reject(e) {
|
|
37
|
+
if (r) return;
|
|
38
|
+
r = !0, a.cleanup();
|
|
39
|
+
let t = l.indexOf(a);
|
|
40
|
+
t !== -1 && l.splice(t, 1), n(e);
|
|
41
|
+
},
|
|
42
|
+
resolve() {
|
|
43
|
+
r || (r = !0, a.cleanup(), t());
|
|
44
|
+
}
|
|
45
|
+
}, o = () => a.reject(i(e));
|
|
46
|
+
e?.addEventListener("abort", o, { once: !0 }), l.push(a);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function w(e) {
|
|
50
|
+
let t = c.shift();
|
|
51
|
+
t ? (t.resolve(e), x()) : s.push(e);
|
|
52
|
+
}
|
|
53
|
+
async function T(n) {
|
|
54
|
+
if (g) throw new t();
|
|
55
|
+
if (_) throw new t("Worker is draining");
|
|
56
|
+
if (n.signal?.aborted) throw i(n.signal);
|
|
57
|
+
for (; o.maxQueue !== void 0 && c.length >= o.maxQueue;) {
|
|
58
|
+
if (o.onFull === "reject") throw new e(o.maxQueue);
|
|
59
|
+
if (await C(n.signal), g) throw new t();
|
|
60
|
+
if (_) throw new t("Worker is draining");
|
|
61
|
+
if (n.signal?.aborted) throw i(n.signal);
|
|
62
|
+
}
|
|
63
|
+
return s.pop() || new Promise((e, t) => {
|
|
64
|
+
let r = {
|
|
65
|
+
cleanup() {
|
|
66
|
+
r.signal?.removeEventListener("abort", a);
|
|
67
|
+
},
|
|
68
|
+
priority: n.priority ?? 0,
|
|
69
|
+
reject(e) {
|
|
70
|
+
r.cleanup();
|
|
71
|
+
let n = c.indexOf(r);
|
|
72
|
+
n !== -1 && (c.splice(n, 1), x()), t(e), y();
|
|
73
|
+
},
|
|
74
|
+
resolve(t) {
|
|
75
|
+
r.cleanup(), e(t);
|
|
76
|
+
},
|
|
77
|
+
sequence: h++,
|
|
78
|
+
signal: n.signal
|
|
79
|
+
}, a = () => r.reject(i(r.signal));
|
|
80
|
+
r.signal?.addEventListener("abort", a, { once: !0 }), c.push(r), c.sort((e, t) => t.priority - e.priority || e.sequence - t.sequence);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function E() {
|
|
84
|
+
if (!g) {
|
|
85
|
+
g = !0, u.abort();
|
|
86
|
+
for (let e of a) e.terminate();
|
|
87
|
+
for (let e of c.splice(0)) e.reject(new t());
|
|
88
|
+
S(new t()), y();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function D(e = {}) {
|
|
92
|
+
if (g) return Promise.resolve();
|
|
93
|
+
if (_) return _;
|
|
94
|
+
for (let e of c.splice(0)) e.reject(new t("Worker is draining"));
|
|
95
|
+
return S(new t("Worker is draining")), _ = b(e).then(() => E(), (e) => {
|
|
96
|
+
throw E(), e;
|
|
97
|
+
}), _;
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
get disposalSignal() {
|
|
101
|
+
return u.signal;
|
|
102
|
+
},
|
|
103
|
+
dispose: E,
|
|
104
|
+
get disposed() {
|
|
105
|
+
return g;
|
|
106
|
+
},
|
|
107
|
+
drain: D,
|
|
108
|
+
async prime() {
|
|
109
|
+
await Promise.all(a.map((e) => e.prime()));
|
|
110
|
+
},
|
|
111
|
+
runStream(e, n = {}) {
|
|
112
|
+
let r = new AbortController(), a = () => r.abort(n.signal.reason);
|
|
113
|
+
return n.signal?.addEventListener("abort", a, { once: !0 }), { [Symbol.asyncIterator]: async function* () {
|
|
114
|
+
let s, c;
|
|
115
|
+
try {
|
|
116
|
+
s = await T({
|
|
117
|
+
...n,
|
|
118
|
+
signal: r.signal
|
|
119
|
+
}), f += 1, c = () => s?.cancel(i(r.signal)), r.signal.addEventListener("abort", c, { once: !0 });
|
|
120
|
+
let t = s.stream(e, {
|
|
121
|
+
...n,
|
|
122
|
+
signal: r.signal,
|
|
123
|
+
timeout: n.timeout ?? o.defaultTimeout
|
|
124
|
+
});
|
|
125
|
+
for await (let e of t.iterable) yield e;
|
|
126
|
+
await t.done, p += 1;
|
|
127
|
+
} catch (e) {
|
|
128
|
+
throw e?.constructor?.name !== "AbortError" && !(e instanceof t) && (m += 1), e;
|
|
129
|
+
} finally {
|
|
130
|
+
n.signal?.removeEventListener("abort", a), s && (c && r.signal.removeEventListener("abort", c), --f, w(s), y());
|
|
131
|
+
}
|
|
132
|
+
} };
|
|
133
|
+
},
|
|
134
|
+
get stats() {
|
|
135
|
+
return {
|
|
136
|
+
active: f,
|
|
137
|
+
completed: p,
|
|
138
|
+
failed: m,
|
|
139
|
+
queued: c.length
|
|
140
|
+
};
|
|
141
|
+
},
|
|
142
|
+
get status() {
|
|
143
|
+
return g ? "terminated" : f === 0 ? "idle" : "running";
|
|
144
|
+
},
|
|
145
|
+
[Symbol.asyncDispose]: () => D(),
|
|
146
|
+
[Symbol.dispose]: E
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
export { a as createStreamPool };
|
|
151
|
+
|
|
152
|
+
//# sourceMappingURL=_stream-pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_stream-pool.js","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type { PoolOptions } from './_pool';\nimport type { DrainOptions, RunOptions, StreamWorkerPool, WorkerStats, WorkerStatus } from './types';\nimport type { RunningStream } from './worker';\n\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n prime(): Promise<void>;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const disposalController = new AbortController();\n const idleWaiters: Array<() => void> = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let sequence = 0;\n let terminated = false;\n let drainPromise: Promise<void> | undefined;\n\n function idle(): boolean {\n return active === 0 && waiters.length === 0;\n }\n\n function settleIdle(): void {\n if (!idle()) return;\n\n for (const resolve of idleWaiters.splice(0)) resolve();\n }\n\n function waitForIdle(options: DrainOptions): Promise<void> {\n if (idle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n idleWaiters.push(resolve);\n\n if (options.timeout !== undefined) {\n const timer = setTimeout(() => {\n const index = idleWaiters.indexOf(resolve);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(options.timeout!));\n }, options.timeout);\n\n unrefTimer(timer);\n }\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(runOptions.signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n releaseCapacity();\n }\n\n reject(reason);\n settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n for (const slot of slots) slot.terminate();\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions = {}): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n return {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n async prime(): Promise<void> {\n await Promise.all(slots.map((slot) => slot.prime()));\n },\n runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(runOptions.signal!.reason);\n\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n [Symbol.asyncIterator]: async function* () {\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n try {\n slot = await acquire({ ...runOptions, signal: controller.signal });\n active += 1;\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, {\n ...runOptions,\n signal: controller.signal,\n timeout: runOptions.timeout ?? options.defaultTimeout,\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n completed += 1;\n } catch (error) {\n if (error?.constructor?.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError)) failed += 1;\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n active -= 1;\n release(slot);\n settleIdle();\n }\n }\n },\n };\n },\n get stats(): WorkerStats {\n return { active, completed, failed, queued: waiters.length };\n },\n get status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n },\n [Symbol.asyncDispose]: () => drain(),\n [Symbol.dispose]: dispose,\n };\n}\n"],"mappings":";;;;AA+BA,SAAgB,EACd,GACA,GACkC;CAClC,IAAM,IAAY,CAAC,GAAG,CAAK,GACrB,IAAgD,CAAC,GACjD,IAAoC,CAAC,GACrC,IAAqB,IAAI,gBAAgB,GACzC,IAAiC,CAAC,GACpC,IAAS,GACT,IAAY,GACZ,IAAS,GACT,IAAW,GACX,IAAa,IACb;CAEJ,SAAS,IAAgB;EACvB,OAAO,MAAW,KAAK,EAAQ,WAAW;CAC5C;CAEA,SAAS,IAAmB;EACrB,MAAK,GAEV,KAAK,IAAM,KAAW,EAAY,OAAO,CAAC,GAAG,EAAQ;CACvD;CAEA,SAAS,EAAY,GAAsC;EAGzD,OAFI,EAAK,IAAU,QAAQ,QAAQ,IAE5B,IAAI,SAAe,GAAS,MAAW;GAG5C,IAFA,EAAY,KAAK,CAAO,GAEpB,EAAQ,YAAY,KAAA,GAAW;IACjC,IAAM,IAAQ,iBAAiB;KAC7B,IAAM,IAAQ,EAAY,QAAQ,CAAO;KAIzC,AAFI,MAAU,MAAI,EAAY,OAAO,GAAO,CAAC,GAE7C,EAAO,IAAI,EAAqB,EAAQ,OAAQ,CAAC;IACnD,GAAG,EAAQ,OAAO;IAElB,EAAW,CAAK;GAClB;EACF,CAAC;CACH;CAEA,SAAS,IAAwB;EAC/B,EAAgB,MAAM,CAAC,EAAE,QAAQ;CACnC;CAEA,SAAS,EAAe,GAAuB;EAC7C,KAAK,IAAM,KAAU,EAAgB,OAAO,CAAC,GAAG,EAAO,OAAO,CAAM;CACtE;CAEA,SAAS,EAAgB,GAAgD;EAGvE,OAFI,GAAQ,UAAgB,QAAQ,OAAO,EAAW,CAAM,CAAC,IAEtD,IAAI,SAAe,GAAS,MAAW;GAC5C,IAAI,IAAU,IACR,IAAyB;IAC7B,UAAU;KACR,GAAQ,oBAAoB,SAAS,CAAO;IAC9C;IACA,OAAO,GAAQ;KACb,IAAI,GAAS;KAGb,AADA,IAAU,IACV,EAAO,QAAQ;KAEf,IAAM,IAAQ,EAAgB,QAAQ,CAAM;KAI5C,AAFI,MAAU,MAAI,EAAgB,OAAO,GAAO,CAAC,GAEjD,EAAO,CAAM;IACf;IACA,UAAU;KACJ,MAEJ,IAAU,IACV,EAAO,QAAQ,GACf,EAAQ;IACV;GACF,GACM,UAAgB,EAAO,OAAO,EAAW,CAAO,CAAC;GAGvD,AADA,GAAQ,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC,GACzD,EAAgB,KAAK,CAAM;EAC7B,CAAC;CACH;CAEA,SAAS,EAAQ,GAAwC;EACvD,IAAM,IAAO,EAAQ,MAAM;EAE3B,AAAI,KACF,EAAK,QAAQ,CAAI,GACjB,EAAgB,KAEhB,EAAU,KAAK,CAAI;CAEvB;CAEA,eAAe,EAAQ,GAA6D;EAClF,IAAI,GAAY,MAAM,IAAI,EAAwB;EAElD,IAAI,GAAc,MAAM,IAAI,EAAwB,oBAAoB;EAExE,IAAI,EAAW,QAAQ,SAAS,MAAM,EAAW,EAAW,MAAM;EAElE,OAAO,EAAQ,aAAa,KAAA,KAAa,EAAQ,UAAU,EAAQ,WAAU;GAC3E,IAAI,EAAQ,WAAW,UAAU,MAAM,IAAI,EAAuB,EAAQ,QAAQ;GAIlF,IAFA,MAAM,EAAgB,EAAW,MAAM,GAEnC,GAAY,MAAM,IAAI,EAAwB;GAElD,IAAI,GAAc,MAAM,IAAI,EAAwB,oBAAoB;GAExE,IAAI,EAAW,QAAQ,SAAS,MAAM,EAAW,EAAW,MAAM;EACpE;EAMA,OAJa,EAAU,IAEnB,KAEG,IAAI,SAAqC,GAAS,MAAW;GAClE,IAAM,IAA6C;IACjD,UAAU;KACR,EAAO,QAAQ,oBAAoB,SAAS,CAAO;IACrD;IACA,UAAU,EAAW,YAAY;IACjC,OAAO,GAAQ;KACb,EAAO,QAAQ;KAEf,IAAM,IAAQ,EAAQ,QAAQ,CAAM;KAQpC,AANI,MAAU,OACZ,EAAQ,OAAO,GAAO,CAAC,GACvB,EAAgB,IAGlB,EAAO,CAAM,GACb,EAAW;IACb;IACA,QAAQ,GAAM;KAEZ,AADA,EAAO,QAAQ,GACf,EAAQ,CAAI;IACd;IACA,UAAU;IACV,QAAQ,EAAW;GACrB,GACM,UAAgB,EAAO,OAAO,EAAW,EAAO,MAAO,CAAC;GAI9D,AAFA,EAAO,QAAQ,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC,GAChE,EAAQ,KAAK,CAAM,GACnB,EAAQ,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ;EAC3E,CAAC;CACH;CAEA,SAAS,IAAgB;EACnB,QAGJ;GADA,IAAa,IACb,EAAmB,MAAM;GACzB,KAAK,IAAM,KAAQ,GAAO,EAAK,UAAU;GACzC,KAAK,IAAM,KAAU,EAAQ,OAAO,CAAC,GAAG,EAAO,OAAO,IAAI,EAAwB,CAAC;GAEnF,AADA,EAAe,IAAI,EAAwB,CAAC,GAC5C,EAAW;EAJc;CAK3B;CAEA,SAAS,EAAM,IAA6B,CAAC,GAAkB;EAC7D,IAAI,GAAY,OAAO,QAAQ,QAAQ;EAEvC,IAAI,GAAc,OAAO;EAEzB,KAAK,IAAM,KAAU,EAAQ,OAAO,CAAC,GAAG,EAAO,OAAO,IAAI,EAAwB,oBAAoB,CAAC;EAUvG,OATA,EAAe,IAAI,EAAwB,oBAAoB,CAAC,GAChE,IAAe,EAAY,CAAY,CAAC,CAAC,WACjC,EAAQ,IACb,MAAmB;GAElB,MADA,EAAQ,GACF;EACR,CACF,GAEO;CACT;CAEA,OAAO;EACL,IAAI,iBAAiB;GACnB,OAAO,EAAmB;EAC5B;EACA;EACA,IAAI,WAAW;GACb,OAAO;EACT;EACA;EACA,MAAM,QAAuB;GAC3B,MAAM,QAAQ,IAAI,EAAM,KAAK,MAAS,EAAK,MAAM,CAAC,CAAC;EACrD;EACA,UAAU,GAAO,IAAa,CAAC,GAA0B;GACvD,IAAM,IAAa,IAAI,gBAAgB,GACjC,UAAgB,EAAW,MAAM,EAAW,OAAQ,MAAM;GAIhE,OAFA,EAAW,QAAQ,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC,GAE7D,EACL,CAAC,OAAO,gBAAgB,mBAAmB;IACzC,IAAI,GACA;IAEJ,IAAI;KAIF,AAHA,IAAO,MAAM,EAAQ;MAAE,GAAG;MAAY,QAAQ,EAAW;KAAO,CAAC,GACjE,KAAU,GACV,UAAiB,GAAM,OAAO,EAAW,EAAW,MAAM,CAAC,GAC3D,EAAW,OAAO,iBAAiB,SAAS,GAAU,EAAE,MAAM,GAAK,CAAC;KAEpE,IAAM,IAAU,EAAK,OAAO,GAAO;MACjC,GAAG;MACH,QAAQ,EAAW;MACnB,SAAS,EAAW,WAAW,EAAQ;KACzC,CAAC;KAED,WAAW,IAAM,KAAS,EAAQ,UAAU,MAAM;KAElD,AADA,MAAM,EAAQ,MACd,KAAa;IACf,SAAS,GAAO;KAGd,MAFI,GAAO,aAAa,SAAS,gBAAgB,EAAE,aAAiB,OAA0B,KAAU,IAElG;IACR,UAAU;KAGR,AAFA,EAAW,QAAQ,oBAAoB,SAAS,CAAO,GAEnD,MACE,KAAU,EAAW,OAAO,oBAAoB,SAAS,CAAQ,GAErE,KACA,EAAQ,CAAI,GACZ,EAAW;IAEf;GACF,EACF;EACF;EACA,IAAI,QAAqB;GACvB,OAAO;IAAE;IAAQ;IAAW;IAAQ,QAAQ,EAAQ;GAAO;EAC7D;EACA,IAAI,SAAuB;GAGzB,OAFI,IAAmB,eAEhB,MAAW,IAAI,SAAS;EACjC;GACC,OAAO,qBAAqB,EAAM;GAClC,OAAO,UAAU;CACpB;AACF"}
|
package/dist/errors.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is FamiliarError {\n return err instanceof FamiliarError;\n }\n}\n\n/** Thrown when invalid options are passed to
|
|
1
|
+
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is FamiliarError {\n return err instanceof FamiliarError;\n }\n}\n\n/** Thrown when invalid options are passed to a Familiar pool factory. */\nexport class FamiliarInvalidOptionsError extends FamiliarError {}\n\n/** Thrown when run() is called and the queue is full (`onFull='reject'`). */\nexport class FamiliarQueueFullError extends FamiliarError {\n /** The configured `maxQueue` value. */\n readonly maxQueue: number;\n\n constructor(maxQueue: number) {\n super(`Queue is full (maxQueue=${maxQueue})`);\n this.maxQueue = maxQueue;\n }\n}\n\n/** Thrown when the task function throws. The original error is available as `.cause`. */\nexport class FamiliarTaskError extends FamiliarError {}\n\n/** Thrown when a task or operation is rejected because the worker was terminated. */\nexport class FamiliarTerminatedError extends FamiliarError {\n constructor(message = 'Worker was terminated') {\n super(message);\n }\n}\n\n/** Thrown when a task exceeds its timeout or `drain()` times out. */\nexport class FamiliarTimeoutError extends FamiliarError {\n /** The configured timeout in milliseconds. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number) {\n super(`Task timed out after ${timeoutMs}ms`);\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */\nexport class FamiliarRuntimeError extends FamiliarError {}\n"],"mappings":"AACA,IAAa,EAAb,MAAa,UAAsB,KAAM,CACvC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CAEA,OAAO,GAAG,EAAoC,CAC5C,OAAO,aAAe,CACxB,CACF,EAGa,EAAb,cAAiD,CAAc,CAAC,EAGnD,EAAb,cAA4C,CAAc,CAExD,SAEA,YAAY,EAAkB,CAC5B,MAAM,2BAA2B,EAAS,EAAE,EAC5C,KAAK,SAAW,CAClB,CACF,EAGa,EAAb,cAAuC,CAAc,CAAC,EAGzC,EAAb,cAA6C,CAAc,CACzD,YAAY,EAAU,wBAAyB,CAC7C,MAAM,CAAO,CACf,CACF,EAGa,EAAb,cAA0C,CAAc,CAEtD,UAEA,YAAY,EAAmB,CAC7B,MAAM,wBAAwB,EAAU,GAAG,EAC3C,KAAK,UAAY,CACnB,CACF,EAGa,EAAb,cAA0C,CAAc,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export declare class FamiliarError extends Error {
|
|
|
3
3
|
constructor(message: string, opts?: ErrorOptions);
|
|
4
4
|
static is(err: unknown): err is FamiliarError;
|
|
5
5
|
}
|
|
6
|
-
/** Thrown when invalid options are passed to
|
|
6
|
+
/** Thrown when invalid options are passed to a Familiar pool factory. */
|
|
7
7
|
export declare class FamiliarInvalidOptionsError extends FamiliarError {
|
|
8
8
|
}
|
|
9
9
|
/** Thrown when run() is called and the queue is full (`onFull='reject'`). */
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;IAMhD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,aAAa;CAG9C;AAED,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;IAMhD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,aAAa;CAG9C;AAED,yEAAyE;AACzE,qBAAa,2BAA4B,SAAQ,aAAa;CAAG;AAEjE,6EAA6E;AAC7E,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM;CAI7B;AAED,yFAAyF;AACzF,qBAAa,iBAAkB,SAAQ,aAAa;CAAG;AAEvD,qFAAqF;AACrF,qBAAa,uBAAwB,SAAQ,aAAa;gBAC5C,OAAO,SAA0B;CAG9C;AAED,qEAAqE;AACrE,qBAAa,oBAAqB,SAAQ,aAAa;IACrD,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,SAAS,EAAE,MAAM;CAI9B;AAED,mGAAmG;AACnG,qBAAa,oBAAqB,SAAQ,aAAa;CAAG"}
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is FamiliarError {\n return err instanceof FamiliarError;\n }\n}\n\n/** Thrown when invalid options are passed to
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is FamiliarError {\n return err instanceof FamiliarError;\n }\n}\n\n/** Thrown when invalid options are passed to a Familiar pool factory. */\nexport class FamiliarInvalidOptionsError extends FamiliarError {}\n\n/** Thrown when run() is called and the queue is full (`onFull='reject'`). */\nexport class FamiliarQueueFullError extends FamiliarError {\n /** The configured `maxQueue` value. */\n readonly maxQueue: number;\n\n constructor(maxQueue: number) {\n super(`Queue is full (maxQueue=${maxQueue})`);\n this.maxQueue = maxQueue;\n }\n}\n\n/** Thrown when the task function throws. The original error is available as `.cause`. */\nexport class FamiliarTaskError extends FamiliarError {}\n\n/** Thrown when a task or operation is rejected because the worker was terminated. */\nexport class FamiliarTerminatedError extends FamiliarError {\n constructor(message = 'Worker was terminated') {\n super(message);\n }\n}\n\n/** Thrown when a task exceeds its timeout or `drain()` times out. */\nexport class FamiliarTimeoutError extends FamiliarError {\n /** The configured timeout in milliseconds. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number) {\n super(`Task timed out after ${timeoutMs}ms`);\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */\nexport class FamiliarRuntimeError extends FamiliarError {}\n"],"mappings":";AACA,IAAa,IAAb,MAAa,UAAsB,MAAM;CACvC,YAAY,GAAiB,GAAqB;EAGhD,AAFA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAO,WAAW,MACvB,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;CAEA,OAAO,GAAG,GAAoC;EAC5C,OAAO,aAAe;CACxB;AACF,GAGa,IAAb,cAAiD,EAAc,CAAC,GAGnD,IAAb,cAA4C,EAAc;CAExD;CAEA,YAAY,GAAkB;EAE5B,AADA,MAAM,2BAA2B,EAAS,EAAE,GAC5C,KAAK,WAAW;CAClB;AACF,GAGa,IAAb,cAAuC,EAAc,CAAC,GAGzC,IAAb,cAA6C,EAAc;CACzD,YAAY,IAAU,yBAAyB;EAC7C,MAAM,CAAO;CACf;AACF,GAGa,IAAb,cAA0C,EAAc;CAEtD;CAEA,YAAY,GAAmB;EAE7B,AADA,MAAM,wBAAwB,EAAU,GAAG,GAC3C,KAAK,YAAY;CACnB;AACF,GAGa,IAAb,cAA0C,EAAc,CAAC"}
|
package/dist/familiar.cjs
CHANGED
|
@@ -1,28 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},t=class extends e{},n=class extends e{maxQueue;constructor(e){super(`Queue is full (maxQueue=${e})`),this.maxQueue=e}},r=class extends e{},i=class extends e{constructor(e=`Worker was terminated`){super(e)}},a=class extends e{timeoutMs;constructor(e){super(`Task timed out after ${e}ms`),this.timeoutMs=e}},o=class extends e{};function s(e){return e?.reason??new DOMException(`Aborted`,`AbortError`)}var c=class{heap=[];liveCount=0;seq=0;get size(){return this.liveCount}enqueue(e,t){return t!==void 0&&this.liveCount>=t?!1:(this.heap.push({_seq:this.seq++,item:e}),this.siftUp(this.heap.length-1),this.liveCount++,!0)}shift(){for(;this.heap.length>0;){let{item:e}=this.extractTop();if(!e.cancelled)return this.liveCount--,e}}remove(e){if(e.cancelled)return!1;for(let t=0;t<this.heap.length;t++)if(this.heap[t].item===e)return e.cancelled=!0,this.liveCount--,!0;return!1}extractTop(){let e=this.heap[0],t=this.heap.pop();return this.heap.length>0&&(this.heap[0]=t,this.siftDown(0)),e}higher(e,t){return e.item.priority===t.item.priority?e._seq<t._seq:e.item.priority>t.item.priority}siftUp(e){for(;e>0;){let t=e-1>>1;if(this.higher(this.heap[e],this.heap[t]))[this.heap[e],this.heap[t]]=[this.heap[t],this.heap[e]],e=t;else break}}siftDown(e){let t=this.heap.length;for(;;){let n=e,r=2*e+1,i=2*e+2;if(r<t&&this.higher(this.heap[r],this.heap[n])&&(n=r),i<t&&this.higher(this.heap[i],this.heap[n])&&(n=i),n===e)break;[this.heap[e],this.heap[n]]=[this.heap[n],this.heap[e]],e=n}}};function l(e){typeof e==`object`&&e&&`unref`in e&&e.unref()}function u(e,t){let{concurrency:r,defaultTimeout:u,maxQueue:d,onFull:f}=t,p=[...e],m=new c,h=new AbortController,g=[],_=[],v=0,y,b=0,x=0,S=0,C=!1;function w(){return v===0&&m.size===0}function T(){if(!w()||g.length===0)return;let e=g.splice(0);for(let t of e)t()}function E(e){return w()?Promise.resolve():new Promise((t,n)=>{g.push(t),e!==void 0&&l(setTimeout(()=>{let r=g.indexOf(t);r!==-1&&g.splice(r,1),n(new a(e))},e))})}function D(){let e=_.shift();e&&e()}let O=!1;function k(){if(!(C||O)){for(O=!0;!C&&p.length>0&&m.size>0;){let e=A();if(!e)break;let t=p.pop();e.cleanupAbort?.(),v+=1,D();let n=e.timeout??u;t.run(e.input,e.transferables,n).then(n=>{p.push(t),--v,b+=1,e.resolve(n),k(),w()&&T()},n=>{p.push(t),--v,n instanceof i||(x+=1),e.reject(n),k(),w()&&T()})}O=!1}}function A(){for(;m.size>0;){let e=m.shift();if(!e)break;if(e.signal?.aborted){e.cleanupAbort?.(),e.reject(s(e.signal));continue}return e}T()}function j(){if(C)return;C=!0,h.abort();for(let t of e)t.terminate();for(;m.size>0;){let e=m.shift();if(!e)break;e.cleanupAbort?.(),e.reject(new i)}let t=g.splice(0);for(let e of t)e();for(let e of _.splice(0))e()}function M(e){return C?Promise.resolve():y||(y=E(e).then(j,e=>{throw j(),e}),y)}async function N(e,t={}){let{priority:r=0,signal:a,timeout:o,transferables:c=[]}=t;if(C)throw new i;if(y)throw new i(`Worker is draining`);if(a?.aborted)throw s(a);if(f===`wait`&&d!==void 0){for(;!C&&!y&&m.size>=d;)await new Promise(e=>_.push(e));if(C)throw new i;if(y)throw new i(`Worker is draining`)}let l,u,p=new Promise((e,t)=>{l=e,u=t}),h={input:e,priority:r,reject:u,resolve:l,signal:a,timeout:o,transferables:c};if(!m.enqueue(h,f===`wait`?void 0:d))throw new n(d);if(a){let e=()=>{m.remove(h)&&(h.cleanupAbort?.(),u(s(a)),T())};h.cleanupAbort=()=>{a.removeEventListener(`abort`,e),h.cleanupAbort=void 0},a.addEventListener(`abort`,e,{once:!0})}return k(),p}function P(t,n={}){if(C)throw new o(`Worker was terminated`);let r=p.pop();if(!r)throw new o(`runStream() requires a free worker slot; all ${e.length} slot${e.length===1?``:`s`} are busy`);let{timeout:i,transferables:a=[]}=n,s=r.runStream(t,a,i);return{[Symbol.asyncIterator](){let e=s[Symbol.asyncIterator](),t=!1,n=()=>{t||(t=!0,p.push(r))};return{async next(){let t=await e.next();return t.done&&n(),t},async return(t){return r.cancel(),n(),e.return?.(t)??{done:!0,value:t}},async throw(t){if(r.cancel(),n(),e.throw)return e.throw(t);throw t}}}}}async function*F(e,t={}){if(e.length===0)return;let{ordered:n=!0,...i}=t,a=new AbortController;try{if(n){let t=e.map(e=>N(e,{...i,signal:a.signal}));for(let e of t)yield await e}else{let t=[],n=null,s=0,c=Math.max(1,r);function o(){if(s>=e.length)return;let r=e[s++];N(r,{...i,signal:a.signal}).then(e=>{t.push({value:e}),n?.(),n=null},e=>{t.push({error:e}),n?.(),n=null})}for(let t=0;t<c&&t<e.length;t++)o();for(let r=0;r<e.length;r++){for(;t.length===0;)await new Promise(e=>{n=e});let e=t.shift();if(`error`in e)throw e.error;yield e.value,o()}}}finally{a.abort()}}function I(e,t={}){let n=new AbortController;if(t.signal){let e=t.signal;e.aborted?n.abort(e.reason):e.addEventListener(`abort`,()=>n.abort(e.reason),{once:!0})}S+=1;let r=0,i=0,a=!1,o=[];function s(){!a&&r>0&&r===i&&(a=!0,--S)}return{abort(e){n.abort(e)},drain(){let e=o.splice(0);return a||(a=!0,--S),Promise.allSettled(e)},get name(){return e},get pending(){return r-i},run(e,t={}){r+=1;let a=N(e,{...t,signal:n.signal});return o.push(a),a.then(()=>{i+=1,s()},()=>{i+=1,s()}),a},get size(){return r}}}function L(){return C?`terminated`:v>0||m.size>0?`running`:`idle`}return{get active(){return v},batch:F,get completed(){return b},get concurrency(){return r},get disposalSignal(){return h.signal},dispose:j,get disposed(){return C},drain:M,get failed(){return x},group:I,get groupCount(){return S},prime(){return Promise.all(e.map(e=>e.prime())).then(()=>{})},get queued(){return m.size},run:N,runStream:P,get status(){return L()},[Symbol.asyncDispose]:()=>M(),[Symbol.dispose]:j}}function d(e){if(e.toString().includes(`[native code]`))throw new t(`Task function cannot be a bound or native function`);return e}var f=512;function p(e){if(e===void 0)return 1;if(e===`auto`)return Math.max(1,globalThis.navigator?.hardwareConcurrency??1);if(!Number.isInteger(e)||e<1||e>f)throw new t(`\`concurrency\` must be a positive integer ≤ ${f} or "auto"`);return e}function m(e={}){let n=p(e.concurrency),{heartbeatWindow:r,maxQueue:i,onFull:a=`reject`,onSlotError:o,timeout:s}=e;if(s!==void 0&&(!Number.isFinite(s)||s<=0))throw new t("`timeout` must be a finite number greater than 0");if(i!==void 0&&(!Number.isInteger(i)||i<1))throw new t("`maxQueue` must be a positive integer");if(r!==void 0&&(!Number.isFinite(r)||r<=0))throw new t("`heartbeatWindow` must be a finite number greater than 0");return{concurrency:n,heartbeatWindow:r,maxQueue:i,onFull:a,onSlotError:o,timeout:s}}function h(e,t){return`
|
|
2
|
-
const __fn = (${e.toString()});
|
|
3
|
-
|
|
4
|
-
self.onmessage = async function (event) {
|
|
5
|
-
const { id, input, stream } = event.data;
|
|
6
|
-
|
|
7
|
-
// Automatically send heartbeats at half the heartbeatWindow interval.
|
|
8
|
-
let heartbeatTimer = null;
|
|
9
|
-
${t==null?``:`heartbeatTimer = setInterval(() => self.postMessage({ id, heartbeat: true }), ${t});`}
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
if (stream) {
|
|
13
|
-
const iterable = await __fn(input);
|
|
14
|
-
for await (const chunk of iterable) {
|
|
15
|
-
self.postMessage({ id, chunk });
|
|
16
|
-
}
|
|
17
|
-
self.postMessage({ id, result: undefined });
|
|
18
|
-
} else {
|
|
19
|
-
const result = await __fn(input);
|
|
20
|
-
self.postMessage({ id, result });
|
|
21
|
-
}
|
|
22
|
-
} catch (error) {
|
|
23
|
-
self.postMessage({ id, error });
|
|
24
|
-
} finally {
|
|
25
|
-
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
|
26
|
-
}
|
|
27
|
-
}`.trim()}var g=class{config;onSlotError;disposed=!1;pending=null;taskId=0;worker=null;constructor(e,t){this.config=e,this.onSlotError=t}prime(){if(this.disposed)return Promise.resolve();try{this.ensureWorker()}catch{}return Promise.resolve()}run(e,t,n){return this.dispatch(e,t,n,!1)}runStream(e,t,n){let r=[],i=!1,a,o=[],s=e=>{r.push(e),o.shift()?.()},c=e=>{i=!0,a=e;for(let e of o.splice(0))e()};return this.dispatch(e,t,n,!0,s).then(()=>c(),c),this.pending&&(this.pending.finishStream=c),{[Symbol.asyncIterator](){let e=0;return{async next(){for(;e>=r.length&&!i;)await new Promise(e=>o.push(e));if(e<r.length){let t=r[e];return r[e]=null,e++,{done:!1,value:t}}if(a!==void 0)throw a;return{done:!0,value:void 0}}}}}}cancel(){let e=this.pending;e&&(clearTimeout(e.timer),clearTimeout(e.heartbeatWatchdog),this.pending=null,this.stopWorker(),e.finishStream?.(new i(`Stream was cancelled`)))}terminate(){this.disposed=!0,this.stopWorker(),this.failPending(new i)}dispatch(e,t,n,r,s){if(this.disposed)return Promise.reject(new i);let c;try{c=this.ensureWorker()}catch(e){return Promise.reject(e)}let u=this.config.kind===`inline`&&this.config.heartbeatInterval!=null?this.config.heartbeatInterval*2:void 0;return new Promise((i,d)=>{let f=this.taskId++,p={emit:s,id:f,reject:d,resolve:i,watchdogMs:u};n!==void 0&&(p.timer=setTimeout(()=>{this.restart(new a(n))},n),l(p.timer)),u!==void 0&&(p.heartbeatWatchdog=setTimeout(()=>{this.restart(new a(u))},u),l(p.heartbeatWatchdog)),this.pending=p;try{c.postMessage({id:f,input:e,stream:r},t)}catch(e){this.failPending(new o(e instanceof Error?e.message:String(e),{cause:e}))}})}ensureWorker(){if(this.worker)return this.worker;if(typeof globalThis.Worker!=`function`)throw new o(`Worker API is unavailable in this runtime`);let e;if(this.config.kind===`module`)try{e=new Worker(this.config.url,{type:`module`})}catch(e){throw new o(`Failed to create Worker`,{cause:e})}else try{let t=new Blob([h(this.config.fn,this.config.heartbeatInterval)],{type:`application/javascript`}),n=URL.createObjectURL(t);try{e=new Worker(n)}finally{URL.revokeObjectURL(n)}}catch(e){throw new o(`Failed to create Worker`,{cause:e})}return e.onmessage=e=>{let t=this.pending;if(!(!t||e.data.id!==t.id)){if(`heartbeat`in e.data){t.watchdogMs!==void 0&&(clearTimeout(t.heartbeatWatchdog),t.heartbeatWatchdog=setTimeout(()=>{this.restart(new a(t.watchdogMs))},t.watchdogMs),l(t.heartbeatWatchdog));return}if(`chunk`in e.data){t.emit?.(e.data.chunk);return}if(clearTimeout(t.timer),clearTimeout(t.heartbeatWatchdog),this.pending=null,`error`in e.data){let n=e.data.error instanceof Error?e.data.error:Error(String(e.data.error));t.reject(new r(n.message,{cause:n}))}else t.resolve(e.data.result)}},e.onerror=e=>{let t=new o(e.message);this.stopWorker(),this.failPending(t),this.onSlotError?.(t,()=>void this.prime())},this.worker=e,e}failPending(e){let t=this.pending;t&&(clearTimeout(t.timer),clearTimeout(t.heartbeatWatchdog),this.pending=null,t.reject(e))}restart(e){this.stopWorker(),this.failPending(e)}stopWorker(){this.worker&&=(this.worker.terminate(),null)}};function _(e,t){let{concurrency:n,heartbeatWindow:r,maxQueue:i,onFull:a,onSlotError:o,timeout:s}=m(t),c=r==null?void 0:Math.floor(r/2);return u(Array.from({length:n},()=>new g({fn:e,heartbeatInterval:c,kind:`inline`},o)),{concurrency:n,defaultTimeout:s,maxQueue:i,onFull:a})}function v(e,t){let{concurrency:n,heartbeatWindow:r,maxQueue:i,onFull:a,onSlotError:o,timeout:s}=m(t),c=typeof e==`string`?e:e.href;return u(Array.from({length:n},()=>new g({kind:`module`,url:c},o)),{concurrency:n,defaultTimeout:s,maxQueue:i,onFull:a})}exports.FamiliarError=e,exports.FamiliarInvalidOptionsError=t,exports.FamiliarQueueFullError=n,exports.FamiliarRuntimeError=o,exports.FamiliarTaskError=r,exports.FamiliarTerminatedError=i,exports.FamiliarTimeoutError=a,exports.createModuleWorker=v,exports.createWorker=_,exports.task=d;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},t=class extends e{},n=class extends e{maxQueue;constructor(e){super(`Queue is full (maxQueue=${e})`),this.maxQueue=e}},r=class extends e{},i=class extends e{constructor(e=`Worker was terminated`){super(e)}},a=class extends e{timeoutMs;constructor(e){super(`Task timed out after ${e}ms`),this.timeoutMs=e}},o=class extends e{};function s(e){return e?.reason??new DOMException(`Aborted`,`AbortError`)}var c=class{#e=[];#t=0;#n=0;get size(){return this.#t}enqueue(e,t){return t!==void 0&&this.#t>=t?!1:(this.#e.push({item:e,sequence:this.#n++}),this.#a(this.#e.length-1),this.#t+=1,!0)}remove(e){if(e.cancelled)return!1;for(let t of this.#e)if(t.item===e)return e.cancelled=!0,--this.#t,!0;return!1}shift(){for(;this.#e.length>0;){let e=this.#r().item;if(!e.cancelled)return--this.#t,e}}#r(){let e=this.#e[0],t=this.#e.pop();return this.#e.length>0&&(this.#e[0]=t,this.#o(0)),e}#i(e,t){return e.item.priority===t.item.priority?e.sequence<t.sequence:e.item.priority>t.item.priority}#a(e){for(;e>0;){let t=e-1>>1;if(!this.#i(this.#e[e],this.#e[t]))return;[this.#e[e],this.#e[t]]=[this.#e[t],this.#e[e]],e=t}}#o(e){for(;;){let t=e*2+1,n=t+1,r=e;if(t<this.#e.length&&this.#i(this.#e[t],this.#e[r])&&(r=t),n<this.#e.length&&this.#i(this.#e[n],this.#e[r])&&(r=n),r===e)return;[this.#e[e],this.#e[r]]=[this.#e[r],this.#e[e]],e=r}}};function l(e){typeof e==`object`&&e&&`unref`in e&&e.unref()}function u(e,t){let r=[...e],o=new c,u=new AbortController,d=[],f=[],p=0,m=0,h=0,g,_=!1,v=!1;function y(){return p===0&&o.size===0}function b(){if(y())for(let e of d.splice(0))e.timer&&clearTimeout(e.timer),e.resolve()}function x(e={}){return y()?Promise.resolve():new Promise((t,n)=>{let r={reject:n,resolve:t};e.timeout!==void 0&&(r.timer=setTimeout(()=>{let t=d.indexOf(r);t!==-1&&d.splice(t,1),n(new a(e.timeout))},e.timeout),l(r.timer)),d.push(r)})}function S(){f.shift()?.resolve()}function C(e){for(let t of f.splice(0))t.reject(e)}function w(e){return e?.aborted?Promise.reject(s(e)):new Promise((t,n)=>{let r=!1,i={cleanup(){e?.removeEventListener(`abort`,a)},reject(e){if(r)return;r=!0,i.cleanup();let t=f.indexOf(i);t!==-1&&f.splice(t,1),n(e)},resolve(){r||(r=!0,i.cleanup(),t())}},a=()=>i.reject(s(e));e?.addEventListener(`abort`,a,{once:!0}),f.push(i)})}function T(){for(;o.size>0;){let e=o.shift();if(!e)break;if(e.signal?.aborted){e.cleanupAbort?.(),e.reject(s(e.signal)),S();continue}return e}b()}function E(){if(!(_||v)){for(_=!0;!v&&r.length>0&&o.size>0;){let a=T();if(!a)break;let o=a,c=r.pop(),l=o.timeout??t.defaultTimeout;p+=1,S();let u=()=>c.cancel(s(o.signal));o.cleanupAbort=()=>{o.signal?.removeEventListener(`abort`,u),o.cleanupAbort=void 0},o.signal?.addEventListener(`abort`,u,{once:!0}),c.run(o.input,o.transferables,l).then(t=>e(t),e=>n(e));function e(e){o.cleanupAbort?.(),r.push(c),--p,m+=1,o.resolve(e),E(),b()}function n(e){o.cleanupAbort?.(),r.push(c),--p,!(e instanceof i)&&e?.constructor?.name!==`AbortError`&&(h+=1),o.reject(e),E(),b()}}_=!1}}async function D(e,r={}){let{priority:a=0,signal:c,timeout:l,transferables:u=[]}=r;if(v)throw new i;if(g)throw new i(`Worker is draining`);if(c?.aborted)throw s(c);for(;t.onFull===`wait`&&t.maxQueue!==void 0&&o.size>=t.maxQueue;){if(await w(c),v)throw new i;if(g)throw new i(`Worker is draining`);if(c?.aborted)throw s(c)}let d,f,p=new Promise((e,t)=>{d=e,f=t}),m={input:e,priority:a,reject:f,resolve:d,signal:c,timeout:l,transferables:u};if(!o.enqueue(m,t.onFull===`wait`?void 0:t.maxQueue))throw new n(t.maxQueue);if(c){let e=()=>{o.remove(m)&&(m.cleanupAbort?.(),f(s(c)),S(),b())};m.cleanupAbort=()=>{c.removeEventListener(`abort`,e),m.cleanupAbort=void 0},c.addEventListener(`abort`,e,{once:!0})}return E(),p}function O(){if(!v){v=!0,u.abort();for(let t of e)t.terminate();for(;o.size>0;){let e=o.shift();if(!e)break;e.cleanupAbort?.(),e.reject(new i)}C(new i),b()}}function k(e={}){return v?Promise.resolve():g||(C(new i(`Worker is draining`)),g=x(e).then(()=>O(),e=>{throw O(),e}),g)}return{get disposalSignal(){return u.signal},dispose:O,get disposed(){return v},drain:k,async prime(){await Promise.all(e.map(e=>e.prime()))},run:D,get stats(){return{active:p,completed:m,failed:h,queued:o.size}},get status(){return v?`terminated`:p===0?`idle`:`running`},[Symbol.asyncDispose]:()=>k(),[Symbol.dispose]:O}}async function*d(e,t,n={}){let r=new AbortController,i=()=>r.abort(n.signal.reason);n.signal?.addEventListener(`abort`,i,{once:!0});let a=t.map(t=>e.run(t,{...n,signal:r.signal}));try{for(let e of a)yield await e}catch(e){throw r.abort(e),await Promise.allSettled(a),e}finally{n.signal?.removeEventListener(`abort`,i),r.abort(),await Promise.allSettled(a)}}function f(e,t=void 0,n={}){let r=new AbortController,i=new Set,a=0;return n.signal?.addEventListener(`abort`,()=>r.abort(n.signal.reason),{once:!0}),{abort(e){r.abort(e)},async drain(){return Promise.allSettled([...i])},get name(){return t},get pending(){return i.size},run(t,n={}){let o=e.run(t,{...n,signal:r.signal});return a+=1,i.add(o),o.finally(()=>i.delete(o)),o},get size(){return a}}}function p(e,t){let r=[...e],o=[],c=[],u=new AbortController,d=[],f=0,p=0,m=0,h=0,g=!1,_;function v(){return f===0&&o.length===0}function y(){if(v())for(let e of d.splice(0))e()}function b(e){return v()?Promise.resolve():new Promise((t,n)=>{d.push(t),e.timeout!==void 0&&l(setTimeout(()=>{let r=d.indexOf(t);r!==-1&&d.splice(r,1),n(new a(e.timeout))},e.timeout))})}function x(){c.shift()?.resolve()}function S(e){for(let t of c.splice(0))t.reject(e)}function C(e){return e?.aborted?Promise.reject(s(e)):new Promise((t,n)=>{let r=!1,i={cleanup(){e?.removeEventListener(`abort`,a)},reject(e){if(r)return;r=!0,i.cleanup();let t=c.indexOf(i);t!==-1&&c.splice(t,1),n(e)},resolve(){r||(r=!0,i.cleanup(),t())}},a=()=>i.reject(s(e));e?.addEventListener(`abort`,a,{once:!0}),c.push(i)})}function w(e){let t=o.shift();t?(t.resolve(e),x()):r.push(e)}async function T(e){if(g)throw new i;if(_)throw new i(`Worker is draining`);if(e.signal?.aborted)throw s(e.signal);for(;t.maxQueue!==void 0&&o.length>=t.maxQueue;){if(t.onFull===`reject`)throw new n(t.maxQueue);if(await C(e.signal),g)throw new i;if(_)throw new i(`Worker is draining`);if(e.signal?.aborted)throw s(e.signal)}return r.pop()||new Promise((t,n)=>{let r={cleanup(){r.signal?.removeEventListener(`abort`,i)},priority:e.priority??0,reject(e){r.cleanup();let t=o.indexOf(r);t!==-1&&(o.splice(t,1),x()),n(e),y()},resolve(e){r.cleanup(),t(e)},sequence:h++,signal:e.signal},i=()=>r.reject(s(r.signal));r.signal?.addEventListener(`abort`,i,{once:!0}),o.push(r),o.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}function E(){if(!g){g=!0,u.abort();for(let t of e)t.terminate();for(let e of o.splice(0))e.reject(new i);S(new i),y()}}function D(e={}){if(g)return Promise.resolve();if(_)return _;for(let e of o.splice(0))e.reject(new i(`Worker is draining`));return S(new i(`Worker is draining`)),_=b(e).then(()=>E(),e=>{throw E(),e}),_}return{get disposalSignal(){return u.signal},dispose:E,get disposed(){return g},drain:D,async prime(){await Promise.all(e.map(e=>e.prime()))},runStream(e,n={}){let r=new AbortController,a=()=>r.abort(n.signal.reason);return n.signal?.addEventListener(`abort`,a,{once:!0}),{[Symbol.asyncIterator]:async function*(){let o,c;try{o=await T({...n,signal:r.signal}),f+=1,c=()=>o?.cancel(s(r.signal)),r.signal.addEventListener(`abort`,c,{once:!0});let i=o.stream(e,{...n,signal:r.signal,timeout:n.timeout??t.defaultTimeout});for await(let e of i.iterable)yield e;await i.done,p+=1}catch(e){throw e?.constructor?.name!==`AbortError`&&!(e instanceof i)&&(m+=1),e}finally{n.signal?.removeEventListener(`abort`,a),o&&(c&&r.signal.removeEventListener(`abort`,c),--f,w(o),y())}}}},get stats(){return{active:f,completed:p,failed:m,queued:o.length}},get status(){return g?`terminated`:f===0?`idle`:`running`},[Symbol.asyncDispose]:()=>D(),[Symbol.dispose]:E}}var m=512;function h(e={}){let{concurrency:n=1,maxQueue:r,onFull:i=`reject`,onSlotError:a,timeout:o}=e,s=n===`auto`?Math.max(1,globalThis.navigator?.hardwareConcurrency??1):n;if(!Number.isInteger(s)||s<1||s>m)throw new t(`\`concurrency\` must be a positive integer ≤ ${m} or "auto"`);if(r!==void 0&&(!Number.isInteger(r)||r<1))throw new t("`maxQueue` must be a positive integer");if(o!==void 0&&(!Number.isFinite(o)||o<=0))throw new t("`timeout` must be a finite number greater than 0");return{concurrency:s,maxQueue:r,onFull:i,onSlotError:a,timeout:o}}function g(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.version===1&&typeof t.id==`number`&&(t.kind===`chunk`||t.kind===`error`||t.kind===`result`)}function _(e){let t=Error(e.message);return t.name=e.name,t.stack=e.stack,new r(e.message,{cause:t})}var v=class{#e;#t;#n=!1;#r;#i=0;#a;constructor(e,t){this.#t=e,this.#e=t}cancel(e){this.#a?.terminate(),this.#a=void 0,this.#l(`reject`,e)}prime(){return this.#n||this.#s(),Promise.resolve()}run(e,t,n){return this.#o(e,t,n,`run`)}stream(e,t){let n=()=>this.cancel(new i(`Stream consumer stopped`)),r=[],a=[],o=!1,s,c=e=>{let t=a.shift();t?t({done:!1,value:e}):r.push(e)},l=e=>{for(o=!0,s=e;a.length>0;)a.shift()(e===void 0?{done:!0,value:void 0}:Promise.reject(e))};return{done:this.#o(e,t.transferables??[],t.timeout,`stream`,c).then(()=>l(),e=>l(e)),iterable:{[Symbol.asyncIterator]:()=>({async next(){if(r.length>0)return{done:!1,value:r.shift()};if(s!==void 0)throw s;return o?{done:!0,value:void 0}:new Promise((e,t)=>{a.push(n=>{n instanceof Promise?n.then(e,t):e(n)})})},async return(){return n(),{done:!0,value:void 0}}})}}}terminate(){this.#n=!0,this.cancel(new i)}#o(e,t,n,r,s){if(this.#n)return Promise.reject(new i);if(this.#r)return Promise.reject(new o(`Worker slot is already busy`));try{let i=this.#s(),c=this.#i++;return new Promise((u,d)=>{let f={emit:s,id:c,reject:d,resolve:u};this.#r=f,n!==void 0&&(f.timer=setTimeout(()=>this.cancel(new a(n)),n),l(f.timer));try{i.postMessage({id:c,input:e,kind:r,version:1},t)}catch(e){this.cancel(new o(`Failed to post message to worker`,{cause:e}))}})}catch(e){return Promise.reject(e)}}#s(){if(this.#a)return this.#a;if(typeof Worker>`u`)throw new o(`Worker API is unavailable in this runtime`);try{let e=new Worker(this.#t,{type:`module`});return e.onmessage=e=>this.#c(e.data),e.onerror=e=>{let t=new o(e.message||`Worker failed`);this.#a=void 0,this.#e?.(t),this.#l(`reject`,t)},this.#a=e,e}catch(e){throw new o(`Failed to create Worker`,{cause:e})}}#c(e){if(this.#r){if(!g(e)||e.id!==this.#r.id){this.cancel(new o(`Worker returned an incompatible protocol response`));return}if(e.kind===`chunk`){this.#r.emit?.(e.value);return}if(e.kind===`error`){this.#l(`reject`,_(e.error));return}this.#l(`resolve`,e.value)}}#l(e,t){let n=this.#r;n&&(this.#r=void 0,n.timer&&clearTimeout(n.timer),e===`resolve`?n.resolve(t):n.reject(t))}};function y(e,t){return Array.from({length:t.concurrency},()=>new v(e,t.onSlotError))}function b(e,t={}){let n=h(t);return u(y(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}function x(e,t={}){let n=h(t);return p(y(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}exports.FamiliarError=e,exports.FamiliarInvalidOptionsError=t,exports.FamiliarQueueFullError=n,exports.FamiliarRuntimeError=o,exports.FamiliarTaskError=r,exports.FamiliarTerminatedError=i,exports.FamiliarTimeoutError=a,exports.batch=d,exports.createStreamWorker=x,exports.createTaskGroup=f,exports.createWorker=b;
|
|
28
2
|
//# sourceMappingURL=familiar.cjs.map
|