@praxisjs/concurrent 0.2.2 → 0.2.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @praxisjs/concurrent
2
2
 
3
+ ## 0.2.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [d11a10a]
8
+ - @praxisjs/core@0.4.2
9
+
3
10
  ## 0.2.2
4
11
 
5
12
  ### Patch Changes
@@ -1,4 +1,4 @@
1
- import { describe, it, expect } from "vitest";
1
+ import { describe, it, expect, vi } from "vitest";
2
2
  import { pool } from "../pool";
3
3
  describe("pool", () => {
4
4
  it("executes a task and resolves with its result", async () => {
@@ -60,5 +60,67 @@ describe("pool", () => {
60
60
  await t2;
61
61
  expect(p.pending()).toBe(0);
62
62
  });
63
+ it("wraps non-Error throws in an Error object", async () => {
64
+ const p = pool(1, async () => {
65
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
66
+ throw "plain string error";
67
+ });
68
+ const result = await p();
69
+ expect(result).toBeUndefined();
70
+ expect(p.error()).toBeInstanceOf(Error);
71
+ expect(p.error()?.message).toBe("plain string error");
72
+ });
73
+ it("concurrency=1 guarantees serial execution", async () => {
74
+ const order = [];
75
+ let resolveFirst;
76
+ const p = pool(1, async (n) => {
77
+ if (n === 0)
78
+ await new Promise((r) => { resolveFirst = r; });
79
+ order.push(n);
80
+ });
81
+ const t1 = p(0);
82
+ const t2 = p(1);
83
+ // t2 cannot start until t1 finishes
84
+ expect(p.active()).toBe(1);
85
+ expect(p.pending()).toBe(1);
86
+ resolveFirst();
87
+ await t1;
88
+ await t2;
89
+ expect(order).toEqual([0, 1]); // serial order preserved
90
+ });
91
+ it("error in one task does not block subsequent tasks", async () => {
92
+ const results = [];
93
+ const p = pool(1, async (n) => {
94
+ if (n === 0)
95
+ throw new Error("task 0 failed");
96
+ return n;
97
+ });
98
+ const r0 = p(0);
99
+ const r1 = p(1);
100
+ results.push(await r0);
101
+ results.push(await r1);
102
+ expect(results[0]).toBeUndefined(); // error → undefined
103
+ expect(results[1]).toBe(1); // subsequent task ran
104
+ });
105
+ it("concurrency=0 — tasks are enqueued but never executed", async () => {
106
+ const fn = vi.fn(async () => "result");
107
+ const p = pool(0, fn);
108
+ // Queue a task — tryRun() bails immediately because _active(0) >= concurrency(0)
109
+ void p();
110
+ await new Promise((r) => setTimeout(r, 0));
111
+ expect(fn).not.toHaveBeenCalled();
112
+ expect(p.pending()).toBe(1);
113
+ expect(p.loading()).toBe(false);
114
+ });
115
+ it("active() never exceeds concurrency", async () => {
116
+ const concurrency = 2;
117
+ let maxObservedActive = 0;
118
+ const p = pool(concurrency, async () => {
119
+ maxObservedActive = Math.max(maxObservedActive, p.active());
120
+ await new Promise((r) => setTimeout(r, 5));
121
+ });
122
+ await Promise.all([p(), p(), p(), p()]);
123
+ expect(maxObservedActive).toBeLessThanOrEqual(concurrency);
124
+ });
63
125
  });
64
126
  //# sourceMappingURL=pool.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pool.test.js","sourceRoot":"","sources":["../../src/__tests__/pool.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAU,EAAE,EAAE,CAAE,CAAY,GAAG,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;YAC3B,MAAM,EAAE,CAAC;YACT,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACxC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,SAAS,GAAsB,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,CACZ,CAAC,EACD,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAClD,CAAC;QAEF,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3B,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,IAAI,OAAoB,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CACZ,CAAC,EACD,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CACjD,CAAC;QACF,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC;QACjB,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,EAAE,CAAC;QACV,MAAM,IAAI,CAAC;QACX,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,IAAI,YAAyB,CAAC;QAC9B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE;YACvC,OAAO,CAAC,IAAI,CAAC,GAAa,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,CAAC;gBAAE,MAAM,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhB,0CAA0C;QAC1C,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,CAAC;QACT,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"pool.test.js","sourceRoot":"","sources":["../../src/__tests__/pool.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAU,EAAE,EAAE,CAAE,CAAY,GAAG,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;YAC3B,MAAM,EAAE,CAAC;YACT,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACxC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,SAAS,GAAsB,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,CACZ,CAAC,EACD,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAClD,CAAC;QAEF,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3B,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,IAAI,OAAoB,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CACZ,CAAC,EACD,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CACjD,CAAC;QACF,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC;QACjB,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,EAAE,CAAC;QACV,MAAM,IAAI,CAAC;QACX,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,IAAI,YAAyB,CAAC;QAC9B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE;YACvC,OAAO,CAAC,IAAI,CAAC,GAAa,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,CAAC;gBAAE,MAAM,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhB,0CAA0C;QAC1C,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,CAAC;QACT,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;YAC3B,+DAA+D;YAC/D,MAAM,oBAAoB,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,YAAyB,CAAC;QAE9B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAU,EAAE,EAAE;YACrC,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnE,KAAK,CAAC,IAAI,CAAC,CAAW,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhB,oCAAoC;QACpC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE5B,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,CAAC;QAET,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,OAAO,GAA8B,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAU,EAAE,EAAE;YACrC,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;YAC9C,OAAO,CAAW,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhB,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAEvB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,oBAAoB;QACxD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAS,sBAAsB;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEtB,iFAAiF;QACjF,KAAK,CAAC,EAAE,CAAC;QACT,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAE3C,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,WAAW,GAAG,CAAC,CAAC;QACtB,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAE1B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;YACrC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5D,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,iBAAiB,CAAC,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -45,6 +45,28 @@ describe("queue", () => {
45
45
  await expect(q()).rejects.toThrow("boom");
46
46
  expect(q.error()?.message).toBe("boom");
47
47
  });
48
+ it("wraps non-Error throws in an Error", async () => {
49
+ const q = queue(async () => {
50
+ // eslint-disable-next-line @typescript-eslint/no-throw-literal
51
+ throw "string error";
52
+ });
53
+ await expect(q()).rejects.toThrow("string error");
54
+ expect(q.error()?.message).toBe("string error");
55
+ });
56
+ it("error in one task does not prevent subsequent tasks from running", async () => {
57
+ const q = queue(async (n) => {
58
+ if (n === 0)
59
+ throw new Error("task 0 failed");
60
+ return n;
61
+ });
62
+ const p0 = q(0); // will reject
63
+ const p1 = q(1); // should still run despite p0 failing
64
+ const p2 = q(2);
65
+ await expect(p0).rejects.toThrow("task 0 failed");
66
+ expect(await p1).toBe(1);
67
+ expect(await p2).toBe(2);
68
+ expect(q.error()?.message).toBe("task 0 failed");
69
+ });
48
70
  it("clear() empties the pending queue", async () => {
49
71
  let resolveFirst;
50
72
  const q = queue((_, idx) => idx === 0
@@ -1 +1 @@
1
- {"version":3,"file":"queue.test.js","sourceRoot":"","sources":["../../src/__tests__/queue.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queue.test.js","sourceRoot":"","sources":["../../src/__tests__/queue.test.ts"],"names":[],"mappings":"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"}
@@ -51,5 +51,63 @@ describe("task", () => {
51
51
  expect(result).toBeUndefined();
52
52
  expect(t.loading()).toBe(false);
53
53
  });
54
+ it("cancelAll() during a failing task discards the error", async () => {
55
+ let reject;
56
+ const t = task(() => new Promise((_res, rej) => { reject = rej; }));
57
+ const p = t();
58
+ t.cancelAll();
59
+ reject(new Error("cancelled"));
60
+ const result = await p;
61
+ // The error was from a stale run — result is undefined, no error stored
62
+ expect(result).toBeUndefined();
63
+ expect(t.error()).toBeNull();
64
+ });
65
+ it("wraps non-Error throws in an Error object", async () => {
66
+ const t = task(async () => {
67
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
68
+ throw "string-error";
69
+ });
70
+ const result = await t();
71
+ expect(result).toBeUndefined();
72
+ expect(t.error()).toBeInstanceOf(Error);
73
+ expect(t.error()?.message).toBe("string-error");
74
+ });
75
+ it("second run while first is pending discards the first result", async () => {
76
+ let resolveFirst;
77
+ let resolveSecond;
78
+ const t = task((_run) => (_run === 1
79
+ ? new Promise((r) => { resolveFirst = r; })
80
+ : new Promise((r) => { resolveSecond = r; })));
81
+ let run = 1;
82
+ const p1 = t(run++); // run 1
83
+ const p2 = t(run++); // run 2 — increments _runId, making run 1 stale
84
+ resolveSecond("result-2");
85
+ resolveFirst("result-1"); // stale
86
+ const [r1, r2] = await Promise.all([p1, p2]);
87
+ expect(r2).toBe("result-2");
88
+ expect(r1).toBeUndefined(); // stale run discarded
89
+ expect(t.lastResult()).toBe("result-2");
90
+ });
91
+ it("synchronous function (non-async) resolves correctly via await", async () => {
92
+ // await on a non-Promise simply resolves the value
93
+ const t = task((() => 42));
94
+ const result = await t();
95
+ expect(result).toBe(42);
96
+ expect(t.lastResult()).toBe(42);
97
+ expect(t.loading()).toBe(false);
98
+ });
99
+ it("cancelAll() followed by a new run works correctly", async () => {
100
+ const t = task(async () => "fresh");
101
+ let resolve;
102
+ const staleTask = task(() => new Promise((r) => { resolve = r; }));
103
+ const p = staleTask();
104
+ staleTask.cancelAll();
105
+ resolve("stale");
106
+ await p;
107
+ // Now run a fresh task after cancelAll
108
+ const result = await t();
109
+ expect(result).toBe("fresh");
110
+ expect(t.loading()).toBe(false);
111
+ });
54
112
  });
55
113
  //# sourceMappingURL=task.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"task.test.js","sourceRoot":"","sources":["../../src/__tests__/task.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task.test.js","sourceRoot":"","sources":["../../src/__tests__/task.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisjs/concurrent",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -14,7 +14,7 @@
14
14
  "typescript": "^5.9.3"
15
15
  },
16
16
  "dependencies": {
17
- "@praxisjs/core": "0.4.1",
17
+ "@praxisjs/core": "0.4.2",
18
18
  "@praxisjs/shared": "0.2.0"
19
19
  },
20
20
  "scripts": {
@@ -1,4 +1,4 @@
1
- import { describe, it, expect } from "vitest";
1
+ import { describe, it, expect, vi } from "vitest";
2
2
 
3
3
  import { pool } from "../pool";
4
4
 
@@ -77,4 +77,81 @@ describe("pool", () => {
77
77
  await t2;
78
78
  expect(p.pending()).toBe(0);
79
79
  });
80
+
81
+ it("wraps non-Error throws in an Error object", async () => {
82
+ const p = pool(1, async () => {
83
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
84
+ throw "plain string error";
85
+ });
86
+ const result = await p();
87
+ expect(result).toBeUndefined();
88
+ expect(p.error()).toBeInstanceOf(Error);
89
+ expect(p.error()?.message).toBe("plain string error");
90
+ });
91
+
92
+ it("concurrency=1 guarantees serial execution", async () => {
93
+ const order: number[] = [];
94
+ let resolveFirst!: () => void;
95
+
96
+ const p = pool(1, async (n: unknown) => {
97
+ if (n === 0) await new Promise<void>((r) => { resolveFirst = r; });
98
+ order.push(n as number);
99
+ });
100
+
101
+ const t1 = p(0);
102
+ const t2 = p(1);
103
+
104
+ // t2 cannot start until t1 finishes
105
+ expect(p.active()).toBe(1);
106
+ expect(p.pending()).toBe(1);
107
+
108
+ resolveFirst();
109
+ await t1;
110
+ await t2;
111
+
112
+ expect(order).toEqual([0, 1]); // serial order preserved
113
+ });
114
+
115
+ it("error in one task does not block subsequent tasks", async () => {
116
+ const results: Array<number | undefined> = [];
117
+ const p = pool(1, async (n: unknown) => {
118
+ if (n === 0) throw new Error("task 0 failed");
119
+ return n as number;
120
+ });
121
+
122
+ const r0 = p(0);
123
+ const r1 = p(1);
124
+
125
+ results.push(await r0);
126
+ results.push(await r1);
127
+
128
+ expect(results[0]).toBeUndefined(); // error → undefined
129
+ expect(results[1]).toBe(1); // subsequent task ran
130
+ });
131
+
132
+ it("concurrency=0 — tasks are enqueued but never executed", async () => {
133
+ const fn = vi.fn(async () => "result");
134
+ const p = pool(0, fn);
135
+
136
+ // Queue a task — tryRun() bails immediately because _active(0) >= concurrency(0)
137
+ void p();
138
+ await new Promise((r) => setTimeout(r, 0));
139
+
140
+ expect(fn).not.toHaveBeenCalled();
141
+ expect(p.pending()).toBe(1);
142
+ expect(p.loading()).toBe(false);
143
+ });
144
+
145
+ it("active() never exceeds concurrency", async () => {
146
+ const concurrency = 2;
147
+ let maxObservedActive = 0;
148
+
149
+ const p = pool(concurrency, async () => {
150
+ maxObservedActive = Math.max(maxObservedActive, p.active());
151
+ await new Promise((r) => setTimeout(r, 5));
152
+ });
153
+
154
+ await Promise.all([p(), p(), p(), p()]);
155
+ expect(maxObservedActive).toBeLessThanOrEqual(concurrency);
156
+ });
80
157
  });
@@ -61,6 +61,31 @@ describe("queue", () => {
61
61
  expect(q.error()?.message).toBe("boom");
62
62
  });
63
63
 
64
+ it("wraps non-Error throws in an Error", async () => {
65
+ const q = queue(async () => {
66
+ // eslint-disable-next-line @typescript-eslint/no-throw-literal
67
+ throw "string error";
68
+ });
69
+ await expect(q()).rejects.toThrow("string error");
70
+ expect(q.error()?.message).toBe("string error");
71
+ });
72
+
73
+ it("error in one task does not prevent subsequent tasks from running", async () => {
74
+ const q = queue(async (n: unknown) => {
75
+ if (n === 0) throw new Error("task 0 failed");
76
+ return n as number;
77
+ });
78
+
79
+ const p0 = q(0); // will reject
80
+ const p1 = q(1); // should still run despite p0 failing
81
+ const p2 = q(2);
82
+
83
+ await expect(p0).rejects.toThrow("task 0 failed");
84
+ expect(await p1).toBe(1);
85
+ expect(await p2).toBe(2);
86
+ expect(q.error()?.message).toBe("task 0 failed");
87
+ });
88
+
64
89
  it("clear() empties the pending queue", async () => {
65
90
  let resolveFirst!: () => void;
66
91
  const q = queue(
@@ -61,4 +61,77 @@ describe("task", () => {
61
61
  expect(result).toBeUndefined();
62
62
  expect(t.loading()).toBe(false);
63
63
  });
64
+
65
+ it("cancelAll() during a failing task discards the error", async () => {
66
+ let reject!: (err: unknown) => void;
67
+ const t = task(() => new Promise<string>((_res, rej) => { reject = rej; }));
68
+
69
+ const p = t();
70
+ t.cancelAll();
71
+ reject(new Error("cancelled"));
72
+ const result = await p;
73
+
74
+ // The error was from a stale run — result is undefined, no error stored
75
+ expect(result).toBeUndefined();
76
+ expect(t.error()).toBeNull();
77
+ });
78
+
79
+ it("wraps non-Error throws in an Error object", async () => {
80
+ const t = task(async () => {
81
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
82
+ throw "string-error";
83
+ });
84
+ const result = await t();
85
+ expect(result).toBeUndefined();
86
+ expect(t.error()).toBeInstanceOf(Error);
87
+ expect(t.error()?.message).toBe("string-error");
88
+ });
89
+
90
+ it("second run while first is pending discards the first result", async () => {
91
+ let resolveFirst!: (v: string) => void;
92
+ let resolveSecond!: (v: string) => void;
93
+
94
+ const t = task((_run: unknown) =>
95
+ (_run === 1
96
+ ? new Promise<string>((r) => { resolveFirst = r; })
97
+ : new Promise<string>((r) => { resolveSecond = r; })),
98
+ );
99
+
100
+ let run = 1;
101
+ const p1 = t(run++); // run 1
102
+ const p2 = t(run++); // run 2 — increments _runId, making run 1 stale
103
+
104
+ resolveSecond("result-2");
105
+ resolveFirst("result-1"); // stale
106
+
107
+ const [r1, r2] = await Promise.all([p1, p2]);
108
+ expect(r2).toBe("result-2");
109
+ expect(r1).toBeUndefined(); // stale run discarded
110
+ expect(t.lastResult()).toBe("result-2");
111
+ });
112
+
113
+ it("synchronous function (non-async) resolves correctly via await", async () => {
114
+ // await on a non-Promise simply resolves the value
115
+ const t = task((() => 42) as unknown as () => Promise<number>);
116
+ const result = await t();
117
+ expect(result).toBe(42);
118
+ expect(t.lastResult()).toBe(42);
119
+ expect(t.loading()).toBe(false);
120
+ });
121
+
122
+ it("cancelAll() followed by a new run works correctly", async () => {
123
+ const t = task(async () => "fresh");
124
+ let resolve!: (v: string) => void;
125
+ const staleTask = task(() => new Promise<string>((r) => { resolve = r; }));
126
+
127
+ const p = staleTask();
128
+ staleTask.cancelAll();
129
+ resolve("stale");
130
+ await p;
131
+
132
+ // Now run a fresh task after cancelAll
133
+ const result = await t();
134
+ expect(result).toBe("fresh");
135
+ expect(t.loading()).toBe(false);
136
+ });
64
137
  });