use Friendica\DI;
use Friendica\Model\Process;
use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Network;
/**
* Contains the class for the worker background job processing
const FAST_COMMANDS = ['APDelivery', 'Delivery', 'CreateShadowEntry'];
+ const LOCK_PROCESS = 'worker_process';
+ const LOCK_WORKER = 'worker';
private static $up_start;
private static $db_duration = 0;
// At first check the maximum load. We shouldn't continue with a high load
if (DI::process()->isMaxLoadReached()) {
- Logger::log('Pre check: maximum load reached, quitting.', Logger::DEBUG);
+ Logger::info('Pre check: maximum load reached, quitting.');
return;
}
// Count active workers and compare them with a maximum value that depends on the load
if (self::tooMuchWorkers()) {
- Logger::log('Pre check: Active worker limit reached, quitting.', Logger::DEBUG);
+ Logger::info('Pre check: Active worker limit reached, quitting.');
return;
}
// Do we have too few memory?
if (DI::process()->isMinMemoryReached()) {
- Logger::log('Pre check: Memory limit reached, quitting.', Logger::DEBUG);
+ Logger::info('Pre check: Memory limit reached, quitting.');
return;
}
// Possibly there are too much database connections
if (self::maxConnectionsReached()) {
- Logger::log('Pre check: maximum connections reached, quitting.', Logger::DEBUG);
+ Logger::info('Pre check: maximum connections reached, quitting.');
return;
}
// Possibly there are too much database processes that block the system
if (DI::process()->isMaxProcessesReached()) {
- Logger::log('Pre check: maximum processes reached, quitting.', Logger::DEBUG);
+ Logger::info('Pre check: maximum processes reached, quitting.');
return;
}
// The work will be done
if (!self::execute($entry)) {
- Logger::log('Process execution failed, quitting.', Logger::DEBUG);
+ Logger::info('Process execution failed, quitting.');
return;
}
// Trying to fetch new processes - but only once when successful
- if (!$refetched && DI::lock()->acquire('worker_process', 0)) {
+ if (!$refetched && DI::lock()->acquire(self::LOCK_PROCESS, 0)) {
self::findWorkerProcesses();
- DI::lock()->release('worker_process');
+ DI::lock()->release(self::LOCK_PROCESS);
self::$state = self::STATE_REFETCH;
$refetched = true;
} else {
if (!self::getWaitingJobForPID()) {
self::$state = self::STATE_LONG_LOOP;
- if (DI::lock()->acquire('worker', 0)) {
+ if (DI::lock()->acquire(self::LOCK_WORKER, 0)) {
// Count active workers and compare them with a maximum value that depends on the load
if (self::tooMuchWorkers()) {
- Logger::log('Active worker limit reached, quitting.', Logger::DEBUG);
- DI::lock()->release('worker');
+ Logger::info('Active worker limit reached, quitting.');
+ DI::lock()->release(self::LOCK_WORKER);
return;
}
// Check free memory
if (DI::process()->isMinMemoryReached()) {
- Logger::log('Memory limit reached, quitting.', Logger::DEBUG);
- DI::lock()->release('worker');
+ Logger::info('Memory limit reached, quitting.');
+ DI::lock()->release(self::LOCK_WORKER);
return;
}
- DI::lock()->release('worker');
+ DI::lock()->release(self::LOCK_WORKER);
}
}
if (DI::config()->get('system', 'worker_daemon_mode', false)) {
self::IPCSetJobState(false);
}
- Logger::log("Couldn't select a workerqueue entry, quitting process " . getmypid() . ".", Logger::DEBUG);
+ Logger::info("Couldn't select a workerqueue entry, quitting process", ['pid' => getmypid()]);
}
/**
// Quit when in maintenance
if (DI::config()->get('system', 'maintenance', false, true)) {
- Logger::log("Maintenance mode - quit process ".$mypid, Logger::DEBUG);
+ Logger::info("Maintenance mode - quit process", ['pid' => $mypid]);
return false;
}
// Constantly check the number of parallel database processes
if (DI::process()->isMaxProcessesReached()) {
- Logger::log("Max processes reached for process ".$mypid, Logger::DEBUG);
+ Logger::info("Max processes reached for process", ['pid' => $mypid]);
return false;
}
// Constantly check the number of available database connections to let the frontend be accessible at any time
if (self::maxConnectionsReached()) {
- Logger::log("Max connection reached for process ".$mypid, Logger::DEBUG);
+ Logger::info("Max connection reached for process", ['pid' => $mypid]);
return false;
}
$argv = json_decode($queue["parameter"], true);
+ if (empty($argv)) {
+ Logger::error('Parameter is empty', ['queue' => $queue]);
+ return false;
+ }
// Check for existance and validity of the include file
$include = $argv[0];
{
$a = DI::app();
- $argc = count($argv);
-
Logger::enableWorker($funcname);
Logger::info("Process start.", ['priority' => $queue["priority"], 'id' => $queue["id"]]);
if ($method_call) {
call_user_func_array(sprintf('Friendica\Worker\%s::execute', $funcname), $argv);
} else {
- $funcname($argv, $argc);
+ $funcname($argv, count($argv));
}
Logger::disableWorker();
$used = DBA::numRows($r);
DBA::close($r);
- Logger::log("Connection usage (user values): ".$used."/".$max, Logger::DEBUG);
+ Logger::info("Connection usage (user values)", ['usage' => $used, 'max' => $max]);
$level = ($used / $max) * 100;
if ($used == 0) {
return false;
}
- Logger::log("Connection usage (system values): ".$used."/".$max, Logger::DEBUG);
+ Logger::info("Connection usage (system values)", ['used' => $used, 'max' => $max]);
$level = $used / $max * 100;
$max_duration = $max_duration_defaults[$entry["priority"]];
$argv = json_decode($entry["parameter"], true);
+ if (empty($argv)) {
+ return;
+ }
+
$argv[0] = basename($argv[0]);
// How long is the process already running?
self::$db_duration += (microtime(true) - $stamp);
self::$db_duration_write += (microtime(true) - $stamp);
} else {
- Logger::log("Worker process ".$entry["pid"]." (".substr(json_encode($argv), 0, 50).") now runs for ".round($duration)." of ".$max_duration." allowed minutes. That's okay.", Logger::DEBUG);
+ Logger::info('Process runtime is okay', ['pid' => $entry["pid"], 'duration' => $duration, 'max' => $max_duration, 'command' => substr(json_encode($argv), 0, 50)]);
}
}
}
+ DBA::close($entries);
}
/**
self::$db_duration_stat += (microtime(true) - $stamp);
while ($entry = DBA::fetch($jobs)) {
$stamp = (float)microtime(true);
- $processes = DBA::p("SELECT COUNT(*) AS `running` FROM `process` INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid` WHERE NOT `done` AND `priority` = ?", $entry["priority"]);
+ $processes = DBA::p("SELECT COUNT(*) AS `running` FROM `workerqueue-view` WHERE `priority` = ?", $entry["priority"]);
self::$db_duration += (microtime(true) - $stamp);
self::$db_duration_stat += (microtime(true) - $stamp);
if ($process = DBA::fetch($processes)) {
} else {
$waiting_processes = self::totalEntries();
$stamp = (float)microtime(true);
- $jobs = DBA::p("SELECT COUNT(*) AS `running`, `priority` FROM `process` INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid` AND NOT `done` GROUP BY `priority` ORDER BY `priority`");
+ $jobs = DBA::p("SELECT COUNT(*) AS `running`, `priority` FROM `workerqueue-view` GROUP BY `priority` ORDER BY `priority`");
self::$db_duration += (microtime(true) - $stamp);
self::$db_duration_stat += (microtime(true) - $stamp);
$high_running = self::processWithPriorityActive($top_priority);
if (!$high_running && ($top_priority > PRIORITY_UNDEFINED) && ($top_priority < PRIORITY_NEGLIGIBLE)) {
- Logger::log("There are jobs with priority ".$top_priority." waiting but none is executed. Open a fastlane.", Logger::DEBUG);
+ Logger::info("Jobs with a higher priority are waiting but none is executed. Open a fastlane.", ['priority' => $top_priority]);
$queues = $active + 1;
}
}
- Logger::log("Load: " . $load ."/" . $maxsysload . " - processes: " . $deferred . "/" . $active . "/" . $waiting_processes . $processlist . " - maximum: " . $queues . "/" . $maxqueues, Logger::DEBUG);
+ Logger::notice("Load: " . $load ."/" . $maxsysload . " - processes: " . $deferred . "/" . $active . "/" . $waiting_processes . $processlist . " - maximum: " . $queues . "/" . $maxqueues);
// Are there fewer workers running as possible? Then fork a new one.
if (!DI::config()->get("system", "worker_dont_fork", false) && ($queues > ($active + 1)) && self::entriesExists()) {
- Logger::log("Active workers: ".$active."/".$queues." Fork a new worker.", Logger::DEBUG);
+ Logger::info("There are fewer workers as possible, fork a new worker.", ['active' => $active, 'queues' => $queues]);
if (DI::config()->get('system', 'worker_daemon_mode', false)) {
self::IPCSetJobState(true);
} else {
$running = [];
$running_total = 0;
$stamp = (float)microtime(true);
- $processes = DBA::p("SELECT COUNT(DISTINCT(`process`.`pid`)) AS `running`, `priority` FROM `process`
- INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`
- WHERE NOT `done` GROUP BY `priority`");
+ $processes = DBA::p("SELECT COUNT(DISTINCT(`pid`)) AS `running`, `priority` FROM `workerqueue-view` GROUP BY `priority`");
self::$db_duration += (microtime(true) - $stamp);
while ($process = DBA::fetch($processes)) {
$running[$process['priority']] = $process['running'];
/**
* Returns the next worker process
*
- * @return string SQL statement
+ * @return array worker processes
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function workerProcess()
}
$stamp = (float)microtime(true);
- if (!DI::lock()->acquire('worker_process')) {
+ if (!DI::lock()->acquire(self::LOCK_PROCESS)) {
return false;
}
self::$lock_duration += (microtime(true) - $stamp);
$found = self::findWorkerProcesses();
- DI::lock()->release('worker_process');
+ DI::lock()->release(self::LOCK_PROCESS);
if ($found) {
$stamp = (float)microtime(true);
}
$url = DI::baseUrl() . '/worker';
- Network::fetchUrl($url, false, 1);
+ DI::httpRequest()->fetch($url, false, 1);
}
/**
self::runCron();
- Logger::log('Call worker', Logger::DEBUG);
+ Logger::info('Call worker');
self::spawnWorker();
return;
}
*/
private static function runCron()
{
- Logger::log('Add cron entries', Logger::DEBUG);
+ Logger::info('Add cron entries');
// Check for spooled items
self::add(['priority' => PRIORITY_HIGH, 'force_priority' => true], 'SpoolPost');
}
// If there is a lock then we don't have to check for too much worker
- if (!DI::lock()->acquire('worker', 0)) {
+ if (!DI::lock()->acquire(self::LOCK_WORKER, 0)) {
return $added;
}
// If there are already enough workers running, don't fork another one
$quit = self::tooMuchWorkers();
- DI::lock()->release('worker');
+ DI::lock()->release(self::LOCK_WORKER);
if ($quit) {
return $added;