Completed
Push — master ( 692985...e555b8 )
by Matthew
18:05
created

RunCommand::configure()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 64
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 43
CRAP Score 2.0073

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 2
eloc 50
c 3
b 0
f 0
nc 2
nop 0
dl 0
loc 64
ccs 43
cts 49
cp 0.8776
crap 2.0073
rs 9.0909

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Dtc\QueueBundle\Command;
4
5
use Dtc\QueueBundle\Exception\ClassNotSubclassException;
6
use Dtc\QueueBundle\Model\Job;
7
use Dtc\QueueBundle\Run\Loop;
8
use Dtc\QueueBundle\Util\Util;
9
use Psr\Log\LoggerInterface;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\Console\Input\InputArgument;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\HttpKernel\Kernel;
16
17
class RunCommand extends Command
18
{
19
    protected $loggerPrivate = false;
20
    protected $nanoSleepOption = null;
21
22 1
    /** @var Loop */
23
    private $runLoop;
24 1
25 1
    protected function symfonyDetect()
26 1
    {
27 1
        $this->nanoSleepOption = null;
28
        if (class_exists('Symfony\Component\HttpKernel\Kernel')) {
29 1
            if (Kernel::VERSION_ID >= 30000) {
30 1
                $this->nanoSleepOption = 's';
31
            }
32
            if (Kernel::VERSION_ID >= 30400) {
33 1
                $this->loggerPrivate = true;
34
            }
35 1
        }
36
    }
37 1
38
    protected function configure()
39 1
    {
40 1
        $this->symfonyDetect();
41 1
        $options = array(
42 1
            new InputArgument('worker-name', InputArgument::OPTIONAL, 'Name of worker', null),
43 1
            new InputArgument('method', InputArgument::OPTIONAL, 'DI method of worker', null),
44 1
            new InputOption(
45 1
                'id',
46 1
                'i',
47
                InputOption::VALUE_REQUIRED,
48 1
                'Id of Job to run',
49 1
                null
50 1
            ),
51 1
            new InputOption(
52 1
                'max-count',
53 1
                'm',
54
                InputOption::VALUE_REQUIRED,
55 1
                'Maximum number of jobs to work on before exiting',
56 1
                null
57 1
            ),
58 1
            new InputOption(
59 1
                'duration',
60 1
                'd',
61
                InputOption::VALUE_REQUIRED,
62 1
                'Duration to run for in seconds',
63 1
                null
64 1
            ),
65 1
            new InputOption(
66 1
                'timeout',
67 1
                't',
68
                InputOption::VALUE_REQUIRED,
69 1
                'Process timeout in seconds (hard exit of process regardless)',
70 1
                3600
71 1
            ),
72 1
            new InputOption(
73 1
                'nano-sleep',
74 1
                $this->nanoSleepOption,
75
                InputOption::VALUE_REQUIRED,
76 1
                'If using duration, this is the time to sleep when there\'s no jobs in nanoseconds',
77 1
                500000000
78 1
            ),
79 1
            new InputOption(
80 1
                'disable-gc',
81
                null,
82
                InputOption::VALUE_NONE,
83
                'Disable garbage collection'
84
            ),
85 1
        );
86
87
        // Symfony 4 and Symfony 3.4 out-of-the-box makes the logger private
88
        if (!$this->loggerPrivate) {
89
            $options[] =
90
                new InputOption(
91
                    'logger',
92
                    'l',
93
                    InputOption::VALUE_REQUIRED,
94
                    'Log using the logger service specified, or output to console if null (or an invalid logger service id) is passed in'
95
                );
96 1
        }
97 1
98 1
        $this
99 1
            ->setName('dtc:queue:run')
100
            ->setDefinition($options)
101 1
            ->setDescription('Start up a job in queue');
102
    }
103 1
104 1
    public function setRunLoop($runLoop) {
105 1
        $this->runLoop = $runLoop;
106 1
    }
107 1
108 1
    protected function execute(InputInterface $input, OutputInterface $output)
109 1
    {
110 1
        $start = microtime(true);
111 1
        // @TODO: move this to dependency injection.
112 1
        $this->runLoop->setOutput($output);
113 1
        $workerName = $input->getArgument('worker-name');
114 1
        $methodName = $input->getArgument('method');
115 1
        $maxCount = $input->getOption('max-count');
116
        $duration = $input->getOption('duration');
117 1
        $processTimeout = $input->getOption('timeout');
118
        $nanoSleep = $input->getOption('nano-sleep');
119 1
        $loggerService = !$this->loggerPrivate ? $input->getOption('logger', null) : null;
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Component\Consol...tInterface::getOption() has too many arguments starting with null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

119
        $loggerService = !$this->loggerPrivate ? $input->/** @scrutinizer ignore-call */ getOption('logger', null) : null;

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. Please note the @ignore annotation hint above.

Loading history...
120 1
        $disableGc = $input->getOption('disable-gc', false);
121 1
        $this->setGc($disableGc);
122 1
123 1
        $this->setLoggerService($this->runLoop, $loggerService);
124
125
        $maxCount = Util::validateIntNull('max_count', $maxCount, 32);
126 1
        $duration = Util::validateIntNull('duration', $duration, 32);
127
        $nanoSleep = Util::validateIntNull('nano_sleep', $nanoSleep, 63);
128 1
        $processTimeout = Util::validateIntNull('timeout', $processTimeout, 32);
129
        $this->runLoop->checkMaxCountDuration($maxCount, $duration, $processTimeout);
130
131
        // Check to see if there are other instances
132 1
        set_time_limit($processTimeout); // Set timeout on the process
133
134
        if ($jobId = $input->getOption('id')) {
135
            return $this->runLoop->runJobById($start, $jobId); // Run a single job
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->runLoop->runJobById($start, $jobId) targeting Dtc\QueueBundle\Run\Loop::runJobById() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
136
        }
137
138 1
        return $this->runLoop->runLoop($start, $workerName, $methodName, $maxCount, $duration, $nanoSleep);
139
    }
140 1
141
    /**
142
     * @param bool $disableGc
143
     */
144
    protected function setGc($disableGc)
145
    {
146
        if ($disableGc) {
147
            if (gc_enabled()) {
148 1
                gc_disable();
149
            }
150
151 1
            return;
152
        }
153 1
154
        if (!gc_enabled()) {
155 1
            gc_enable();
156 1
        }
157
    }
158
159
    protected function setLoggerService(Loop $loop, $loggerService)
160
    {
161
        if (!$loggerService) {
162
            return;
163
        }
164
165
        $container = $this->getContainer();
0 ignored issues
show
Bug introduced by
The method getContainer() does not exist on Dtc\QueueBundle\Command\RunCommand. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

165
        /** @scrutinizer ignore-call */ 
166
        $container = $this->getContainer();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
166
        if (!$container->has($loggerService)) {
167
            return;
168
        }
169
170
        $logger = $container->get($loggerService);
171
        if (!$logger instanceof LoggerInterface) {
172
            throw new ClassNotSubclassException("$loggerService must be instance of Psr\\Log\\LoggerInterface");
173
        }
174
        $loop->setLogger($logger);
175
    }
176
}
177