Merge pull request #21840 from fcharlaix-opendsi/21780

Work for #21780 Add cleanUnfinishedCronjob job
This commit is contained in:
Laurent Destailleur 2022-08-26 18:41:41 +02:00 committed by GitHub
commit 1f2c367ec3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 1 deletions

View File

@ -1334,4 +1334,74 @@ class Utils
return $result;
}
}
/**
* Clean unfinished cronjob in processing when pid is no longer present in the system
* CAN BE A CRON TASK
*
* @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK)
* @throws Exception
*/
public function cleanUnfinishedCronjob()
{
global $db, $user;
dol_syslog("Utils::cleanUnfinishedCronjob Starting cleaning");
// Import Cronjob class if not present
dol_include_once('/cron/class/cronjob.class.php');
// Get this job object
$this_job = new Cronjob($db);
$this_job->fetch(-1, 'Utils', 'cleanUnfinishedCronjob');
if (empty($this_job->id) || !empty($this_job->error)) {
dol_syslog("Utils::cleanUnfinishedCronjob Unable to fetch himself: ".$this_job->error, LOG_ERR);
return -1;
}
// Set this job processing to 0 to avoid being locked by his processing state
$this_job->processing = 0;
if ($this_job->update($user) < 0) {
dol_syslog("Utils::cleanUnfinishedCronjob Unable to update himself: ".implode(', ', $this_job->errors), LOG_ERR);
return -1;
}
$cron_job = new Cronjob($db);
$cron_job->fetchAll('DESC', 't.rowid', 0, 0, 1, '', 1);
// Iterate over all jobs in processing (this can't be this job since his state is set to 0 before)
foreach ($cron_job->lines as $job_line) {
// Avoid job with no PID
if (empty($job_line->pid)) {
dol_syslog("Utils::cleanUnfinishedCronjob Cronjob ".$job_line->id." don't have a PID", LOG_DEBUG);
continue;
}
$job = new Cronjob($db);
$job->fetch($job_line->id);
if (empty($job->id) || !empty($job->error)) {
dol_syslog("Utils::cleanUnfinishedCronjob Cronjob ".$job_line->id." can't be fetch: ".$job->error, LOG_ERR);
continue;
}
// Calling posix_kill with the 0 kill signal will return true if the process is running, false otherwise.
if (! posix_kill($job->pid, 0)) {
// Clean processing and pid values
$job->processing = 0;
$job->pid = null;
// Set last result as an error and add the reason on the last output
$job->lastresult = -1;
$job->lastoutput = 'Job cleaned';
if ($job->update($user) < 0) {
dol_syslog("Utils::cleanUnfinishedCronjob Cronjob ".$job_line->id." can't be updated: ".implode(', ', $job->errors), LOG_ERR);
continue;
}
dol_syslog("Utils::cleanUnfinishedCronjob Cronjob ".$job_line->id." cleaned");
}
}
dol_syslog("Utils::cleanUnfinishedCronjob Cleaning completed");
return 0;
}
}

View File

@ -101,6 +101,7 @@ class modCron extends DolibarrModules
0=>array('entity'=>0, 'label'=>'PurgeDeleteTemporaryFilesShort', 'jobtype'=>'method', 'class'=>'core/class/utils.class.php', 'objectname'=>'Utils', 'method'=>'purgeFiles', 'parameters'=>'tempfilesold+logfiles', 'comment'=>'PurgeDeleteTemporaryFiles', 'frequency'=>2, 'unitfrequency'=>3600 * 24 * 7, 'priority'=>50, 'status'=>1, 'test'=>true),
1=>array('entity'=>0, 'label'=>'MakeLocalDatabaseDumpShort', 'jobtype'=>'method', 'class'=>'core/class/utils.class.php', 'objectname'=>'Utils', 'method'=>'dumpDatabase', 'parameters'=>'none,auto,1,auto,10', 'comment'=>'MakeLocalDatabaseDump', 'frequency'=>1, 'unitfrequency'=>3600 * 24 * 7, 'priority'=>90, 'status'=>0, 'test'=>'in_array($conf->db->type, array(\'mysql\', \'mysqli\'))'),
2=>array('entity'=>0, 'label'=>'MakeSendLocalDatabaseDumpShort', 'jobtype'=>'method', 'class'=>'core/class/utils.class.php', 'objectname'=>'Utils', 'method'=>'sendDumpDatabase', 'parameters'=>',,,,,sql', 'comment'=>'MakeSendLocalDatabaseDump', 'frequency'=>1, 'unitfrequency'=>604800, 'priority'=>91, 'status'=>0, 'test'=>'!empty($conf->global->MAIN_ALLOW_BACKUP_BY_EMAIL) && in_array($conf->db->type, array(\'mysql\', \'mysqli\'))'),
3=>array('entity'=>0, 'label'=>'CleanUnfinishedCronjobShort', 'jobtype'=>'method', 'class'=>'core/class/utils.class.php', 'objectname'=>'Utils', 'method'=>'cleanUnfinishedCronjob', 'parameters'=>'', 'comment'=>'CleanUnfinishedCronjob', 'frequency'=>5, 'unitfrequency'=>60, 'priority'=>10, 'status'=>1, 'test'=>true),
// 1=>array('entity'=>0, 'label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24)
);

View File

@ -1140,7 +1140,7 @@ class Cronjob extends CommonObject
$this->lastoutput = '';
$this->lastresult = '';
$this->processing = 1; // To know job was started
$this->pid = dol_getmypid();
$this->pid = function_exists('getmypid') ? getmypid() : null; // Avoid dol_getmypid to get null if the function is not available
$this->nbrun = $this->nbrun + 1;
$result = $this->update($user); // This include begin/commit
if ($result < 0) {

View File

@ -84,6 +84,8 @@ MakeLocalDatabaseDumpShort=Local database backup
MakeLocalDatabaseDump=Create a local database dump. Parameters are: compression ('gz' or 'bz' or 'none'), backup type ('mysql', 'pgsql', 'auto'), 1, 'auto' or filename to build, number of backup files to keep
MakeSendLocalDatabaseDumpShort=Send local database backup
MakeSendLocalDatabaseDump=Send local database backup by email. Parameters are: to, from, subject, message, filename (Name of file sent), filter ('sql' for backup of database only)
CleanUnfinishedCronjobShort=Clean unfinished cronjob
CleanUnfinishedCronjob=Clean cronjob stuck in processing when the process is no longer running
WarningCronDelayed=Attention, for performance purpose, whatever is next date of execution of enabled jobs, your jobs may be delayed to a maximum of %s hours, before being run.
DATAPOLICYJob=Data cleaner and anonymizer
JobXMustBeEnabled=Job %s must be enabled