Your IP : 216.73.217.79


Current Path : /var/www/v3.cesa.co.za/src/CoreBundle/Services/
Upload File :
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;
    }

}