| Current Path : /var/www/v3.cesa.co.za/src/CoreBundle/Services/ |
| Current File : /var/www/v3.cesa.co.za/src/CoreBundle/Services/BatchJobsManager.php |
<?php
namespace App\CoreBundle\Services;
use Symfony\Component\DependencyInjection\ContainerInterface;
use App\CoreBundle\Entity\BatchJobs;
use App\CoreBundle\Services\Utils;
/**
* Batch Jobs manager
*
* @author Otto Saayman <otto@igotafrica.com>
* @package CoreBundle
* @subpackage BatchJobs
* @version 0.0.1
*/
final class BatchJobsManager {
/**
* Service Container
* @var object
*/
private $container = null;
/**
* Entity manager
* @var object
*/
private $em;
/**
* IGA Error logger
* @var object
*/
private $logger = null;
/**
* Class construct
*
* @param ContainerInterface $container
* @param Logger $logger
* @return void
*/
public function __construct(
ContainerInterface $container) {
$this->setContainer($container);
$this->setEm($container->get('doctrine')->getManager('default'));
return;
}
/**
* Get Container
*
* @return ContainerInterface $container
*/
public function getContainer() {
return $this->container;
}
/**
* Set Container
*
* @param ContainerInterface $container
* @return void
*/
public function setContainer($container) {
$this->container = $container;
}
/**
* Get Entity Manager
*
* @return string
*/
public function getEm() {
return $this->em;
}
/**
* Set Container
*
* @param string $em
* @return void
*/
public function setEm($em) {
$this->em = $em;
}
/**
* save a batch job
*
* @param string $phpScript
*/
public function save($phpScript, $checkExists = true, $forceCreate = false, $priority = 1000, $secondsToWait = -1) {
$userListManager = $this->getContainer()->get('user_list.manager');
$userList = $userListManager->getLoggedInUser();
$batchJob = null;
if ($checkExists) {
$batchJob = $this->getEm()->getRepository(BatchJobs::class)->findOneBy(array('php_script' => $phpScript));
if (is_object($batchJob) && !$batchJob->getSuccess()) {
//Job is there and has not finished
return false;
}
if ($secondsToWait < 0) {
// 10 days
$secondsToWait = 60 * 60 * 24 * 10;
}
if (is_object($batchJob) && is_object($batchJob->getUpdatedAt()) && $batchJob->getUpdatedAt()->getTimestamp() >= (time() - $secondsToWait) && !$forceCreate) {
//Job was run less than seven days ago
return false;
}
}
if (!is_object($batchJob)) {
$batchJob = new BatchJobs();
}
if (isset($_SERVER["HTTP_HOST"])) {
$batchJob->setSiteHost($_SERVER["HTTP_HOST"]);
} else {
$batchJob->setSiteHost('');
}
$batchJob->setPhpScript($phpScript);
$batchJob->setFailCount(0);
$batchJob->setFailed(false);
$batchJob->setInProgress(false);
$batchJob->setSuccess(false);
$batchJob->setIsLocked(false);
$batchJob->setJobPriority($priority);
if (is_object($userList)) {
$batchJob->setCreatedBy($userList->getId());
}
$this->getEm()->persist($batchJob);
$this->getEm()->flush();
}
/**
* Find batch jobs
*
* @param array $params
* @return array
*/
public function findBy($params) {
return $this->getEm()->getRepository(BatchJobs::class)->findBy($params);
}
public function checkBusy() {
$load = sys_getloadavg();
if ($load[0] > 6) {
//Server too busy - sleep for a while
sleep(60);
}
}
/**
* do batch job
*
*/
public function doJob($maxPriority = 0) {
$batchJobs = $this->getEm()->getRepository(BatchJobs::class)->findNextJobs($maxPriority);
$logger = $this->getContainer()->get('error_log.manager');
$output = '';
$_SERVER["HTTP_HOST"] = 'igotafrica.com';
$phpScript = '';
if (!is_array($batchJobs) || count($batchJobs) <= 0) {
return false;
}
foreach ($batchJobs as $batchJob) {
$batchJob->setIsLocked(true);
$this->getEm()->persist($batchJob);
$this->getEm()->flush();
} //foreach
foreach ($batchJobs as $batchJob) {
$this->checkBusy();
try {
$this->getEm()->refresh($batchJob);
} catch (\Exception $ex) {
$logger->info('Error on job refresh: ' . $ex->getMessage() . ' - ' . $ex->getTraceAsString());
}
try {
if ($batchJob->getSuccess() > 0) {
// echo 'skipping completed job: ' . $batchJob->getSuccess() . ' - ' . $batchJob->getId() . "\r\n";
$batchJob->setInProgress(false);
$batchJob->setSuccess(true);
$batchJob->setFailed(false);
$batchJob->setIsLocked(false);
$this->getEm()->persist($batchJob);
$this->getEm()->flush();
continue;
}
$batchJob->setInProgress(true);
$batchJob->setSuccess(false);
$batchJob->setIsLocked(true);
$batchJob->setExecutionStarted(new \DateTime());
if (strlen($batchJob->getSiteHost()) > 0) {
$phpScript = "\$_SERVER['HTTP_HOST'] = '" . $batchJob->getSiteHost() . "'; " . $phpScript;
$_SERVER["HTTP_HOST"] = $batchJob->getSiteHost();
}
$this->getEm()->persist($batchJob);
$this->getEm()->flush();
// echo "\r\n Now executing: " . $batchJob->getPhpScript() . "\r\n";
$output = eval($phpScript . ' ' . $batchJob->getPhpScript());
// $this->getContainer()->get('error_log.manager')->info('Host is set to ' . $_SERVER["HTTP_HOST"] . ' - ' . $phpScript . ' ' . $batchJob->getPhpScript());
if ($output === false) {
// $logger->info('Bad syntax/ unable to execute: ' . $phpScript . ' ' . $batchJob->getPhpScript());
throw new \Exception('Bad syntax/ unable to execute');
}
$batchJob->setInProgress(false);
$batchJob->setSuccess(true);
$batchJob->setFailed(false);
$batchJob->setIsLocked(false);
$batchJob->setExecutionEnded(new \DateTime());
$this->getEm()->persist($batchJob);
$this->getEm()->flush();
// echo 'Executed ' . $batchJob->getId() . "\r\n";
} catch (\Throwable $ex) {
// echo 'Error ' . $batchJob->getId() . ' - ' . $ex->getMessage() . ' - ' . $ex->getTraceAsString() . "\r\n";
// echo $ex->getTraceAsString() . "\r\n\r\n";
$logger->error('Error on batch job ' . $batchJob->getPhpScript() . ' - ' . $ex->getMessage() . ' - ' . $output . ' - ' . $ex->getTraceAsString());
$batchJob->setInProgress(false);
$batchJob->setSuccess(false);
$batchJob->setFailed(true);
$batchJob->setIsLocked(false);
$batchJob->setFailCount($batchJob->getFailCount() + 1);
$batchJob->setExecutionEnded(new \DateTime());
$this->getEm()->persist($batchJob);
$this->getEm()->flush();
}
//Check for duplicate jobs
$this->getEm()->getRepository(BatchJobs::class)->removeDuplicates($batchJob);
} //foreach
}
/**
* Delete all un-executed jobs
*/
public function clearQueue() {
$this->em->getRepository(BatchJobs::class)->clearQueue();
}
/**
* Clean up old jobs
*/
public function cleanUpQueue() {
$this->em->getRepository(BatchJobs::class)->cleanUpQueue();
}
/**
* Clean up old jobs
*/
public function resetJob(BatchJobs $batchJob) {
$batchJob->setSuccess(false);
$batchJob->setFailCount(0);
$batchJob->setFailed(false);
$batchJob->setInProgress(false);
$batchJob->setIsLocked(false);
$this->getEm()->persist($batchJob);
$this->getEm()->flush();
}
/**
* Check if job is in process
* @param string $scriptPart
* @return integer
*/
public function isProcessing($scriptPart) {
return $this->em->getRepository(BatchJobs::class)->isProcessing($scriptPart);
}
/**
* Check if jobs can run
* @param string $scriptPart
* @return integer
*/
public function canProcessAny($output, $processName) {
$pCountRes = popen("ps aux | grep \"" . $processName . "\" | wc -l", 'r');
$pCount = '';
While ($data = @fread($pCountRes, 64000)) {
$pCount .= $data;
}
$output->writeln('Finished process count for ' . $processName . ': ' . $pCount);
if ($pCount >= 8) {
$output->writeln('Server too busy, ' . $pCount . ' processes already running');
return false;
}
return true;
}
public function canProcess() {
$databaseServer = $this->getContainer()->get('system_setting.manager')->getSetting('load_check_database_server', '', true);
$loadCheckMaxWorker = $this->getContainer()->get('system_setting.manager')->getSetting('load_check_max_worker', 4);
$loadCheckMaxDB = $this->getContainer()->get('system_setting.manager')->getSetting('load_check_max_db', 2);
$load = sys_getloadavg();
if (strlen($databaseServer) > 0) {
$db_load = file_get_contents($databaseServer);
} else {
$db_load = 0;
}
$ramArr = Utils::getSystemMemInfo();
$ramPerc = trim(str_replace("kB", "", $ramArr['MemFree'])) / trim(str_replace("kB", "", $ramArr['MemTotal']));
$this->getContainer()->get('translator')->setLocale('en');
if ($load[0] > $loadCheckMaxWorker || $ramPerc <= 0.01 || $db_load > $loadCheckMaxDB) {
return false;
}
return true;
}
}