Skip to content

Commit

Permalink
Initial import of CronBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
predakanga committed Aug 30, 2012
0 parents commit 47ec5dd
Show file tree
Hide file tree
Showing 18 changed files with 1,086 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vendor
13 changes: 13 additions & 0 deletions Annotation/CronJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
namespace ColourStream\Bundle\CronBundle\Annotation;

/**
* @Annotation()
* @Target("CLASS")
*/
use Doctrine\Common\Annotations\Annotation;

class CronJob extends Annotation
{
public $value;
}
9 changes: 9 additions & 0 deletions ColourStreamCronBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace ColourStream\Bundle\CronBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ColourStreamCronBundle extends Bundle
{
}
40 changes: 40 additions & 0 deletions Command/CronDisableJobCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
namespace ColourStream\Bundle\CronBundle\Command;
use Symfony\Component\Console\Input\InputArgument;

use Symfony\Component\Console\Output\OutputInterface;

use Symfony\Component\Console\Input\InputInterface;

use ColourStream\Bundle\CronBundle\Entity\CronJobResult;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

class CronDisableJobCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName("cron:disable-job")
->setDescription("Disables a cron job")
->addArgument("job", InputArgument::REQUIRED, "Name of the job to disable");
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$jobName = $input->getArgument('job');
$em = $this->getContainer()->get("doctrine.orm.entity_manager");
$jobRepo = $em->getRepository('ColourStreamCronBundle:CronJob');

$job = $jobRepo->findOneByCommand($jobName);
if(!$job)
{
$output->writeln("Couldn't find a job by the name of " . $jobName);
return CronJobResult::FAILED;
}

$job->setEnabled(false);
$em->flush();

$output->writeln("Disabled cron job by the name of " . $jobName);
}
}
38 changes: 38 additions & 0 deletions Command/CronEnableJobCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
namespace ColourStream\Bundle\CronBundle\Command;
use Symfony\Component\Console\Input\InputArgument;

use Symfony\Component\Console\Output\OutputInterface;

use Symfony\Component\Console\Input\InputInterface;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

class CronEnableJobCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName("cron:enable-job")
->setDescription("Enables a cron job")
->addArgument("job", InputArgument::REQUIRED, "Name of the job to enable");
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$jobName = $input->getArgument('job');
$em = $this->getContainer()->get("doctrine.orm.entity_manager");
$jobRepo = $em->getRepository('ColourStreamCronBundle:CronJob');

$job = $jobRepo->findOneByCommand($jobName);
if(!$job)
{
$output->writeln("Couldn't find a job by the name of " . $jobName);
return CronJobResult::FAILED;
}

$job->setEnabled(true);
$em->flush();

$output->writeln("Disabled cron job by the name of " . $jobName);
}
}
59 changes: 59 additions & 0 deletions Command/CronPruneLogsCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
namespace ColourStream\Bundle\CronBundle\Command;

use Fusion\Framework\CronBundle\Entity\CronJobResult;

use Symfony\Component\Console\Output\OutputInterface;

use Symfony\Component\Console\Input\InputInterface;

use Symfony\Component\Console\Input\InputArgument;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

class CronPruneLogsCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName("cron:pruneLogs")
->setDescription("Prunes the logs for each cron job, leaving only recent failures and the most recent success")
->addArgument('job', InputArgument::OPTIONAL, 'Operate only on this job');
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->getContainer()->get("doctrine.orm.entity_manager");
$job = $input->getArgument('job');

if($job)
{
$output->writeln("Pruning logs for cron job $job");
}
else
{
$output->writeln("Pruning logs for all cron jobs");
}

if($job)
{
$jobObj = $em->getRepository('ColourStreamCronBundle:CronJob')->findOneByCommand($job);
if(!$jobObj)
{
$output->writeln("Couldn't find a job by the name of " . $job);
return CronJobResult::FAILED;
}

$em->getRepository('ColourStreamCronBundle:CronJobResult')->deleteOldLogs($jobObj);
}
else
{
$em->getRepository('ColourStreamCronBundle:CronJobResult')->deleteOldLogs();
}

// Flush the EM
$em->flush();

$output->writeln("Logs pruned successfully");
return CronJobResult::SUCCEEDED;
}
}
152 changes: 152 additions & 0 deletions Command/CronRunCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<?php
namespace ColourStream\Bundle\CronBundle\Command;
use Doctrine\ORM\EntityManager;

use Symfony\Component\Console\Input\ArgvInput;

use ColourStream\Bundle\CronBundle\Entity\CronJobResult;

use ColourStream\Bundle\CronBundle\Entity\CronJob;

use Symfony\Component\Console\Output\OutputInterface;

use Symfony\Component\Console\Input\InputInterface;

use Symfony\Component\Console\Input\InputArgument;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

class CronRunCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName("cron:run")
->setDescription("Runs any currently schedule cron jobs")
->addArgument("job", InputArgument::OPTIONAL, "Run only this job (if enabled)");
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$start = microtime(true);
$em = $this->getContainer()->get("doctrine.orm.entity_manager");
$jobRepo = $em->getRepository('ColourStreamCronBundle:CronJob');

$jobsToRun = array();
if($jobName = $input->getArgument('job'))
{
try
{
$jobObj = $jobRepo->findOneByCommand($jobName);
if($jobObj->getEnabled())
{
$jobsToRun = array($jobObj);
}
}
catch(\Exception $e)
{
$output->writeln("Couldn't find a job by the name of $jobName");
return CronJobResult::FAILED;
}
}
else
{
$jobsToRun = $jobRepo->findDueTasks();
}

$jobCount = count($jobsToRun);
$output->writeln("Running $jobCount jobs:");

foreach($jobsToRun as $job)
{
$this->runJob($job, $output, $em);
}

// Flush our results to the DB
$em->flush();

$end = microtime(true);
$duration = sprintf("%0.2f", $end-$start);
$output->writeln("Cron run completed in $duration seconds");
}

protected function runJob(CronJob $job, OutputInterface $output, EntityManager $em)
{
$output->write("Running " . $job->getCommand() . ": ");

try
{
$commandToRun = $this->getApplication()->get($job->getCommand());
}
catch(InvalidArgumentException $ex)
{
$output->writeln(" skipped (command no longer exists)");
$this->recordJobResult($em, $job, 0, "Command no longer exists", CronJobResult::SKIPPED);

// No need to reschedule non-existant commands
return;
}

$emptyInput = new ArgvInput();
$jobOutput = new MemoryWriter();

$jobStart = microtime(true);
try
{
$returnCode = $commandToRun->execute($emptyInput, $jobOutput);
}
catch(\Exception $ex)
{
$returnCode = CronJobResult::FAILED;
$jobOutput->writeln("");
$jobOutput->writeln("Job execution failed with exception " . get_class($ex) . ":");
$jobOutput->writeln($ex->__toString());
}
$jobEnd = microtime(true);

// Clamp the result to accepted values
if($returnCode < CronJobResult::RESULT_MIN || $returnCode > CronJobResult::RESULT_MAX)
{
$returnCode = CronJobResult::FAILED;
}

// Output the result
$statusStr = "unknown";
if($returnCode == CronJobResult::SKIPPED)
{
$statusStr = "skipped";
}
elseif($returnCode == CronJobResult::SUCCEEDED)
{
$statusStr = "succeeded";
}
elseif($returnCode == CronJobResult::FAILED)
{
$statusStr = "failed";
}

$durationStr = sprintf("%0.2f", $jobEnd-$jobStart);
$output->writeln("$statusStr in $durationStr seconds");

// Record the result
$this->recordJobResult($em, $job, $jobEnd-$jobStart, $jobOutput->getOutput(), $returnCode);

// And update the job with it's next scheduled time
$newTime = new \DateTime();
$newTime = $newTime->add(new \DateInterval($job->getInterval()));
$job->setNextRun($newTime);
}

protected function recordJobResult(EntityManager $em, CronJob $job, $timeTaken, $output, $resultCode)
{
// Create a new CronJobResult
$result = new CronJobResult();
$result->setJob($job);
$result->setRunTime($timeTaken);
$result->setOutput($output);
$result->setResult($resultCode);

// Then update associations and persist it
$job->setMostRecentRun($result);
$em->persist($result);
}
}
Loading

0 comments on commit 47ec5dd

Please sign in to comment.