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.
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.
Description
Currently Tinypool can be used to run tasks in
node:worker_threadsonly. However it seems that various Node ecosystem packages are incompatible withworker_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 useworker_threadsby default.Add an option to choose between
node:worker_threadsandnode:child_processruntimes.Constructor
In future we might even add support for third party runtimes. These could be for example browser runtimes:
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()At this point pool has 4 idle
worker_threads. We want to run next task inchild_processinstead: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_threadsand 1child_processworkers 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.
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.