@rspack/core 1.3.2 โ 1.3.4
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/compiled/tinypool/LICENSE +24 -0
- package/compiled/tinypool/README.md +212 -0
- package/compiled/tinypool/dist/chunk-6LX4VMOV.js +31 -0
- package/compiled/tinypool/dist/chunk-ACQHDOFQ.js +12 -0
- package/compiled/tinypool/dist/chunk-E2J7JLFN.js +53 -0
- package/compiled/tinypool/dist/chunk-UBWFVGJX.js +38 -0
- package/compiled/tinypool/dist/entry/process.d.ts +2 -0
- package/compiled/tinypool/dist/entry/process.js +92 -0
- package/compiled/tinypool/dist/entry/utils.d.ts +5 -0
- package/compiled/tinypool/dist/entry/utils.js +9 -0
- package/compiled/tinypool/dist/entry/worker.d.ts +2 -0
- package/compiled/tinypool/dist/entry/worker.js +103 -0
- package/compiled/tinypool/dist/index.d.ts +188 -0
- package/compiled/tinypool/dist/index.js +1080 -0
- package/compiled/tinypool/package.json +55 -0
- package/dist/Module.d.ts +1 -0
- package/dist/ModuleGraph.d.ts +1 -2
- package/dist/RuntimeGlobals.d.ts +1 -0
- package/dist/config/zod.d.ts +2 -2
- package/dist/exports.d.ts +2 -1
- package/dist/index.js +59 -56
- package/dist/loader-runner/service.d.ts +1 -1
- package/package.json +4 -4
- package/dist/ModuleGraphConnection.d.ts +0 -12
@@ -0,0 +1,24 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 James M Snell and the Piscina contributors
|
4
|
+
|
5
|
+
Piscina contributors listed at https://github.com/jasnell/piscina#the-team and
|
6
|
+
in the README file.
|
7
|
+
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
10
|
+
in the Software without restriction, including without limitation the rights
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
13
|
+
furnished to do so, subject to the following conditions:
|
14
|
+
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
16
|
+
copies or substantial portions of the Software.
|
17
|
+
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
24
|
+
SOFTWARE.
|
@@ -0,0 +1,212 @@
|
|
1
|
+
# Tinypool - the node.js worker pool ๐งต
|
2
|
+
|
3
|
+
> Piscina: A fast, efficient Node.js Worker Thread Pool implementation
|
4
|
+
|
5
|
+
Tinypool is a fork of piscina. What we try to achieve in this library, is to eliminate some dependencies and features that our target users don't need (currently, our main user will be Vitest). Tinypool's install size (38KB) can then be smaller than Piscina's install size (6MB). If you need features like [utilization](https://github.com/piscinajs/piscina#property-utilization-readonly) or [NAPI](https://github.com/piscinajs/piscina#thread-priority-on-linux-systems), [Piscina](https://github.com/piscinajs/piscina) is a better choice for you. We think that Piscina is an amazing library, and we may try to upstream some of the dependencies optimization in this fork.
|
6
|
+
|
7
|
+
- โ
Smaller install size, 38KB
|
8
|
+
- โ
Minimal
|
9
|
+
- โ
No dependencies
|
10
|
+
- โ
Physical cores instead of Logical cores with [physical-cpu-count](https://www.npmjs.com/package/physical-cpu-count)
|
11
|
+
- โ
Supports `worker_threads` and `child_process`
|
12
|
+
- โ No utilization
|
13
|
+
- โ No NAPI
|
14
|
+
|
15
|
+
- Written in TypeScript, and ESM support only. For Node.js 18.x and higher.
|
16
|
+
|
17
|
+
_In case you need more tiny libraries like tinypool or tinyspy, please consider submitting an [RFC](https://github.com/tinylibs/rfcs)_
|
18
|
+
|
19
|
+
## Example
|
20
|
+
|
21
|
+
### Using `node:worker_threads`
|
22
|
+
|
23
|
+
#### Basic usage
|
24
|
+
|
25
|
+
```js
|
26
|
+
// main.mjs
|
27
|
+
import Tinypool from 'tinypool'
|
28
|
+
|
29
|
+
const pool = new Tinypool({
|
30
|
+
filename: new URL('./worker.mjs', import.meta.url).href,
|
31
|
+
})
|
32
|
+
const result = await pool.run({ a: 4, b: 6 })
|
33
|
+
console.log(result) // Prints 10
|
34
|
+
|
35
|
+
// Make sure to destroy pool once it's not needed anymore
|
36
|
+
// This terminates all pool's idle workers
|
37
|
+
await pool.destroy()
|
38
|
+
```
|
39
|
+
|
40
|
+
```js
|
41
|
+
// worker.mjs
|
42
|
+
export default ({ a, b }) => {
|
43
|
+
return a + b
|
44
|
+
}
|
45
|
+
```
|
46
|
+
|
47
|
+
#### Main thread <-> worker thread communication
|
48
|
+
|
49
|
+
<details>
|
50
|
+
<summary>See code</summary>
|
51
|
+
|
52
|
+
```js
|
53
|
+
// main.mjs
|
54
|
+
import Tinypool from 'tinypool'
|
55
|
+
import { MessageChannel } from 'node:worker_threads'
|
56
|
+
|
57
|
+
const pool = new Tinypool({
|
58
|
+
filename: new URL('./worker.mjs', import.meta.url).href,
|
59
|
+
})
|
60
|
+
const { port1, port2 } = new MessageChannel()
|
61
|
+
const promise = pool.run({ port: port1 }, { transferList: [port1] })
|
62
|
+
|
63
|
+
port2.on('message', (message) => console.log('Main thread received:', message))
|
64
|
+
setTimeout(() => port2.postMessage('Hello from main thread!'), 1000)
|
65
|
+
|
66
|
+
await promise
|
67
|
+
|
68
|
+
port1.close()
|
69
|
+
port2.close()
|
70
|
+
```
|
71
|
+
|
72
|
+
```js
|
73
|
+
// worker.mjs
|
74
|
+
export default ({ port }) => {
|
75
|
+
return new Promise((resolve) => {
|
76
|
+
port.on('message', (message) => {
|
77
|
+
console.log('Worker received:', message)
|
78
|
+
|
79
|
+
port.postMessage('Hello from worker thread!')
|
80
|
+
resolve()
|
81
|
+
})
|
82
|
+
})
|
83
|
+
}
|
84
|
+
```
|
85
|
+
|
86
|
+
</details>
|
87
|
+
|
88
|
+
### Using `node:child_process`
|
89
|
+
|
90
|
+
#### Basic usage
|
91
|
+
|
92
|
+
<details>
|
93
|
+
<summary>See code</summary>
|
94
|
+
|
95
|
+
```js
|
96
|
+
// main.mjs
|
97
|
+
import Tinypool from 'tinypool'
|
98
|
+
|
99
|
+
const pool = new Tinypool({
|
100
|
+
runtime: 'child_process',
|
101
|
+
filename: new URL('./worker.mjs', import.meta.url).href,
|
102
|
+
})
|
103
|
+
const result = await pool.run({ a: 4, b: 6 })
|
104
|
+
console.log(result) // Prints 10
|
105
|
+
```
|
106
|
+
|
107
|
+
```js
|
108
|
+
// worker.mjs
|
109
|
+
export default ({ a, b }) => {
|
110
|
+
return a + b
|
111
|
+
}
|
112
|
+
```
|
113
|
+
|
114
|
+
</details>
|
115
|
+
|
116
|
+
#### Main process <-> worker process communication
|
117
|
+
|
118
|
+
<details>
|
119
|
+
<summary>See code</summary>
|
120
|
+
|
121
|
+
```js
|
122
|
+
// main.mjs
|
123
|
+
import Tinypool from 'tinypool'
|
124
|
+
|
125
|
+
const pool = new Tinypool({
|
126
|
+
runtime: 'child_process',
|
127
|
+
filename: new URL('./worker.mjs', import.meta.url).href,
|
128
|
+
})
|
129
|
+
|
130
|
+
const messages = []
|
131
|
+
const listeners = []
|
132
|
+
const channel = {
|
133
|
+
onMessage: (listener) => listeners.push(listener),
|
134
|
+
postMessage: (message) => messages.push(message),
|
135
|
+
}
|
136
|
+
|
137
|
+
const promise = pool.run({}, { channel })
|
138
|
+
|
139
|
+
// Send message to worker
|
140
|
+
setTimeout(
|
141
|
+
() => listeners.forEach((listener) => listener('Hello from main process')),
|
142
|
+
1000
|
143
|
+
)
|
144
|
+
|
145
|
+
// Wait for task to finish
|
146
|
+
await promise
|
147
|
+
|
148
|
+
console.log(messages)
|
149
|
+
// [{ received: 'Hello from main process', response: 'Hello from worker' }]
|
150
|
+
```
|
151
|
+
|
152
|
+
```js
|
153
|
+
// worker.mjs
|
154
|
+
export default async function run() {
|
155
|
+
return new Promise((resolve) => {
|
156
|
+
process.on('message', (message) => {
|
157
|
+
// Ignore Tinypool's internal messages
|
158
|
+
if (message?.__tinypool_worker_message__) return
|
159
|
+
|
160
|
+
process.send({ received: message, response: 'Hello from worker' })
|
161
|
+
resolve()
|
162
|
+
})
|
163
|
+
})
|
164
|
+
}
|
165
|
+
```
|
166
|
+
|
167
|
+
</details>
|
168
|
+
|
169
|
+
## API
|
170
|
+
|
171
|
+
We have a similar API to Piscina, so for more information, you can read Piscina's detailed [documentation](https://github.com/piscinajs/piscina#piscina---the-nodejs-worker-pool) and apply the same techniques here.
|
172
|
+
|
173
|
+
### Tinypool specific APIs
|
174
|
+
|
175
|
+
#### Pool constructor options
|
176
|
+
|
177
|
+
- `isolateWorkers`: Disabled by default. Always starts with a fresh worker when running tasks to isolate the environment.
|
178
|
+
- `terminateTimeout`: Disabled by default. If terminating a worker takes `terminateTimeout` amount of milliseconds to execute, an error is raised.
|
179
|
+
- `maxMemoryLimitBeforeRecycle`: Disabled by default. When defined, the worker's heap memory usage is compared against this value after task has been finished. If the current memory usage exceeds this limit, worker is terminated and a new one is started to take its place. This option is useful when your tasks leak memory and you don't want to enable `isolateWorkers` option.
|
180
|
+
- `runtime`: Used to pick worker runtime. Default value is `worker_threads`.
|
181
|
+
- `worker_threads`: Runs workers in [`node:worker_threads`](https://nodejs.org/api/worker_threads.html). For `main thread <-> worker thread` communication you can use [`MessagePort`](https://nodejs.org/api/worker_threads.html#class-messageport) in the `pool.run()` method's [`transferList` option](https://nodejs.org/api/worker_threads.html#portpostmessagevalue-transferlist). See [example](#main-thread---worker-thread-communication).
|
182
|
+
- `child_process`: Runs workers in [`node:child_process`](https://nodejs.org/api/child_process.html). For `main thread <-> worker process` communication you can use `TinypoolChannel` in the `pool.run()` method's `channel` option. For filtering out the Tinypool's internal messages see `TinypoolWorkerMessage`. See [example](#main-process---worker-process-communication).
|
183
|
+
|
184
|
+
#### Pool methods
|
185
|
+
|
186
|
+
- `cancelPendingTasks()`: Gracefully cancels all pending tasks without stopping or interfering with on-going tasks. This method is useful when your tasks may have side effects and should not be terminated forcefully during task execution. If your tasks don't have any side effects you may want to use [`{ signal }`](https://github.com/piscinajs/piscina#cancelable-tasks) option for forcefully terminating all tasks, including the on-going ones, instead.
|
187
|
+
- `recycleWorkers(options)`: Waits for all current tasks to finish and re-creates all workers. Can be used to force isolation imperatively even when `isolateWorkers` is disabled. Accepts `{ runtime }` option as argument.
|
188
|
+
|
189
|
+
#### Exports
|
190
|
+
|
191
|
+
- `workerId`: Each worker now has an id ( <= `maxThreads`) that can be imported from `tinypool` in the worker itself (or `process.__tinypool_state__.workerId`).
|
192
|
+
|
193
|
+
## Authors
|
194
|
+
|
195
|
+
| <a href="https://github.com/Aslemammad"> <img width='150' src="https://avatars.githubusercontent.com/u/37929992?v=4" /><br> Mohammad Bagher </a> |
|
196
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
197
|
+
|
198
|
+
## Sponsors
|
199
|
+
|
200
|
+
Your sponsorship can make a huge difference in continuing our work in open source!
|
201
|
+
|
202
|
+
<p align="center">
|
203
|
+
<a href="https://cdn.jsdelivr.net/gh/aslemammad/static/sponsors.svg">
|
204
|
+
<img src='https://cdn.jsdelivr.net/gh/aslemammad/static/sponsors.svg'/>
|
205
|
+
</a>
|
206
|
+
</p>
|
207
|
+
|
208
|
+
## Credits
|
209
|
+
|
210
|
+
[The Vitest team](https://vitest.dev/) for giving me the chance of creating and maintaing this project for vitest.
|
211
|
+
|
212
|
+
[Piscina](https://github.com/piscinajs/piscina), because Tinypool is not more than a friendly fork of piscina.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
var __defProp = Object.defineProperty;
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
3
|
+
var __publicField = (obj, key, value) => {
|
4
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
5
|
+
return value;
|
6
|
+
};
|
7
|
+
var __accessCheck = (obj, member, msg) => {
|
8
|
+
if (!member.has(obj))
|
9
|
+
throw TypeError("Cannot " + msg);
|
10
|
+
};
|
11
|
+
var __privateGet = (obj, member, getter) => {
|
12
|
+
__accessCheck(obj, member, "read from private field");
|
13
|
+
return getter ? getter.call(obj) : member.get(obj);
|
14
|
+
};
|
15
|
+
var __privateAdd = (obj, member, value) => {
|
16
|
+
if (member.has(obj))
|
17
|
+
throw TypeError("Cannot add the same private member more than once");
|
18
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
19
|
+
};
|
20
|
+
var __privateSet = (obj, member, value, setter) => {
|
21
|
+
__accessCheck(obj, member, "write to private field");
|
22
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
23
|
+
return value;
|
24
|
+
};
|
25
|
+
|
26
|
+
export {
|
27
|
+
__publicField,
|
28
|
+
__privateGet,
|
29
|
+
__privateAdd,
|
30
|
+
__privateSet
|
31
|
+
};
|
@@ -0,0 +1,53 @@
|
|
1
|
+
// src/entry/utils.ts
|
2
|
+
import { pathToFileURL } from "url";
|
3
|
+
var importESMCached;
|
4
|
+
function getImportESM() {
|
5
|
+
if (importESMCached === void 0) {
|
6
|
+
importESMCached = new Function(
|
7
|
+
"specifier",
|
8
|
+
"return import(specifier)"
|
9
|
+
);
|
10
|
+
}
|
11
|
+
return importESMCached;
|
12
|
+
}
|
13
|
+
var handlerCache = /* @__PURE__ */ new Map();
|
14
|
+
async function getHandler(filename, name) {
|
15
|
+
let handler = handlerCache.get(`${filename}/${name}`);
|
16
|
+
if (handler !== void 0) {
|
17
|
+
return handler;
|
18
|
+
}
|
19
|
+
try {
|
20
|
+
const handlerModule = await import(filename);
|
21
|
+
handler = typeof handlerModule.default !== "function" && handlerModule.default || handlerModule;
|
22
|
+
if (typeof handler !== "function") {
|
23
|
+
handler = await handler[name];
|
24
|
+
}
|
25
|
+
} catch {
|
26
|
+
}
|
27
|
+
if (typeof handler !== "function") {
|
28
|
+
handler = await getImportESM()(pathToFileURL(filename).href);
|
29
|
+
if (typeof handler !== "function") {
|
30
|
+
handler = await handler[name];
|
31
|
+
}
|
32
|
+
}
|
33
|
+
if (typeof handler !== "function") {
|
34
|
+
return null;
|
35
|
+
}
|
36
|
+
if (handlerCache.size > 1e3) {
|
37
|
+
const [handler2] = handlerCache;
|
38
|
+
const key = handler2[0];
|
39
|
+
handlerCache.delete(key);
|
40
|
+
}
|
41
|
+
handlerCache.set(`${filename}/${name}`, handler);
|
42
|
+
return handler;
|
43
|
+
}
|
44
|
+
function throwInNextTick(error) {
|
45
|
+
process.nextTick(() => {
|
46
|
+
throw error;
|
47
|
+
});
|
48
|
+
}
|
49
|
+
|
50
|
+
export {
|
51
|
+
getHandler,
|
52
|
+
throwInNextTick
|
53
|
+
};
|
@@ -0,0 +1,38 @@
|
|
1
|
+
// src/common.ts
|
2
|
+
var kMovable = Symbol("Tinypool.kMovable");
|
3
|
+
var kTransferable = Symbol.for("Tinypool.transferable");
|
4
|
+
var kValue = Symbol.for("Tinypool.valueOf");
|
5
|
+
var kQueueOptions = Symbol.for("Tinypool.queueOptions");
|
6
|
+
function isTransferable(value) {
|
7
|
+
return value != null && typeof value === "object" && kTransferable in value && kValue in value;
|
8
|
+
}
|
9
|
+
function isMovable(value) {
|
10
|
+
return isTransferable(value) && value[kMovable] === true;
|
11
|
+
}
|
12
|
+
function markMovable(value) {
|
13
|
+
Object.defineProperty(value, kMovable, {
|
14
|
+
enumerable: false,
|
15
|
+
configurable: true,
|
16
|
+
writable: true,
|
17
|
+
value: true
|
18
|
+
});
|
19
|
+
}
|
20
|
+
function isTaskQueue(value) {
|
21
|
+
return typeof value === "object" && value !== null && "size" in value && typeof value.shift === "function" && typeof value.remove === "function" && typeof value.push === "function";
|
22
|
+
}
|
23
|
+
var kRequestCountField = 0;
|
24
|
+
var kResponseCountField = 1;
|
25
|
+
var kFieldCount = 2;
|
26
|
+
|
27
|
+
export {
|
28
|
+
kTransferable,
|
29
|
+
kValue,
|
30
|
+
kQueueOptions,
|
31
|
+
isTransferable,
|
32
|
+
isMovable,
|
33
|
+
markMovable,
|
34
|
+
isTaskQueue,
|
35
|
+
kRequestCountField,
|
36
|
+
kResponseCountField,
|
37
|
+
kFieldCount
|
38
|
+
};
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import {
|
2
|
+
stderr,
|
3
|
+
stdout
|
4
|
+
} from "../chunk-ACQHDOFQ.js";
|
5
|
+
import {
|
6
|
+
getHandler,
|
7
|
+
throwInNextTick
|
8
|
+
} from "../chunk-E2J7JLFN.js";
|
9
|
+
import "../chunk-6LX4VMOV.js";
|
10
|
+
|
11
|
+
// src/entry/process.ts
|
12
|
+
process.__tinypool_state__ = {
|
13
|
+
isChildProcess: true,
|
14
|
+
isTinypoolWorker: true,
|
15
|
+
workerData: null,
|
16
|
+
workerId: Number(process.env.TINYPOOL_WORKER_ID)
|
17
|
+
};
|
18
|
+
var memoryUsage = process.memoryUsage.bind(process);
|
19
|
+
var send = process.send.bind(process);
|
20
|
+
process.on("message", (message) => {
|
21
|
+
if (!message || !message.__tinypool_worker_message__)
|
22
|
+
return;
|
23
|
+
if (message.source === "pool") {
|
24
|
+
const { filename, name } = message;
|
25
|
+
(async function() {
|
26
|
+
if (filename !== null) {
|
27
|
+
await getHandler(filename, name);
|
28
|
+
}
|
29
|
+
send(
|
30
|
+
{
|
31
|
+
ready: true,
|
32
|
+
source: "pool",
|
33
|
+
__tinypool_worker_message__: true
|
34
|
+
},
|
35
|
+
() => {
|
36
|
+
}
|
37
|
+
);
|
38
|
+
})().catch(throwInNextTick);
|
39
|
+
return;
|
40
|
+
}
|
41
|
+
if (message.source === "port") {
|
42
|
+
onMessage(message).catch(throwInNextTick);
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
throw new Error(`Unexpected TinypoolWorkerMessage ${JSON.stringify(message)}`);
|
46
|
+
});
|
47
|
+
async function onMessage(message) {
|
48
|
+
const { taskId, task, filename, name } = message;
|
49
|
+
let response;
|
50
|
+
try {
|
51
|
+
const handler = await getHandler(filename, name);
|
52
|
+
if (handler === null) {
|
53
|
+
throw new Error(`No handler function exported from ${filename}`);
|
54
|
+
}
|
55
|
+
const result = await handler(task);
|
56
|
+
response = {
|
57
|
+
source: "port",
|
58
|
+
__tinypool_worker_message__: true,
|
59
|
+
taskId,
|
60
|
+
result,
|
61
|
+
error: null,
|
62
|
+
usedMemory: memoryUsage().heapUsed
|
63
|
+
};
|
64
|
+
if (stdout()?.writableLength > 0) {
|
65
|
+
await new Promise((resolve) => process.stdout.write("", resolve));
|
66
|
+
}
|
67
|
+
if (stderr()?.writableLength > 0) {
|
68
|
+
await new Promise((resolve) => process.stderr.write("", resolve));
|
69
|
+
}
|
70
|
+
} catch (error) {
|
71
|
+
response = {
|
72
|
+
source: "port",
|
73
|
+
__tinypool_worker_message__: true,
|
74
|
+
taskId,
|
75
|
+
result: null,
|
76
|
+
error: serializeError(error),
|
77
|
+
usedMemory: memoryUsage().heapUsed
|
78
|
+
};
|
79
|
+
}
|
80
|
+
send(response);
|
81
|
+
}
|
82
|
+
function serializeError(error) {
|
83
|
+
if (error instanceof Error) {
|
84
|
+
return {
|
85
|
+
...error,
|
86
|
+
name: error.name,
|
87
|
+
stack: error.stack,
|
88
|
+
message: error.message
|
89
|
+
};
|
90
|
+
}
|
91
|
+
return String(error);
|
92
|
+
}
|
@@ -0,0 +1,103 @@
|
|
1
|
+
import {
|
2
|
+
isMovable,
|
3
|
+
kRequestCountField,
|
4
|
+
kResponseCountField,
|
5
|
+
kTransferable,
|
6
|
+
kValue
|
7
|
+
} from "../chunk-UBWFVGJX.js";
|
8
|
+
import {
|
9
|
+
stderr,
|
10
|
+
stdout
|
11
|
+
} from "../chunk-ACQHDOFQ.js";
|
12
|
+
import {
|
13
|
+
getHandler,
|
14
|
+
throwInNextTick
|
15
|
+
} from "../chunk-E2J7JLFN.js";
|
16
|
+
import "../chunk-6LX4VMOV.js";
|
17
|
+
|
18
|
+
// src/entry/worker.ts
|
19
|
+
import {
|
20
|
+
parentPort,
|
21
|
+
receiveMessageOnPort,
|
22
|
+
workerData as tinypoolData
|
23
|
+
} from "worker_threads";
|
24
|
+
var [tinypoolPrivateData, workerData] = tinypoolData;
|
25
|
+
process.__tinypool_state__ = {
|
26
|
+
isWorkerThread: true,
|
27
|
+
isTinypoolWorker: true,
|
28
|
+
workerData,
|
29
|
+
workerId: tinypoolPrivateData.workerId
|
30
|
+
};
|
31
|
+
var memoryUsage = process.memoryUsage.bind(process);
|
32
|
+
var useAtomics = process.env.PISCINA_DISABLE_ATOMICS !== "1";
|
33
|
+
parentPort.on("message", (message) => {
|
34
|
+
useAtomics = process.env.PISCINA_DISABLE_ATOMICS === "1" ? false : message.useAtomics;
|
35
|
+
const { port, sharedBuffer, filename, name } = message;
|
36
|
+
(async function() {
|
37
|
+
if (filename !== null) {
|
38
|
+
await getHandler(filename, name);
|
39
|
+
}
|
40
|
+
const readyMessage = { ready: true };
|
41
|
+
parentPort.postMessage(readyMessage);
|
42
|
+
port.on("message", onMessage.bind(null, port, sharedBuffer));
|
43
|
+
atomicsWaitLoop(port, sharedBuffer);
|
44
|
+
})().catch(throwInNextTick);
|
45
|
+
});
|
46
|
+
var currentTasks = 0;
|
47
|
+
var lastSeenRequestCount = 0;
|
48
|
+
function atomicsWaitLoop(port, sharedBuffer) {
|
49
|
+
if (!useAtomics)
|
50
|
+
return;
|
51
|
+
while (currentTasks === 0) {
|
52
|
+
Atomics.wait(sharedBuffer, kRequestCountField, lastSeenRequestCount);
|
53
|
+
lastSeenRequestCount = Atomics.load(sharedBuffer, kRequestCountField);
|
54
|
+
let entry;
|
55
|
+
while ((entry = receiveMessageOnPort(port)) !== void 0) {
|
56
|
+
onMessage(port, sharedBuffer, entry.message);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
function onMessage(port, sharedBuffer, message) {
|
61
|
+
currentTasks++;
|
62
|
+
const { taskId, task, filename, name } = message;
|
63
|
+
(async function() {
|
64
|
+
let response;
|
65
|
+
let transferList = [];
|
66
|
+
try {
|
67
|
+
const handler = await getHandler(filename, name);
|
68
|
+
if (handler === null) {
|
69
|
+
throw new Error(`No handler function exported from ${filename}`);
|
70
|
+
}
|
71
|
+
let result = await handler(task);
|
72
|
+
if (isMovable(result)) {
|
73
|
+
transferList = transferList.concat(result[kTransferable]);
|
74
|
+
result = result[kValue];
|
75
|
+
}
|
76
|
+
response = {
|
77
|
+
taskId,
|
78
|
+
result,
|
79
|
+
error: null,
|
80
|
+
usedMemory: memoryUsage().heapUsed
|
81
|
+
};
|
82
|
+
if (stdout()?.writableLength > 0) {
|
83
|
+
await new Promise((resolve) => process.stdout.write("", resolve));
|
84
|
+
}
|
85
|
+
if (stderr()?.writableLength > 0) {
|
86
|
+
await new Promise((resolve) => process.stderr.write("", resolve));
|
87
|
+
}
|
88
|
+
} catch (error) {
|
89
|
+
response = {
|
90
|
+
taskId,
|
91
|
+
result: null,
|
92
|
+
// It may be worth taking a look at the error cloning algorithm we
|
93
|
+
// use in Node.js core here, it's quite a bit more flexible
|
94
|
+
error,
|
95
|
+
usedMemory: memoryUsage().heapUsed
|
96
|
+
};
|
97
|
+
}
|
98
|
+
currentTasks--;
|
99
|
+
port.postMessage(response, transferList);
|
100
|
+
Atomics.add(sharedBuffer, kResponseCountField, 1);
|
101
|
+
atomicsWaitLoop(port, sharedBuffer);
|
102
|
+
})().catch(throwInNextTick);
|
103
|
+
}
|