@vielzeug/familiar 2.1.0 → 3.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.
Files changed (68) hide show
  1. package/README.md +4 -11
  2. package/dist/_dev.cjs +2 -0
  3. package/dist/_dev.cjs.map +1 -0
  4. package/dist/_dev.js +6 -0
  5. package/dist/_dev.js.map +1 -0
  6. package/dist/_pool-core.cjs +2 -0
  7. package/dist/_pool-core.cjs.map +1 -0
  8. package/dist/_pool-core.d.ts +41 -0
  9. package/dist/_pool-core.d.ts.map +1 -0
  10. package/dist/_pool-core.js +118 -0
  11. package/dist/_pool-core.js.map +1 -0
  12. package/dist/_pool.cjs +1 -1
  13. package/dist/_pool.cjs.map +1 -1
  14. package/dist/_pool.d.ts +8 -9
  15. package/dist/_pool.d.ts.map +1 -1
  16. package/dist/_pool.js +117 -164
  17. package/dist/_pool.js.map +1 -1
  18. package/dist/_queue.cjs +1 -1
  19. package/dist/_queue.cjs.map +1 -1
  20. package/dist/_queue.d.ts +1 -1
  21. package/dist/_queue.d.ts.map +1 -1
  22. package/dist/_queue.js +10 -7
  23. package/dist/_queue.js.map +1 -1
  24. package/dist/_stream-pool.cjs +1 -1
  25. package/dist/_stream-pool.cjs.map +1 -1
  26. package/dist/_stream-pool.d.ts +3 -4
  27. package/dist/_stream-pool.d.ts.map +1 -1
  28. package/dist/_stream-pool.js +84 -118
  29. package/dist/_stream-pool.js.map +1 -1
  30. package/dist/errors.cjs +1 -1
  31. package/dist/errors.cjs.map +1 -1
  32. package/dist/errors.d.ts +8 -1
  33. package/dist/errors.d.ts.map +1 -1
  34. package/dist/errors.js +16 -6
  35. package/dist/errors.js.map +1 -1
  36. package/dist/familiar.cjs +1 -1
  37. package/dist/familiar.cjs.map +1 -1
  38. package/dist/familiar.iife.js +1 -1
  39. package/dist/familiar.iife.js.map +1 -1
  40. package/dist/familiar.js +1 -1
  41. package/dist/familiar.js.map +1 -1
  42. package/dist/index.cjs +1 -1
  43. package/dist/index.d.ts +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +3 -3
  46. package/dist/protocol.cjs +1 -1
  47. package/dist/protocol.cjs.map +1 -1
  48. package/dist/protocol.d.ts +1 -0
  49. package/dist/protocol.d.ts.map +1 -1
  50. package/dist/protocol.js +16 -5
  51. package/dist/protocol.js.map +1 -1
  52. package/dist/testing/index.d.ts +1 -1
  53. package/dist/testing/index.d.ts.map +1 -1
  54. package/dist/testing/testing.cjs +1 -1
  55. package/dist/testing/testing.cjs.map +1 -1
  56. package/dist/testing/testing.d.ts +3 -3
  57. package/dist/testing/testing.d.ts.map +1 -1
  58. package/dist/testing/testing.js +25 -24
  59. package/dist/testing/testing.js.map +1 -1
  60. package/dist/types.d.ts +7 -28
  61. package/dist/types.d.ts.map +1 -1
  62. package/dist/worker.cjs +1 -1
  63. package/dist/worker.cjs.map +1 -1
  64. package/dist/worker.d.ts +5 -4
  65. package/dist/worker.d.ts.map +1 -1
  66. package/dist/worker.js +49 -38
  67. package/dist/worker.js.map +1 -1
  68. package/package.json +10 -8
package/dist/_pool.js CHANGED
@@ -1,206 +1,159 @@
1
- import { TaskQueue as e } from "./_queue.js";
2
- import { unrefTimer as t } from "./_timers.js";
3
- import { FamiliarQueueFullError as n, FamiliarTerminatedError as r, FamiliarTimeoutError as i } from "./errors.js";
4
- import { abortError as a } from "@vielzeug/arsenal/async";
1
+ import { FamiliarQueueFullError as e, FamiliarRuntimeError as t, FamiliarTerminatedError as n } from "./errors.js";
2
+ import { createPoolCore as r, validatePriority as i, validateTimeout as a } from "./_pool-core.js";
3
+ import { TaskQueue as o } from "./_queue.js";
4
+ import { abortError as s } from "@vielzeug/arsenal";
5
5
  //#region src/_pool.ts
6
- function o(o, s) {
7
- let c = [...o], l = new e(), u = new AbortController(), d = [], f = [], p = 0, m = 0, h = 0, g, _ = !1, v = !1;
8
- function y() {
9
- return p === 0 && l.size === 0;
10
- }
11
- function b() {
12
- if (y()) for (let e of d.splice(0)) e.timer && clearTimeout(e.timer), e.resolve();
13
- }
14
- function x(e = {}) {
15
- return y() ? Promise.resolve() : new Promise((n, r) => {
16
- let a = {
17
- reject: r,
18
- resolve: n
19
- };
20
- e.timeout !== void 0 && (a.timer = setTimeout(() => {
21
- let t = d.indexOf(a);
22
- t !== -1 && d.splice(t, 1), r(new i(e.timeout));
23
- }, e.timeout), t(a.timer)), d.push(a);
24
- });
25
- }
26
- function S() {
27
- f.shift()?.resolve();
28
- }
29
- function C(e) {
30
- for (let t of f.splice(0)) t.reject(e);
31
- }
32
- function w(e) {
33
- return e?.aborted ? Promise.reject(a(e)) : new Promise((t, n) => {
34
- let r = !1, i = {
35
- cleanup() {
36
- e?.removeEventListener("abort", o);
37
- },
38
- reject(e) {
39
- if (r) return;
40
- r = !0, i.cleanup();
41
- let t = f.indexOf(i);
42
- t !== -1 && f.splice(t, 1), n(e);
43
- },
44
- resolve() {
45
- r || (r = !0, i.cleanup(), t());
46
- }
47
- }, o = () => i.reject(a(e));
48
- e?.addEventListener("abort", o, { once: !0 }), f.push(i);
49
- });
50
- }
51
- function T() {
52
- for (; l.size > 0;) {
53
- let e = l.shift();
6
+ function c(t, c) {
7
+ let l = [...t], u = new o(), d = !1, f = r({
8
+ isIdle: () => l.length === t.length && u.size === 0,
9
+ onDispose() {
10
+ for (let e of t) e.terminate();
11
+ for (; u.size > 0;) {
12
+ let e = u.shift();
13
+ if (!e) break;
14
+ e.cleanupAbort?.(), e.reject(new n());
15
+ }
16
+ },
17
+ onDrainStart() {}
18
+ });
19
+ function p() {
20
+ for (; u.size > 0;) {
21
+ let e = u.shift();
54
22
  if (!e) break;
55
23
  if (e.signal?.aborted) {
56
- e.cleanupAbort?.(), e.reject(a(e.signal)), S();
24
+ e.cleanupAbort?.(), e.reject(s(e.signal)), f.releaseCapacity();
57
25
  continue;
58
26
  }
59
27
  return e;
60
28
  }
61
- b();
29
+ f.settleIdle();
62
30
  }
63
- function E() {
64
- if (!(_ || v)) {
65
- for (_ = !0; !v && c.length > 0 && l.size > 0;) {
66
- let e = T();
31
+ function m() {
32
+ if (!(d || f.disposed)) {
33
+ for (d = !0; !f.disposed && l.length > 0 && u.size > 0;) {
34
+ let e = p();
67
35
  if (!e) break;
68
- let t = e, n = c.pop(), i = t.timeout ?? s.defaultTimeout;
69
- p += 1, S();
70
- let o = () => n.cancel(a(t.signal));
36
+ let t = e, r = l.pop(), i = t.timeout ?? c.defaultTimeout;
37
+ f.trackActive(1), f.releaseCapacity();
38
+ let a = () => {
39
+ t.aborted = !0, r.cancel(s(t.signal));
40
+ };
71
41
  t.cleanupAbort = () => {
72
- t.signal?.removeEventListener("abort", o), t.cleanupAbort = void 0;
73
- }, t.signal?.addEventListener("abort", o, { once: !0 }), n.run(t.input, t.transferables, i).then((e) => l(e), (e) => u(e));
74
- function l(e) {
75
- t.cleanupAbort?.(), c.push(n), --p, m += 1, t.resolve(e), E(), b();
42
+ t.signal?.removeEventListener("abort", a), t.cleanupAbort = void 0;
43
+ }, t.signal?.addEventListener("abort", a, { once: !0 }), r.run(t.input, t.transferables, i).then((e) => o(e), (e) => u(e));
44
+ function o(e) {
45
+ t.cleanupAbort?.(), l.push(r), f.trackActive(-1), f.trackCompleted(), t.resolve(e), m(), f.settleIdle();
76
46
  }
77
47
  function u(e) {
78
- t.cleanupAbort?.(), c.push(n), --p, !(e instanceof r) && e?.constructor?.name !== "AbortError" && (h += 1), t.reject(e), E(), b();
48
+ t.cleanupAbort?.(), l.push(r), f.trackActive(-1), !t.aborted && !(e instanceof n) && f.trackFailed(), t.reject(e), m(), f.settleIdle();
79
49
  }
80
50
  }
81
- _ = !1;
51
+ d = !1;
82
52
  }
83
53
  }
84
- async function D(e, t = {}) {
85
- let { priority: i = 0, signal: o, timeout: c, transferables: u = [] } = t;
86
- if (v) throw new r();
87
- if (g) throw new r("Worker is draining");
88
- if (o?.aborted) throw a(o);
89
- for (; s.onFull === "wait" && s.maxQueue !== void 0 && l.size >= s.maxQueue;) {
90
- if (await w(o), v) throw new r();
91
- if (g) throw new r("Worker is draining");
92
- if (o?.aborted) throw a(o);
54
+ async function h(t, r = {}) {
55
+ let { signal: o } = r, l = i(r.priority ?? 0), d = a(r.timeout), p = [...r.transferables ?? []];
56
+ if (f.disposed) throw new n();
57
+ if (f.drainPromise) throw new n("Worker is draining");
58
+ if (o?.aborted) throw s(o);
59
+ for (; c.onFull === "wait" && c.maxQueue !== void 0 && u.size >= c.maxQueue;) {
60
+ if (await f.waitForCapacity(o, l), f.disposed) throw new n();
61
+ if (f.drainPromise) throw new n("Worker is draining");
62
+ if (o?.aborted) throw f.releaseCapacity(), s(o);
93
63
  }
94
- let d, f, p = new Promise((e, t) => {
95
- d = e, f = t;
96
- }), m = {
97
- input: e,
98
- priority: i,
99
- reject: f,
100
- resolve: d,
64
+ let h, g, _ = new Promise((e, t) => {
65
+ h = e, g = t;
66
+ }), v = {
67
+ input: t,
68
+ priority: l,
69
+ reject: g,
70
+ resolve: h,
101
71
  signal: o,
102
- timeout: c,
103
- transferables: u
72
+ timeout: d,
73
+ transferables: p
104
74
  };
105
- if (!l.enqueue(m, s.onFull === "wait" ? void 0 : s.maxQueue)) throw new n(s.maxQueue);
75
+ if (!u.enqueue(v, c.onFull === "wait" ? void 0 : c.maxQueue)) throw new e(c.maxQueue);
106
76
  if (o) {
107
77
  let e = () => {
108
- l.remove(m) && (m.cleanupAbort?.(), f(a(o)), S(), b());
78
+ u.remove(v) && (v.cleanupAbort?.(), g(s(o)), f.releaseCapacity(), f.settleIdle());
109
79
  };
110
- m.cleanupAbort = () => {
111
- o.removeEventListener("abort", e), m.cleanupAbort = void 0;
80
+ v.cleanupAbort = () => {
81
+ o.removeEventListener("abort", e), v.cleanupAbort = void 0;
112
82
  }, o.addEventListener("abort", e, { once: !0 });
113
83
  }
114
- return E(), p;
115
- }
116
- function O() {
117
- if (!v) {
118
- v = !0, u.abort();
119
- for (let e of o) e.terminate();
120
- for (; l.size > 0;) {
121
- let e = l.shift();
122
- if (!e) break;
123
- e.cleanupAbort?.(), e.reject(new r());
124
- }
125
- C(new r()), b();
126
- }
127
- }
128
- function k(e = {}) {
129
- return v ? Promise.resolve() : g || (C(new r("Worker is draining")), g = x(e).then(() => O(), (e) => {
130
- throw O(), e;
131
- }), g);
84
+ return m(), _;
132
85
  }
133
86
  return {
134
87
  get disposalSignal() {
135
- return u.signal;
88
+ return f.disposalSignal;
136
89
  },
137
- dispose: O,
90
+ dispose: f.dispose,
138
91
  get disposed() {
139
- return v;
140
- },
141
- drain: k,
142
- async prime() {
143
- await Promise.all(o.map((e) => e.prime()));
92
+ return f.disposed;
144
93
  },
145
- run: D,
94
+ drain: f.drain,
95
+ run: h,
146
96
  get stats() {
147
- return {
148
- active: p,
149
- completed: m,
150
- failed: h,
151
- queued: l.size
152
- };
97
+ return f.stats(u.size);
153
98
  },
154
99
  get status() {
155
- return v ? "terminated" : p === 0 ? "idle" : "running";
100
+ return f.status();
156
101
  },
157
- [Symbol.asyncDispose]: () => k(),
158
- [Symbol.dispose]: O
102
+ [Symbol.asyncDispose]: () => f.drain({}),
103
+ [Symbol.dispose]: f.dispose
159
104
  };
160
105
  }
161
- async function* s(e, t, n = {}) {
162
- let r = new AbortController(), i = () => r.abort(n.signal?.reason);
163
- n.signal?.addEventListener("abort", i, { once: !0 });
164
- let a = t.map((t) => e.run(t, {
165
- ...n,
166
- signal: r.signal
167
- }));
168
- try {
169
- for (let e of a) yield await e;
170
- } catch (e) {
171
- throw r.abort(e), await Promise.allSettled(a), e;
172
- } finally {
173
- n.signal?.removeEventListener("abort", i), r.abort(), await Promise.allSettled(a);
174
- }
175
- }
176
- function c(e, t = void 0, n = {}) {
177
- let r = new AbortController(), i = /* @__PURE__ */ new Set(), a = 0;
178
- return n.signal?.addEventListener("abort", () => r.abort(n.signal?.reason), { once: !0 }), {
179
- abort(e) {
180
- r.abort(e);
181
- },
182
- async drain() {
183
- return Promise.allSettled([...i]);
184
- },
185
- get name() {
186
- return t;
187
- },
188
- get pending() {
189
- return i.size;
190
- },
191
- run(t, n = {}) {
192
- let o = e.run(t, {
193
- ...n,
194
- signal: r.signal
195
- });
196
- return a += 1, i.add(o), o.finally(() => i.delete(o)), o;
197
- },
198
- get size() {
199
- return a;
106
+ function l(e, r, i = {}) {
107
+ let a, o = async function* (t) {
108
+ let n = [], a = () => t.abort(i.signal?.reason);
109
+ i.signal?.aborted ? t.abort(i.signal.reason) : i.signal?.addEventListener("abort", a, { once: !0 });
110
+ try {
111
+ for (let [a, o] of r.entries()) {
112
+ let r = e.run(o, {
113
+ priority: i.priority,
114
+ signal: t.signal,
115
+ timeout: i.timeout,
116
+ transferables: i.getTransferables?.(o, a)
117
+ }).catch((e) => {
118
+ throw t.abort(e), e;
119
+ });
120
+ r.catch(() => void 0), n.push(r);
121
+ }
122
+ if (n.length === 0 && t.signal.aborted) throw s(t.signal);
123
+ for (let e of n) {
124
+ if (t.signal.aborted) throw s(t.signal);
125
+ let n = await e;
126
+ if (t.signal.aborted) throw s(t.signal);
127
+ yield n;
128
+ }
129
+ } catch (e) {
130
+ throw t.abort(e), e;
131
+ } finally {
132
+ i.signal?.removeEventListener("abort", a), t.abort(new DOMException("Batch consumer stopped", "AbortError")), await Promise.allSettled(n);
200
133
  }
201
134
  };
135
+ return { [Symbol.asyncIterator]() {
136
+ let e = {}, r = new AbortController(), i, s = () => {
137
+ if (a ??= e, a === e) return i ??= o(r), i;
138
+ };
139
+ return {
140
+ next: () => s()?.next() ?? Promise.reject(new t("Worker batches can only be consumed once")),
141
+ return: async (t) => !a || a !== e ? {
142
+ done: !0,
143
+ value: t
144
+ } : (r.abort(new n("Batch consumer stopped")), i?.return(t) ?? {
145
+ done: !0,
146
+ value: t
147
+ }),
148
+ throw: async (e) => {
149
+ let n = s();
150
+ if (!n) throw new t("Worker batches can only be consumed once");
151
+ return r.abort(e), n.throw(e);
152
+ }
153
+ };
154
+ } };
202
155
  }
203
156
  //#endregion
204
- export { s as batch, o as createPool, c as createTaskGroup };
157
+ export { c as createPool, l as runBatch };
205
158
 
206
159
  //# sourceMappingURL=_pool.js.map
package/dist/_pool.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"_pool.js","names":[],"sources":["../src/_pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\nimport { type QueueItem, TaskQueue } from './_queue';\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type {\n BatchOptions,\n DrainOptions,\n RunOptions,\n SlotStrategy,\n TaskGroup,\n TaskGroupOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\n\nexport type PoolOptions = {\n concurrency: number;\n defaultTimeout: number | undefined;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n};\n\ntype IdleWaiter = {\n reject: (reason: unknown) => void;\n resolve: () => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\nexport function createPool<TInput, TOutput>(\n slots: SlotStrategy<TInput, TOutput>[],\n options: PoolOptions,\n): WorkerPool<TInput, TOutput> {\n const freeSlots = [...slots];\n const queue = new TaskQueue<TInput, TOutput>();\n const disposalController = new AbortController();\n const idleWaiters: IdleWaiter[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let drainPromise: Promise<void> | undefined;\n let draining = false;\n let terminated = false;\n\n function isIdle(): boolean {\n return active === 0 && queue.size === 0;\n }\n\n function settleIdle(): void {\n if (!isIdle()) return;\n\n for (const waiter of idleWaiters.splice(0)) {\n if (waiter.timer) clearTimeout(waiter.timer);\n\n waiter.resolve();\n }\n }\n\n function waitForIdle(drainOptions: DrainOptions = {}): Promise<void> {\n if (isIdle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n const waiter: IdleWaiter = { reject, resolve };\n\n if (drainOptions.timeout !== undefined) {\n waiter.timer = setTimeout(() => {\n const index = idleWaiters.indexOf(waiter);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(drainOptions.timeout!));\n }, drainOptions.timeout);\n unrefTimer(waiter.timer);\n }\n\n idleWaiters.push(waiter);\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function nextItem(): QueueItem<TInput, TOutput> | undefined {\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n if (item.signal?.aborted) {\n item.cleanupAbort?.();\n item.reject(abortError(item.signal));\n releaseCapacity();\n continue;\n }\n\n return item;\n }\n\n settleIdle();\n\n return undefined;\n }\n\n function drainQueue(): void {\n if (draining || terminated) return;\n\n draining = true;\n\n while (!terminated && freeSlots.length > 0 && queue.size > 0) {\n const next = nextItem();\n\n if (!next) break;\n\n const item = next;\n const slot = freeSlots.pop()!;\n const timeout = item.timeout ?? options.defaultTimeout;\n\n active += 1;\n releaseCapacity();\n\n const onAbort = () => slot.cancel(abortError(item.signal!));\n\n item.cleanupAbort = () => {\n item.signal?.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n item.signal?.addEventListener('abort', onAbort, { once: true });\n\n slot.run(item.input, item.transferables, timeout).then(\n (value) => finish(value),\n (error: unknown) => fail(error),\n );\n\n function finish(value: TOutput): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n active -= 1;\n completed += 1;\n item.resolve(value);\n drainQueue();\n settleIdle();\n }\n\n function fail(error: unknown): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n active -= 1;\n\n if (!(error instanceof FamiliarTerminatedError) && error?.constructor?.name !== 'AbortError') failed += 1;\n\n item.reject(error);\n drainQueue();\n settleIdle();\n }\n }\n\n draining = false;\n }\n\n async function run(input: TInput, runOptions: RunOptions = {}): Promise<TOutput> {\n const { priority = 0, signal, timeout, transferables = [] } = runOptions;\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n\n while (options.onFull === 'wait' && options.maxQueue !== undefined && queue.size >= options.maxQueue) {\n await waitForCapacity(signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n }\n\n let resolve!: (value: TOutput) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<TOutput>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const item: QueueItem<TInput, TOutput> = { input, priority, reject, resolve, signal, timeout, transferables };\n\n if (!queue.enqueue(item, options.onFull === 'wait' ? undefined : options.maxQueue)) {\n throw new FamiliarQueueFullError(options.maxQueue!);\n }\n\n if (signal) {\n const onAbort = () => {\n if (!queue.remove(item)) return;\n\n item.cleanupAbort?.();\n reject(abortError(signal));\n releaseCapacity();\n settleIdle();\n };\n\n item.cleanupAbort = () => {\n signal.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n\n drainQueue();\n\n return promise;\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n for (const slot of slots) slot.terminate();\n\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n item.cleanupAbort?.();\n item.reject(new FamiliarTerminatedError());\n }\n\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions = {}): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n return {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n async prime(): Promise<void> {\n await Promise.all(slots.map((slot) => slot.prime()));\n },\n run,\n get stats(): WorkerStats {\n return { active, completed, failed, queued: queue.size };\n },\n get status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n },\n [Symbol.asyncDispose]: () => drain(),\n [Symbol.dispose]: dispose,\n };\n}\n\nexport async function* batch<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n inputs: readonly TInput[],\n options: BatchOptions = {},\n): AsyncIterable<TOutput> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n const tasks = inputs.map((input) => pool.run(input, { ...options, signal: controller.signal }));\n\n try {\n for (const task of tasks) yield await task;\n } catch (error) {\n controller.abort(error);\n await Promise.allSettled(tasks);\n throw error;\n } finally {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort();\n await Promise.allSettled(tasks);\n }\n}\n\nexport function createTaskGroup<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n name: string | undefined = undefined,\n options: TaskGroupOptions = {},\n): TaskGroup<TInput, TOutput> {\n const controller = new AbortController();\n const tasks = new Set<Promise<TOutput>>();\n let size = 0;\n const onAbort = () => controller.abort(options.signal?.reason);\n\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n abort(reason?: unknown): void {\n controller.abort(reason);\n },\n async drain(): Promise<PromiseSettledResult<TOutput>[]> {\n return Promise.allSettled([...tasks]);\n },\n get name() {\n return name;\n },\n get pending() {\n return tasks.size;\n },\n run(input, runOptions = {}): Promise<TOutput> {\n const task = pool.run(input, { ...runOptions, signal: controller.signal });\n\n size += 1;\n tasks.add(task);\n void task.finally(() => tasks.delete(task));\n\n return task;\n },\n get size() {\n return size;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"_pool.js","names":[],"sources":["../src/_pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal';\nimport { createPoolCore, type PoolCore, type PoolOptions, validatePriority, validateTimeout } from './_pool-core.js';\nimport { type QueueItem, TaskQueue } from './_queue.js';\nimport { FamiliarQueueFullError, FamiliarRuntimeError, FamiliarTerminatedError } from './errors.js';\nimport type { RunOptions, SlotStrategy, WorkerPool } from './types.js';\n\nexport type { PoolOptions } from './_pool-core.js';\n\nexport function createPool<TInput, TOutput>(\n slots: SlotStrategy<TInput, TOutput>[],\n options: PoolOptions,\n): WorkerPool<TInput, TOutput> {\n const freeSlots = [...slots];\n const queue = new TaskQueue<TInput, TOutput>();\n let draining = false;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && queue.size === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n item.cleanupAbort?.();\n item.reject(new FamiliarTerminatedError());\n }\n },\n onDrainStart() {\n // No pending waiters to reject for the queue-based pool; capacity waiters\n // are rejected by the core's drain().\n },\n });\n\n function nextItem(): QueueItem<TInput, TOutput> | undefined {\n while (queue.size > 0) {\n const item = queue.shift();\n\n if (!item) break;\n\n if (item.signal?.aborted) {\n item.cleanupAbort?.();\n item.reject(abortError(item.signal));\n core.releaseCapacity();\n continue;\n }\n\n return item;\n }\n\n core.settleIdle();\n\n return undefined;\n }\n\n function drainQueue(): void {\n if (draining || core.disposed) return;\n\n draining = true;\n\n while (!core.disposed && freeSlots.length > 0 && queue.size > 0) {\n const next = nextItem();\n\n if (!next) break;\n\n const item = next;\n const slot = freeSlots.pop()!;\n const timeout = item.timeout ?? options.defaultTimeout;\n\n core.trackActive(1);\n core.releaseCapacity();\n\n const onAbort = () => {\n item.aborted = true;\n slot.cancel(abortError(item.signal!));\n };\n\n item.cleanupAbort = () => {\n item.signal?.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n item.signal?.addEventListener('abort', onAbort, { once: true });\n\n slot.run(item.input, item.transferables, timeout).then(\n (value) => finish(value),\n (error: unknown) => fail(error),\n );\n\n function finish(value: TOutput): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n core.trackActive(-1);\n core.trackCompleted();\n item.resolve(value);\n drainQueue();\n core.settleIdle();\n }\n\n function fail(error: unknown): void {\n item.cleanupAbort?.();\n freeSlots.push(slot);\n core.trackActive(-1);\n\n if (!item.aborted && !(error instanceof FamiliarTerminatedError)) core.trackFailed();\n\n item.reject(error);\n drainQueue();\n core.settleIdle();\n }\n }\n\n draining = false;\n }\n\n async function run(input: TInput, runOptions: RunOptions = {}): Promise<TOutput> {\n const { signal } = runOptions;\n const priority = validatePriority(runOptions.priority ?? 0);\n const timeout = validateTimeout(runOptions.timeout);\n const transferables = [...(runOptions.transferables ?? [])];\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) throw abortError(signal);\n\n while (options.onFull === 'wait' && options.maxQueue !== undefined && queue.size >= options.maxQueue) {\n await core.waitForCapacity(signal, priority);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (signal?.aborted) {\n core.releaseCapacity();\n throw abortError(signal);\n }\n }\n\n let resolve!: (value: TOutput) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<TOutput>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const item: QueueItem<TInput, TOutput> = { input, priority, reject, resolve, signal, timeout, transferables };\n\n if (!queue.enqueue(item, options.onFull === 'wait' ? undefined : options.maxQueue)) {\n throw new FamiliarQueueFullError(options.maxQueue!);\n }\n\n if (signal) {\n const onAbort = () => {\n if (!queue.remove(item)) return;\n\n item.cleanupAbort?.();\n reject(abortError(signal));\n core.releaseCapacity();\n core.settleIdle();\n };\n\n item.cleanupAbort = () => {\n signal.removeEventListener('abort', onAbort);\n item.cleanupAbort = undefined;\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n\n drainQueue();\n\n return promise;\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n run,\n get stats() {\n return core.stats(queue.size);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n\nexport type BatchOptions<TInput> = Pick<RunOptions, 'priority' | 'signal' | 'timeout'> & {\n getTransferables?: (input: TInput, index: number) => readonly Transferable[];\n};\n\n/** Run related tasks concurrently and yield their results in input order. */\nexport function runBatch<TInput, TOutput>(\n pool: WorkerPool<TInput, TOutput>,\n inputs: readonly TInput[],\n options: BatchOptions<TInput> = {},\n): AsyncIterable<TOutput> {\n let owner: object | undefined;\n\n const iterate = async function* (controller: AbortController): AsyncGenerator<TOutput> {\n const tasks: Promise<TOutput>[] = [];\n const onAbort = () => controller.abort(options.signal?.reason);\n\n if (options.signal?.aborted) controller.abort(options.signal.reason);\n else options.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n for (const [index, input] of inputs.entries()) {\n const task = pool\n .run(input, {\n priority: options.priority,\n signal: controller.signal,\n timeout: options.timeout,\n transferables: options.getTransferables?.(input, index),\n })\n .catch((error: unknown) => {\n controller.abort(error);\n throw error;\n });\n\n void task.catch(() => undefined);\n tasks.push(task);\n }\n\n if (tasks.length === 0 && controller.signal.aborted) throw abortError(controller.signal);\n for (const task of tasks) {\n if (controller.signal.aborted) throw abortError(controller.signal);\n const value = await task;\n if (controller.signal.aborted) throw abortError(controller.signal);\n yield value;\n }\n } catch (error) {\n controller.abort(error);\n throw error;\n } finally {\n options.signal?.removeEventListener('abort', onAbort);\n controller.abort(new DOMException('Batch consumer stopped', 'AbortError'));\n await Promise.allSettled(tasks);\n }\n };\n\n return {\n [Symbol.asyncIterator]() {\n const token = {};\n const controller = new AbortController();\n let iterator: AsyncGenerator<TOutput> | undefined;\n const start = (): AsyncGenerator<TOutput> | undefined => {\n owner ??= token;\n if (owner !== token) return undefined;\n iterator ??= iterate(controller);\n return iterator;\n };\n\n return {\n next: () =>\n start()?.next() ?? Promise.reject(new FamiliarRuntimeError('Worker batches can only be consumed once')),\n return: async (value?: unknown) => {\n if (!owner || owner !== token) return { done: true, value: value as TOutput };\n controller.abort(new FamiliarTerminatedError('Batch consumer stopped'));\n return iterator?.return(value as TOutput) ?? { done: true, value: value as TOutput };\n },\n throw: async (error?: unknown) => {\n const active = start();\n if (!active) throw new FamiliarRuntimeError('Worker batches can only be consumed once');\n controller.abort(error);\n return active.throw(error);\n },\n };\n },\n };\n}\n"],"mappings":"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"}
package/dist/_queue.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=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}}};exports.TaskQueue=e;
1
+ var e=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){let t=this.#e.findIndex(t=>t.item===e);if(t===-1)return!1;let n=this.#e.pop();if(--this.#t,t<this.#e.length){this.#e[t]=n;let e=t-1>>1;t>0&&this.#i(this.#e[t],this.#e[e])?this.#a(t):this.#o(t)}return!0}shift(){if(this.#e.length!==0)return--this.#t,this.#r().item}#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}}};exports.TaskQueue=e;
2
2
  //# sourceMappingURL=_queue.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"_queue.cjs","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,EAAb,KAAwC,CACtC,GAA2C,CAAC,EAC5C,GAAQ,EACR,GAAY,EAEZ,IAAI,MAAe,CACjB,OAAO,KAAKC,EACd,CAEA,QAAQ,EAAkC,EAAsC,CAO9E,OANI,IAAY,IAAA,IAAa,KAAKA,IAAS,EAAgB,IAE3D,KAAKD,GAAM,KAAK,CAAE,OAAM,SAAU,KAAKE,IAAY,CAAC,EACpD,KAAKC,GAAQ,KAAKH,GAAM,OAAS,CAAC,EAClC,KAAKC,IAAS,EAEP,GACT,CAEA,OAAO,EAA2C,CAChD,GAAI,EAAK,UAAW,MAAO,GAE3B,IAAK,IAAM,KAAS,KAAKD,GACvB,GAAI,EAAM,OAAS,EAIjB,MAHA,GAAK,UAAY,GACjB,OAAKC,GAEE,GAIX,MAAO,EACT,CAEA,OAAgD,CAC9C,KAAO,KAAKD,GAAM,OAAS,GAAG,CAC5B,IAAM,EAAO,KAAKI,GAAS,CAAC,CAAC,KAE7B,GAAI,CAAC,EAAK,UAGR,MAFA,OAAKH,GAEE,CAEX,CAGF,CAEA,IAAmC,CACjC,IAAM,EAAM,KAAKD,GAAM,GACjB,EAAO,KAAKA,GAAM,IAAI,EAO5B,OALI,KAAKA,GAAM,OAAS,IACtB,KAAKA,GAAM,GAAK,EAChB,KAAKK,GAAU,CAAC,GAGX,CACT,CAEA,GAAQ,EAA2B,EAAoC,CACrE,OAAO,EAAE,KAAK,WAAa,EAAE,KAAK,SAAW,EAAE,SAAW,EAAE,SAAW,EAAE,KAAK,SAAW,EAAE,KAAK,QAClG,CAEA,GAAQ,EAAqB,CAC3B,KAAO,EAAQ,GAAG,CAChB,IAAM,EAAU,EAAQ,GAAM,EAE9B,GAAI,CAAC,KAAKC,GAAQ,KAAKN,GAAM,GAAS,KAAKA,GAAM,EAAQ,EAAG,OAE5D,CAAC,KAAKA,GAAM,GAAQ,KAAKA,GAAM,IAAW,CAAC,KAAKA,GAAM,GAAU,KAAKA,GAAM,EAAO,EAClF,EAAQ,CACV,CACF,CAEA,GAAU,EAAqB,CAC7B,OAAS,CACP,IAAM,EAAO,EAAQ,EAAI,EACnB,EAAQ,EAAO,EACjB,EAAO,EAMX,GAJI,EAAO,KAAKA,GAAM,QAAU,KAAKM,GAAQ,KAAKN,GAAM,GAAQ,KAAKA,GAAM,EAAM,IAAG,EAAO,GAEvF,EAAQ,KAAKA,GAAM,QAAU,KAAKM,GAAQ,KAAKN,GAAM,GAAS,KAAKA,GAAM,EAAM,IAAG,EAAO,GAEzF,IAAS,EAAO,OAEpB,CAAC,KAAKA,GAAM,GAAQ,KAAKA,GAAM,IAAS,CAAC,KAAKA,GAAM,GAAQ,KAAKA,GAAM,EAAO,EAC9E,EAAQ,CACV,CACF,CACF"}
1
+ {"version":3,"file":"_queue.cjs","names":[],"sources":["../src/_queue.ts"],"sourcesContent":["export type QueueItem<TInput, TOutput> = {\n aborted?: 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 const index = this.#heap.findIndex((entry) => entry.item === item);\n if (index === -1) return false;\n\n const last = this.#heap.pop()!;\n this.#live -= 1;\n\n if (index < this.#heap.length) {\n this.#heap[index] = last;\n const parent = (index - 1) >> 1;\n if (index > 0 && this.#before(this.#heap[index]!, this.#heap[parent]!)) this.#siftUp(index);\n else this.#siftDown(index);\n }\n\n return true;\n }\n\n shift(): QueueItem<TInput, TOutput> | undefined {\n if (this.#heap.length === 0) return undefined;\n this.#live -= 1;\n return this.#extract().item;\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,EAAb,KAAwC,CACtC,GAA2C,CAAC,EAC5C,GAAQ,EACR,GAAY,EAEZ,IAAI,MAAe,CACjB,OAAO,KAAK,EACd,CAEA,QAAQ,EAAkC,EAAsC,CAO9E,OANI,IAAY,IAAA,IAAa,KAAK,IAAS,EAAgB,IAE3D,KAAK,GAAM,KAAK,CAAE,OAAM,SAAU,KAAK,IAAY,CAAC,EACpD,KAAK,GAAQ,KAAK,GAAM,OAAS,CAAC,EAClC,KAAK,IAAS,EAEP,GACT,CAEA,OAAO,EAA2C,CAChD,IAAM,EAAQ,KAAK,GAAM,UAAW,GAAU,EAAM,OAAS,CAAI,EACjE,GAAI,IAAU,GAAI,MAAO,GAEzB,IAAM,EAAO,KAAK,GAAM,IAAI,EAG5B,GAFA,OAAK,GAED,EAAQ,KAAK,GAAM,OAAQ,CAC7B,KAAK,GAAM,GAAS,EACpB,IAAM,EAAU,EAAQ,GAAM,EAC1B,EAAQ,GAAK,KAAK,GAAQ,KAAK,GAAM,GAAS,KAAK,GAAM,EAAQ,EAAG,KAAK,GAAQ,CAAK,EACrF,KAAK,GAAU,CAAK,CAC3B,CAEA,MAAO,EACT,CAEA,OAAgD,CAC1C,QAAK,GAAM,SAAW,EAE1B,MADA,OAAK,GACE,KAAK,GAAS,CAAC,CAAC,IACzB,CAEA,IAAmC,CACjC,IAAM,EAAM,KAAK,GAAM,GACjB,EAAO,KAAK,GAAM,IAAI,EAO5B,OALI,KAAK,GAAM,OAAS,IACtB,KAAK,GAAM,GAAK,EAChB,KAAK,GAAU,CAAC,GAGX,CACT,CAEA,GAAQ,EAA2B,EAAoC,CACrE,OAAO,EAAE,KAAK,WAAa,EAAE,KAAK,SAAW,EAAE,SAAW,EAAE,SAAW,EAAE,KAAK,SAAW,EAAE,KAAK,QAClG,CAEA,GAAQ,EAAqB,CAC3B,KAAO,EAAQ,GAAG,CAChB,IAAM,EAAU,EAAQ,GAAM,EAE9B,GAAI,CAAC,KAAK,GAAQ,KAAK,GAAM,GAAS,KAAK,GAAM,EAAQ,EAAG,OAE5D,CAAC,KAAK,GAAM,GAAQ,KAAK,GAAM,IAAW,CAAC,KAAK,GAAM,GAAU,KAAK,GAAM,EAAO,EAClF,EAAQ,CACV,CACF,CAEA,GAAU,EAAqB,CAC7B,OAAS,CACP,IAAM,EAAO,EAAQ,EAAI,EACnB,EAAQ,EAAO,EACjB,EAAO,EAMX,GAJI,EAAO,KAAK,GAAM,QAAU,KAAK,GAAQ,KAAK,GAAM,GAAQ,KAAK,GAAM,EAAM,IAAG,EAAO,GAEvF,EAAQ,KAAK,GAAM,QAAU,KAAK,GAAQ,KAAK,GAAM,GAAS,KAAK,GAAM,EAAM,IAAG,EAAO,GAEzF,IAAS,EAAO,OAEpB,CAAC,KAAK,GAAM,GAAQ,KAAK,GAAM,IAAS,CAAC,KAAK,GAAM,GAAQ,KAAK,GAAM,EAAO,EAC9E,EAAQ,CACV,CACF,CACF"}
package/dist/_queue.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type QueueItem<TInput, TOutput> = {
2
- cancelled?: boolean;
2
+ aborted?: boolean;
3
3
  cleanupAbort?: () => void;
4
4
  input: TInput;
5
5
  priority: number;
@@ -1 +1 @@
1
- {"version":3,"file":"_queue.d.ts","sourceRoot":"","sources":["../src/_queue.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,CAAC,MAAM,EAAE,OAAO,IAAI;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B,CAAC;AAIF,qBAAa,SAAS,CAAC,MAAM,EAAE,OAAO;;IAKpC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;IAU/E,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IAejD,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;CAyDhD"}
1
+ {"version":3,"file":"_queue.d.ts","sourceRoot":"","sources":["../src/_queue.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,CAAC,MAAM,EAAE,OAAO,IAAI;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B,CAAC;AAIF,qBAAa,SAAS,CAAC,MAAM,EAAE,OAAO;;IAKpC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;IAU/E,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IAiBjD,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;CAiDhD"}
package/dist/_queue.js CHANGED
@@ -13,15 +13,18 @@ var e = class {
13
13
  }), this.#a(this.#e.length - 1), this.#t += 1, !0);
14
14
  }
15
15
  remove(e) {
16
- if (e.cancelled) return !1;
17
- for (let t of this.#e) if (t.item === e) return e.cancelled = !0, --this.#t, !0;
18
- return !1;
16
+ let t = this.#e.findIndex((t) => t.item === e);
17
+ if (t === -1) return !1;
18
+ let n = this.#e.pop();
19
+ if (--this.#t, t < this.#e.length) {
20
+ this.#e[t] = n;
21
+ let e = t - 1 >> 1;
22
+ t > 0 && this.#i(this.#e[t], this.#e[e]) ? this.#a(t) : this.#o(t);
23
+ }
24
+ return !0;
19
25
  }
20
26
  shift() {
21
- for (; this.#e.length > 0;) {
22
- let e = this.#r().item;
23
- if (!e.cancelled) return --this.#t, e;
24
- }
27
+ if (this.#e.length !== 0) return --this.#t, this.#r().item;
25
28
  }
26
29
  #r() {
27
30
  let e = this.#e[0], t = this.#e.pop();
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"_queue.js","names":[],"sources":["../src/_queue.ts"],"sourcesContent":["export type QueueItem<TInput, TOutput> = {\n aborted?: 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 const index = this.#heap.findIndex((entry) => entry.item === item);\n if (index === -1) return false;\n\n const last = this.#heap.pop()!;\n this.#live -= 1;\n\n if (index < this.#heap.length) {\n this.#heap[index] = last;\n const parent = (index - 1) >> 1;\n if (index > 0 && this.#before(this.#heap[index]!, this.#heap[parent]!)) this.#siftUp(index);\n else this.#siftDown(index);\n }\n\n return true;\n }\n\n shift(): QueueItem<TInput, TOutput> | undefined {\n if (this.#heap.length === 0) return undefined;\n this.#live -= 1;\n return this.#extract().item;\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,KAAK;CACd;CAEA,QAAQ,GAAkC,GAAsC;EAO9E,OANI,MAAY,KAAA,KAAa,KAAK,MAAS,IAAgB,MAE3D,KAAK,GAAM,KAAK;GAAE;GAAM,UAAU,KAAK;EAAY,CAAC,GACpD,KAAK,GAAQ,KAAK,GAAM,SAAS,CAAC,GAClC,KAAK,MAAS,GAEP;CACT;CAEA,OAAO,GAA2C;EAChD,IAAM,IAAQ,KAAK,GAAM,WAAW,MAAU,EAAM,SAAS,CAAI;EACjE,IAAI,MAAU,IAAI,OAAO;EAEzB,IAAM,IAAO,KAAK,GAAM,IAAI;EAG5B,IAFA,OAAK,IAED,IAAQ,KAAK,GAAM,QAAQ;GAC7B,KAAK,GAAM,KAAS;GACpB,IAAM,IAAU,IAAQ,KAAM;GAC9B,AAAI,IAAQ,KAAK,KAAK,GAAQ,KAAK,GAAM,IAAS,KAAK,GAAM,EAAQ,IAAG,KAAK,GAAQ,CAAK,IACrF,KAAK,GAAU,CAAK;EAC3B;EAEA,OAAO;CACT;CAEA,QAAgD;EAC1C,SAAK,GAAM,WAAW,GAE1B,OADA,OAAK,IACE,KAAK,GAAS,CAAC,CAAC;CACzB;CAEA,KAAmC;EACjC,IAAM,IAAM,KAAK,GAAM,IACjB,IAAO,KAAK,GAAM,IAAI;EAO5B,OALI,KAAK,GAAM,SAAS,MACtB,KAAK,GAAM,KAAK,GAChB,KAAK,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,KAAK,GAAQ,KAAK,GAAM,IAAS,KAAK,GAAM,EAAQ,GAAG;GAG5D,AADA,CAAC,KAAK,GAAM,IAAQ,KAAK,GAAM,MAAW,CAAC,KAAK,GAAM,IAAU,KAAK,GAAM,EAAO,GAClF,IAAQ;EACV;CACF;CAEA,GAAU,GAAqB;EAC7B,SAAS;GACP,IAAM,IAAO,IAAQ,IAAI,GACnB,IAAQ,IAAO,GACjB,IAAO;GAMX,IAJI,IAAO,KAAK,GAAM,UAAU,KAAK,GAAQ,KAAK,GAAM,IAAQ,KAAK,GAAM,EAAM,MAAG,IAAO,IAEvF,IAAQ,KAAK,GAAM,UAAU,KAAK,GAAQ,KAAK,GAAM,IAAS,KAAK,GAAM,EAAM,MAAG,IAAO,IAEzF,MAAS,GAAO;GAGpB,AADA,CAAC,KAAK,GAAM,IAAQ,KAAK,GAAM,MAAS,CAAC,KAAK,GAAM,IAAQ,KAAK,GAAM,EAAO,GAC9E,IAAQ;EACV;CACF;AACF"}
@@ -1,2 +1,2 @@
1
- const e=require("./_timers.cjs"),t=require("./errors.cjs");let n=require("@vielzeug/arsenal/async");function r(r,i){let a=[...r],o=[],s=[],c=new AbortController,l=[],u=0,d=0,f=0,p=0,m=!1,h;function g(){return u===0&&o.length===0}function _(){if(g())for(let e of l.splice(0))e()}function v(n){return g()?Promise.resolve():new Promise((r,i)=>{if(l.push(r),n.timeout!==void 0){let a=setTimeout(()=>{let e=l.indexOf(r);e!==-1&&l.splice(e,1),i(new t.FamiliarTimeoutError(n.timeout))},n.timeout);e.unrefTimer(a)}})}function y(){s.shift()?.resolve()}function b(e){for(let t of s.splice(0))t.reject(e)}function x(e){return e?.aborted?Promise.reject((0,n.abortError)(e)):new Promise((t,r)=>{let i=!1,a={cleanup(){e?.removeEventListener(`abort`,o)},reject(e){if(i)return;i=!0,a.cleanup();let t=s.indexOf(a);t!==-1&&s.splice(t,1),r(e)},resolve(){i||(i=!0,a.cleanup(),t())}},o=()=>a.reject((0,n.abortError)(e));e?.addEventListener(`abort`,o,{once:!0}),s.push(a)})}function S(e){let t=o.shift();t?(t.resolve(e),y()):a.push(e)}async function C(e){if(m)throw new t.FamiliarTerminatedError;if(h)throw new t.FamiliarTerminatedError(`Worker is draining`);if(e.signal?.aborted)throw(0,n.abortError)(e.signal);for(;i.maxQueue!==void 0&&o.length>=i.maxQueue;){if(i.onFull===`reject`)throw new t.FamiliarQueueFullError(i.maxQueue);if(await x(e.signal),m)throw new t.FamiliarTerminatedError;if(h)throw new t.FamiliarTerminatedError(`Worker is draining`);if(e.signal?.aborted)throw(0,n.abortError)(e.signal)}return a.pop()||new Promise((t,r)=>{let i={cleanup(){i.signal?.removeEventListener(`abort`,a)},priority:e.priority??0,reject(e){i.cleanup();let t=o.indexOf(i);t!==-1&&(o.splice(t,1),y()),r(e),_()},resolve(e){i.cleanup(),t(e)},sequence:p++,signal:e.signal},a=()=>i.reject((0,n.abortError)(i.signal));i.signal?.addEventListener(`abort`,a,{once:!0}),o.push(i),o.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}function w(){if(!m){m=!0,c.abort();for(let e of r)e.terminate();for(let e of o.splice(0))e.reject(new t.FamiliarTerminatedError);b(new t.FamiliarTerminatedError),_()}}function T(e={}){if(m)return Promise.resolve();if(h)return h;for(let e of o.splice(0))e.reject(new t.FamiliarTerminatedError(`Worker is draining`));return b(new t.FamiliarTerminatedError(`Worker is draining`)),h=v(e).then(()=>w(),e=>{throw w(),e}),h}return{get disposalSignal(){return c.signal},dispose:w,get disposed(){return m},drain:T,async prime(){await Promise.all(r.map(e=>e.prime()))},runStream(e,r={}){let a=new AbortController,o=()=>a.abort(r.signal?.reason);return r.signal?.addEventListener(`abort`,o,{once:!0}),{[Symbol.asyncIterator]:async function*(){let s,c;try{s=await C({...r,signal:a.signal}),u+=1,c=()=>s?.cancel((0,n.abortError)(a.signal)),a.signal.addEventListener(`abort`,c,{once:!0});let t=s.stream(e,{...r,signal:a.signal,timeout:r.timeout??i.defaultTimeout});for await(let e of t.iterable)yield e;await t.done,d+=1}catch(e){throw e?.constructor?.name!==`AbortError`&&!(e instanceof t.FamiliarTerminatedError)&&(f+=1),e}finally{r.signal?.removeEventListener(`abort`,o),s&&(c&&a.signal.removeEventListener(`abort`,c),--u,S(s),_())}}}},get stats(){return{active:u,completed:d,failed:f,queued:o.length}},get status(){return m?`terminated`:u===0?`idle`:`running`},[Symbol.asyncDispose]:()=>T(),[Symbol.dispose]:w}}exports.createStreamPool=r;
1
+ const e=require("./errors.cjs"),t=require("./_pool-core.cjs");let n=require("@vielzeug/arsenal");function r(r,i){let a=[...r],o=[],s=0,c=t.createPoolCore({isIdle:()=>a.length===r.length&&o.length===0,onDispose(){for(let e of r)e.terminate();for(let t of o.splice(0))t.reject(new e.FamiliarTerminatedError)},onDrainStart(){for(let t of o.splice(0))t.reject(new e.FamiliarTerminatedError(`Worker is draining`))}});function l(e){let t=o.shift();t?(t.resolve(e),c.releaseCapacity()):a.push(e)}async function u(t){if(c.disposed)throw new e.FamiliarTerminatedError;if(c.drainPromise)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 c.waitForCapacity(t.signal,t.priority??0),c.disposed)throw new e.FamiliarTerminatedError;if(c.drainPromise)throw new e.FamiliarTerminatedError(`Worker is draining`);if(t.signal?.aborted)throw c.releaseCapacity(),(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),c.releaseCapacity()),r(e),c.settleIdle()},resolve(t){i.cleanup(),e(t)},sequence:s++,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)})}return{get disposalSignal(){return c.disposalSignal},dispose:c.dispose,get disposed(){return c.disposed},drain:c.drain,runStream(r,a={}){let o=t.validatePriority(a.priority??0),s=t.validateTimeout(a.timeout)??i.defaultTimeout,d=[...a.transferables??[]],f,p=async function*(t){let i=()=>t.abort(a.signal?.reason),f,p;a.signal?.aborted?t.abort(a.signal.reason):a.signal?.addEventListener(`abort`,i,{once:!0});try{f=await u({priority:o,signal:t.signal,timeout:s,transferables:d}),c.trackActive(1),p=()=>f?.cancel((0,n.abortError)(t.signal)),t.signal.addEventListener(`abort`,p,{once:!0});let e=f.stream(r,{priority:o,signal:t.signal,timeout:s,transferables:d});for await(let t of e.iterable)yield t;await e.done,c.trackCompleted()}catch(n){throw f&&!t.signal.aborted&&!(n instanceof e.FamiliarTerminatedError)&&c.trackFailed(),n}finally{a.signal?.removeEventListener(`abort`,i),f&&(p&&t.signal.removeEventListener(`abort`,p),c.trackActive(-1),l(f),c.settleIdle())}};return{[Symbol.asyncIterator](){let t={},n=new AbortController,r,i=()=>{if(f??=t,f===t)return r??=p(n),r};return{next:()=>i()?.next()??Promise.reject(new e.FamiliarRuntimeError(`Worker streams can only be consumed once`)),return:async i=>!f||f!==t?{done:!0,value:i}:(n.abort(new e.FamiliarTerminatedError(`Stream consumer stopped`)),r?.return(i)??{done:!0,value:i}),throw:async t=>{let r=i();if(!r)throw new e.FamiliarRuntimeError(`Worker streams can only be consumed once`);return n.abort(t),r.throw(t)}}}}},get stats(){return c.stats(o.length)},get status(){return c.status()},[Symbol.asyncDispose]:()=>c.drain({}),[Symbol.dispose]:c.dispose}}exports.createStreamPool=r;
2
2
  //# sourceMappingURL=_stream-pool.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"_stream-pool.cjs","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport type { PoolOptions } from './_pool';\nimport { unrefTimer } from './_timers';\nimport { FamiliarQueueFullError, FamiliarTerminatedError, FamiliarTimeoutError } from './errors';\nimport type { DrainOptions, RunOptions, StreamWorkerPool, WorkerStats, WorkerStatus } from './types';\nimport type { RunningStream } from './worker';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n prime(): Promise<void>;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype CapacityWaiter = {\n cleanup(): void;\n reject(reason: unknown): void;\n resolve(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n const capacityWaiters: CapacityWaiter[] = [];\n const disposalController = new AbortController();\n const idleWaiters: Array<() => void> = [];\n let active = 0;\n let completed = 0;\n let failed = 0;\n let sequence = 0;\n let terminated = false;\n let drainPromise: Promise<void> | undefined;\n\n function idle(): boolean {\n return active === 0 && waiters.length === 0;\n }\n\n function settleIdle(): void {\n if (!idle()) return;\n\n for (const resolve of idleWaiters.splice(0)) resolve();\n }\n\n function waitForIdle(options: DrainOptions): Promise<void> {\n if (idle()) return Promise.resolve();\n\n return new Promise<void>((resolve, reject) => {\n idleWaiters.push(resolve);\n\n if (options.timeout !== undefined) {\n const timer = setTimeout(() => {\n const index = idleWaiters.indexOf(resolve);\n\n if (index !== -1) idleWaiters.splice(index, 1);\n\n reject(new FamiliarTimeoutError(options.timeout!));\n }, options.timeout);\n\n unrefTimer(timer);\n }\n });\n }\n\n function releaseCapacity(): void {\n capacityWaiters.shift()?.resolve();\n }\n\n function rejectCapacity(reason: unknown): void {\n for (const waiter of capacityWaiters.splice(0)) waiter.reject(reason);\n }\n\n function waitForCapacity(signal: AbortSignal | undefined): Promise<void> {\n if (signal?.aborted) return Promise.reject(abortError(signal));\n\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const waiter: CapacityWaiter = {\n cleanup() {\n signal?.removeEventListener('abort', onAbort);\n },\n reject(reason) {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n\n const index = capacityWaiters.indexOf(waiter);\n\n if (index !== -1) capacityWaiters.splice(index, 1);\n\n reject(reason);\n },\n resolve() {\n if (settled) return;\n\n settled = true;\n waiter.cleanup();\n resolve();\n },\n };\n const onAbort = () => waiter.reject(abortError(signal!));\n\n signal?.addEventListener('abort', onAbort, { once: true });\n capacityWaiters.push(waiter);\n });\n }\n\n function release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await waitForCapacity(runOptions.signal);\n\n if (terminated) throw new FamiliarTerminatedError();\n\n if (drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n releaseCapacity();\n }\n\n reject(reason);\n settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\n }\n\n function dispose(): void {\n if (terminated) return;\n\n terminated = true;\n disposalController.abort();\n for (const slot of slots) slot.terminate();\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n rejectCapacity(new FamiliarTerminatedError());\n settleIdle();\n }\n\n function drain(drainOptions: DrainOptions = {}): Promise<void> {\n if (terminated) return Promise.resolve();\n\n if (drainPromise) return drainPromise;\n\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\n rejectCapacity(new FamiliarTerminatedError('Worker is draining'));\n drainPromise = waitForIdle(drainOptions).then(\n () => dispose(),\n (error: unknown) => {\n dispose();\n throw error;\n },\n );\n\n return drainPromise;\n }\n\n return {\n get disposalSignal() {\n return disposalController.signal;\n },\n dispose,\n get disposed() {\n return terminated;\n },\n drain,\n async prime(): Promise<void> {\n await Promise.all(slots.map((slot) => slot.prime()));\n },\n runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(runOptions.signal?.reason);\n\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n [Symbol.asyncIterator]: async function* () {\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n try {\n slot = await acquire({ ...runOptions, signal: controller.signal });\n active += 1;\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, {\n ...runOptions,\n signal: controller.signal,\n timeout: runOptions.timeout ?? options.defaultTimeout,\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n completed += 1;\n } catch (error) {\n if (error?.constructor?.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError)) failed += 1;\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n active -= 1;\n release(slot);\n settleIdle();\n }\n }\n },\n };\n },\n get stats(): WorkerStats {\n return { active, completed, failed, queued: waiters.length };\n },\n get status(): WorkerStatus {\n if (terminated) return 'terminated';\n\n return active === 0 ? 'idle' : 'running';\n },\n [Symbol.asyncDispose]: () => drain(),\n [Symbol.dispose]: dispose,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"_stream-pool.cjs","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal';\nimport { createPoolCore, type PoolCore, type PoolOptions, validatePriority, validateTimeout } from './_pool-core.js';\nimport { FamiliarQueueFullError, FamiliarRuntimeError, FamiliarTerminatedError } from './errors.js';\nimport type { RunOptions, StreamWorkerPool } from './types.js';\nimport type { RunningStream } from './worker.js';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n let sequence = 0;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && waiters.length === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n },\n onDrainStart() {\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\n },\n });\n\n function release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n core.releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await core.waitForCapacity(runOptions.signal, runOptions.priority ?? 0);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) {\n core.releaseCapacity();\n throw abortError(runOptions.signal);\n }\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n core.releaseCapacity();\n }\n\n reject(reason);\n core.settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const priority = validatePriority(runOptions.priority ?? 0);\n const timeout = validateTimeout(runOptions.timeout) ?? options.defaultTimeout;\n const transferables = [...(runOptions.transferables ?? [])];\n let owner: object | undefined;\n\n const iterate = async function* (controller: AbortController): AsyncGenerator<TChunk> {\n const onAbort = () => controller.abort(runOptions.signal?.reason);\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n if (runOptions.signal?.aborted) controller.abort(runOptions.signal.reason);\n else runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n slot = await acquire({ priority, signal: controller.signal, timeout, transferables });\n core.trackActive(1);\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, { priority, signal: controller.signal, timeout, transferables });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n core.trackCompleted();\n } catch (error) {\n if (slot && !controller.signal.aborted && !(error instanceof FamiliarTerminatedError)) core.trackFailed();\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n core.trackActive(-1);\n release(slot);\n core.settleIdle();\n }\n }\n };\n\n return {\n [Symbol.asyncIterator]() {\n const token = {};\n const controller = new AbortController();\n let iterator: AsyncGenerator<TChunk> | undefined;\n const start = (): AsyncGenerator<TChunk> | undefined => {\n owner ??= token;\n if (owner !== token) return undefined;\n iterator ??= iterate(controller);\n return iterator;\n };\n\n return {\n next: () =>\n start()?.next() ?? Promise.reject(new FamiliarRuntimeError('Worker streams can only be consumed once')),\n return: async (value?: unknown) => {\n if (!owner) return { done: true, value: value as TChunk };\n if (owner !== token) return { done: true, value: value as TChunk };\n controller.abort(new FamiliarTerminatedError('Stream consumer stopped'));\n return iterator?.return(value as TChunk) ?? { done: true, value: value as TChunk };\n },\n throw: async (error?: unknown) => {\n const active = start();\n if (!active) throw new FamiliarRuntimeError('Worker streams can only be consumed once');\n controller.abort(error);\n return active.throw(error);\n },\n };\n },\n };\n },\n get stats() {\n return core.stats(waiters.length);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n"],"mappings":"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"}
@@ -1,9 +1,8 @@
1
- import type { PoolOptions } from './_pool';
2
- import type { RunOptions, StreamWorkerPool } from './types';
3
- import type { RunningStream } from './worker';
1
+ import { type PoolOptions } from './_pool-core.js';
2
+ import type { RunOptions, StreamWorkerPool } from './types.js';
3
+ import type { RunningStream } from './worker.js';
4
4
  export type StreamSlot<TInput, TChunk> = {
5
5
  cancel(reason: unknown): void;
6
- prime(): Promise<void>;
7
6
  stream(input: TInput, options: RunOptions): RunningStream<TChunk>;
8
7
  terminate(): void;
9
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"_stream-pool.d.ts","sourceRoot":"","sources":["../src/_stream-pool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,OAAO,KAAK,EAAgB,UAAU,EAAE,gBAAgB,EAA6B,MAAM,SAAS,CAAC;AACrG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,MAAM,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI;IACvC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClE,SAAS,IAAI,IAAI,CAAC;CACnB,CAAC;AAiBF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAC7C,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EACnC,OAAO,EAAE,WAAW,GACnB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CA2PlC"}
1
+ {"version":3,"file":"_stream-pool.d.ts","sourceRoot":"","sources":["../src/_stream-pool.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,KAAK,WAAW,EAAqC,MAAM,iBAAiB,CAAC;AAErH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI;IACvC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClE,SAAS,IAAI,IAAI,CAAC;CACnB,CAAC;AAWF,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,CAmLlC"}