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.
		
		
		
		
		
			
		
			
				
					157 lines
				
				3.4 KiB
			
		
		
			
		
	
	
					157 lines
				
				3.4 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _types() {
							 | 
						||
| 
								 | 
							
								  const data = require('../types');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _types = function () {
							 | 
						||
| 
								 | 
							
								    return data;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This source code is licensed under the MIT license found in the
							 | 
						||
| 
								 | 
							
								 * LICENSE file in the root directory of this source tree.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								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.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const messageListener = 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]
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								process.on('message', messageListener);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function reportSuccess(result) {
							 | 
						||
| 
								 | 
							
								  if (!process || !process.send) {
							 | 
						||
| 
								 | 
							
								    throw new Error('Child can only be used on a forked process');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  process.send([_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 (!process || !process.send) {
							 | 
						||
| 
								 | 
							
								    throw new Error('Child can only be used on a forked process');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (error == null) {
							 | 
						||
| 
								 | 
							
								    error = new Error('"null" or "undefined" thrown');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  process.send([
							 | 
						||
| 
								 | 
							
								    type,
							 | 
						||
| 
								 | 
							
								    error.constructor && error.constructor.name,
							 | 
						||
| 
								 | 
							
								    error.message,
							 | 
						||
| 
								 | 
							
								    error.stack,
							 | 
						||
| 
								 | 
							
								    typeof error === 'object' ? {...error} : error
							 | 
						||
| 
								 | 
							
								  ]);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function end() {
							 | 
						||
| 
								 | 
							
								  const main = require(file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!main.teardown) {
							 | 
						||
| 
								 | 
							
								    exitProcess();
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  execFunction(main.teardown, main, [], exitProcess, exitProcess);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function exitProcess() {
							 | 
						||
| 
								 | 
							
								  // Clean up open handles so the process ideally exits gracefully
							 | 
						||
| 
								 | 
							
								  process.removeListener('message', messageListener);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const isPromise = obj =>
							 | 
						||
| 
								 | 
							
								  !!obj &&
							 | 
						||
| 
								 | 
							
								  (typeof obj === 'object' || typeof obj === 'function') &&
							 | 
						||
| 
								 | 
							
								  typeof obj.then === 'function';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function execFunction(fn, ctx, args, onResult, onError) {
							 | 
						||
| 
								 | 
							
								  let result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    result = fn.apply(ctx, args);
							 | 
						||
| 
								 | 
							
								  } catch (err) {
							 | 
						||
| 
								 | 
							
								    onError(err);
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (isPromise(result)) {
							 | 
						||
| 
								 | 
							
								    result.then(onResult, onError);
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    onResult(result);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |