BaseWorkerPool.js 4.7 KB

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