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.
		
		
		
		
			
				
					185 lines
				
				5.2 KiB
			
		
		
			
		
	
	
					185 lines
				
				5.2 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'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;
							 |