HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux ip-172-31-4-197 6.8.0-1036-aws #38~22.04.1-Ubuntu SMP Fri Aug 22 15:44:33 UTC 2025 x86_64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //var/www/api-storage/node_modules/piscina/test/pool-close.ts
import { test } from 'tap';
import Piscina from '..';
import { resolve } from 'path';
import { once } from 'events';

test('close()', async (t) => {
  t.test('no pending tasks', async (t) => {
    const pool = new Piscina({ filename: resolve(__dirname, 'fixtures/sleep.js') });
    await pool.close();
    t.pass('pool closed successfully');
  });

  t.test('no pending tasks (with minThreads=0)', async (t) => {
    const pool = new Piscina({ filename: resolve(__dirname, 'fixtures/sleep.js'), minThreads: 0 });
    await pool.close();
    t.pass('pool closed successfully');
  });

  t.test('queued tasks waits for all tasks to complete', async (t) => {
    const pool = new Piscina({ filename: resolve(__dirname, 'fixtures/sleep.js'), maxThreads: 1 });

    const task1 = pool.run({ time: 100 });
    const task2 = pool.run({ time: 100 });

    setImmediate(() => t.resolves(pool.close(), 'close is resolved when all running tasks are completed'));

    await Promise.all([
      t.resolves(once(pool, 'close'), 'handler is called when pool is closed'),
      t.resolves(task1, 'complete running task'),
      t.resolves(task2, 'complete running task')
    ]);
  });

  t.test('abort any task enqueued during closing up', async (t) => {
    const pool = new Piscina({ filename: resolve(__dirname, 'fixtures/sleep.js'), maxThreads: 1 });

    setImmediate(() => {
      t.resolves(pool.close(), 'close is resolved when running tasks are completed');
      t.resolves(pool.run({ time: 1000 }).then(null, err => {
        t.equal(err.message, 'The task has been aborted');
        t.equal(err.cause, 'queue is closing up');
      }));
    });

    await t.resolves(pool.run({ time: 100 }), 'complete running task');
  });
});

test('close({force: true})', async (t) => {
  t.test('queued tasks waits for all tasks already running and aborts tasks that are not started yet', async (t) => {
    const pool = new Piscina({ filename: resolve(__dirname, 'fixtures/sleep.js'), maxThreads: 1, concurrentTasksPerWorker: 1 });

    const task1 = pool.run({ time: 1000 });
    const task2 = pool.run({ time: 200 });

    setImmediate(() => t.resolves(pool.close({ force: true }), 'close is resolved when all running tasks are completed'));

    await Promise.all([
      t.resolves(once(pool, 'close'), 'handler is called when pool is closed'),
      t.resolves(task1, 'complete running task'),
      t.resolves(task2.then(null, err => {
        t.equal(err.message, 'The task has been aborted');
        t.equal(err.cause, 'pool is closed');
      }))
    ]);
  });

  t.test('queued tasks waits for all tasks already running and aborts tasks that are not started yet', async (t) => {
    const pool = new Piscina({ filename: resolve(__dirname, 'fixtures/sleep.js'), maxThreads: 1, concurrentTasksPerWorker: 2 });

    const task1 = pool.run({ time: 500 });
    const task2 = pool.run({ time: 100 });
    const task3 = pool.run({ time: 100 });
    const task4 = pool.run({ time: 100 });

    setImmediate(() => t.resolves(pool.close({ force: true }), 'close is resolved when all running tasks are completed'));

    await Promise.all([
      t.resolves(once(pool, 'close'), 'handler is called when pool is closed'),
      t.resolves(task1, 'complete running task'),
      t.resolves(task2, 'complete running task'),
      t.rejects(task3, /The task has been aborted/, 'abort task that are not started yet'),
      t.rejects(task4, /The task has been aborted/, 'abort task that are not started yet')
    ]);
  });
});

test('timed out close operation destroys the pool', async (t) => {
  const pool = new Piscina({
    filename: resolve(__dirname, 'fixtures/sleep.js'),
    maxThreads: 1,
    closeTimeout: 500
  });

  const task1 = pool.run({ time: 5000 });
  const task2 = pool.run({ time: 5000 });

  setImmediate(() => t.resolves(pool.close(), 'close is resolved on timeout'));

  await Promise.all([
    t.resolves(once(pool, 'error'), 'error handler is called on timeout'),
    t.rejects(task1, /Terminating worker thread/, 'task is aborted due to timeout'),
    t.rejects(task2, /Terminating worker thread/, 'task is aborted due to timeout')
  ]);
});