2016-03-22 23:33:43 +01:00
/**
2022-01-19 11:41:33 +01:00
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
2016-03-22 23:33:43 +01:00
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
2022-02-09 10:19:31 +01:00
const eachLimit = require ( 'async/eachLimit' ) ;
const debug = require ( 'debug' ) ( 'pm2:worker' ) ;
const domain = require ( 'domain' ) ;
const Cron = require ( 'croner' ) ;
const pkg = require ( '../package.json' ) ;
var cst = require ( '../constants.js' ) ;
2019-12-10 16:42:31 +01:00
var vCheck = require ( './VersionCheck.js' )
2014-11-07 17:38:37 +01:00
2014-11-10 14:45:41 +01:00
module . exports = function ( God ) {
var timer = null ;
2014-11-07 17:38:37 +01:00
2018-10-09 11:04:30 +02:00
God . CronJobs = new Map ( ) ;
2014-11-10 14:45:41 +01:00
God . Worker = { } ;
2014-11-18 18:14:34 +01:00
God . Worker . is _running = false ;
2014-11-07 17:38:37 +01:00
2019-11-18 15:36:26 +01:00
God . getCronID = function ( pm _id ) {
return ` cron- ${ pm _id } `
}
2019-11-14 23:37:35 +01:00
God . registerCron = function ( pm2 _env ) {
if ( ! pm2 _env ||
pm2 _env . pm _id === undefined ||
! pm2 _env . cron _restart ||
2021-09-24 12:40:46 +02:00
pm2 _env . cron _restart == '0' ||
2019-11-18 15:36:26 +01:00
God . CronJobs . has ( God . getCronID ( pm2 _env . pm _id ) ) )
2018-10-06 10:52:18 +02:00
return ;
2020-12-09 11:55:41 +01:00
var pm _id = pm2 _env . pm _id
console . log ( '[PM2][WORKER] Registering a cron job on:' , pm _id ) ;
2018-10-06 10:52:18 +02:00
2022-02-09 10:19:31 +01:00
var job = Cron ( pm2 _env . cron _restart , function ( ) {
2021-09-24 22:57:02 +02:00
God . restartProcessId ( { id : pm _id } , function ( err , data ) {
if ( err )
console . error ( err . stack || err ) ;
return ;
} ) ;
2018-10-06 10:52:18 +02:00
} ) ;
2020-12-09 11:55:41 +01:00
God . CronJobs . set ( God . getCronID ( pm _id ) , job ) ;
2019-11-14 23:37:35 +01:00
}
/**
* Deletes the cron job on deletion of process
*/
God . deleteCron = function ( id ) {
2019-11-18 15:36:26 +01:00
if ( typeof ( id ) !== 'undefined' && God . CronJobs . has ( God . getCronID ( id ) ) === false )
2019-11-14 23:37:35 +01:00
return ;
console . log ( '[PM2] Deregistering a cron job on:' , id ) ;
2019-11-18 15:36:26 +01:00
var job = God . CronJobs . get ( God . getCronID ( id ) ) ;
2022-02-08 10:14:16 +01:00
if ( job )
2022-02-09 10:19:31 +01:00
job . stop ( ) ;
2022-02-08 10:14:16 +01:00
2019-11-18 15:36:26 +01:00
God . CronJobs . delete ( God . getCronID ( id ) ) ;
2019-11-14 23:37:35 +01:00
} ;
var _getProcessById = function ( pm _id ) {
var proc = God . clusters _db [ pm _id ] ;
return proc ? proc : null ;
2018-10-06 10:52:18 +02:00
} ;
2014-11-18 18:14:34 +01:00
var maxMemoryRestart = function ( proc _key , cb ) {
var proc = _getProcessById ( proc _key . pm2 _env . pm _id ) ;
2014-11-18 15:41:20 +01:00
2014-11-18 18:14:34 +01:00
if ( ! ( proc &&
proc . pm2 _env &&
2014-11-21 16:53:14 +01:00
proc _key . monit ) )
2014-11-18 18:14:34 +01:00
return cb ( ) ;
2014-11-21 16:53:14 +01:00
if ( proc _key . monit . memory !== undefined &&
proc . pm2 _env . max _memory _restart !== undefined &&
2016-11-28 16:14:20 +01:00
proc . pm2 _env . max _memory _restart < proc _key . monit . memory &&
2016-11-30 10:53:30 +01:00
proc . pm2 _env . axm _options &&
2016-11-28 16:14:20 +01:00
proc . pm2 _env . axm _options . pid === undefined ) {
2016-08-06 21:13:40 -07:00
console . log ( '[PM2][WORKER] Process %s restarted because it exceeds --max-memory-restart value (current_memory=%s max_memory_limit=%s [octets])' , proc . pm2 _env . pm _id , proc _key . monit . memory , proc . pm2 _env . max _memory _restart ) ;
2020-12-09 11:55:41 +01:00
God . reloadProcessId ( {
2016-03-11 16:23:11 +01:00
id : proc . pm2 _env . pm _id
} , function ( err , data ) {
2014-11-18 18:14:34 +01:00
if ( err )
console . error ( err . stack || err ) ;
2014-11-18 15:41:20 +01:00
return cb ( ) ;
2014-11-18 18:14:34 +01:00
} ) ;
}
2014-11-21 16:53:14 +01:00
else {
2014-11-18 18:14:34 +01:00
return cb ( ) ;
2014-11-21 16:53:14 +01:00
}
2014-11-17 17:47:52 +01:00
} ;
2014-11-10 14:45:41 +01:00
var tasks = function ( ) {
2014-11-18 18:14:34 +01:00
if ( God . Worker . is _running === true ) {
debug ( '[PM2][WORKER] Worker is already running, skipping this round' ) ;
return false ;
}
God . Worker . is _running = true ;
2014-11-16 13:20:14 +01:00
2014-11-18 15:41:20 +01:00
God . getMonitorData ( null , function ( err , data ) {
2014-11-18 18:14:34 +01:00
if ( err || ! data || typeof ( data ) !== 'object' ) {
God . Worker . is _running = false ;
return console . error ( err ) ;
}
2014-11-17 17:47:52 +01:00
2018-10-03 11:17:53 +02:00
eachLimit ( data , 1 , function ( proc , next ) {
if ( ! proc || ! proc . pm2 _env || proc . pm2 _env . pm _id === undefined )
2014-11-18 18:14:34 +01:00
return next ( ) ;
2014-11-18 15:41:20 +01:00
2018-10-03 11:17:53 +02:00
debug ( '[PM2][WORKER] Processing proc id:' , proc . pm2 _env . pm _id ) ;
// Reset restart delay if application has an uptime of more > 30secs
if ( proc . pm2 _env . exp _backoff _restart _delay !== undefined &&
proc . pm2 _env . prev _restart _delay && proc . pm2 _env . prev _restart _delay > 0 ) {
var app _uptime = Date . now ( ) - proc . pm2 _env . pm _uptime
if ( app _uptime > cst . EXP _BACKOFF _RESET _TIMER ) {
var ref _proc = _getProcessById ( proc . pm2 _env . pm _id ) ;
ref _proc . pm2 _env . prev _restart _delay = 0
2020-08-11 20:59:11 +10:00
console . log ( ` [PM2][WORKER] Reset the restart delay, as app ${ proc . name } has been up for more than ${ cst . EXP _BACKOFF _RESET _TIMER } ms ` )
2018-10-03 11:17:53 +02:00
}
}
// Check if application has reached memory threshold
maxMemoryRestart ( proc , function ( ) {
2018-09-28 20:47:57 +02:00
return next ( ) ;
2014-11-18 15:41:20 +01:00
} ) ;
2014-11-18 18:14:34 +01:00
} , function ( err ) {
God . Worker . is _running = false ;
2015-01-09 16:01:14 +01:00
debug ( '[PM2][WORKER] My job here is done, next job in %d seconds' , parseInt ( cst . WORKER _INTERVAL / 1000 ) ) ;
2014-11-18 15:41:20 +01:00
} ) ;
} ) ;
2014-11-10 14:45:41 +01:00
} ;
2015-06-05 17:50:30 +02:00
var wrappedTasks = function ( ) {
var d = domain . create ( ) ;
d . once ( 'error' , function ( err ) {
console . error ( '[PM2][WORKER] Error caught by domain:\n' + ( err . stack || err ) ) ;
God . Worker . is _running = false ;
} ) ;
d . run ( function ( ) {
tasks ( ) ;
} ) ;
} ;
2014-11-10 14:45:41 +01:00
God . Worker . start = function ( ) {
2015-06-05 17:50:30 +02:00
timer = setInterval ( wrappedTasks , cst . WORKER _INTERVAL ) ;
2019-12-10 16:42:31 +01:00
2024-07-07 14:36:36 -04:00
if ( ! process . env . PM2 _DISABLE _VERSION _CHECK ) {
setInterval ( ( ) => {
vCheck ( {
state : 'check' ,
version : pkg . version ,
} ) ;
} , 1000 * 60 * 60 * 24 ) ;
}
2014-11-10 14:45:41 +01:00
} ;
God . Worker . stop = function ( ) {
if ( timer !== null )
clearInterval ( timer ) ;
} ;
} ;