TaskRunner.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _os = _interopRequireDefault(require("os"));
  7. var _pLimit = _interopRequireDefault(require("p-limit"));
  8. var _jestWorker = _interopRequireDefault(require("jest-worker"));
  9. var _serializeJavascript = _interopRequireDefault(require("serialize-javascript"));
  10. var _minify = _interopRequireDefault(require("./minify"));
  11. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  12. const workerPath = require.resolve('./worker');
  13. class TaskRunner {
  14. constructor(options = {}) {
  15. this.taskGenerator = options.taskGenerator;
  16. this.files = options.files;
  17. this.cache = options.cache;
  18. this.availableNumberOfCores = TaskRunner.getAvailableNumberOfCores(options.parallel);
  19. }
  20. static getAvailableNumberOfCores(parallel) {
  21. // In some cases cpus() returns undefined
  22. // https://github.com/nodejs/node/issues/19022
  23. const cpus = _os.default.cpus() || {
  24. length: 1
  25. };
  26. return parallel === true ? cpus.length - 1 : Math.min(Number(parallel) || 0, cpus.length - 1);
  27. }
  28. async runTask(task) {
  29. if (this.worker) {
  30. return this.worker.transform((0, _serializeJavascript.default)(task));
  31. }
  32. return (0, _minify.default)(task);
  33. }
  34. async run() {
  35. const {
  36. availableNumberOfCores,
  37. cache,
  38. files,
  39. taskGenerator
  40. } = this;
  41. let concurrency = Infinity;
  42. if (availableNumberOfCores > 0) {
  43. // Do not create unnecessary workers when the number of files is less than the available cores, it saves memory
  44. const numWorkers = Math.min(files.length, availableNumberOfCores);
  45. concurrency = numWorkers;
  46. this.worker = new _jestWorker.default(workerPath, {
  47. numWorkers
  48. }); // https://github.com/facebook/jest/issues/8872#issuecomment-524822081
  49. const workerStdout = this.worker.getStdout();
  50. if (workerStdout) {
  51. workerStdout.on('data', chunk => {
  52. return process.stdout.write(chunk);
  53. });
  54. }
  55. const workerStderr = this.worker.getStderr();
  56. if (workerStderr) {
  57. workerStderr.on('data', chunk => {
  58. return process.stderr.write(chunk);
  59. });
  60. }
  61. }
  62. const limit = (0, _pLimit.default)(concurrency);
  63. const scheduledTasks = [];
  64. for (const file of files) {
  65. const enqueue = async task => {
  66. let taskResult;
  67. try {
  68. taskResult = await this.runTask(task);
  69. } catch (error) {
  70. taskResult = {
  71. error
  72. };
  73. }
  74. if (cache.isEnabled() && !taskResult.error) {
  75. taskResult = await cache.store(task, taskResult).then(() => taskResult, () => taskResult);
  76. }
  77. task.callback(taskResult);
  78. return taskResult;
  79. };
  80. scheduledTasks.push(limit(() => {
  81. const task = taskGenerator(file).next().value;
  82. if (!task) {
  83. // Something went wrong, for example the `cacheKeys` option throw an error
  84. return Promise.resolve();
  85. }
  86. if (cache.isEnabled()) {
  87. return cache.get(task).then(taskResult => task.callback(taskResult), () => enqueue(task));
  88. }
  89. return enqueue(task);
  90. }));
  91. }
  92. return Promise.all(scheduledTasks);
  93. }
  94. async exit() {
  95. if (!this.worker) {
  96. return Promise.resolve();
  97. }
  98. return this.worker.end();
  99. }
  100. }
  101. exports.default = TaskRunner;