Package Exports
- twerker
- twerker/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (twerker) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Twerker
A powerful and type-safe TypeScript worker thread pool implementation for Node.js with zero dependencies.
Why Twerker?
I created Twerker out of necessity. While there are several worker thread libraries available, none of them provided the perfect combination of simplicity, type-safety, and bare-minimum functionality that I was looking for. Most existing solutions were either over-engineered or lacked proper TypeScript support.
Twerker aims to do one thing and do it well: provide a straightforward, type-safe way to run CPU-intensive tasks in worker threads. No bells and whistles, no complex configurations - just a clean API that works out of the box.
Features
- 📦 Zero dependencies - uses only Node.js built-in modules
- 🚀 Simple and intuitive API for managing worker threads
- 💪 Fully type-safe with TypeScript
- 🔄 Automatic thread pool management
- 📊 Dynamic task queuing and distribution
- 🎯 Console output forwarding from workers
- ⚡ Built for performance with minimal overhead
- 🛡️ Robust error handling
Installation
pnpm add twerker
Quick Start
Create two separate files: one for defining your worker and another for using it. Name your worker file using kebab-case to match the function it implements.
[!WARNING] Always use
createPool()
for running multiple tasks. Do not usePromise.all()
with multiple.run()
calls, as this will create a new worker thread for each task, which is inefficient and can overwhelm your system.
heavy-computation.ts
- Define your worker
import run from 'twerker';
// Define your worker function
const heavyComputation = (a: number, b: number): number => {
// Simulate CPU-intensive work
let result = 0;
for (let i = 0; i < 1000000000; i++) {
result += Math.sqrt(a * b + i);
}
return result;
};
// Export the runner directly
export default run(heavyComputation);
main.ts
- Use the worker
import worker from './heavy-computation';
async function main() {
// Method 1: Run a single task
const result = await worker.run(10, 20);
console.log('Single task result:', result);
// Method 2: Create a pool for multiple tasks
const pool = worker.createPool(); // Uses number of CPU cores by default
// Queue tasks as needed
const result1 = await pool.queue(10, 20);
const result2 = await pool.queue(30, 40);
const result3 = await pool.queue(50, 60);
console.log('Pool results:', [result1, result2, result3]);
// Terminate the pool when done
await pool.terminateWhenDone();
}
main().catch(console.error);
API Reference
run<TArgs, TReturn>(fn: WorkerFunction<TArgs, TReturn>)
Creates a worker thread runner for the given function.
Returns an object with:
createPool(numWorkers?: number)
: Creates a worker pool with the specified number of workersrun(...args: TArgs)
: Runs a single task in a new worker
WorkerPool
The worker pool instance provides:
queue(...args: TArgs)
: Queues a task for executionterminateWhenDone()
: Gracefully terminates the pool after completing all tasks
Error Handling
[!WARNING] For pool operations, if you don't handle worker errors using
handleError()
, any error in the worker will crash your main thread.
For single tasks using .run()
, you can use regular try-catch:
try {
const result = await worker.run(10, 20);
} catch (error) {
console.error('Worker failed:', error.message);
}
For pool operations, you must use handleError()
:
const pool = createPool();
const task = pool.queue(10, 20).handleError((error) => {
console.error('Worker failed:', error.message);
// Handle the error as needed
});
Configuration
The default number of workers is set to the number of CPU cores. You can override this when creating a pool:
const pool = createPool(4); // Creates a pool with 4 workers
Best Practices
- Use worker pools for CPU-intensive tasks that can run in parallel
- Keep worker functions pure and avoid side effects
- Terminate pools when they're no longer needed
- Handle errors appropriately for each task
- Consider the overhead of data serialization when passing arguments
Contribution Guidelines
Issues and discussions are welcome! However, please note that this project aims to maintain a focused scope:
[!NOTE] The core mission of Twerker is to provide the simplest possible API for running code in worker threads with full type safety. Feature requests should align with this goal of simplifying the developer experience for common threading scenarios, rather than adding complexity for edge cases.
Coming soon: Contribution setup and guidelines.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Core Maintainer
Dak Washbrook (@dakdevs on X)
Made with ❤️ using TypeScript and Node.js