Completed
Push — master ( 01dfa3...bd9515 )
by C
05:18
created

DownloadCommand::doWork()   D

Complexity

Conditions 27
Paths 64

Size

Total Lines 147
Code Lines 74

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 74
CRAP Score 27

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 147
ccs 74
cts 74
cp 1
rs 4.509
cc 27
eloc 74
nc 64
nop 2
crap 27

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace Local\Console\Command;
3
4
use GuzzleHttp\Promise;
5
use Joomla\Registry\Registry;
6
use League\Flysystem\Adapter\Local;
7
use Monolog\Logger;
8
use Tartana\Component\Command\Command;
9
use Tartana\Domain\Command\SaveDownloads;
10
use Tartana\Domain\DownloadRepository;
11
use Tartana\Entity\Download;
12
use Tartana\Host\Common\Http;
13
use Tartana\Host\HostFactory;
14
use Tartana\Mixins\CommandBusAwareTrait;
15
use Tartana\Mixins\LoggerAwareTrait;
16
use Tartana\Util;
17
use Symfony\Component\Console\Input\InputInterface;
18
use Symfony\Component\Console\Input\InputOption;
19
use Symfony\Component\Console\Output\OutputInterface;
20
use Tartana\Console\Command\AbstractDaemonCommand;
21
use Tartana\Component\Command\Runner;
22
23
class DownloadCommand extends AbstractDaemonCommand
24
{
25
	use LoggerAwareTrait;
26
	use CommandBusAwareTrait;
27
28
	private $repository = null;
29
30
	private $factory = null;
31
32 16
	public function __construct(DownloadRepository $repository, HostFactory $factory, Runner $runner)
33
	{
34 16
		parent::__construct($runner);
35
36 16
		$this->repository = $repository;
37 16
		$this->factory = $factory;
38 16
	}
39
40 16
	protected function configure()
41
	{
42 16
		parent::configure();
43
44 16
		$this->setName('download');
45 16
		$this->setDescription('Downloads links from the database. This command is running in foreground!');
46
47 16
		$this->addOption('force', 'f', InputOption::VALUE_NONE, 'Should all downloads set back to not started.');
48 16
	}
49
50 15
	protected function doWork(InputInterface $input, OutputInterface $output)
51
	{
52 15
		$repository = $this->repository;
53
54 15
		$this->log('Started to download links from the database');
55
56
		// Loading configuration for the hosters if it exists
57 15
		$config = new Registry();
58 15
		if (file_exists(TARTANA_PATH_ROOT . '/app/config/parameters.yml'))
59
		{
60 15
			$config->loadFile(TARTANA_PATH_ROOT . '/app/config/parameters.yml', 'yaml');
61
		}
62 15
		if (file_exists(TARTANA_PATH_ROOT . '/app/config/hosters.yml'))
63
		{
64 1
			$config->loadFile(TARTANA_PATH_ROOT . '/app/config/hosters.yml', 'yaml');
65
		}
66
67 15
		$force = (boolean)$input->getOption('force');
68 15
		$this->log('Restarting zombie downloads, error downloads will be ' . ($force ? '' : 'not') . ' restarted');
69
70 15
		$resets = $repository->findDownloads([
71 15
				Download::STATE_DOWNLOADING_STARTED,
72 15
				Download::STATE_DOWNLOADING_ERROR
73
		]);
74 15
		$hasChanged = false;
75 15
		foreach ($resets as $resetDownload)
76
		{
77 5
			if ($resetDownload->getState() != Download::STATE_DOWNLOADING_STARTED && !$force)
78
			{
79
				// When not forcing only check for zombie downloads
80 2
				continue;
81
			}
82 4
			if ($resetDownload->getState() == Download::STATE_DOWNLOADING_STARTED && $resetDownload->getPid() && Util::isPidRunning(
83 4
					$resetDownload->getPid()))
84
			{
85
				// There is an active process
86 1
				continue;
87
			}
88 3
			$resetDownload = Download::reset($resetDownload);
89 3
			$hasChanged = true;
90
		}
91 15
		if ($hasChanged)
92
		{
93 3
			$this->handleCommand(new SaveDownloads($resets));
94
		}
95
96 15
		while (true)
97
		{
98 15
			$notStartedDownloads = $repository->findDownloads(Download::STATE_DOWNLOADING_NOT_STARTED);
99 15
			if (empty($notStartedDownloads))
100
			{
101
				// Nothing to do anymore
102 15
				break;
103
			}
104
105 11
			$concurrentDownloads = 5;
106 11
			$counter = count($repository->findDownloads(Download::STATE_DOWNLOADING_STARTED));
107
108
			// Set download speed limit
109 11
			if (isset($config->get('parameters')->{'tartana.local.downloads.speedlimit'}) &&
110 11
					 $config->get('parameters')->{'tartana.local.downloads.speedlimit'} > 0)
111
			{
112 1
				$config->set('speedlimit', $config->get('parameters')->{'tartana.local.downloads.speedlimit'} / $concurrentDownloads);
113
			}
114
115
			// Check day limit
116 11
			if (isset($config->get('parameters')->{'tartana.local.downloads.daylimit'}) &&
117 11
					 $config->get('parameters')->{'tartana.local.downloads.daylimit'} > 0)
118
			{
119 2
				$dayLimit = $config->get('parameters')->{'tartana.local.downloads.daylimit'} * 1000;
120
121 2
				$today = (new \DateTime())->format('D');
122 2
				foreach ($repository->findDownloads(Download::STATE_DOWNLOADING_COMPLETED) as $download)
123
				{
124 2
					if ($download->getFinishedAt() && $download->getFinishedAt()->format('D') != $today)
125
					{
126 1
						continue;
127
					}
128
129 2
					$dayLimit -= $download->getSize();
130
				}
131
132 2
				if ($dayLimit <= 0)
133
				{
134 1
					$this->log('Reached day limit, not starting any download');
135 1
					$counter = $concurrentDownloads;
136
				}
137
			}
138
139 11
			$this->log('Found ' . $counter . ' started downloads.');
140
141
			// Processing the downloads
142 11
			$promises = [];
143 11
			$sharedClients = [];
144 11
			foreach ($notStartedDownloads as $download)
145
			{
146 11
				if ($counter >= $concurrentDownloads)
147
				{
148 2
					break;
149
				}
150
151 9
				$downloader = $this->factory->createHostDownloader($download->getLink(), $config);
152 9
				if ($downloader == null)
153
				{
154 1
					$this->log('No downloader found for link ' . $download->getLink(), Logger::WARNING);
155 1
					continue;
156
				}
157
158 8
				$this->log('Started to download ' . $download->getLink() . ' with the class ' . get_class($downloader));
159
160 8
				$download = Download::reset($download);
161 8
				$download->setState(Download::STATE_DOWNLOADING_STARTED);
162 8
				$download->setPid(getmypid());
163 8
				$this->handleCommand(new SaveDownloads([
164 8
						$download
165
				]));
166
167 8
				if ($downloader instanceof Http)
168
				{
169 2
					$name = get_class($downloader);
170 2
					if (!key_exists($name, $sharedClients))
171
					{
172 2
						$sharedClients[$name] = $downloader->getClient();
173
					}
174
					else
175
					{
176 1
						$downloader->setClient($sharedClients[$name]);
177
					}
178
				}
179
180 8
				$tmp = $downloader->download([
181 8
						clone $download
182
				]);
183
184 8
				$promises = array_merge($promises, $tmp ? $tmp : []);
185 8
				$counter ++;
186
			}
187
188 11
			$this->log('Downloading ' . count($promises) . ' links');
189
190 11
			Promise\unwrap($promises);
191
192
			// We sleep her as we are a daemon to relax the system a bit
193 11
			sleep($config->get('sleepTime', 10));
194
		}
195 15
		$this->log('Finished to download links from the database');
196 15
	}
197
}
198