Completed
Push — master ( d448ac...513048 )
by Matthew
31:40 queued 17:02
created

RunCommand::setGc()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 4
cts 8
cp 0.5
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 4
nop 1
crap 6
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\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
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 ContainerAwareCommand
18
{
19
    protected $loggerPrivate = false;
20
    protected $nanoSleepOption = null;
21
22 1
    protected function symfonyDetect()
23
    {
24 1
        $this->nanoSleepOption = null;
25 1
        if (class_exists('Symfony\Component\HttpKernel\Kernel')) {
26 1
            if (Kernel::VERSION_ID >= 30000) {
27 1
                $this->nanoSleepOption = 's';
28
            }
29 1
            if (Kernel::VERSION_ID >= 30400) {
30 1
                $this->loggerPrivate = true;
31
            }
32
        }
33 1
    }
34
35 1
    protected function configure()
36
    {
37 1
        $this->symfonyDetect();
38
        $options = array(
39 1
            new InputArgument('worker-name', InputArgument::OPTIONAL, 'Name of worker', null),
40 1
            new InputArgument('method', InputArgument::OPTIONAL, 'DI method of worker', null),
41 1
            new InputOption(
42 1
                'id',
43 1
                'i',
44 1
                InputOption::VALUE_REQUIRED,
45 1
                'Id of Job to run',
46 1
                null
47
            ),
48 1
            new InputOption(
49 1
                'max-count',
50 1
                'm',
51 1
                InputOption::VALUE_REQUIRED,
52 1
                'Maximum number of jobs to work on before exiting',
53 1
                null
54
            ),
55 1
            new InputOption(
56 1
                'duration',
57 1
                'd',
58 1
                InputOption::VALUE_REQUIRED,
59 1
                'Duration to run for in seconds',
60 1
                null
61
            ),
62 1
            new InputOption(
63 1
                'timeout',
64 1
                't',
65 1
                InputOption::VALUE_REQUIRED,
66 1
                'Process timeout in seconds (hard exit of process regardless)',
67 1
                3600
68
            ),
69 1
            new InputOption(
70 1
                'nano-sleep',
71 1
                $this->nanoSleepOption,
72 1
                InputOption::VALUE_REQUIRED,
73 1
                'If using duration, this is the time to sleep when there\'s no jobs in nanoseconds',
74 1
                500000000
75
            ),
76 1
            new InputOption(
77 1
                'disable-gc',
78 1
                null,
79 1
                InputOption::VALUE_NONE,
80 1
                'Disable garbage collection'
81
            ),
82
        );
83
84
        // Symfony 4 and Symfony 3.4 out-of-the-box makes the logger private
85 1
        if (!$this->loggerPrivate) {
86
            $options[] =
87
                new InputOption(
88
                    'logger',
89
                    'l',
90
                    InputOption::VALUE_REQUIRED,
91
                    'Log using the logger service specified, or output to console if null (or an invalid logger service id) is passed in'
92
                );
93
        }
94
95
        $this
96 1
            ->setName('dtc:queue:run')
97 1
            ->setDefinition($options)
98 1
            ->setDescription('Start up a job in queue');
99 1
    }
100
101 1
    protected function execute(InputInterface $input, OutputInterface $output)
102
    {
103 1
        $start = microtime(true);
104 1
        $container = $this->getContainer();
105 1
        $loop = $container->get('dtc_queue.run.loop');
106 1
        $loop->setOutput($output);
107 1
        $workerName = $input->getArgument('worker-name');
108 1
        $methodName = $input->getArgument('method');
109 1
        $maxCount = $input->getOption('max-count');
110 1
        $duration = $input->getOption('duration');
111 1
        $processTimeout = $input->getOption('timeout');
112 1
        $nanoSleep = $input->getOption('nano-sleep');
113 1
        $loggerService = !$this->loggerPrivate ? $input->getOption('logger', null) : null;
0 ignored issues
show
Unused Code introduced by
The call to InputInterface::getOption() has too many arguments starting with 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.

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

Loading history...
114 1
        $disableGc = $input->getOption('disable-gc', false);
0 ignored issues
show
Unused Code introduced by
The call to InputInterface::getOption() has too many arguments starting with false.

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...
115 1
        $this->setGc($disableGc);
116
117 1
        $this->setLoggerService($loop, $loggerService);
118
119 1
        $maxCount = Util::validateIntNull('max_count', $maxCount, 32);
120 1
        $duration = Util::validateIntNull('duration', $duration, 32);
121 1
        $nanoSleep = Util::validateIntNull('nano_sleep', $nanoSleep, 63);
122 1
        $processTimeout = Util::validateIntNull('timeout', $processTimeout, 32);
123 1
        $loop->checkMaxCountDuration($maxCount, $duration, $processTimeout);
124
125
        // Check to see if there are other instances
126 1
        set_time_limit($processTimeout); // Set timeout on the process
127
128 1
        if ($jobId = $input->getOption('id')) {
129
            return $loop->runJobById($start, $jobId); // Run a single job
130
        }
131
132 1
        return $loop->runLoop($start, $workerName, $methodName, $maxCount, $duration, $nanoSleep);
133
    }
134
135
    /**
136
     * @param bool $disableGc
137
     */
138 1
    protected function setGc($disableGc)
139
    {
140 1
        if ($disableGc) {
141
            if (gc_enabled()) {
142
                gc_disable();
143
            }
144
145
            return;
146
        }
147
148 1
        if (!gc_enabled()) {
149
            gc_enable();
150
        }
151 1
    }
152
153 1
    protected function setLoggerService(Loop $loop, $loggerService)
154
    {
155 1
        if (!$loggerService) {
156 1
            return;
157
        }
158
159
        $container = $this->getContainer();
160
        if (!$container->has($loggerService)) {
161
            return;
162
        }
163
164
        $logger = $container->get($loggerService);
165
        if (!$logger instanceof LoggerInterface) {
166
            throw new ClassNotSubclassException("$loggerService must be instance of Psr\\Log\\LoggerInterface");
167
        }
168
        $loop->setLogger($logger);
169
    }
170
}
171