Passed
Push — test-scrutinizer-new-analyser ( 748b29 )
by Branko
05:41
created

BackgroundService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017, Matias De lellis <[email protected]>
4
 * @copyright Copyright (c) 2018, Branko Kokanovic <[email protected]>
5
 *
6
 * @author Branko Kokanovic <[email protected]>
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
namespace OCA\FaceRecognition\BackgroundJob;
25
26
use OCA\FaceRecognition\AppInfo\Application;
27
use OCA\FaceRecognition\Helper\Requirements;
28
29
use OCA\FaceRecognition\BackgroundJob\Tasks\CheckCronTask;
30
use OCA\FaceRecognition\BackgroundJob\Tasks\CheckRequirementsTask;
31
use OCA\FaceRecognition\BackgroundJob\Tasks\LockTask;
32
use OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask;
33
use OCA\FaceRecognition\BackgroundJob\Tasks\AddMissingImagesTask;
34
use OCA\FaceRecognition\BackgroundJob\Tasks\EnumerateImagesMissingFacesTask;
35
use OCA\FaceRecognition\BackgroundJob\Tasks\ImageProcessingTask;
36
use OCA\FaceRecognition\BackgroundJob\Tasks\UnlockTask;
37
38
use Symfony\Component\Console\Output\OutputInterface;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Console\Output\OutputInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
39
40
/**
41
 * Background service. Both command and cron job are calling this service for long-running background operations.
42
 * Background processing for face recognition is comprised of several steps, called tasks. Each task is independent,
43
 * idempotent, DI-aware logic unit that yields. Since tasks are non-preemptive, they should yield from time to time, so we son't end up
44
 * working for more than given timeout.
45
 *
46
 * Tasks can be seen as normal sequential functions, but they are easier to work with,
47
 * reason about them and test them independently. Other than that, they are really glorified functions.
48
 */
49
class BackgroundService {
50
51
	/** @var Application $application */
52
	private $application;
53
54
	/** @var FaceRecognitionContext */
55
	private $context;
56
57
	public function __construct(Application $application, FaceRecognitionContext $context) {
58
		$this->application = $application;
59
		$this->context = $context;
60
	}
61
62
	public function setLogger($logger) {
63
		if (!is_null($this->context->logger)) {
64
			// If you get this exception, it means you already initialized context->logger. Double-check your flow.
65
			throw new \LogicException('You cannot call setLogger after you set it once');
66
		}
67
68
		$this->context->logger = new FaceRecognitionLogger($logger);
69
	}
70
71
	/**
72
	 * Starts background tasks sequentially.
73
	 * @param int $timeout Maximum allowed time (in seconds) to execute
74
	 * @param bool $verbose Whether to be more verbose
75
	 * @param IUser|null $user ID of user to execute background operations for
76
	 *
77
	 */
78
	public function execute(int $timeout, bool $verbose, IUser $user = null) {
0 ignored issues
show
Bug introduced by
The type OCA\FaceRecognition\BackgroundJob\IUser was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
79
		// Put to context all the stuff we are figuring only now
80
		//
81
		$this->context->user = $user;
82
		$this->context->verbose = $verbose;
83
		$this->context->setRunningThroughCommand();
84
85
		// Here we are defining all the tasks that will get executed.
86
		//
87
		$task_classes = [
88
			CheckRequirementsTask::class,
89
			CheckCronTask::class,
90
			LockTask::class,
91
			CreateClustersTask::class,
92
			AddMissingImagesTask::class,
93
			EnumerateImagesMissingFacesTask::class,
94
			ImageProcessingTask::class,
95
			UnlockTask::class
96
		];
97
98
		// todo: implement bailing with exceptions
99
		// Main logic to iterate over all tasks and executes them.
100
		//
101
		$startTime = time();
102
		for ($i=0; $i < count($task_classes); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
103
			$task_class = $task_classes[$i];
104
			$task = $this->application->getContainer()->query($task_class);
105
			$this->context->logger->logInfo(sprintf("%d/%d - Executing task %s (%s)",
106
				$i+1, count($task_classes), (new \ReflectionClass($task_class))->getShortName(), $task->description()));
107
108
			$generator = $task->do($this->context);
109
			foreach ($generator as $_) {
110
				$currentTime = time();
111
				if (($timeout > 0) && ($currentTime - $startTime > $timeout)) {
112
					$this->context->logger->logInfo("Time out. Quitting...");
113
					return;
114
				}
115
116
				$this->context->logger->logDebug('yielding');
117
			}
118
		}
119
	}
120
}