Completed
Push — output_parsers_refactor ( ea70d9...668933 )
by Alessandro
02:32
created

Runner::runProcess()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.128

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 15
ccs 8
cts 10
cp 0.8
rs 9.2
cc 4
eloc 8
nc 3
nop 1
crap 4.128
1
<?php
2
3
namespace Paraunit\Runner;
4
5
use Paraunit\Configuration\PHPUnitConfigFile;
6
use Paraunit\Printer\DebugPrinter;
7
use Paraunit\Process\ParaunitProcessAbstract;
8
use Paraunit\Process\ParaunitProcessInterface;
9
use Paraunit\Process\ProcessFactory;
10
use Paraunit\Lifecycle\EngineEvent;
11
use Paraunit\Lifecycle\ProcessEvent;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
14
15
/**
16
 * Class Runner.
17
 */
18
class Runner
19
{
20
    /** @var int */
21
    protected $maxProcessNumber;
22
23
    /** @var ParaunitProcessAbstract[] */
24
    protected $processStack;
25
26
    /** @var ParaunitProcessAbstract[] */
27
    protected $processCompleted;
28
29
    /** @var ParaunitProcessAbstract[] */
30
    protected $processRunning;
31
32
    /** @var  ProcessFactory */
33
    protected $processFactory;
34
35
    /** @var EventDispatcherInterface */
36
    protected $eventDispatcher;
37
38
    /**
39
     * @param int $maxProcessNumber
40
     * @param EventDispatcherInterface $eventDispatcher
41
     * @param ProcessFactory $processFactory
42
     */
43 7
    public function __construct(
44
        $maxProcessNumber = 10,
45
        EventDispatcherInterface $eventDispatcher,
46
        ProcessFactory $processFactory
47
    )
48
    {
49 7
        $this->eventDispatcher = $eventDispatcher;
50 7
        $this->maxProcessNumber = $maxProcessNumber;
51 7
        $this->processFactory = $processFactory;
52
53 7
        $this->processStack = array();
54 7
        $this->processCompleted = array();
55 7
        $this->processRunning = array();
56 7
    }
57
58
    /**
59
     * @param                 $files
60
     * @param OutputInterface $outputInterface
61
     * @param PHPUnitConfigFile $phpunitConfigFile
62
     * @param bool $debug
63
     * @return int
64
     */
65 7
    public function run($files, OutputInterface $outputInterface, PHPUnitConfigFile $phpunitConfigFile, $debug = false)
66
    {
67 7
        $this->eventDispatcher->dispatch(EngineEvent::BEFORE_START, new EngineEvent($outputInterface));
68
69 7
        $this->processFactory->setConfigFile($phpunitConfigFile);
70 7
        $start = new \Datetime('now');
71 7
        $this->createProcessStackFromFiles($files);
72
73 7
        $this->eventDispatcher->dispatch(
74 7
            EngineEvent::START,
75 7
            new EngineEvent($outputInterface, array('start' => $start,))
76 7
        );
77
78 7
        while ( ! empty($this->processStack) || ! empty($this->processRunning)) {
79
80 7
            if ($process = $this->runProcess($debug)) {
81 7
                $this->eventDispatcher->dispatch(ProcessEvent::PROCESS_STARTED, new ProcessEvent($process));
82 7
            }
83
84 7
            foreach ($this->processRunning as $process) {
85
86 7
                if ($process->isTerminated()) {
87
88 7
                    $this->eventDispatcher->dispatch(
89 7
                        ProcessEvent::PROCESS_TERMINATED,
90 7
                        new ProcessEvent($process, array('output_interface' => $outputInterface,))
91 7
                    );
92
                    // Completed or back to the stack
93 7
                    $this->markProcessCompleted($process);
94 7
                }
95
96 7
                usleep(500);
97 7
            }
98 7
        }
99
100 7
        $end = new \Datetime('now');
101
102 7
        $this->eventDispatcher->dispatch(
103 7
            EngineEvent::END,
104 7
            new EngineEvent(
105 7
                $outputInterface,
106 7
                array('end' => $end, 'start' => $start, 'process_completed' => $this->processCompleted)
107 7
            )
108 7
        );
109
110 7
        return $this->getReturnCode();
111
    }
112
113
    /**
114
     * @return int
115
     */
116 7
    protected function getReturnCode()
117
    {
118 7
        foreach ($this->processCompleted as $process) {
119 7
            if ($process->getExitCode() != 0) {
120 5
                return 10;
121
            }
122 2
        }
123
124 2
        return 0;
125
    }
126
127
    /**
128
     * @param string[] $files
129
     */
130 7
    protected function createProcessStackFromFiles($files)
131
    {
132 7
        foreach ($files as $file) {
133 7
            $process = $this->processFactory->createProcess($file);
134 7
            $this->processStack[$process->getUniqueId()] = $process;
135 7
        }
136 7
    }
137
138
    /**
139
     * @param $debug
140
     *
141
     * @return ParaunitProcessAbstract
142
     */
143 7
    protected function runProcess($debug)
144
    {
145 7
        if ($this->maxProcessNumber > count($this->processRunning) && ! empty($this->processStack)) {
146
            /** @var ParaunitProcessInterface $process */
147 7
            $process = array_pop($this->processStack);
148 7
            $process->start();
149 7
            $this->processRunning[$process->getUniqueId()] = $process;
150
151 7
            if ($debug) {
152
                DebugPrinter::printDebugOutput($process, $this->processRunning);
153
            }
154
155 7
            return $process;
156
        }
157 7
    }
158
159
    /**
160
     * @param ParaunitProcessAbstract $process
161
     * @throws \Exception
162
     */
163 7
    protected function markProcessCompleted(ParaunitProcessAbstract $process)
164
    {
165 7
        $pHash = $process->getUniqueId();
166
167 7
        if (array_key_exists($pHash, $this->processRunning)) {
168 7
            unset($this->processRunning[$pHash]);
169 7
        } else {
170
            throw new \Exception('Trying to remove a non-existing process from running stack\! ID: ' . $pHash);
171
        }
172
173 7
        if ($process->isToBeRetried()) {
174 3
            $process->reset();
175 3
            $process->increaseRetryCount();
176 3
            $this->processStack[$pHash] = $process;
177 3
        } else {
178 7
            $this->processCompleted[$pHash] = $process;
179
        }
180 7
    }
181
}
182