CronRunCommand   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 8

Importance

Changes 0
Metric Value
wmc 15
lcom 2
cbo 8
dl 0
loc 118
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 6 1
B execute() 0 35 5
B runJob() 0 56 8
A recordJobResult() 0 15 1
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 Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
8
use Symfony\Component\Console\Input\ArgvInput;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Output\OutputInterface;
12
13
class CronRunCommand extends ContainerAwareCommand
14
{
15
    protected function configure()
16
    {
17
        $this->setName('cron:run')
18
             ->setDescription('Runs any currently schedule cron jobs')
19
             ->addArgument('job', InputArgument::OPTIONAL, 'Run only this job (if enabled)');
20
    }
21
22
    protected function execute(InputInterface $input, OutputInterface $output)
23
    {
24
        $start = microtime(true);
25
        $entityManager = $this->getContainer()->get('doctrine.orm.entity_manager');
26
        $jobRepo = $entityManager->getRepository('CronBundle:CronJob');
27
28
        $jobsToRun = [];
29
        if ($jobName = $input->getArgument('job')) {
30
            try {
31
                $jobObj = $jobRepo->findOneByCommand($jobName);
32
                if ($jobObj->getEnabled()) {
33
                    $jobsToRun = [$jobObj];
34
                }
35
            } catch (\Exception $e) {
36
                $output->writeln("Couldn't find a job by the name of $jobName");
37
38
                return CronJobResult::FAILED;
39
            }
40
        } else {
41
            $jobsToRun = $jobRepo->findDueTasks();
42
        }
43
44
        $jobCount = count($jobsToRun);
45
        $output->writeln("Running $jobCount jobs:");
46
47
        foreach ($jobsToRun as $job) {
48
            $this->runJob($job, $output);
49
        }
50
51
        $entityManager->flush();
52
53
        $end = microtime(true);
54
        $duration = sprintf('%0.2f', $end - $start);
55
        $output->writeln("Cron run completed in $duration seconds");
56
    }
57
58
    protected function runJob(CronJob $job, OutputInterface $output)
59
    {
60
        $entityManager = $this->getContainer()->get('doctrine.orm.entity_manager');
61
        $output->write('Running '.$job->getCommand().': ');
62
63
        try {
64
            $commandToRun = $this->getApplication()->get($job->getCommand());
65
        } catch (\Symfony\Component\Console\Exception\InvalidArgumentException $ex) {
66
            $output->writeln(' skipped (command no longer exists)');
67
            $this->recordJobResult($entityManager, $job, 0, 'Command no longer exists', CronJobResult::SKIPPED);
0 ignored issues
show
Unused Code introduced by
The call to CronRunCommand::recordJobResult() has too many arguments starting with \Alpixel\Bundle\CronBund...\CronJobResult::SKIPPED.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
68
69
            // No need to reschedule non-existant commands
70
            return;
71
        }
72
73
        $emptyInput = new ArgvInput();
74
        $jobOutput = new MemoryWriter();
75
76
        $jobStart = microtime(true);
77
        try {
78
            $returnCode = $commandToRun->execute($emptyInput, $jobOutput);
79
        } catch (\Exception $ex) {
80
            $returnCode = CronJobResult::FAILED;
81
            $jobOutput->writeln('');
82
            $jobOutput->writeln('Job execution failed with exception '.get_class($ex).':');
83
            $jobOutput->writeln($ex->__toString());
84
        }
85
        $jobEnd = microtime(true);
86
87
        // Clamp the result to accepted values
88
        if ($returnCode < CronJobResult::RESULT_MIN || $returnCode > CronJobResult::RESULT_MAX) {
89
            $returnCode = CronJobResult::FAILED;
90
        }
91
92
        // Output the result
93
        $statusStr = 'unknown';
94
        if ($returnCode == CronJobResult::SKIPPED) {
95
            $statusStr = 'skipped';
96
        } elseif ($returnCode == CronJobResult::SUCCEEDED) {
97
            $statusStr = 'succeeded';
98
        } elseif ($returnCode == CronJobResult::FAILED) {
99
            $statusStr = 'failed';
100
        }
101
102
        $durationStr = sprintf('%0.2f', $jobEnd - $jobStart);
103
        $output->writeln("$statusStr in $durationStr seconds");
104
105
        // Record the result
106
        $this->recordJobResult($job, $jobEnd - $jobStart, $jobOutput->getOutput(), $returnCode);
107
108
        // And update the job with it's next scheduled time
109
        $interval = new \DateInterval($job->getInterval());
110
        $newTime = clone $job->getNextRun();
111
        $newTime->add($interval);
112
        $job->setNextRun($newTime);
113
    }
114
115
    protected function recordJobResult(CronJob $job, $timeTaken, $output, $resultCode)
116
    {
117
        $entityManager = $this->getContainer()->get('doctrine.orm.entity_manager');
118
119
        // Create a new CronJobResult
120
        $result = new CronJobResult();
121
        $result->setJob($job);
122
        $result->setRunTime($timeTaken);
123
        $result->setOutput($output);
124
        $result->setResult($resultCode);
125
126
        // Then update associations and persist it
127
        $job->setMostRecentRun($result);
128
        $entityManager->persist($result);
129
    }
130
}
131