You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					210 lines
				
				4.7 KiB
			
		
		
			
		
	
	
					210 lines
				
				4.7 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Object.defineProperty(exports, '__esModule', {
							 | 
						||
| 
								 | 
							
								  value: true
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								exports.default = void 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function path() {
							 | 
						||
| 
								 | 
							
								  const data = _interopRequireWildcard(require('path'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  path = function () {
							 | 
						||
| 
								 | 
							
								    return data;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _mergeStream() {
							 | 
						||
| 
								 | 
							
								  const data = _interopRequireDefault(require('merge-stream'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _mergeStream = function () {
							 | 
						||
| 
								 | 
							
								    return data;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _types() {
							 | 
						||
| 
								 | 
							
								  const data = require('../types');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _types = function () {
							 | 
						||
| 
								 | 
							
								    return data;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _interopRequireDefault(obj) {
							 | 
						||
| 
								 | 
							
								  return obj && obj.__esModule ? obj : {default: obj};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _getRequireWildcardCache() {
							 | 
						||
| 
								 | 
							
								  if (typeof WeakMap !== 'function') return null;
							 | 
						||
| 
								 | 
							
								  var cache = new WeakMap();
							 | 
						||
| 
								 | 
							
								  _getRequireWildcardCache = function () {
							 | 
						||
| 
								 | 
							
								    return cache;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  return cache;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _interopRequireWildcard(obj) {
							 | 
						||
| 
								 | 
							
								  if (obj && obj.__esModule) {
							 | 
						||
| 
								 | 
							
								    return obj;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
							 | 
						||
| 
								 | 
							
								    return {default: obj};
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  var cache = _getRequireWildcardCache();
							 | 
						||
| 
								 | 
							
								  if (cache && cache.has(obj)) {
							 | 
						||
| 
								 | 
							
								    return cache.get(obj);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  var newObj = {};
							 | 
						||
| 
								 | 
							
								  var hasPropertyDescriptor =
							 | 
						||
| 
								 | 
							
								    Object.defineProperty && Object.getOwnPropertyDescriptor;
							 | 
						||
| 
								 | 
							
								  for (var key in obj) {
							 | 
						||
| 
								 | 
							
								    if (Object.prototype.hasOwnProperty.call(obj, key)) {
							 | 
						||
| 
								 | 
							
								      var desc = hasPropertyDescriptor
							 | 
						||
| 
								 | 
							
								        ? Object.getOwnPropertyDescriptor(obj, key)
							 | 
						||
| 
								 | 
							
								        : null;
							 | 
						||
| 
								 | 
							
								      if (desc && (desc.get || desc.set)) {
							 | 
						||
| 
								 | 
							
								        Object.defineProperty(newObj, key, desc);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        newObj[key] = obj[key];
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  newObj.default = obj;
							 | 
						||
| 
								 | 
							
								  if (cache) {
							 | 
						||
| 
								 | 
							
								    cache.set(obj, newObj);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return newObj;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _defineProperty(obj, key, value) {
							 | 
						||
| 
								 | 
							
								  if (key in obj) {
							 | 
						||
| 
								 | 
							
								    Object.defineProperty(obj, key, {
							 | 
						||
| 
								 | 
							
								      value: value,
							 | 
						||
| 
								 | 
							
								      enumerable: true,
							 | 
						||
| 
								 | 
							
								      configurable: true,
							 | 
						||
| 
								 | 
							
								      writable: true
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    obj[key] = value;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return obj;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// How long to wait for the child process to terminate
							 | 
						||
| 
								 | 
							
								// after CHILD_MESSAGE_END before sending force exiting.
							 | 
						||
| 
								 | 
							
								const FORCE_EXIT_DELAY = 500;
							 | 
						||
| 
								 | 
							
								/* istanbul ignore next */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const emptyMethod = () => {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BaseWorkerPool {
							 | 
						||
| 
								 | 
							
								  constructor(workerPath, options) {
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_stderr', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_stdout', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_options', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_workers', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this._options = options;
							 | 
						||
| 
								 | 
							
								    this._workers = new Array(options.numWorkers);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!path().isAbsolute(workerPath)) {
							 | 
						||
| 
								 | 
							
								      workerPath = require.resolve(workerPath);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const stdout = (0, _mergeStream().default)();
							 | 
						||
| 
								 | 
							
								    const stderr = (0, _mergeStream().default)();
							 | 
						||
| 
								 | 
							
								    const {forkOptions, maxRetries, resourceLimits, setupArgs} = options;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let i = 0; i < options.numWorkers; i++) {
							 | 
						||
| 
								 | 
							
								      const workerOptions = {
							 | 
						||
| 
								 | 
							
								        forkOptions,
							 | 
						||
| 
								 | 
							
								        maxRetries,
							 | 
						||
| 
								 | 
							
								        resourceLimits,
							 | 
						||
| 
								 | 
							
								        setupArgs,
							 | 
						||
| 
								 | 
							
								        workerId: i,
							 | 
						||
| 
								 | 
							
								        workerPath
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      const worker = this.createWorker(workerOptions);
							 | 
						||
| 
								 | 
							
								      const workerStdout = worker.getStdout();
							 | 
						||
| 
								 | 
							
								      const workerStderr = worker.getStderr();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (workerStdout) {
							 | 
						||
| 
								 | 
							
								        stdout.add(workerStdout);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (workerStderr) {
							 | 
						||
| 
								 | 
							
								        stderr.add(workerStderr);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this._workers[i] = worker;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this._stdout = stdout;
							 | 
						||
| 
								 | 
							
								    this._stderr = stderr;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  getStderr() {
							 | 
						||
| 
								 | 
							
								    return this._stderr;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  getStdout() {
							 | 
						||
| 
								 | 
							
								    return this._stdout;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  getWorkers() {
							 | 
						||
| 
								 | 
							
								    return this._workers;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  getWorkerById(workerId) {
							 | 
						||
| 
								 | 
							
								    return this._workers[workerId];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  createWorker(_workerOptions) {
							 | 
						||
| 
								 | 
							
								    throw Error('Missing method createWorker in WorkerPool');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  async end() {
							 | 
						||
| 
								 | 
							
								    // We do not cache the request object here. If so, it would only be only
							 | 
						||
| 
								 | 
							
								    // processed by one of the workers, and we want them all to close.
							 | 
						||
| 
								 | 
							
								    const workerExitPromises = this._workers.map(async worker => {
							 | 
						||
| 
								 | 
							
								      worker.send(
							 | 
						||
| 
								 | 
							
								        [_types().CHILD_MESSAGE_END, false],
							 | 
						||
| 
								 | 
							
								        emptyMethod,
							 | 
						||
| 
								 | 
							
								        emptyMethod,
							 | 
						||
| 
								 | 
							
								        emptyMethod
							 | 
						||
| 
								 | 
							
								      ); // Schedule a force exit in case worker fails to exit gracefully so
							 | 
						||
| 
								 | 
							
								      // await worker.waitForExit() never takes longer than FORCE_EXIT_DELAY
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let forceExited = false;
							 | 
						||
| 
								 | 
							
								      const forceExitTimeout = setTimeout(() => {
							 | 
						||
| 
								 | 
							
								        worker.forceExit();
							 | 
						||
| 
								 | 
							
								        forceExited = true;
							 | 
						||
| 
								 | 
							
								      }, FORCE_EXIT_DELAY);
							 | 
						||
| 
								 | 
							
								      await worker.waitForExit(); // Worker ideally exited gracefully, don't send force exit then
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      clearTimeout(forceExitTimeout);
							 | 
						||
| 
								 | 
							
								      return forceExited;
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const workerExits = await Promise.all(workerExitPromises);
							 | 
						||
| 
								 | 
							
								    return workerExits.reduce(
							 | 
						||
| 
								 | 
							
								      (result, forceExited) => ({
							 | 
						||
| 
								 | 
							
								        forceExited: result.forceExited || forceExited
							 | 
						||
| 
								 | 
							
								      }),
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        forceExited: false
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exports.default = BaseWorkerPool;
							 |