Совместное использование глобального объекта между узлами процесса.

1

У меня проблемы с процессами с помощью Node.js

Поэтому у меня есть реализация родительского/дочернего процесса для отправки gps-информации устройства, и мне нужно разделить токен с устройства между родителем и дочерним.

Моя проблема в том, что thay не разделяет этот объект, и ребенок всегда просит новый tokwn. вместо того, чтобы использовать то же самое до истечения срока его действия.

Мой токен - это что-то вроде:

{"token":"f93cefe254ca873755b3bbbdca2f4c94","timeout":300,"expire":1512552810822}

И когда я отлаживаю в runChild, я всегда получаю разные значения для radioAccess и для каждого нового токена, который мне нужен, я делаю новый запрос на устройство...

Что я могу сделать, чтобы перенести глобальный объект "radioAcess"?

nsGPSService.js

  require('./globals');

var listRoutDirectories = getDirectories(routeDirectory);
for (var i = 0; i < listRoutDirectories.length; i++) {
    var directoryName = listRoutDirectories[i];
    var directoryPath = routeDirectory + '/' + listRoutDirectories[i];
    var directoryFiles = getFiles(directoryPath);

    for (var j = 0; j < directoryFiles.length; j++) {
        var file = directoryFiles[j];
        if (file.indexOf('Controller.js') > -1) {
            global.Controllers[file.replace('Controller.js', '')] = require(directoryPath + '/' + file);
        } else if (file.indexOf('Model.js') > -1) {
            global.Models[file.replace('Model.js', '')] = require(directoryPath + '/' + file);
        } else if (file.indexOf('Database.js') > -1) {
            global.Database[file.replace('Database.js', '')] = require(directoryPath + '/' + file);
        }
    }
}

var child_process = require("child_process");
var argv = require('minimist')(process.argv.slice(2));

//ex: nsGPSService.js -d 1111-11-11-111
var deviceId = argv.d;
var processDevices = [];

function runParent () {
    setTimeout(function() {
    var numDevice = 1;
        createLog('info', __dirname, __filename.slice(__dirname.length + 1, -3), null, 'runParent', "");
        return Database.Devices.getDevices().then(function (devices) {
            return new Promise(function (resolve, reject) {
                async.each(devices, function (device, callback) {   
                    var result = _.filter(processDevices, {"id": device.id});

                    if(result.length == 0) {
                        logger.info('WSController-Service', 'runParent', 'getRadioInfo  --> ', device.id, ' :: ', numDevice++, '/', devices.length);
                        var process = child_process.fork(__dirname + '/nsGPSService.js', ["-d", device.id]);

                        processDevices.push({ "process": process, "id": device.id });

                        process.radioAccess = radioAccess[deviceId] || {};

                        createLog('debug', __dirname, __filename.slice(__dirname.length + 1, -3), device.id, 'runParent', 'process.radioAccess ', process.radioAccess);


                        process.on('message', function(data) {
                            //receber mensagens do filho
                            createLog('debug', __dirname, __filename.slice(__dirname.length + 1, -3), data.deviceId, 'runParent data', data);
                            if(data.reason == "deleted") {
                               //child acabou o processo e informa o parent para remover da lista
                                var index = _.findIndex(processDevices, {"id": data.deviceId});
                                processDevices.splice(index, 1);
                            }
                        });
                        process.on('exit', function(code) {
                            createLog('debug', __dirname, __filename.slice(__dirname.length + 1, -3), device.id, 'runParent', 'Exiting with code', code);   
                        });
                        process.on("uncaughtException", function (error) {
                            createLog('error', __dirname, __filename.slice(__dirname.length + 1, -3), device.id, 'runParent', 'error', error);
                            process.exit(1);
                        });
                    }

                    callback();
                }, function(error) {
                    // createLog('error', __dirname, __filename.slice(__dirname.length + 1, -3), null, 'runParent', 'error', error);
                     error ? reject(error) : resolve();
                });
            }).then(function() {
                runParent()
            }).catch(function(error) {
                createLog('error', __dirname, __filename.slice(__dirname.length + 1, -3), null, 'runParent', 'catch error', error);
                runParent()
            });
        }); 
    },5000);
}

if(!deviceId) {
    createLog('info', __dirname, __filename.slice(__dirname.length + 1, -3), deviceId, 'runParent');
    runParent();
}

function runChild (id) {
    createLog('info', __dirname, __filename.slice(__dirname.length + 1, -3), id, 'runChild', "");
    setTimeout(function() {
        return Database.Devices.getDeviceById(id).then(function(device) {
            process.radioAccess = radioAccess[deviceId] || {};
            createLog('debug', __dirname, __filename.slice(__dirname.length + 1, -3), device.id, 'runChild', 'process.radioAccess 1', process.radioAccess);
            if(!device) {
                process.exit();
                return;
            }
            return Controllers.Gps.getRadioInfo('gps', 'info', {}, device).then(function (data) {
                createLog('debug', __dirname, __filename.slice(__dirname.length + 1, - 3), id, 'runChild', 'data', data);

                createLog('debug', __dirname, __filename.slice(__dirname.length + 1, -3), device.id, 'runChild', 'process.radioAccess 2', process.radioAccess);

                return Controllers.Gps.sendDeviceInfo(data, device);
            }).then(function() {
                return runChild(id);
            }).catch(function (e) {
                createLog('error', __dirname, __filename.slice(__dirname.length + 1, - 3), id, 'runChild callback error', e);
                return runChild(id);    
            });
        });
    }, 5000);
}

 runChild(deviceId);

globals.js

global.radioAccess   = {};

Я попытался использовать глобальный процесс и добавить "process.radioAcess", но родитель всегда дает {}, а дочерние элементы can not сохраняют токен.

  • 0
    почему бы вам не попробовать записать и прочитать токен из файла? Когда вы будете готовы запросить токен, сначала проверьте, существует ли файл, и если он есть, используйте там токен; в противном случае создайте новый токен и запишите в файл. удалить файл в соответствующем месте в логике.
  • 0
    У меня не может быть прав доступа для записи в файл в mahcine, где находится код .. поэтому, если мне нужно только записать, нет проблем, но удалить и изменить это не жизнеспособно ... Мне действительно нужно разделить глобальный var между parent и child и обновлять токен только после истечения срока действия ..
Показать ещё 7 комментариев
Теги:

1 ответ

0

Вот рабочий пример того, как вы можете это сделать. Пожалуйста, будьте осторожны, пытаясь отправлять сообщения от процессов до их инициализации (пример в two.js), а в main.js я выхожу из процессов в таймаут, чтобы дать two.js возможность отправить что-то в one.js

Отладка это очень сложно, я не знаю, почему, но хром-отладчик не может присоединяться к дочерним процессам и не останавливается на операторах отладчика. Также не отображается ни одно из операторов console.log из дочерних процессов.

main.js

const fork = require('child_process').fork;
const path = require('path');

const[one,two] = ["one.js","two.js"]
  .map(
    fileName => [path.resolve(fileName),fileName]
  )
  .map(
    ([file,fileName]) => {
      const x = fork(
        file, 
        [], 
        {
          stdio: [ 'pipe', 'pipe', 'pipe', 'ipc' ],
          silent:false
        }
      );
      x.stderr.on(//doesn't do anything
        'error', 
        data =>
          console.log('got error from ${fileName}:',data)
      );
      x.on(
        'message',
        message =>
          (message.type==="relay")
            ? one.send({type:"ping",text:'relayed from ${fileName}: ${message.text}'})
            : console.log('got message from ${fileName}:',message.text)
      );
      return x;
    }
  );
setTimeout(
  _=>{
    //do this after two can send relayd message (after the send on the que from two)
    one.send({type:"ping",text:"hello one"})
    one.send({type:"exit"})
    two.send({type:"ping",text:"hello two"})
    two.send({type:"exit"})
  }
  ,100
);

two.js

//process is impossible to debug:
// debugger;//never breaks and about:inspect in chrome
//   after init doesn't show this process either
// console.log("useless in forked process"); console.log doesn't show

const processMessage = message => {
  switch (message.type) {
    case "exit":
      process.send({type:"string",text:"Going to exit."});
      process.exit(0);
      break;
    case "ping":
      process.send({type:"string",text:message.text});
      break;
    default:
      process.send({type:"string",text:"unknown message"});
  }
};

process.on(
  'message',
  message =>
    processMessage(message)
);

//this part is not in one.js
Promise.resolve()
.then(
  //send message after main had time to initialize all processes
  x=>process.send({type:"relay",text:"HELLO THERE ONE"})
)

one.js

То же, что и two.js, но без последней части.

  • 0
    Я попробовал такой подход, но Шанель закрыли. Здесь stackoverflow.com/questions/47677083/…
  • 0
    Давайте обсудим это в чате PLS? @HMR

Ещё вопросы

Сообщество Overcoder
Наверх
Меню