Completed
Push — master ( f0b8b1...988dc2 )
by Maxence
02:48 queued 57s
created

Runner::getInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * FullTextSearch - Full text search framework for Nextcloud
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2018
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
28
namespace OCA\FullTextSearch\Model;
29
30
use OCA\FullTextSearch\Exceptions\InterruptException;
31
use OCA\FullTextSearch\Exceptions\RunnerAlreadyUpException;
32
use OCA\FullTextSearch\Exceptions\TickDoesNotExistException;
33
use OCA\FullTextSearch\Exceptions\TickIsNotAliveException;
34
use OCA\FullTextSearch\Service\RunningService;
35
use Symfony\Component\Console\Output\OutputInterface;
36
37
38
class Runner {
39
40
41
	const TICK_TTL = 300;
42
	const TICK_MINIMUM = 2;
43
	const INFO_UPDATE = 10;
44
45
	/** @var RunningService */
46
	private $runningService;
47
48
	/** @var string */
49
	private $source;
50
51
	/** @var bool */
52
	private $strict = false;
53
54
	/** @var int */
55
	private $tickId;
56
57
	/** @var ExtendedBase */
58
	private $commandBase = null;
59
60
	/** @var OutputInterface */
61
	private $outputInterface = null;
62
63
	/** @var array */
64
	private $info = [];
65
66
	/** @var int */
67
	private $oldTick = 0;
68
69
	/** @var string */
70
	private $oldAction = '';
71
72
	/** @var int */
73
	private $ramTick = 0;
74
75
	/** @var array */
76
	private $methodOnKeyPress = [];
77
78
	/** @var array */
79
	private $methodOnNewAction = [];
80
81
	/** @var array */
82
	private $methodOnInfoUpdate = [];
83
84
	/** @var array */
85
	private $methodOnIndexError = [];
86
87
	/** @var bool */
88
	private $paused = false;
89
90
	/** @var bool */
91
	private $pauseRunning = false;
92
93
	/** @var array */
94
	private $keys = ['nextStep' => 'n'];
95
96
97
	/**
98
	 * Runner constructor.
99
	 *
100
	 * @param RunningService $runningService
101
	 * @param string $source
102
	 * @param array $keys
103
	 */
104
	public function __construct(RunningService $runningService, $source, $keys = []) {
105
		$this->runningService = $runningService;
106
		$this->source = $source;
107
108
		if (sizeof($keys) > 0) {
109
			$this->keys = $keys;
110
		}
111
	}
112
113
114
	/**
115
	 * @param bool $strict
116
	 *
117
	 * @throws RunnerAlreadyUpException
118
	 */
119
	public function start($strict = false) {
120
		$this->strict = $strict;
121
		$this->tickId = $this->runningService->start($this->source);
122
	}
123
124
125
	/**
126
	 * @param string $action
127
	 * @param bool $force
128
	 *
129
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
130
	 * @throws InterruptException
131
	 * @throws TickDoesNotExistException
132
	 */
133
	public function updateAction($action = '', $force = false) {
134
		$n = '';
135
		if (sizeof($this->methodOnKeyPress) > 0) {
136
			$n = fread(STDIN, 9999);
137
			if ($n !== '') {
138
				$n = substr($n, 0, 1);
139
				$this->keyPressed($n);
140
			}
141
		}
142
143
		if ($action === '') {
144
			return $n;
145
		}
146
147
		$tick = time();
148
		try {
149
			$this->hasBeenInterrupted();
150
		} catch (InterruptException $e) {
151
			$this->stop();
152
			throw $e;
153
		}
154
155
		if ($this->oldAction !== $action || $force) {
156
			while (true) {
157
				if (!$this->isPaused()) {
158
					break;
159
				}
160
161
				$this->pauseRunning(true);
162
				$pressed = strtolower($this->updateAction(''));
163
				if ($pressed === $this->keys['nextStep']) {
164
					break;
165
				}
166
				usleep(300000);
167
			}
168
169
			$this->pauseRunning(false);
170
			$this->newAction($action);
171
		}
172
173
		if ($this->oldAction === $action && ($this->oldTick + self::TICK_MINIMUM > $tick)) {
174
			return '';
175
		}
176
177
		$this->setInfo('action', $action);
178
		try {
179
			$this->runningService->update($this->tickId, $action);
180
		} catch (TickIsNotAliveException $e) {
181
			$this->output('Force Quit');
182
			exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method updateAction() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
183
		}
184
185
		$this->updateTick($tick);
186
		$this->oldAction = $action;
187
		$this->oldTick = $tick;
188
189
		return '';
190
	}
191
192
193
	/**
194
	 * @param string $info
195
	 * @param string $value
196
	 * @param string $colored
197
	 */
198
	public function setInfo($info, $value, $colored = '') {
199
		$this->info[$info] = $value;
200
		$this->setInfoColored($info, $value, $colored);
201
		$this->infoUpdated();
202
	}
203
204
	/**
205
	 * @param array $data
206
	 */
207
	public function setInfoArray($data) {
208
		$keys = array_keys($data);
209
		//$this->info['info'] = '';
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
210
		foreach ($keys as $k) {
211
			$this->info[$k] = $data[$k];
212
		}
213
214
		$this->infoUpdated();
215
	}
216
217
	private function setInfoColored($info, $value, $colored) {
218
		if ($colored === '') {
219
			return;
220
		}
221
222
		$color = '';
223
		switch ($colored) {
224
			case 'success':
225
				$color = 'info';
226
				break;
227
228
			case 'fail' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
229
				$color = 'error';
230
				break;
231
232
			case 'warning':
233
				$color = 'comment';
234
				break;
235
		}
236
237
		if ($color !== '') {
238
			$this->info[$info . 'Colored'] = '<' . $color . '>' . $value . '</' . $color . '>';
239
		}
240
241
242
	}
243
244
	/**
245
	 * @return array
246
	 */
247
	public function getInfo() {
248
		return $this->info;
249
	}
250
251
252
	/**
253
	 * @param array $method
254
	 */
255
	public function onKeyPress($method) {
256
		$this->methodOnKeyPress[] = $method;
257
	}
258
259
	/**
260
	 * @param $key
261
	 */
262
	public function keyPressed($key) {
263
		foreach ($this->methodOnKeyPress as $method) {
264
			call_user_func($method, $key);
265
		}
266
	}
267
268
269
	/**
270
	 * @param array $method
271
	 */
272
	public function onNewAction($method) {
273
		$this->methodOnNewAction[] = $method;
274
	}
275
276
	/**
277
	 * @param string $action
278
	 */
279
	public function newAction($action) {
280
		foreach ($this->methodOnNewAction as $method) {
281
			call_user_func($method, $action);
282
		}
283
	}
284
285
286
	/**
287
	 * @param array $method
288
	 */
289
	public function onInfoUpdate($method) {
290
		$this->methodOnInfoUpdate[] = $method;
291
	}
292
293
	/**
294
	 * @param $key
295
	 */
296
	public function infoUpdated() {
297
		foreach ($this->methodOnInfoUpdate as $method) {
298
			call_user_func($method, $this->info);
299
		}
300
	}
301
302
303
	/**
304
	 * @param array $method
305
	 */
306
	public function onNewIndexError($method) {
307
		$this->methodOnIndexError[] = $method;
308
	}
309
310
	/**
311
	 * @param Index $index
312
	 * @param string $message
313
	 * @param string $class
314
	 * @param int $sev
315
	 */
316
	public function newIndexError($index, $message, $class = '', $sev = 3) {
317
		$error = [
318
			'index'     => $index,
319
			'message'   => $message,
320
			'exception' => $class,
321
			'severity'  => $sev
322
		];
323
324
		foreach ($this->methodOnIndexError as $method) {
325
			call_user_func($method, $error);
326
		}
327
	}
328
329
330
	/**
331
	 * @throws InterruptException
332
	 */
333
	private function hasBeenInterrupted() {
334
		if ($this->commandBase === null) {
335
			return;
336
		}
337
		$this->commandBase->hasBeenInterrupted();
338
	}
339
340
341
	/**
342
	 * @param $tick
343
	 */
344
	private function updateTick($tick) {
345
		if (($this->ramTick + self::INFO_UPDATE) > $tick) {
346
			return;
347
		}
348
349
		$this->setInfo('_memory', round((memory_get_usage() / 1024 / 1024)) . ' MB');
350
		$this->ramTick = $tick;
351
	}
352
353
354
	/**
355
	 * @deprecated - verifier l'interet !?
356
	 * @param $reason
357
	 * @param $stop
358
	 */
359
	public function exception($reason, $stop) {
360
		if (!$stop) {
361
			$this->output('Exception: ' . $reason);
362
			// TODO: feed an array of exceptions for log;
363
		}
364
		$this->runningService->exception($this->tickId, $reason, $stop);
0 ignored issues
show
Deprecated Code introduced by
The method OCA\FullTextSearch\Servi...ingService::exception() has been deprecated with message: - verifier l'interet !

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
365
	}
366
367
368
	/**
369
	 * @throws TickDoesNotExistException
370
	 */
371
	public function stop() {
372
		$this->runningService->stop($this->tickId);
373
	}
374
375
376
	/**
377
	 * @param ExtendedBase $base
378
	 * @param OutputInterface $output
379
	 */
380
	public function sourceIsCommandLine(ExtendedBase $base, OutputInterface $output) {
381
		$this->outputInterface = $output;
382
		$this->commandBase = $base;
383
	}
384
385
386
	/**
387
	 * @param bool $pause
388
	 */
389
	public function pause($pause) {
390
		$this->paused = $pause;
391
		$this->infoUpdated();
392
	}
393
394
	/**
395
	 * @return bool
396
	 */
397
	public function isPaused() {
398
		return $this->paused;
399
	}
400
401
402
	/**
403
	 * @param bool $running
404
	 */
405
	public function pauseRunning($running) {
406
		$this->pauseRunning = $running;
407
		$this->infoUpdated();
408
	}
409
410
411
	public function isPauseRunning() {
412
		return $this->pauseRunning;
413
	}
414
415
416
	/**
417
	 * @return bool
418
	 */
419
	public function isStrict() {
420
		return $this->strict;
421
	}
422
423
	/**
424
	 * @param string $line
425
	 */
426
	public function output($line) {
427
		if ($this->outputInterface === null) {
428
			return;
429
		}
430
431
		$this->outputInterface->writeln($line);
432
	}
433
434
435
}