threadChild.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. 'use strict';
  2. function _worker_threads() {
  3. const data = require('worker_threads');
  4. _worker_threads = function _worker_threads() {
  5. return data;
  6. };
  7. return data;
  8. }
  9. var _types = require('../types');
  10. function _objectSpread(target) {
  11. for (var i = 1; i < arguments.length; i++) {
  12. var source = arguments[i] != null ? arguments[i] : {};
  13. var ownKeys = Object.keys(source);
  14. if (typeof Object.getOwnPropertySymbols === 'function') {
  15. ownKeys = ownKeys.concat(
  16. Object.getOwnPropertySymbols(source).filter(function(sym) {
  17. return Object.getOwnPropertyDescriptor(source, sym).enumerable;
  18. })
  19. );
  20. }
  21. ownKeys.forEach(function(key) {
  22. _defineProperty(target, key, source[key]);
  23. });
  24. }
  25. return target;
  26. }
  27. function _defineProperty(obj, key, value) {
  28. if (key in obj) {
  29. Object.defineProperty(obj, key, {
  30. value: value,
  31. enumerable: true,
  32. configurable: true,
  33. writable: true
  34. });
  35. } else {
  36. obj[key] = value;
  37. }
  38. return obj;
  39. }
  40. let file = null;
  41. let setupArgs = [];
  42. let initialized = false;
  43. /**
  44. * This file is a small bootstrapper for workers. It sets up the communication
  45. * between the worker and the parent process, interpreting parent messages and
  46. * sending results back.
  47. *
  48. * The file loaded will be lazily initialized the first time any of the workers
  49. * is called. This is done for optimal performance: if the farm is initialized,
  50. * but no call is made to it, child Node processes will be consuming the least
  51. * possible amount of memory.
  52. *
  53. * If an invalid message is detected, the child will exit (by throwing) with a
  54. * non-zero exit code.
  55. */
  56. _worker_threads().parentPort.on('message', request => {
  57. switch (request[0]) {
  58. case _types.CHILD_MESSAGE_INITIALIZE:
  59. const init = request;
  60. file = init[2];
  61. setupArgs = request[3];
  62. break;
  63. case _types.CHILD_MESSAGE_CALL:
  64. const call = request;
  65. execMethod(call[2], call[3]);
  66. break;
  67. case _types.CHILD_MESSAGE_END:
  68. end();
  69. break;
  70. default:
  71. throw new TypeError(
  72. 'Unexpected request from parent process: ' + request[0]
  73. );
  74. }
  75. });
  76. function reportSuccess(result) {
  77. if (_worker_threads().isMainThread) {
  78. throw new Error('Child can only be used on a forked process');
  79. }
  80. _worker_threads().parentPort.postMessage([_types.PARENT_MESSAGE_OK, result]);
  81. }
  82. function reportClientError(error) {
  83. return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR);
  84. }
  85. function reportInitializeError(error) {
  86. return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR);
  87. }
  88. function reportError(error, type) {
  89. if (_worker_threads().isMainThread) {
  90. throw new Error('Child can only be used on a forked process');
  91. }
  92. if (error == null) {
  93. error = new Error('"null" or "undefined" thrown');
  94. }
  95. _worker_threads().parentPort.postMessage([
  96. type,
  97. error.constructor && error.constructor.name,
  98. error.message,
  99. error.stack,
  100. typeof error === 'object' ? _objectSpread({}, error) : error
  101. ]);
  102. }
  103. function end() {
  104. const main = require(file);
  105. if (!main.teardown) {
  106. exitProcess();
  107. return;
  108. }
  109. execFunction(main.teardown, main, [], exitProcess, exitProcess);
  110. }
  111. function exitProcess() {
  112. process.exit(0);
  113. }
  114. function execMethod(method, args) {
  115. const main = require(file);
  116. let fn;
  117. if (method === 'default') {
  118. fn = main.__esModule ? main['default'] : main;
  119. } else {
  120. fn = main[method];
  121. }
  122. function execHelper() {
  123. execFunction(fn, main, args, reportSuccess, reportClientError);
  124. }
  125. if (initialized || !main.setup) {
  126. execHelper();
  127. return;
  128. }
  129. initialized = true;
  130. execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
  131. }
  132. function execFunction(fn, ctx, args, onResult, onError) {
  133. let result;
  134. try {
  135. result = fn.apply(ctx, args);
  136. } catch (err) {
  137. onError(err);
  138. return;
  139. }
  140. if (result && typeof result.then === 'function') {
  141. result.then(onResult, onError);
  142. } else {
  143. onResult(result);
  144. }
  145. }