UNPKG

multiprocessor

Version:

Multiprocessing pool implementation for NodeJS and TypeScript

262 lines (198 loc) 7.57 kB
import { describe, expect, it } from "@jest/globals"; import { infinite, single } from "itertools-ts"; import { Pool } from "../src"; import { TaskHandlers } from "../src/types"; describe('Pool IMap Unordered Extended Tests', () => { it('Array Input Calc Sinus Test', async () => { const poolSize = 4; const pool = new Pool(poolSize); const input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; const results = []; results.length = input.length; const errors = []; errors.length = input.length; for await (const [index, result, error] of pool.imapUnorderedExtended(input, calcSinTask)) { results[index] = result; errors[index] = error; } pool.close(); expect(results.length).toBe(input.length); expect(errors.length).toBe(input.length); expect(results.filter((x) => x !== undefined).length).toBe(input.length); expect(errors.filter((x) => x !== undefined).length).toBe(0); for (let i = 0; i < results.length; i++) { expect(results[i]).toBeCloseTo(Math.sin(input[i])); } }, 10000); it('Iterable Inputs Calc Sinus Test', async () => { const poolSize = 4; const pool = new Pool(poolSize); const inputCount = 100; const input = single.limit(single.map(infinite.count(), (x) => x/inputCount), inputCount); const inputArray = [...single.limit(single.map(infinite.count(), (x) => x/inputCount), inputCount)]; const results = []; results.length = inputArray.length; const errors = []; errors.length = inputArray.length; for await (const [index, result, error] of pool.imapUnorderedExtended(input, calcSinTask)) { results[index] = result; errors[index] = error; } pool.close(); expect(results.length).toBe(inputArray.length); expect(errors.length).toBe(inputArray.length); expect(results.filter((x) => x !== undefined).length).toBe(inputArray.length); expect(errors.filter((x) => x !== undefined).length).toBe(0); for (let i = 0; i < results.length; i++) { expect(results[i]).toBeCloseTo(Math.sin(inputArray[i])); } }, 10000); it('Async Iterable Inputs Calc Sinus Test', async () => { const poolSize = 4; const pool = new Pool(poolSize); const inputCount = 100; const input = single.limitAsync(single.mapAsync(infinite.count(), (x) => x/inputCount), inputCount); const inputArray = [...single.limit(single.map(infinite.count(), (x) => x/inputCount), inputCount)]; const results = []; results.length = inputArray.length; const errors = []; errors.length = inputArray.length; for await (const [index, result, error] of pool.imapUnorderedExtended(input, calcSinTask)) { results[index] = result; errors[index] = error; } pool.close(); expect(results.length).toBe(inputArray.length); expect(errors.length).toBe(inputArray.length); expect(results.filter((x) => x !== undefined).length).toBe(inputArray.length); expect(errors.filter((x) => x !== undefined).length).toBe(0); for (let i = 0; i < results.length; i++) { expect(results[i]).toBeCloseTo(Math.sin(inputArray[i])); } }, 10000); it('Async Calc Sinus With Errors And Handlers Test', async () => { const poolSize = 4; const pool = new Pool(poolSize); const inputCount = 100; const input = single.limit(single.map(infinite.count(), (x) => x/inputCount), inputCount); const inputArray = [...single.limit(single.map(infinite.count(), (x) => x/inputCount), inputCount)]; let resultsCount = 0; let errorsCount = 0; const taskHandlers: TaskHandlers<number, number> = { onTaskSuccess: (result: number, input: number, index: number) => { console.log('taskSuccess', result, input, index); resultsCount++; }, onTaskError: (error: string, input: number, index: number) => { console.log('taskError', error, input, index); errorsCount++; }, }; const results = []; results.length = inputArray.length; const errors = []; errors.length = inputArray.length; for await (const [index, result, error] of pool.imapUnorderedExtended(input, calcSinWithRandomErrorTask, taskHandlers)) { results[index] = result; errors[index] = error; } pool.close(); expect(results.length).toBe(inputCount); expect(resultsCount + errorsCount).toBe(inputCount); expect(resultsCount).toBeGreaterThan(0); expect(results.length).toBe(inputArray.length); expect(errors.length).toBe(inputArray.length); expect(results.filter((x) => x !== undefined).length).toBe(resultsCount); expect(results.filter((x) => x === undefined).length).toBe(errorsCount); expect(errors.filter((x) => x !== undefined).length).toBe(errorsCount); expect(errors.filter((x) => x === undefined).length).toBe(resultsCount); for (let i = 0; i < results.length; i++) { if (results[i] === undefined) { continue; } expect(results[i]).toBeCloseTo(Math.sin(inputArray[i])); } const errorsSet = new Set(errors.filter((x) => x !== undefined)); expect(errorsSet.size).toBe(1) expect(errorsSet.has('Random error')).toBe(true); }, 10000); it('Long Test', async () => { const poolSize = 4; const inputsCount = 100; const pool = new Pool(poolSize); const data = [...single.limit(infinite.count(), inputsCount)].map((x) => [x]); const task = (input: number[]) => { let r = 0; for (let i = 0; i < 100000000; ++i) { r += input[0] ** 2; } if (Math.random() > 0.9) { throw new Error('Random error'); } return Promise.resolve(r); }; let resultsCount = 0; let errorsCount = 0; const taskHandlers: TaskHandlers<number[], number> = { onTaskSuccess: (result: number, input: number[], index: number) => { console.log('taskSuccess', result, input, index); resultsCount++; }, onTaskError: (error: string, input: number[], index: number) => { console.log('taskError', error, input, index); errorsCount++; }, }; const results = []; for await (const [_, result] of pool.imapUnorderedExtended(data, task, taskHandlers)) { results.push(result); } pool.close(); expect(results.length).toBe(inputsCount); expect(resultsCount + errorsCount).toBe(inputsCount); expect(resultsCount).toBeGreaterThan(0); expect(results.filter((x) => x !== undefined).length).toBe(resultsCount); expect(results.filter((x) => x === undefined).length).toBe(errorsCount); }, 50000); }); function calcSinTask(x: number): number { let result = 0; let sign = 1; let power = x; let factorial = 1; for (let n = 0; n < 1000000; n++) { if (n > 0) { factorial *= (2 * n) * (2 * n + 1); power *= x * x; sign *= -1; } const delta = sign * (power / factorial); if (isNaN(result + delta)) { return result } result += delta; } return result; } function calcSinWithRandomErrorTask(x: number): Promise<number> { if (Math.random() > 0.5) { throw new Error('Random error'); } let result = 0; let sign = 1; let power = x; let factorial = 1; for (let n = 0; n < 1000000; n++) { if (n > 0) { factorial *= (2 * n) * (2 * n + 1); power *= x * x; sign *= -1; } const delta = sign * (power / factorial); if (isNaN(result + delta)) { return Promise.resolve(result); } result += delta; } return Promise.resolve(result); }