Hone logo
Hone
Problems

Testing a Worker Pool with Jest

Worker pools are a powerful technique for parallelizing tasks, especially in Node.js environments where single-threaded execution can be a bottleneck. This challenge asks you to create a simple worker pool and then write Jest tests to ensure its correct functionality, including handling errors and managing task queues. Successfully completing this challenge demonstrates understanding of asynchronous programming, worker threads, and robust testing practices.

Problem Description

You are tasked with creating a basic worker pool using Node.js worker threads and then writing Jest tests to verify its behavior. The worker pool should be able to accept an array of tasks, distribute them among a fixed number of worker threads, and collect the results. The tasks are simple functions that take a number as input and return its square.

What needs to be achieved:

  1. Worker Pool Implementation: Create a WorkerPool class that manages a pool of worker threads. The constructor should accept the number of workers to create.
  2. Task Distribution: Implement a run method that accepts an array of tasks (functions that take a number and return its square) and distributes them among the worker threads.
  3. Result Collection: The run method should return a Promise that resolves with an array of results, in the same order as the input tasks.
  4. Error Handling: If a worker thread encounters an error while processing a task, the error should be caught and propagated to the run method's Promise rejection.
  5. Jest Tests: Write Jest tests to cover the following scenarios:
    • Successful execution of tasks.
    • Handling of errors within worker threads.
    • Correct ordering of results.
    • Empty task array.
    • Pool creation with zero workers (should throw an error).

Key Requirements:

  • Use Node.js worker_threads module.
  • The WorkerPool class should be reusable.
  • The Jest tests should be well-structured and cover all specified scenarios.
  • Avoid using external libraries beyond Node.js core modules.

Expected Behavior:

  • The WorkerPool should efficiently distribute tasks among worker threads.
  • Results should be returned in the same order as the input tasks.
  • Errors from worker threads should be properly handled and propagated.
  • The Jest tests should pass, indicating that the worker pool is functioning correctly.

Edge Cases to Consider:

  • What happens if a worker thread crashes?
  • What happens if the task queue is empty?
  • What happens if the number of workers is zero or negative?
  • How are errors handled within the worker threads?

Examples

Example 1:

Input: [1, 2, 3, 4, 5]
Output: [1, 4, 9, 16, 25]
Explanation: Each number is squared by a worker thread, and the results are returned in the original order.

Example 2:

Input: [1, 2, () => { throw new Error("Simulated error"); }, 4]
Output: Rejection with Error: "Simulated error"
Explanation: The third task throws an error. The worker pool catches this error and rejects the promise returned by `run`.

Example 3:

Input: []
Output: []
Explanation: An empty array of tasks is passed to the worker pool. The `run` method should resolve with an empty array.

Constraints

  • The number of workers in the pool should be configurable.
  • Tasks should be functions that accept a number and return a number (its square).
  • The run method should return a Promise.
  • The Jest tests should be written using modern Jest syntax (e.g., async/await).
  • The number of workers should be between 1 and 10 (inclusive). Creating a pool with 0 workers should throw an error.

Notes

  • Consider using a queue to manage tasks and worker availability.
  • Think about how to handle errors that occur within the worker threads.
  • The focus is on the core worker pool logic and its testing, not on complex task management or error recovery.
  • Use worker_threads.parentPort.on('message', ...) within the worker thread to receive tasks.
  • Use worker_threads.workerData to pass initial data to the worker thread (if needed).
  • Remember to properly terminate worker threads when the pool is no longer needed.
Loading editor...
typescript