ProcessRun   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 229
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 28
eloc 68
dl 0
loc 229
ccs 81
cts 81
cp 1
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A setUpdateOnProcessOutput() 0 4 1
A getLastMessage() 0 3 1
A isSuccessful() 0 3 1
A getTags() 0 3 1
A isUpdateOnProcessOutput() 0 3 1
A setUpdateOnPoll() 0 4 1
A hasStarted() 0 3 1
A isRunning() 0 3 1
A isUpdateOnPoll() 0 3 1
A getProcess() 0 3 1
A getLastMessageType() 0 3 1
A getExceptions() 0 6 3
A getProgress() 0 3 1
A poll() 0 25 6
A start() 0 23 5
A getEventNames() 0 9 1
1
<?php
2
/**
3
 * This file is part of graze/parallel-process.
4
 *
5
 * Copyright © 2018 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/parallel-process/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/parallel-process
12
 */
13
14
namespace Graze\ParallelProcess;
15
16
use Exception;
17
use Graze\ParallelProcess\Event\EventDispatcherTrait;
18
use Graze\ParallelProcess\Event\PriorityChangedEvent;
19
use Graze\ParallelProcess\Event\RunEvent;
20
use Symfony\Component\Process\Exception\ProcessFailedException;
21
use Symfony\Component\Process\Process;
22
use Throwable;
23
24
class ProcessRun implements RunInterface, OutputterInterface, PrioritisedInterface
25
{
26
    use EventDispatcherTrait;
27
    use RunningStateTrait;
28
    use PrioritisedTrait;
29
30
    /** @var Process */
31
    private $process;
32
    /** @var bool */
33
    private $successful = false;
34
    /** @var bool */
35
    private $completed = false;
36
    /** @var string */
37
    private $last = '';
38
    /** @var string */
39
    private $lastType = 'std';
40
    /** @var bool */
41
    private $updateOnPoll = true;
42
    /** @var bool */
43
    private $updateOnProcessOutput = true;
44
    /** @var string[] */
45
    private $tags;
46
47
    /**
48
     * Run constructor.
49
     *
50
     * @param Process  $process
51
     * @param string[] $tags List of key value tags associated with this run
52
     * @param float    $priority
53
     */
54 51
    public function __construct(Process $process, array $tags = [], $priority = 1.0)
55
    {
56 51
        $this->process = $process;
57 51
        $this->tags = $tags;
58 51
        $this->priority = $priority;
59 51
    }
60
61
    /**
62
     * @return string[]
63
     */
64 46
    protected function getEventNames()
65
    {
66
        return [
67 46
            RunEvent::STARTED,
68 46
            RunEvent::COMPLETED,
69 46
            RunEvent::FAILED,
70 46
            RunEvent::UPDATED,
71 46
            RunEvent::SUCCESSFUL,
72 46
            PriorityChangedEvent::CHANGED,
73 46
        ];
74
    }
75
76
    /**
77
     * Start the process
78
     *
79
     * @return $this
80
     */
81 38
    public function start()
82
    {
83 38
        if (!$this->process->isStarted()) {
84 37
            $this->setStarted();
85 37
            $this->dispatch(RunEvent::STARTED, new RunEvent($this));
86 37
            $this->process->start(
87 21
                function ($type, $data) {
88 21
                    $this->lastType = $type;
89 21
                    foreach (explode("\n", $data) as $line) {
90 21
                        $line = rtrim($line);
91 21
                        if (mb_strlen($line) > 0) {
92 21
                            $this->last = $line;
93 21
                            if ($this->updateOnProcessOutput) {
94 10
                                $this->dispatch(RunEvent::UPDATED, new RunEvent($this));
95 10
                            }
96 21
                        }
97 21
                    }
98 21
                }
99 37
            );
100 37
            $this->completed = false;
101 37
        }
102
103 38
        return $this;
104
    }
105
106
    /**
107
     * Poll the process to see if it is still running, and trigger events
108
     *
109
     * @return bool true if the process is currently running (started and not terminated)
110
     */
111 34
    public function poll()
112
    {
113 34
        if ($this->completed || !$this->hasStarted()) {
114 2
            return false;
115
        }
116
117 34
        if ($this->process->isRunning()) {
118 25
            if ($this->updateOnPoll) {
119 16
                $this->dispatch(RunEvent::UPDATED, new RunEvent($this));
120 16
            }
121 25
            return true;
122
        }
123
124 34
        $this->completed = true;
125 34
        $this->setFinished();
126
127 34
        if ($this->process->isSuccessful()) {
128 30
            $this->successful = true;
129 30
            $this->dispatch(RunEvent::SUCCESSFUL, new RunEvent($this));
130 30
        } else {
131 5
            $this->dispatch(RunEvent::FAILED, new RunEvent($this));
132
        }
133 34
        $this->dispatch(RunEvent::COMPLETED, new RunEvent($this));
134
135 34
        return false;
136
    }
137
138
    /**
139
     * Return if the underlying process is running
140
     *
141
     * @return bool
142
     */
143 37
    public function isRunning()
144
    {
145 37
        return $this->process->isRunning();
146
    }
147
148
    /**
149
     * @return bool
150
     */
151 28
    public function isSuccessful()
152
    {
153 28
        return $this->successful;
154
    }
155
156
    /**
157
     * @return bool
158
     */
159 47
    public function hasStarted()
160
    {
161 47
        return $this->process->isStarted();
162
    }
163
164
    /**
165
     * @return Process
166
     */
167 6
    public function getProcess()
168
    {
169 6
        return $this->process;
170
    }
171
172
    /**
173
     * @param bool $updateOnPoll
174
     *
175
     * @return $this
176
     */
177 10
    public function setUpdateOnPoll($updateOnPoll)
178
    {
179 10
        $this->updateOnPoll = $updateOnPoll;
180 10
        return $this;
181
    }
182
183
    /**
184
     * @return bool
185
     */
186 2
    public function isUpdateOnPoll()
187
    {
188 2
        return $this->updateOnPoll;
189
    }
190
191
    /**
192
     * @param bool $update
193
     *
194
     * @return $this
195
     */
196 15
    public function setUpdateOnProcessOutput($update)
197
    {
198 15
        $this->updateOnProcessOutput = $update;
199 15
        return $this;
200
    }
201
202
    /**
203
     * @return bool
204
     */
205 2
    public function isUpdateOnProcessOutput()
206
    {
207 2
        return $this->updateOnProcessOutput;
208
    }
209
210
    /**
211
     * @return array
212
     */
213 21
    public function getTags()
214
    {
215 21
        return $this->tags;
216
    }
217
218
    /**
219
     * @return float[]|null the process between 0 and 1 if the run supports it, otherwise null
220
     */
221 15
    public function getProgress()
222
    {
223 15
        return null;
224
    }
225
226
    /**
227
     * @return string
228
     */
229 15
    public function getLastMessage()
230
    {
231 15
        return $this->last;
232
    }
233
234
    /**
235
     * @return string
236
     */
237 9
    public function getLastMessageType()
238
    {
239 9
        return $this->lastType;
240
    }
241
242
    /**
243
     * If the run was unsuccessful, get the error if applicable
244
     *
245
     * @return Exception[]|Throwable[]
246
     */
247 5
    public function getExceptions()
248
    {
249 5
        if ($this->hasStarted() && !$this->isSuccessful()) {
250 4
            return [new ProcessFailedException($this->process)];
251
        }
252 1
        return [];
253
    }
254
}
255