6

Сервер NodeJS с Mongo DB - одна функция будет генерировать отчет JSON-файла из БД, что может занять некоторое время (60 секунд - обработать сотни тысяч записей).Как выполнить/прервать выполнение длинных запусков в узле JS?

Мы хотим запустить это как фоновое задание. Нам нужно иметь возможность начать процесс сборки отчета, контролировать его и прервать его, если пользователь решит изменить параметры и восстановить его.

Каков самый простой подход с узлом? Не хотите попасть в сферы обработки отдельных рабочих серверов, очередей сообщений и т. Д. - нам нужно сохранить это в том же поле и довольно простой реализации.

1) Запустите сборку как метод асинхронизации и вернитесь к пользователю с помощью отчета о выпуске socket.io?

2) Выделите дочерний процесс для скрипта сборки?

3) Используйте что-то вроде https://www.npmjs.com/package/webworker-threads?

С несколькими подходами, на которые я смотрел, я застреваю в тех же двух областях;

1) Как отслеживать прогресс? 2) Как прервать существующий процесс сборки, если пользователь повторно передает данные?

Любые указатели больш были бы оценены ...

ответ

5

Лучше всего было бы отделить эту задачу от вашего основного приложения. Тем не менее, было бы легко запустить его в фоновом режиме. Чтобы запустить его в фоновом режиме и сохранить без очереди сообщений и т. Д., Самым простым будет child_process.

  1. Вы можете запустить задание spawn на конечной точке (или url), вызываемой пользователем.
  2. Далее, настроить socket вернуться живым мониторингом процесса
  3. ребенка Добавьте другую конечную точку, чтобы остановить работу, с уникальным идентификатором, возвращенного 1. (или нет, в зависимости от ваших потребностей параллелизма)

Некоторые кодирования идеи:

var spawn = require('child_process').spawn 

var job = null //keeping the job in memory to kill it 

app.get('/save', function(req, res) { 

    if(job && job.pid) 
     return res.status(500).send('Job is already running').end() 

    job = spawn('node', ['/path/to/save/job.js'], 
    { 
     detached: false, //if not detached and your main process dies, the child will be killed too 
     stdio: [process.stdin, process.stdout, process.stderr] //those can be file streams for logs or wathever 
    }) 

    job.on('close', function(code) { 
     job = null 
     //send socket informations about the job ending 
    }) 

    return res.status(201) //created 
}) 

app.get('/stop', function(req, res) { 
    if(!job || !job.pid) 
     return res.status(404).end() 

    job.kill('SIGTERM') 
    //or process.kill(job.pid, 'SIGTERM') 
    job = null 
    return res.status(200).end() 
}) 

app.get('/isAlive', function(req, res) { 
    try { 
     job.kill(0) 
     return res.status(200).end() 
    } catch(e) { return res.status(500).send(e).end() } 
}) 

для MONIT дочернего процесса вы могли бы использовать pidusage, мы используем его в PM2, например. Добавьте маршрут, чтобы выполнить задание и называть его каждую секунду. Не забудьте освободить память, когда работа закончится.


Вы можете проверить this library, который поможет вам управлять несколькими обработки через microservices.

+0

Спасибо за ответ @soyuka. С 'job' var - который привязывается к ссылке на дочерний элемент, поэтому вы можете остановить его, но работает ли он на PID? PID получить re использовали, не так ли? Итак, работа, которую мы создаем, может завершиться, и ее PID освободится для любого другого нового процесса? Что означает, что job.kill() может потенциально убить другой процесс, если он работает только с PID? Или это не работает так .... –

+0

Просто проверьте документы, и он говорит ... «Может выпустить событие« ошибка », когда сигнал не может быть доставлен.Отправка сигнала дочернему процессу, который уже вышел, не является ошибкой, но может иметь непредвиденные последствия: если идентификатор PID (идентификатор процесса) был переназначен другому процессу, вместо этого сигнал будет доставлен в этот процесс. Что происходит дальше - кто-то догадывается ». Но обнуление ссылки на завершение должно решить это в соответствии с вашим exmaple! Извините, пропустил это. –

+0

Этот код, кажется, разрешает только одно задание на отчет за раз и перезаписывает (и теряет следы предыдущее задание), если попытается запустить второй. – jfriend00