index.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. function _os() {
  7. const data = _interopRequireDefault(require('os'));
  8. _os = function _os() {
  9. return data;
  10. };
  11. return data;
  12. }
  13. var _WorkerPool = _interopRequireDefault(require('./WorkerPool'));
  14. var _Farm = _interopRequireDefault(require('./Farm'));
  15. function _interopRequireDefault(obj) {
  16. return obj && obj.__esModule ? obj : {default: obj};
  17. }
  18. function _objectSpread(target) {
  19. for (var i = 1; i < arguments.length; i++) {
  20. var source = arguments[i] != null ? arguments[i] : {};
  21. var ownKeys = Object.keys(source);
  22. if (typeof Object.getOwnPropertySymbols === 'function') {
  23. ownKeys = ownKeys.concat(
  24. Object.getOwnPropertySymbols(source).filter(function(sym) {
  25. return Object.getOwnPropertyDescriptor(source, sym).enumerable;
  26. })
  27. );
  28. }
  29. ownKeys.forEach(function(key) {
  30. _defineProperty(target, key, source[key]);
  31. });
  32. }
  33. return target;
  34. }
  35. function _defineProperty(obj, key, value) {
  36. if (key in obj) {
  37. Object.defineProperty(obj, key, {
  38. value: value,
  39. enumerable: true,
  40. configurable: true,
  41. writable: true
  42. });
  43. } else {
  44. obj[key] = value;
  45. }
  46. return obj;
  47. }
  48. function getExposedMethods(workerPath, options) {
  49. let exposedMethods = options.exposedMethods; // If no methods list is given, try getting it by auto-requiring the module.
  50. if (!exposedMethods) {
  51. const module = require(workerPath);
  52. exposedMethods = Object.keys(module).filter(
  53. // @ts-ignore: no index
  54. name => typeof module[name] === 'function'
  55. );
  56. if (typeof module === 'function') {
  57. exposedMethods = [...exposedMethods, 'default'];
  58. }
  59. }
  60. return exposedMethods;
  61. }
  62. /**
  63. * The Jest farm (publicly called "Worker") is a class that allows you to queue
  64. * methods across multiple child processes, in order to parallelize work. This
  65. * is done by providing an absolute path to a module that will be loaded on each
  66. * of the child processes, and bridged to the main process.
  67. *
  68. * Bridged methods are specified by using the "exposedMethods" property of the
  69. * "options" object. This is an array of strings, where each of them corresponds
  70. * to the exported name in the loaded module.
  71. *
  72. * You can also control the amount of workers by using the "numWorkers" property
  73. * of the "options" object, and the settings passed to fork the process through
  74. * the "forkOptions" property. The amount of workers defaults to the amount of
  75. * CPUS minus one.
  76. *
  77. * Queueing calls can be done in two ways:
  78. * - Standard method: calls will be redirected to the first available worker,
  79. * so they will get executed as soon as they can.
  80. *
  81. * - Sticky method: if a "computeWorkerKey" method is provided within the
  82. * config, the resulting string of this method will be used as a key.
  83. * Every time this key is returned, it is guaranteed that your job will be
  84. * processed by the same worker. This is specially useful if your workers
  85. * are caching results.
  86. */
  87. class JestWorker {
  88. constructor(workerPath, options) {
  89. _defineProperty(this, '_ending', void 0);
  90. _defineProperty(this, '_farm', void 0);
  91. _defineProperty(this, '_options', void 0);
  92. _defineProperty(this, '_workerPool', void 0);
  93. this._options = _objectSpread({}, options);
  94. this._ending = false;
  95. const workerPoolOptions = {
  96. enableWorkerThreads: this._options.enableWorkerThreads || false,
  97. forkOptions: this._options.forkOptions || {},
  98. maxRetries: this._options.maxRetries || 3,
  99. numWorkers:
  100. this._options.numWorkers ||
  101. Math.max(_os().default.cpus().length - 1, 1),
  102. setupArgs: this._options.setupArgs || []
  103. };
  104. if (this._options.WorkerPool) {
  105. // @ts-ignore: constructor target any?
  106. this._workerPool = new this._options.WorkerPool(
  107. workerPath,
  108. workerPoolOptions
  109. );
  110. } else {
  111. this._workerPool = new _WorkerPool.default(workerPath, workerPoolOptions);
  112. }
  113. this._farm = new _Farm.default(
  114. workerPoolOptions.numWorkers,
  115. this._workerPool.send.bind(this._workerPool),
  116. this._options.computeWorkerKey
  117. );
  118. this._bindExposedWorkerMethods(workerPath, this._options);
  119. }
  120. _bindExposedWorkerMethods(workerPath, options) {
  121. getExposedMethods(workerPath, options).forEach(name => {
  122. if (name.startsWith('_')) {
  123. return;
  124. }
  125. if (this.constructor.prototype.hasOwnProperty(name)) {
  126. throw new TypeError('Cannot define a method called ' + name);
  127. } // @ts-ignore: dynamic extension of the class instance is expected.
  128. this[name] = this._callFunctionWithArgs.bind(this, name);
  129. });
  130. }
  131. _callFunctionWithArgs(method, ...args) {
  132. if (this._ending) {
  133. throw new Error('Farm is ended, no more calls can be done to it');
  134. }
  135. return this._farm.doWork(method, ...args);
  136. }
  137. getStderr() {
  138. return this._workerPool.getStderr();
  139. }
  140. getStdout() {
  141. return this._workerPool.getStdout();
  142. }
  143. end() {
  144. if (this._ending) {
  145. throw new Error('Farm is ended, no more calls can be done to it');
  146. }
  147. this._workerPool.end();
  148. this._ending = true;
  149. }
  150. }
  151. exports.default = JestWorker;