Passed
Pull Request — master (#16)
by Harry
07:40 queued 02:51
created

Run::update()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
ccs 8
cts 8
cp 1
cc 2
eloc 7
nc 2
nop 1
crap 2

1 Method

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