Offload functions to worker threads with shared memory primitives for Node.js.
1import { describe, it } from 'node:test';
2import assert from 'node:assert/strict';
3import { workers, assign, channel } from 'moroutine';
4import { identity, countUp } from './fixtures/worker-handle.ts';
5
6describe('WorkerHandle', () => {
7 it('run.workers is a frozen array matching pool size', () => {
8 const run = workers(3);
9 try {
10 assert.equal(run.workers.length, 3);
11 assert.ok(Object.isFrozen(run.workers));
12 } finally {
13 run[Symbol.dispose]();
14 }
15 });
16
17 it('w.exec() dispatches a task to the specific worker', async () => {
18 const run = workers(2);
19 try {
20 const result = await run.workers[0].exec(identity(42));
21 assert.equal(result, 42);
22 } finally {
23 run[Symbol.dispose]();
24 }
25 });
26
27 it('w.exec() dispatches a streaming task', async () => {
28 const run = workers(1);
29 try {
30 const results: number[] = [];
31 for await (const n of run.workers[0].exec(countUp(3))) {
32 results.push(n);
33 }
34 assert.deepEqual(results, [0, 1, 2]);
35 } finally {
36 run[Symbol.dispose]();
37 }
38 });
39
40 it('assign() pins task to a specific worker via run()', async () => {
41 const run = workers(2);
42 try {
43 const result = await run(assign(run.workers[1], identity(99)));
44 assert.equal(result, 99);
45 } finally {
46 run[Symbol.dispose]();
47 }
48 });
49
50 it('assign() works in a batch', async () => {
51 const run = workers(2);
52 try {
53 const results = await run([assign(run.workers[0], identity(1)), assign(run.workers[1], identity(2))]);
54 assert.deepEqual(results, [1, 2]);
55 } finally {
56 run[Symbol.dispose]();
57 }
58 });
59
60 it('w.exec() rejects after dispose', async () => {
61 const run = workers(1);
62 run[Symbol.dispose]();
63 await assert.rejects(() => run.workers[0].exec(identity(1)), { message: /disposed/ });
64 });
65});