Failed Conditions
Pull Request — master (#11)
by jean
12:30
created

LaunchIsolateProcessStep::execute()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 49
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 32
nc 16
nop 1
dl 0
loc 49
rs 8.5906
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Darkilliant\ProcessBundle\Step;
6
7
use Darkilliant\ProcessBundle\State\ProcessState;
8
use Symfony\Component\Console\ConsoleEvents;
9
use Symfony\Component\Console\Event\ConsoleEvent;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
12
use Symfony\Component\OptionsResolver\OptionsResolver;
13
use Symfony\Component\Process\PhpExecutableFinder;
14
use Symfony\Component\Process\Process;
15
use Symfony\Component\Process\ProcessBuilder;
16
17
class LaunchIsolateProcessStep extends AbstractConfigurableStep implements EventSubscriberInterface
18
{
19
    private $processCollection = [];
20
    private $verbosity;
21
    private $environment;
22
23
    public function __construct($environment)
24
    {
25
        $this->environment = $environment;
26
    }
27
28
    /**
29
     * @codeCoverageIgnore
30
     */
31
    public static function getSubscribedEvents()
32
    {
33
        return [
34
            ConsoleEvents::COMMAND => ['onCommand', 255],
35
        ];
36
    }
37
38
    public function onCommand(ConsoleEvent $event)
39
    {
40
        $this->verbosity = $event->getOutput()->getVerbosity();
41
    }
42
43
    public function configureOptionResolver(OptionsResolver $resolver): OptionsResolver
44
    {
45
        $resolver->setRequired(['process_name', 'max_concurency', 'context', 'data', 'timeout', 'bin_console_path']);
46
        $resolver->setDefault('context', []);
47
        $resolver->setDefault('data', []);
48
        $resolver->setDefault('max_concurency', 1);
49
        $resolver->setDefault('timeout', 60 * 20);
50
51
        return parent::configureOptionResolver($resolver);
52
    }
53
54
    public function execute(ProcessState $state)
55
    {
56
        $processName = $state->getOptions()['process_name'];
57
        $maxConcurency = $state->getOptions()['max_concurency'];
58
        $context = $state->getOptions()['context'];
59
        $data = $state->getOptions()['data'];
60
61
        $processBuilder = $this->getProcessBuilder();
62
        $phpFinder = $this->getPhpExecutableFinder();
63
64
        $arguments = [
65
            $phpFinder->find(),
66
            $state->getOptions()['bin_console_path'],
67
            'process:run',
68
            '--env=prod',
69
            '--input-from-stdin',
70
            '--force-color',
71
        ];
72
73
        $verbosityParameter = $this->getVerbosityParameter();
74
        if ($verbosityParameter) {
75
            $arguments[] = $verbosityParameter;
76
        }
77
78
        foreach ($context as $key => $value) {
79
            $arguments[] = sprintf('--context %s=%s', $key, $value);
80
        }
81
82
        if ($state->isDryRun()) {
83
            $arguments[] = '--dry-run';
84
        }
85
86
        $arguments[] = '--';
87
        $arguments[] = $processName;
88
        $processBuilder->setArguments($arguments);
89
90
        $processBuilder->setInput(json_encode($data));
91
        $processBuilder->setTimeout($state->getOptions()['timeout']);
92
        $processBuilder->disableOutput();
93
        $process = $processBuilder->getProcess();
94
95
        $this->processCollection[] = $process;
96
97
        $process->start(function ($type, $output) {
98
            echo $output;
99
        });
100
101
        if (count($this->processCollection) >= $maxConcurency) {
102
            $this->wait();
103
        }
104
    }
105
106
    public function finalize(ProcessState $state)
107
    {
108
        $this->wait();
109
    }
110
111
    /**
112
     * @codeCoverageIgnore
113
     */
114
    protected function getProcessBuilder(): ProcessBuilder
115
    {
116
        return new ProcessBuilder();
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Process\ProcessBuilder has been deprecated: since version 3.4, to be removed in 4.0. Use the Process class instead. ( Ignorable by Annotation )

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

116
        return /** @scrutinizer ignore-deprecated */ new ProcessBuilder();
Loading history...
117
    }
118
119
    /**
120
     * @codeCoverageIgnore
121
     */
122
    protected function getPhpExecutableFinder(): PhpExecutableFinder
123
    {
124
        return new PhpExecutableFinder();
125
    }
126
127
    protected function getVerbosityParameter()
128
    {
129
        if (!$this->verbosity) {
130
            return '-vv';
131
        }
132
        switch ($this->verbosity) {
133
            case OutputInterface::VERBOSITY_QUIET:
134
                return '-q';
135
            case OutputInterface::VERBOSITY_VERBOSE:
136
                return '-v';
137
            case OutputInterface::VERBOSITY_VERY_VERBOSE:
138
                return '-vv';
139
            case OutputInterface::VERBOSITY_DEBUG:
140
                return '-vvv';
141
        }
142
143
        return null;
144
    }
145
146
    private function wait()
147
    {
148
        foreach ($this->processCollection as $process) {
149
            /* @var Process $process */
150
            $process->wait();
151
        }
152
        $this->processCollection = [];
153
    }
154
}
155