123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- /**
- * Copyright 2013-2022 the PM2 project authors. All rights reserved.
- * Use of this source code is governed by a license that
- * can be found in the LICENSE file.
- */
- 'use strict';
- /**
- * @file Reload functions related
- * @author Alexandre Strzelewicz <as@unitech.io>
- * @project PM2
- */
- var cst = require('../../constants.js');
- var Utility = require('../Utility.js');
- /**
- * softReload will wait permission from process to exit
- * @method softReload
- * @param {} God
- * @param {} id
- * @param {} cb
- * @return Literal
- */
- function softReload(God, id, cb) {
- var t_key = '_old_' + id;
- // Move old worker to tmp id
- God.clusters_db[t_key] = God.clusters_db[id];
- delete God.clusters_db[id];
- var old_worker = God.clusters_db[t_key];
- // Deep copy
- var new_env = Utility.clone(old_worker.pm2_env);
- // Reset created_at and unstable_restarts
- God.resetState(new_env);
- new_env.restart_time += 1;
- old_worker.pm2_env.pm_id = t_key;
- old_worker.pm_id = t_key;
- God.executeApp(new_env, function(err, new_worker) {
- if (err) return cb(err);
- var timer = null;
- var onListen = function () {
- clearTimeout(timer);
- softCleanDeleteProcess();
- console.log('-softReload- New worker listening');
- };
- // Bind to know when the new process is up
- new_worker.once('listening', onListen);
- timer = setTimeout(function() {
- new_worker.removeListener('listening', onListen);
- softCleanDeleteProcess();
- }, new_env.listen_timeout || cst.GRACEFUL_LISTEN_TIMEOUT);
- // Remove old worker properly
- var softCleanDeleteProcess = function () {
- var cleanUp = function () {
- clearTimeout(timer);
- console.log('-softReload- Old worker disconnected');
- return God.deleteProcessId(t_key, cb);
- };
- old_worker.once('disconnect', cleanUp);
- try {
- if (old_worker.state != 'dead' && old_worker.state != 'disconnected')
- old_worker.send && old_worker.send('shutdown');
- else {
- clearTimeout(timer);
- console.error('Worker %d is already disconnected', old_worker.pm2_env.pm_id);
- return God.deleteProcessId(t_key, cb);
- }
- } catch(e) {
- clearTimeout(timer);
- console.error('Worker %d is already disconnected', old_worker.pm2_env.pm_id);
- return God.deleteProcessId(t_key, cb);
- }
- timer = setTimeout(function () {
- old_worker.removeListener('disconnect', cleanUp);
- return God.deleteProcessId(t_key, cb);
- }, cst.GRACEFUL_TIMEOUT);
- return false;
- };
- return false;
- });
- return false;
- };
- /**
- * hardReload will reload without waiting permission from process
- * @method hardReload
- * @param {} God
- * @param {} id
- * @param {} cb
- * @return Literal
- */
- function hardReload(God, id, wait_msg, cb) {
- var t_key = '_old_' + id;
- // Move old worker to tmp id
- God.clusters_db[t_key] = God.clusters_db[id];
- delete God.clusters_db[id];
- var old_worker = God.clusters_db[t_key];
- // Deep copy
- var new_env = Utility.clone(old_worker.pm2_env);
- new_env.restart_time += 1;
- // Reset created_at and unstable_restarts
- God.resetState(new_env);
- old_worker.pm2_env.pm_id = t_key;
- old_worker.pm_id = t_key;
- var timer = null;
- var readySignalSent = false;
-
- var onListen = function () {
- clearTimeout(timer);
- readySignalSent = true;
- console.log('-reload- New worker listening');
- return God.deleteProcessId(t_key, cb);
- };
-
- var listener = function (packet) {
- if (packet.raw === 'ready' &&
- packet.process.name === old_worker.pm2_env.name &&
- packet.process.pm_id === id) {
- God.bus.removeListener('process:msg', listener);
- return onListen();
- }
- };
-
- if (wait_msg !== 'listening') {
- God.bus.on('process:msg', listener);
- }
-
- God.executeApp(new_env, function(err, new_worker) {
- if (err) return cb(err);
- // Bind to know when the new process is up
- if (wait_msg === 'listening') {
- new_worker.once('listening', onListen);
- }
- timer = setTimeout(function() {
- if (readySignalSent) {
- return;
- }
-
- if (wait_msg === 'listening')
- new_worker.removeListener(wait_msg, onListen);
- else
- God.bus.removeListener('process:msg', listener);
- return God.deleteProcessId(t_key, cb);
- }, new_env.listen_timeout || cst.GRACEFUL_LISTEN_TIMEOUT);
- return false;
- });
- return false;
- };
- /**
- * Description
- * @method exports
- * @param {} God
- * @return
- */
- module.exports = function(God) {
- /**
- * Reload
- * @method softReloadProcessId
- * @param {} id
- * @param {} cb
- * @return CallExpression
- */
- God.softReloadProcessId = function(opts, cb) {
- var id = opts.id;
- var env = opts.env || {};
- if (!(id in God.clusters_db))
- return cb(new Error(`pm_id ${id} not available in ${id}`));
- if (God.clusters_db[id].pm2_env.status == cst.ONLINE_STATUS &&
- God.clusters_db[id].pm2_env.exec_mode == 'cluster_mode' &&
- !God.clusters_db[id].pm2_env.wait_ready) {
- Utility.extend(God.clusters_db[id].pm2_env.env, opts.env);
- Utility.extendExtraConfig(God.clusters_db[id], opts);
- return softReload(God, id, cb);
- }
- else {
- console.log('Process %s in a stopped status, starting it', id);
- return God.restartProcessId(opts, cb);
- }
- };
- /**
- * Reload
- * @method reloadProcessId
- * @param {} id
- * @param {} cb
- * @return CallExpression
- */
- God.reloadProcessId = function(opts, cb) {
- var id = opts.id;
- var env = opts.env || {};
- if (!(id in God.clusters_db))
- return cb(new Error('PM2 ID unknown'));
- if (God.clusters_db[id].pm2_env.status == cst.ONLINE_STATUS &&
- God.clusters_db[id].pm2_env.exec_mode == 'cluster_mode') {
- Utility.extend(God.clusters_db[id].pm2_env.env, opts.env);
- Utility.extendExtraConfig(God.clusters_db[id], opts);
- var wait_msg = God.clusters_db[id].pm2_env.wait_ready ? 'ready' : 'listening';
- return hardReload(God, id, wait_msg, cb);
- }
- else {
- console.log('Process %s in a stopped status, starting it', id);
- return God.restartProcessId(opts, cb);
- }
- };
- };
|