1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Alpixel\Bundle\CronBundle\Command; |
4
|
|
|
|
5
|
|
|
use Alpixel\Bundle\CronBundle\Entity\CronJob; |
6
|
|
|
use Alpixel\Bundle\CronBundle\Entity\CronJobResult; |
7
|
|
|
use Doctrine\ORM\EntityManager; |
8
|
|
|
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; |
9
|
|
|
use Symfony\Component\Console\Input\ArgvInput; |
10
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
11
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
12
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
13
|
|
|
|
14
|
|
|
class CronRunCommand extends ContainerAwareCommand |
15
|
|
|
{ |
16
|
|
|
protected function configure() |
17
|
|
|
{ |
18
|
|
|
$this->setName('cron:run') |
19
|
|
|
->setDescription('Runs any currently schedule cron jobs') |
20
|
|
|
->addArgument('job', InputArgument::OPTIONAL, 'Run only this job (if enabled)'); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
24
|
|
|
{ |
25
|
|
|
$start = microtime(true); |
26
|
|
|
$em = $this->getContainer()->get('doctrine.orm.entity_manager'); |
27
|
|
|
$jobRepo = $em->getRepository('CronBundle:CronJob'); |
28
|
|
|
|
29
|
|
|
$jobsToRun = []; |
30
|
|
|
if ($jobName = $input->getArgument('job')) { |
31
|
|
|
try { |
32
|
|
|
$jobObj = $jobRepo->findOneByCommand($jobName); |
33
|
|
|
if ($jobObj->getEnabled()) { |
34
|
|
|
$jobsToRun = [$jobObj]; |
35
|
|
|
} |
36
|
|
|
} catch (\Exception $e) { |
37
|
|
|
$output->writeln("Couldn't find a job by the name of $jobName"); |
38
|
|
|
|
39
|
|
|
return CronJobResult::FAILED; |
40
|
|
|
} |
41
|
|
|
} else { |
42
|
|
|
$jobsToRun = $jobRepo->findDueTasks(); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
$jobCount = count($jobsToRun); |
46
|
|
|
$output->writeln("Running $jobCount jobs:"); |
47
|
|
|
|
48
|
|
|
foreach ($jobsToRun as $job) { |
49
|
|
|
$this->runJob($job, $output, $em); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
// Flush our results to the DB |
53
|
|
|
$em->flush(); |
54
|
|
|
|
55
|
|
|
$end = microtime(true); |
56
|
|
|
$duration = sprintf('%0.2f', $end - $start); |
57
|
|
|
$output->writeln("Cron run completed in $duration seconds"); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
protected function runJob(CronJob $job, OutputInterface $output, EntityManager $em) |
61
|
|
|
{ |
62
|
|
|
$output->write('Running '.$job->getCommand().': '); |
63
|
|
|
|
64
|
|
|
try { |
65
|
|
|
$commandToRun = $this->getApplication()->get($job->getCommand()); |
66
|
|
|
} catch (InvalidArgumentException $ex) { |
|
|
|
|
67
|
|
|
$output->writeln(' skipped (command no longer exists)'); |
68
|
|
|
$this->recordJobResult($em, $job, 0, 'Command no longer exists', CronJobResult::SKIPPED); |
69
|
|
|
|
70
|
|
|
// No need to reschedule non-existant commands |
71
|
|
|
return; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
$emptyInput = new ArgvInput(); |
75
|
|
|
$jobOutput = new MemoryWriter(); |
76
|
|
|
|
77
|
|
|
$jobStart = microtime(true); |
78
|
|
|
try { |
79
|
|
|
$returnCode = $commandToRun->execute($emptyInput, $jobOutput); |
80
|
|
|
} catch (\Exception $ex) { |
81
|
|
|
$returnCode = CronJobResult::FAILED; |
82
|
|
|
$jobOutput->writeln(''); |
83
|
|
|
$jobOutput->writeln('Job execution failed with exception '.get_class($ex).':'); |
84
|
|
|
$jobOutput->writeln($ex->__toString()); |
85
|
|
|
} |
86
|
|
|
$jobEnd = microtime(true); |
87
|
|
|
|
88
|
|
|
// Clamp the result to accepted values |
89
|
|
|
if ($returnCode < CronJobResult::RESULT_MIN || $returnCode > CronJobResult::RESULT_MAX) { |
90
|
|
|
$returnCode = CronJobResult::FAILED; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
// Output the result |
94
|
|
|
$statusStr = 'unknown'; |
95
|
|
|
if ($returnCode == CronJobResult::SKIPPED) { |
96
|
|
|
$statusStr = 'skipped'; |
97
|
|
|
} elseif ($returnCode == CronJobResult::SUCCEEDED) { |
98
|
|
|
$statusStr = 'succeeded'; |
99
|
|
|
} elseif ($returnCode == CronJobResult::FAILED) { |
100
|
|
|
$statusStr = 'failed'; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
$durationStr = sprintf('%0.2f', $jobEnd - $jobStart); |
104
|
|
|
$output->writeln("$statusStr in $durationStr seconds"); |
105
|
|
|
|
106
|
|
|
// Record the result |
107
|
|
|
$this->recordJobResult($em, $job, $jobEnd - $jobStart, $jobOutput->getOutput(), $returnCode); |
108
|
|
|
|
109
|
|
|
// And update the job with it's next scheduled time |
110
|
|
|
$newTime = new \DateTime(); |
111
|
|
|
$newTime = $newTime->add(new \DateInterval($job->getInterval())); |
112
|
|
|
$job->setNextRun($newTime); |
|
|
|
|
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
protected function recordJobResult(EntityManager $em, CronJob $job, $timeTaken, $output, $resultCode) |
116
|
|
|
{ |
117
|
|
|
// Create a new CronJobResult |
118
|
|
|
$result = new CronJobResult(); |
119
|
|
|
$result->setJob($job); |
120
|
|
|
$result->setRunTime($timeTaken); |
121
|
|
|
$result->setOutput($output); |
122
|
|
|
$result->setResult($resultCode); |
123
|
|
|
|
124
|
|
|
// Then update associations and persist it |
125
|
|
|
$job->setMostRecentRun($result); |
126
|
|
|
$em->persist($result); |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.