Passed
Push — master ( a67928...026b7a )
by Matthew
08:02 queued 05:58
created

RunCommand   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Test Coverage

Coverage 85.44%

Importance

Changes 8
Bugs 1 Features 0
Metric Value
eloc 97
dl 0
loc 165
ccs 88
cts 103
cp 0.8544
rs 10
c 8
b 1
f 0
wmc 18

8 Methods

Rating   Name   Duplication   Size   Complexity  
A symfonyDetect() 0 9 4
A configure() 0 61 1
A setRunLoop() 0 3 1
A setGc() 0 12 4
A setContainer() 0 3 1
A setLogger() 0 3 1
A execute() 0 31 3
A setLoggerService() 0 11 3
1
<?php
2
3
namespace Dtc\QueueBundle\Command;
4
5
use Dtc\QueueBundle\Exception\ClassNotSubclassException;
6
use Dtc\QueueBundle\Run\Loop;
7
use Dtc\QueueBundle\Util\Util;
8
use Psr\Log\LoggerInterface;
0 ignored issues
show
Bug introduced by
The type Psr\Log\LoggerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Symfony\Component\Console\Command\Command;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Console\Command\Command was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Symfony\Component\Console\Input\InputArgument;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Console\Input\InputArgument was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Symfony\Component\Console\Input\InputInterface;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Console\Input\InputInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Symfony\Component\Console\Input\InputOption;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Console\Input\InputOption was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Symfony\Component\Console\Output\OutputInterface;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Console\Output\OutputInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Symfony\Component\DependencyInjection\Container;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\DependencyInjection\Container was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Symfony\Component\HttpKernel\Kernel;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\HttpKernel\Kernel was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
17
class RunCommand extends Command
18
{
19
    protected $loggerPrivate = false;
20
    protected $nanoSleepOption = null;
21
22
    /** @var Loop */
23
    private $runLoop;
24
    /** @var LoggerInterface */
25
    private $logger;
26
    /** @var Container */
27
    private $container;
28
29 1
    protected function symfonyDetect()
30
    {
31 1
        $this->nanoSleepOption = null;
32 1
        if (class_exists('Symfony\Component\HttpKernel\Kernel')) {
33 1
            if (Kernel::VERSION_ID >= 30000) {
34 1
                $this->nanoSleepOption = 's';
35
            }
36 1
            if (Kernel::VERSION_ID >= 30400) {
37 1
                $this->loggerPrivate = true;
38
            }
39
        }
40 1
    }
41
42 1
    protected function configure()
43
    {
44 1
        $this->symfonyDetect();
45
        $options = [
46 1
            new InputArgument('worker-name', InputArgument::OPTIONAL, 'Name of worker', null),
47 1
            new InputArgument('method', InputArgument::OPTIONAL, 'DI method of worker', null),
48 1
            new InputOption(
49 1
                'id',
50 1
                'i',
51 1
                InputOption::VALUE_REQUIRED,
52 1
                'Id of Job to run',
53 1
                null
54
            ),
55 1
            new InputOption(
56 1
                'max-count',
57 1
                'm',
58 1
                InputOption::VALUE_REQUIRED,
59 1
                'Maximum number of jobs to work on before exiting',
60 1
                null
61
            ),
62 1
            new InputOption(
63 1
                'duration',
64 1
                'd',
65 1
                InputOption::VALUE_REQUIRED,
66 1
                'Duration to run for in seconds',
67 1
                null
68
            ),
69 1
            new InputOption(
70 1
                'timeout',
71 1
                't',
72 1
                InputOption::VALUE_REQUIRED,
73 1
                'Process timeout in seconds (hard exit of process regardless)',
74 1
                3600
75
            ),
76 1
            new InputOption(
77 1
                'nano-sleep',
78 1
                $this->nanoSleepOption,
79 1
                InputOption::VALUE_REQUIRED,
80 1
                'If using duration, this is the time to sleep when there\'s no jobs in nanoseconds',
81 1
                500000000
82
            ),
83 1
            new InputOption(
84 1
                'disable-gc',
85 1
                null,
86 1
                InputOption::VALUE_NONE,
87 1
                'Disable garbage collection'
88
            ),
89
        ];
90
91 1
        $options[] =
92 1
            new InputOption(
93 1
                'logger',
94 1
                'l',
95 1
                InputOption::VALUE_REQUIRED,
96 1
                'Log using the logger service specified. Otherwise if not used will output to console. Logger service must be public, otherwise inject one by overriding the definition for this RunCommand service and calling the setLogger() method instead of using this option.'
97
            );
98
99
        $this
100 1
            ->setName('dtc:queue:run')
101 1
            ->setDefinition($options)
102 1
            ->setDescription('Start up a job in queue');
103 1
    }
104
105 1
    public function setRunLoop($runLoop)
106
    {
107 1
        $this->runLoop = $runLoop;
108 1
    }
109
110
    public function setLogger(LoggerInterface $logger)
111
    {
112
        $this->logger = $logger;
113
    }
114
115
    public function setContainer($container)
116
    {
117
        $this->container = $container;
118
    }
119
120 1
    protected function execute(InputInterface $input, OutputInterface $output)
121
    {
122 1
        $start = microtime(true);
123
        // @TODO: move this to dependency injection.
124 1
        $this->runLoop->setOutput($output);
125 1
        $workerName = $input->getArgument('worker-name');
126 1
        $methodName = $input->getArgument('method');
127 1
        $maxCount = $input->getOption('max-count');
128 1
        $duration = $input->getOption('duration');
129 1
        $processTimeout = $input->getOption('timeout');
130 1
        $nanoSleep = $input->getOption('nano-sleep');
131 1
        $loggerService = !$this->loggerPrivate ? $input->getOption('logger', null) : null;
132 1
        $disableGc = $input->getOption('disable-gc', false);
133 1
        $this->setGc($disableGc);
134
135 1
        $this->setLoggerService($this->runLoop, $loggerService);
136
137 1
        $maxCount = Util::validateIntNull('max_count', $maxCount, 32);
138 1
        $duration = Util::validateIntNull('duration', $duration, 32);
139 1
        $nanoSleep = Util::validateIntNull('nano_sleep', $nanoSleep, 63);
140 1
        $processTimeout = Util::validateIntNull('timeout', $processTimeout, 32);
141 1
        $this->runLoop->checkMaxCountDuration($maxCount, $duration, $processTimeout);
142
143
        // Check to see if there are other instances
144 1
        set_time_limit($processTimeout); // Set timeout on the process
145
146 1
        if ($jobId = $input->getOption('id')) {
147
            return $this->runLoop->runJobById($start, $jobId); // Run a single job
0 ignored issues
show
Bug introduced by
It seems like $start can also be of type string; however, parameter $start of Dtc\QueueBundle\Run\Loop::runJobById() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

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

147
            return $this->runLoop->runJobById(/** @scrutinizer ignore-type */ $start, $jobId); // Run a single job
Loading history...
148
        }
149
150 1
        return $this->runLoop->runLoop($start, $workerName, $methodName, $maxCount, $duration, $nanoSleep);
0 ignored issues
show
Bug introduced by
It seems like $start can also be of type string; however, parameter $start of Dtc\QueueBundle\Run\Loop::runLoop() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

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

150
        return $this->runLoop->runLoop(/** @scrutinizer ignore-type */ $start, $workerName, $methodName, $maxCount, $duration, $nanoSleep);
Loading history...
151
    }
152
153
    /**
154
     * @param bool $disableGc
155
     */
156 1
    protected function setGc($disableGc)
157
    {
158 1
        if ($disableGc) {
159
            if (gc_enabled()) {
160
                gc_disable();
161
            }
162
163
            return;
164
        }
165
166 1
        if (!gc_enabled()) {
167
            gc_enable();
168
        }
169 1
    }
170
171 1
    protected function setLoggerService(Loop $loop, $loggerService)
172
    {
173 1
        if (!$loggerService) {
174 1
            return;
175
        }
176
177
        $logger = $this->container->get($loggerService);
178
        if (!$logger instanceof LoggerInterface) {
179
            throw new ClassNotSubclassException("$loggerService must be instance of Psr\\Log\\LoggerInterface");
180
        }
181
        $loop->setLogger($logger);
182
    }
183
}
184