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.
		
		
		
		
		
			
		
			
				
					
					
						
							184 lines
						
					
					
						
							5.2 KiB
						
					
					
				
			
		
		
	
	
							184 lines
						
					
					
						
							5.2 KiB
						
					
					
				'use strict'; | 
						|
 | 
						|
Object.defineProperty(exports, '__esModule', { | 
						|
  value: true | 
						|
}); | 
						|
exports.default = void 0; | 
						|
 | 
						|
function _os() { | 
						|
  const data = _interopRequireDefault(require('os')); | 
						|
 | 
						|
  _os = function _os() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
var _WorkerPool = _interopRequireDefault(require('./WorkerPool')); | 
						|
 | 
						|
var _Farm = _interopRequireDefault(require('./Farm')); | 
						|
 | 
						|
function _interopRequireDefault(obj) { | 
						|
  return obj && obj.__esModule ? obj : {default: obj}; | 
						|
} | 
						|
 | 
						|
function _objectSpread(target) { | 
						|
  for (var i = 1; i < arguments.length; i++) { | 
						|
    var source = arguments[i] != null ? arguments[i] : {}; | 
						|
    var ownKeys = Object.keys(source); | 
						|
    if (typeof Object.getOwnPropertySymbols === 'function') { | 
						|
      ownKeys = ownKeys.concat( | 
						|
        Object.getOwnPropertySymbols(source).filter(function(sym) { | 
						|
          return Object.getOwnPropertyDescriptor(source, sym).enumerable; | 
						|
        }) | 
						|
      ); | 
						|
    } | 
						|
    ownKeys.forEach(function(key) { | 
						|
      _defineProperty(target, key, source[key]); | 
						|
    }); | 
						|
  } | 
						|
  return target; | 
						|
} | 
						|
 | 
						|
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; | 
						|
} | 
						|
 | 
						|
function getExposedMethods(workerPath, options) { | 
						|
  let exposedMethods = options.exposedMethods; // If no methods list is given, try getting it by auto-requiring the module. | 
						|
 | 
						|
  if (!exposedMethods) { | 
						|
    const module = require(workerPath); | 
						|
 | 
						|
    exposedMethods = Object.keys(module).filter( | 
						|
      // @ts-ignore: no index | 
						|
      name => typeof module[name] === 'function' | 
						|
    ); | 
						|
 | 
						|
    if (typeof module === 'function') { | 
						|
      exposedMethods = [...exposedMethods, 'default']; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  return exposedMethods; | 
						|
} | 
						|
/** | 
						|
 * The Jest farm (publicly called "Worker") is a class that allows you to queue | 
						|
 * methods across multiple child processes, in order to parallelize work. This | 
						|
 * is done by providing an absolute path to a module that will be loaded on each | 
						|
 * of the child processes, and bridged to the main process. | 
						|
 * | 
						|
 * Bridged methods are specified by using the "exposedMethods" property of the | 
						|
 * "options" object. This is an array of strings, where each of them corresponds | 
						|
 * to the exported name in the loaded module. | 
						|
 * | 
						|
 * You can also control the amount of workers by using the "numWorkers" property | 
						|
 * of the "options" object, and the settings passed to fork the process through | 
						|
 * the "forkOptions" property. The amount of workers defaults to the amount of | 
						|
 * CPUS minus one. | 
						|
 * | 
						|
 * Queueing calls can be done in two ways: | 
						|
 *   - Standard method: calls will be redirected to the first available worker, | 
						|
 *     so they will get executed as soon as they can. | 
						|
 * | 
						|
 *   - Sticky method: if a "computeWorkerKey" method is provided within the | 
						|
 *     config, the resulting string of this method will be used as a key. | 
						|
 *     Every time this key is returned, it is guaranteed that your job will be | 
						|
 *     processed by the same worker. This is specially useful if your workers | 
						|
 *     are caching results. | 
						|
 */ | 
						|
 | 
						|
class JestWorker { | 
						|
  constructor(workerPath, options) { | 
						|
    _defineProperty(this, '_ending', void 0); | 
						|
 | 
						|
    _defineProperty(this, '_farm', void 0); | 
						|
 | 
						|
    _defineProperty(this, '_options', void 0); | 
						|
 | 
						|
    _defineProperty(this, '_workerPool', void 0); | 
						|
 | 
						|
    this._options = _objectSpread({}, options); | 
						|
    this._ending = false; | 
						|
    const workerPoolOptions = { | 
						|
      enableWorkerThreads: this._options.enableWorkerThreads || false, | 
						|
      forkOptions: this._options.forkOptions || {}, | 
						|
      maxRetries: this._options.maxRetries || 3, | 
						|
      numWorkers: | 
						|
        this._options.numWorkers || | 
						|
        Math.max(_os().default.cpus().length - 1, 1), | 
						|
      setupArgs: this._options.setupArgs || [] | 
						|
    }; | 
						|
 | 
						|
    if (this._options.WorkerPool) { | 
						|
      // @ts-ignore: constructor target any? | 
						|
      this._workerPool = new this._options.WorkerPool( | 
						|
        workerPath, | 
						|
        workerPoolOptions | 
						|
      ); | 
						|
    } else { | 
						|
      this._workerPool = new _WorkerPool.default(workerPath, workerPoolOptions); | 
						|
    } | 
						|
 | 
						|
    this._farm = new _Farm.default( | 
						|
      workerPoolOptions.numWorkers, | 
						|
      this._workerPool.send.bind(this._workerPool), | 
						|
      this._options.computeWorkerKey | 
						|
    ); | 
						|
 | 
						|
    this._bindExposedWorkerMethods(workerPath, this._options); | 
						|
  } | 
						|
 | 
						|
  _bindExposedWorkerMethods(workerPath, options) { | 
						|
    getExposedMethods(workerPath, options).forEach(name => { | 
						|
      if (name.startsWith('_')) { | 
						|
        return; | 
						|
      } | 
						|
 | 
						|
      if (this.constructor.prototype.hasOwnProperty(name)) { | 
						|
        throw new TypeError('Cannot define a method called ' + name); | 
						|
      } // @ts-ignore: dynamic extension of the class instance is expected. | 
						|
 | 
						|
      this[name] = this._callFunctionWithArgs.bind(this, name); | 
						|
    }); | 
						|
  } | 
						|
 | 
						|
  _callFunctionWithArgs(method, ...args) { | 
						|
    if (this._ending) { | 
						|
      throw new Error('Farm is ended, no more calls can be done to it'); | 
						|
    } | 
						|
 | 
						|
    return this._farm.doWork(method, ...args); | 
						|
  } | 
						|
 | 
						|
  getStderr() { | 
						|
    return this._workerPool.getStderr(); | 
						|
  } | 
						|
 | 
						|
  getStdout() { | 
						|
    return this._workerPool.getStdout(); | 
						|
  } | 
						|
 | 
						|
  end() { | 
						|
    if (this._ending) { | 
						|
      throw new Error('Farm is ended, no more calls can be done to it'); | 
						|
    } | 
						|
 | 
						|
    this._workerPool.end(); | 
						|
 | 
						|
    this._ending = true; | 
						|
  } | 
						|
} | 
						|
 | 
						|
exports.default = JestWorker;
 | 
						|
 |