You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					177 lines
				
				4.0 KiB
			
		
		
			
		
	
	
					177 lines
				
				4.0 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _worker_threads() {
							 | 
						||
| 
								 | 
							
								  const data = require('worker_threads');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _worker_threads = function _worker_threads() {
							 | 
						||
| 
								 | 
							
								    return data;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _types = require('../types');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _objectSpread(target) {
							 | 
						||
| 
								 | 
							
								  for (var i = 1; i < arguments.length; i++) {
							 | 
						||
| 
								 | 
							
								    var source = arguments[i] != null ? arguments[i] : {};
							 | 
						||
| 
								 | 
							
								    var ownKeys = Object.keys(source);
							 | 
						||
| 
								 | 
							
								    if (typeof Object.getOwnPropertySymbols === 'function') {
							 | 
						||
| 
								 | 
							
								      ownKeys = ownKeys.concat(
							 | 
						||
| 
								 | 
							
								        Object.getOwnPropertySymbols(source).filter(function(sym) {
							 | 
						||
| 
								 | 
							
								          return Object.getOwnPropertyDescriptor(source, sym).enumerable;
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    ownKeys.forEach(function(key) {
							 | 
						||
| 
								 | 
							
								      _defineProperty(target, key, source[key]);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return target;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _defineProperty(obj, key, value) {
							 | 
						||
| 
								 | 
							
								  if (key in obj) {
							 | 
						||
| 
								 | 
							
								    Object.defineProperty(obj, key, {
							 | 
						||
| 
								 | 
							
								      value: value,
							 | 
						||
| 
								 | 
							
								      enumerable: true,
							 | 
						||
| 
								 | 
							
								      configurable: true,
							 | 
						||
| 
								 | 
							
								      writable: true
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    obj[key] = value;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return obj;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let file = null;
							 | 
						||
| 
								 | 
							
								let setupArgs = [];
							 | 
						||
| 
								 | 
							
								let initialized = false;
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * This file is a small bootstrapper for workers. It sets up the communication
							 | 
						||
| 
								 | 
							
								 * between the worker and the parent process, interpreting parent messages and
							 | 
						||
| 
								 | 
							
								 * sending results back.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The file loaded will be lazily initialized the first time any of the workers
							 | 
						||
| 
								 | 
							
								 * is called. This is done for optimal performance: if the farm is initialized,
							 | 
						||
| 
								 | 
							
								 * but no call is made to it, child Node processes will be consuming the least
							 | 
						||
| 
								 | 
							
								 * possible amount of memory.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * If an invalid message is detected, the child will exit (by throwing) with a
							 | 
						||
| 
								 | 
							
								 * non-zero exit code.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								_worker_threads().parentPort.on('message', request => {
							 | 
						||
| 
								 | 
							
								  switch (request[0]) {
							 | 
						||
| 
								 | 
							
								    case _types.CHILD_MESSAGE_INITIALIZE:
							 | 
						||
| 
								 | 
							
								      const init = request;
							 | 
						||
| 
								 | 
							
								      file = init[2];
							 | 
						||
| 
								 | 
							
								      setupArgs = request[3];
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case _types.CHILD_MESSAGE_CALL:
							 | 
						||
| 
								 | 
							
								      const call = request;
							 | 
						||
| 
								 | 
							
								      execMethod(call[2], call[3]);
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case _types.CHILD_MESSAGE_END:
							 | 
						||
| 
								 | 
							
								      end();
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      throw new TypeError(
							 | 
						||
| 
								 | 
							
								        'Unexpected request from parent process: ' + request[0]
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function reportSuccess(result) {
							 | 
						||
| 
								 | 
							
								  if (_worker_threads().isMainThread) {
							 | 
						||
| 
								 | 
							
								    throw new Error('Child can only be used on a forked process');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _worker_threads().parentPort.postMessage([_types.PARENT_MESSAGE_OK, result]);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function reportClientError(error) {
							 | 
						||
| 
								 | 
							
								  return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function reportInitializeError(error) {
							 | 
						||
| 
								 | 
							
								  return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function reportError(error, type) {
							 | 
						||
| 
								 | 
							
								  if (_worker_threads().isMainThread) {
							 | 
						||
| 
								 | 
							
								    throw new Error('Child can only be used on a forked process');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (error == null) {
							 | 
						||
| 
								 | 
							
								    error = new Error('"null" or "undefined" thrown');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _worker_threads().parentPort.postMessage([
							 | 
						||
| 
								 | 
							
								    type,
							 | 
						||
| 
								 | 
							
								    error.constructor && error.constructor.name,
							 | 
						||
| 
								 | 
							
								    error.message,
							 | 
						||
| 
								 | 
							
								    error.stack,
							 | 
						||
| 
								 | 
							
								    typeof error === 'object' ? _objectSpread({}, error) : error
							 | 
						||
| 
								 | 
							
								  ]);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function end() {
							 | 
						||
| 
								 | 
							
								  const main = require(file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!main.teardown) {
							 | 
						||
| 
								 | 
							
								    exitProcess();
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  execFunction(main.teardown, main, [], exitProcess, exitProcess);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function exitProcess() {
							 | 
						||
| 
								 | 
							
								  process.exit(0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function execMethod(method, args) {
							 | 
						||
| 
								 | 
							
								  const main = require(file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let fn;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (method === 'default') {
							 | 
						||
| 
								 | 
							
								    fn = main.__esModule ? main['default'] : main;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    fn = main[method];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function execHelper() {
							 | 
						||
| 
								 | 
							
								    execFunction(fn, main, args, reportSuccess, reportClientError);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (initialized || !main.setup) {
							 | 
						||
| 
								 | 
							
								    execHelper();
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  initialized = true;
							 | 
						||
| 
								 | 
							
								  execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function execFunction(fn, ctx, args, onResult, onError) {
							 | 
						||
| 
								 | 
							
								  let result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    result = fn.apply(ctx, args);
							 | 
						||
| 
								 | 
							
								  } catch (err) {
							 | 
						||
| 
								 | 
							
								    onError(err);
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (result && typeof result.then === 'function') {
							 | 
						||
| 
								 | 
							
								    result.then(onResult, onError);
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    onResult(result);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |