BaseWorkerPool.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. function path() {
  7. const data = _interopRequireWildcard(require('path'));
  8. path = function () {
  9. return data;
  10. };
  11. return data;
  12. }
  13. function _mergeStream() {
  14. const data = _interopRequireDefault(require('merge-stream'));
  15. _mergeStream = function () {
  16. return data;
  17. };
  18. return data;
  19. }
  20. var _types = require('../types');
  21. function _interopRequireDefault(obj) {
  22. return obj && obj.__esModule ? obj : {default: obj};
  23. }
  24. function _getRequireWildcardCache(nodeInterop) {
  25. if (typeof WeakMap !== 'function') return null;
  26. var cacheBabelInterop = new WeakMap();
  27. var cacheNodeInterop = new WeakMap();
  28. return (_getRequireWildcardCache = function (nodeInterop) {
  29. return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
  30. })(nodeInterop);
  31. }
  32. function _interopRequireWildcard(obj, nodeInterop) {
  33. if (!nodeInterop && obj && obj.__esModule) {
  34. return obj;
  35. }
  36. if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
  37. return {default: obj};
  38. }
  39. var cache = _getRequireWildcardCache(nodeInterop);
  40. if (cache && cache.has(obj)) {
  41. return cache.get(obj);
  42. }
  43. var newObj = {};
  44. var hasPropertyDescriptor =
  45. Object.defineProperty && Object.getOwnPropertyDescriptor;
  46. for (var key in obj) {
  47. if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
  48. var desc = hasPropertyDescriptor
  49. ? Object.getOwnPropertyDescriptor(obj, key)
  50. : null;
  51. if (desc && (desc.get || desc.set)) {
  52. Object.defineProperty(newObj, key, desc);
  53. } else {
  54. newObj[key] = obj[key];
  55. }
  56. }
  57. }
  58. newObj.default = obj;
  59. if (cache) {
  60. cache.set(obj, newObj);
  61. }
  62. return newObj;
  63. }
  64. function _defineProperty(obj, key, value) {
  65. if (key in obj) {
  66. Object.defineProperty(obj, key, {
  67. value: value,
  68. enumerable: true,
  69. configurable: true,
  70. writable: true
  71. });
  72. } else {
  73. obj[key] = value;
  74. }
  75. return obj;
  76. }
  77. // How long to wait for the child process to terminate
  78. // after CHILD_MESSAGE_END before sending force exiting.
  79. const FORCE_EXIT_DELAY = 500;
  80. /* istanbul ignore next */
  81. const emptyMethod = () => {};
  82. class BaseWorkerPool {
  83. constructor(workerPath, options) {
  84. _defineProperty(this, '_stderr', void 0);
  85. _defineProperty(this, '_stdout', void 0);
  86. _defineProperty(this, '_options', void 0);
  87. _defineProperty(this, '_workers', void 0);
  88. this._options = options;
  89. this._workers = new Array(options.numWorkers);
  90. if (!path().isAbsolute(workerPath)) {
  91. workerPath = require.resolve(workerPath);
  92. }
  93. const stdout = (0, _mergeStream().default)();
  94. const stderr = (0, _mergeStream().default)();
  95. const {forkOptions, maxRetries, resourceLimits, setupArgs} = options;
  96. for (let i = 0; i < options.numWorkers; i++) {
  97. const workerOptions = {
  98. forkOptions,
  99. maxRetries,
  100. resourceLimits,
  101. setupArgs,
  102. workerId: i,
  103. workerPath
  104. };
  105. const worker = this.createWorker(workerOptions);
  106. const workerStdout = worker.getStdout();
  107. const workerStderr = worker.getStderr();
  108. if (workerStdout) {
  109. stdout.add(workerStdout);
  110. }
  111. if (workerStderr) {
  112. stderr.add(workerStderr);
  113. }
  114. this._workers[i] = worker;
  115. }
  116. this._stdout = stdout;
  117. this._stderr = stderr;
  118. }
  119. getStderr() {
  120. return this._stderr;
  121. }
  122. getStdout() {
  123. return this._stdout;
  124. }
  125. getWorkers() {
  126. return this._workers;
  127. }
  128. getWorkerById(workerId) {
  129. return this._workers[workerId];
  130. }
  131. createWorker(_workerOptions) {
  132. throw Error('Missing method createWorker in WorkerPool');
  133. }
  134. async end() {
  135. // We do not cache the request object here. If so, it would only be only
  136. // processed by one of the workers, and we want them all to close.
  137. const workerExitPromises = this._workers.map(async worker => {
  138. worker.send(
  139. [_types.CHILD_MESSAGE_END, false],
  140. emptyMethod,
  141. emptyMethod,
  142. emptyMethod
  143. ); // Schedule a force exit in case worker fails to exit gracefully so
  144. // await worker.waitForExit() never takes longer than FORCE_EXIT_DELAY
  145. let forceExited = false;
  146. const forceExitTimeout = setTimeout(() => {
  147. worker.forceExit();
  148. forceExited = true;
  149. }, FORCE_EXIT_DELAY);
  150. await worker.waitForExit(); // Worker ideally exited gracefully, don't send force exit then
  151. clearTimeout(forceExitTimeout);
  152. return forceExited;
  153. });
  154. const workerExits = await Promise.all(workerExitPromises);
  155. return workerExits.reduce(
  156. (result, forceExited) => ({
  157. forceExited: result.forceExited || forceExited
  158. }),
  159. {
  160. forceExited: false
  161. }
  162. );
  163. }
  164. }
  165. exports.default = BaseWorkerPool;