tao-test/app/taoTaskQueue/model/Worker/WorkerProcessManager.php

175 lines
4.1 KiB
PHP

<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2017 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
*
*/
namespace oat\taoTaskQueue\model\Worker;
use Exception;
use oat\oatbox\log\LoggerAwareTrait;
use oat\oatbox\service\ConfigurableService;
use React\ChildProcess\Process;
class WorkerProcessManager extends ConfigurableService
{
use LoggerAwareTrait;
const SERVICE_ID = 'taoTaskQueue/WorkerProcessManager';
const OPTION_TASK_COMMAND = 'task_command';
/** @var Process[] */
private $processes = [];
/** @var integer */
private $limitOfCpu;
/** @var integer */
private $limitOfMemory;
/**
* @param Process $process
*/
public function addProcess(Process $process)
{
$pid = $process->getPid();
$process->stdout->on('data', function ($status) use ($pid) {
$this->logInfo('Process: ' . $pid . ' status:' . $status);
});
$process->stdout->on('end', function () use ($pid) {
$this->logInfo('Process: ' . $pid . ' ended');
});
$process->stdout->on('error', function (Exception $e) use ($pid) {
$this->logError('Process: ' . $pid . ' error. ' . $e->getMessage());
});
$process->stdout->on('close', function () use ($pid) {
$this->logInfo('Process: ' . $pid . ' closed.');
unset($this->processes[$pid]);
});
$process->stdin->end($data = null);
$this->processes[$pid] = $process;
}
/**
* @return bool
*/
public function canRun()
{
$this->logInfo('No of process workers running: ' . count($this->processes));
$memoryUsage = $this->getMemoryUsage();
$cpuUsage = $this->getCpuUsage();
if (
$memoryUsage < $this->limitOfMemory
&& $cpuUsage < $this->limitOfCpu
) {
return true;
}
$this->logInfo('Limit Of memory and Cpu exceeded waiting for task to finish.
Current memory usage:' . $memoryUsage . ' Cpu usage:' . $cpuUsage);
return false;
}
/**
* @return string
*/
public function getCommand()
{
return $this->getOption(static::OPTION_TASK_COMMAND);
}
/**
* @return float|int
*/
public function getMemoryUsage()
{
$free = shell_exec('free');
$free = (string)trim($free);
$freeArray = explode("\n", $free);
$memory = explode(" ", $freeArray[1]);
$memory = array_filter($memory);
$memory = array_merge($memory);
$memoryUsage = $memory[1] > 0
? $memory[2] / $memory[1] * 100
: 0;
return $memoryUsage;
}
/**
* @return mixed
*/
public function getCpuUsage()
{
$load = sys_getloadavg();
return $load[0];
}
/**
* @return int
*/
public function getLimitOfCpu()
{
return $this->limitOfCpu;
}
/**
* @param int $limitOfCpu
*/
public function setLimitOfCpu($limitOfCpu)
{
$this->limitOfCpu = $limitOfCpu;
}
/**
* @return int
*/
public function getLimitOfMemory()
{
return $this->limitOfMemory;
}
/**
* @param int $limitOfMemory
*/
public function setLimitOfMemory($limitOfMemory)
{
$this->limitOfMemory = $limitOfMemory;
}
/**
* @return Process[]
*/
public function getProcesses()
{
return $this->processes;
}
}