Added InvoiceJob

This commit is contained in:
Frank Schubert
2024-08-29 14:51:37 +02:00
parent 248013423d
commit 1ed2dddb97
13 changed files with 1051 additions and 30 deletions

View File

@@ -0,0 +1,269 @@
#!/usr/bin/php
<?php
if (PHP_SAPI !== 'cli') {
die("This program can only be run on the command line.\n");
}
/*
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$STDIN = fopen('/dev/null', 'r');
$STDOUT = fopen('/dev/null', 'w');
$STDERR = fopen('/dev/null', 'w');
*/
require("../../config/config.php");
define('mfUI',"cli");
define('FRONKDB_SQLDEBUG',false);
define("MFBASE_BYPASS_LOGIN", true);
error_reporting(E_ALL & ~(E_NOTICE | E_STRICT | E_DEPRECATED));
if(defined('MFLOCALE_TIME')) {
setlocale(LC_TIME, MFLOCALE_TIME);
}
if(defined('MFLOCALE_MONETARY')) {
setlocale(LC_MONETARY, MFLOCALE_MONETARY);
}
if(defined('MFLOCALE_NUMERIC')) {
setlocale(LC_NUMERIC, MFLOCALE_NUMERIC);
}
require_once(LIBDIR."/mvcfronk/mfRouter/mfRouter.php");
require_once(LIBDIR."/mvcfronk/mfBase/mfBaseModel.php");
require_once(LIBDIR."/mvcfronk/mfBase/mfBaseController.php");
$me = new User(1);
define("INTERNAL_USER_ID", $me->id);
define("INTERNAL_USER_USERNAME", $me->username);
$request = array();
// Put commandline arguments into $request
if(count($argv)) {
$args=$argv;
array_shift($args); // shift scriptname off of args array
foreach($args as $i => $arg) {
if(preg_match('/^--(.+)/',$arg,$m)) {
if(isset($args[$i+1]) && !preg_match('/^-/',$args[$i+1])) {
$request[$m[1]] = $args[$i+1];
} else {
$request[$m[1]] = true;
}
} elseif(preg_match('/^-([a-zA-Z])(.+)/', $arg, $m)) {
$request[$m[1]] = $m[2];
} elseif(preg_match('/^-([^-])/', $arg, $m)) {
if(isset($args[$i+1]) && !preg_match('/^-/',$args[$i+1])) {
$request[$m[1]] = $args[$i + 1];
} else {
$request[$m[1]] = true;
}
}
}
}
require_once(LIBDIR."/mvcfronk/mfRouter/mfRouter.php");
$log = mfLoghandler::singleton();
cli_set_process_title("thetool-invoice-job-broker");
pcntl_async_signals(true);
pcntl_signal(SIGTERM, 'signalHandler');
$forkcount = 0;
$childpids = [];
if(pidislocked()) {
echo "Invoice Job Broker läuft bereits (pidfile vorhanden)\n";
exit;
}
if(!lockpid()) {
$log->error(__FILE__.": Error creating lock file!");
die("Error creating lock file!\n");
}
$all_pids = [];
$valid_tasks = [
"make-invoice-pdf",
"send-invoice-email"
];
while(1) {
$processes = [];
//sleep(5);
//echo "looking for new jobs\n";
$now = new DateTime("now");
$jobs = InvoiceJobModel::search(["from_date<=" => $now->format("Y-m-d"), "to_date>=" => $now->format("Y-m-d"), "finished" => null], false, false, true);
/*if(!count($jobs)) {
echo "no more jobs. Exiting.\n";
break;
}*/
foreach($jobs as $job) {
$taskname = $job->task;
if(!array_key_exists($job->task, $childpids)) {
$childpids[$taskname] = [];
}
if($job->started && $job->status != "defer") {
//echo "Job ".$job->id." is running already\n";
continue;
}
$proc = [
"job_id" => $job->id,
"task" => $taskname,
"pid" => false,
"processtitle" => "$taskname - running job ".$job->id
];
$processes[] = $proc;
}
if(!count($processes) && !count($all_pids)) {
break;
}
foreach($processes as $proc) {
//echo "process task ".$proc["task"]." pid: ".$proc["pid"]."\n";
if($proc["pid"]) {
// maybe look for new tasks here
continue;
}
$taskname = $proc["task"];
if($childpids[$taskname]) {
//echo "cannot start new $taskname job, because another one is running already\n";
continue;
}
//echo "Starting new child\n";
$pid = pcntl_fork();
if($pid === -1) {
$log->debug("error forking");
exit;
} elseif($pid > 0) {
// in parent
$forkcount++;
$childpids[$taskname] = $pid;
$proc["pid"] = $pid;
$all_pids[$pid] = $proc;
//sleep(1);
} else {
// in child
$mypid = getmypid();
$job_id = $proc["job_id"];
$job = new InvoiceJob($job_id, true);
$job->status = "inprogress";
$job->save();
try {
//echo "in pid $mypid\n";
//echo "looking for runner for job $taskname\n";
cli_set_process_title($proc["processtitle"]);
$include_name = __DIR__ . "/job-runners/" . $taskname . ".php";
if(!file_exists($include_name)) {
echo "[$mypid] Runner $include_name not found\n";
}
require($include_name);
//echo "[$mypid] Runner $include_name is finished\n";
} catch(\Exception $e) {
// exit child process on error
echo "$mypid caught exception: " . $e->getMessage();
echo $e->getTraceAsString()."\n";
exit;
}
exit; // make sure child exits when done
}
}
if(count($all_pids)) {
$status = false;
$return_pid = pcntl_wait($status, WNOHANG);
if($return_pid) {
echo "child $return_pid returned\n";
$pid_proc = $all_pids[$return_pid];
$pid_task = $pid_proc["task"];
$childpids[$pid_task] = null;
unset($all_pids[$return_pid]);
}
}
/*echo "No more PIDs, exiting loop\n";
break;*/
sleep(5);
}
unlockpid();
function signalHandler($sig) {
//global $continue;
global $childpids;
global $invoice_job_lock;
//$continue = false;
//echo "in signal handler\n";
if(count($childpids)) {
foreach($childpids as $taskname => $pids) {
foreach($pids as $childpid) {
posix_kill($childpid, SIGTERM);
}
}
}
unlockpid();
exit;
}
function client_log($pid, $text, $severity = "notice") {
global $log;
global $is_daemon;
if($is_daemon) {
echo "[".date('Y-m-d H:i:s')."] [$pid] $text\n";
}
$log->$severity($text);
return true;
}
function pidislocked() {
$pid = getmypid();
$pidfile = __DIR__."/.invoice-job-broker.lock";
if(file_exists($pidfile)) {
return true;
}
return false;
}
function lockpid() {
$pid = getmypid();
$pidfile = __DIR__."/.invoice-job-broker.lock";
file_put_contents($pidfile, $pid);
if(file_exists($pidfile)) {
return true;
}
return false;
}
function unlockpid() {
$pid = getmypid();
$pidfile = __DIR__."/.invoice-job-broker.lock";
if(file_exists($pidfile)) {
unlink($pidfile);
return true;
}
return false;
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* @var $job InvoiceJob
* @var $proc Array
*/
/*
echo "==========================\n";
echo "in make-invoice-pdf-runner\n";
echo "==========================\n";
*/
/*
* make-invoice-pdf-runner.php
* File is included in Invoice Job Broker
*/
$started = new DateTime("now");
$job->started = $started->format("Y-m-d H:i:s");
$job->reconnectDB();
$job->save();
$job_return = new stdClass();
$job_return->created = 0;
$pdfs_created = 0;
$timeout = false;
if($job->result) {
$job_return = json_decode($job->result);
if(json_last_error() === JSON_ERROR_NONE) {
$pdfs_created = $job_return->created;
} else {
$job_return = new stdClass();
$job_return->created = 0;
}
}
$ic = new InvoiceController(false);
$ic->reconnectDB();
do {
$now = new DateTime("now");
if($now->format("Y-m-d H:i:s") > $job->to_date." 23:59:59") {
$timeout = true;
break;
}
$created = $ic->createPDFs(10);
$pdfs_created += $created;
$job_return->created = $pdfs_created;
$job->result = json_encode($job_return);
//$job->return = json_encode(["created" => $created]);
$job->reconnectDB();
$job->save();
} while($created);
if($timeout) {
$job->status = "timeout";
} else {
$job->status = "finished";
}
$finished = new DateTime("now");
$job->finished = $finished->format("Y-m-d H:i:s");
$job->reconnectDB();
$job->save();

View File

@@ -0,0 +1,74 @@
<?php
/**
* @var $job InvoiceJob
*/
/*
echo "==========================\n";
echo "in send-invoice-email-runner\n";
echo "==========================\n";
*/
$started = new DateTime("now");
if(!$job->started) {
$job->started = $started->format("Y-m-d H:i:s");
$job->reconnectDB();
$job->save();
}
$job_return = new stdClass();
$job_return->sent = 0;
$pdfs_sent = 0;
$defer = false;
$timeout = false;
if($job->result) {
$job_return = json_decode($job->result);
if(json_last_error() === JSON_ERROR_NONE) {
$pdfs_sent = $job_return->sent;
} else {
$job_return = new stdClass();
$job_return->sent = 0;
}
}
$ic = new InvoiceController(false);
$ic->reconnectDB();
// main loop
do {
$now = new DateTime("now");
if($now->format("Y-m-d H:i:s") > $job->to_date." 23:59:59") {
$timeout = true;
break;
}
$email_return = $ic->_sendEmailInvoices(300);
if($email_return["defer"]) {
$defer = true;
}
$sent = $email_return["sent"];
$pdfs_sent += $sent;
$job_return->sent = $pdfs_sent;
$job->result = json_encode($job_return);
//$job->return = json_encode(["sent" => $sent]);
$job->reconnectDB();
$job->save();
} while($sent);
// prepare job update
if($timeout) {
$job->status = "timeout";
} elseif($defer) {
echo "email runner: deferring to next run\n";
$job->status = "defer";
} else {
$finished = new DateTime("now");
$job->finished = $finished->format("Y-m-d H:i:s");
$job->status = "finished";
}
$job->reconnectDB();
$job->save();