-
-
Notifications
You must be signed in to change notification settings - Fork 45
Description
Description
Currently Tinypool can be used to run tasks in node:worker_threads only. However it seems that various Node ecosystem packages are incompatible with worker_threads, e.g. aws-sdk, @prisma/client, bcrypt. Typically the common feature of these packages is that they utilize NodeJS API's through native addons. I guess there is a reason why Jest does not use worker_threads by default.
- Hitting Segmentation fault when running Vitest . vitest-dev/vitest#3143
- Vitest crashes when running tests with Prisma vitest-dev/vitest#3106
- Getting Node low level errors running vitest vitest-dev/vitest#3816
- Crashes bcrypt #48
Add an option to choose between node:worker_threads and node:child_process runtimes.
Constructor
new Tinypool({}) // Defaults to 'worker_threads' for backwards compatibility
new Tinypool({ runtime: 'worker_threads' })
new Tinypool({ runtime: 'child_process' })In future we might even add support for third party runtimes. These could be for example browser runtimes:
new Tinypool({ runtime: 'tinypool-runtime-browser' })
new Tinypool({ runtime: '@organization/tinypool-runtime-custom' })Pool methods
There might be times where we don't know which runtime to use when initializing the pool. We'll need to add support for changing the runtime of existing pool.
pool.run()
const pool = new Tinypool({
runtime: 'worker_threads',
minThreads: 4,
maxThreads: 4
})
await pool.run(task) // Runs in `worker_threads`At this point pool has 4 idle worker_threads. We want to run next task in child_process instead:
await pool.run(task, { runtime: 'child_process' })Pool notices that runtime does not match with idle workers. It has to pick a worker from pool, terminate it and spawn a new worker with different runtime.
Once task has finished there will be 3 worker_threads and 1 child_process workers idle.
pool.recycleWorkers()
For optimal performance the end-users should be able to change runtime of all workers. This can be useful when they can identify which runtimes their predetermined tasks will need.
const tasks = [...]
const pool = new Tinypool({ runtime: 'worker_threads' })
// Run `worker_thread` tasks first
await Promise.all(tasks.filter(pickWorkerThreadCompatibleTasks).map(t => pool.run(t)))
await pool.recycleWorkers({ runtime: 'child_process' })
// All idle workers will now be `child_process` runtimes
await Promise.all(tasks.filter(pickChildProcessTasks).map(t => pool.run(t)))Other
This won't be easy task and might require heavy refactoring. If there are some features that require worker_threads, I think we should simply throw or log an error when those are called with different runtime.
Best approach to start this is to create a common interface for runtimes. This interface would hide implementation details of runtimes and provide a simple API for pool to utilize. Same interface would eventually be used by third party runtime implementors.