Skip to content

Commit

Permalink
Separate DownloadTask
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk committed Jul 18, 2024
1 parent f8772a6 commit 670bcfd
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 50 deletions.
3 changes: 2 additions & 1 deletion src/Command/Get.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,12 @@ protected function execute(
$downloader = $container->get(Downloader::class);
$task = $downloader->download(
$softwareCollection->findSoftware('rr') ?? throw new \RuntimeException('Software not found.'),
$container->get(Destination::class),
// trap(...),
static fn() => null,
);

// $container->get(Destination::class),

($task->handler)();

// $repo = 'roadrunner-server/roadrunner';
Expand Down
70 changes: 39 additions & 31 deletions src/Module/Downloader/Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,25 @@
namespace Internal\DLoad\Module\Downloader;

use Internal\DLoad\Module\Common\Architecture;
use Internal\DLoad\Module\Common\Config\Destination;
use Internal\DLoad\Module\Common\Config\DownloaderConfig;
use Internal\DLoad\Module\Common\Config\Embed\Software;
use Internal\DLoad\Module\Common\OperatingSystem;
use Internal\DLoad\Module\Common\Stability;
use Internal\DLoad\Module\Downloader\Internal\DownloadContext;
use Internal\DLoad\Module\Downloader\Task\DownloadTask;
use Internal\DLoad\Module\Repository\AssetInterface;
use Internal\DLoad\Module\Repository\ReleaseInterface;
use Internal\DLoad\Module\Repository\RepositoryInterface;
use Internal\DLoad\Module\Repository\RepositoryProvider;

use Internal\DLoad\Service\Destroyable;
use Internal\DLoad\Service\Logger;
use React\Promise\PromiseInterface;

use function React\Async\await;
use function React\Async\coroutine;

final class Downloader
{
private array $tasks = [];

public function __construct(
private readonly DownloaderConfig $config,
private readonly Logger $logger,
Expand All @@ -42,34 +41,43 @@ public function __construct(
*/
public function download(
Software $software,
Destination $destination,
\Closure $onProgress,
): Task {
$task = new Task();
): DownloadTask {
$context = new DownloadContext(
software: $software,
destination: $destination,
onProgress: $onProgress,
);

$repositories = $software->repositories;
$task->handler = function () use ($repositories, $context): void {
// todo Try every repo to load software.
start:
$repositories === [] and throw new \RuntimeException('No relevant repository found.');
$context->repoConfig = \array_shift($repositories);
$repository = $this->repositoryProvider->getByConfig($context->repoConfig);

$this->logger->debug('Trying to load from repo `%s`', $repository->getName());

try {
await(coroutine($this->processRepository($repository, $context)));
} catch (\Throwable $e) {
$this->logger->exception($e);
goto start;
}
$handler = function () use ($repositories, $context): PromiseInterface {
return coroutine(function () use ($repositories, $context) {
// Try every repo to load software.
start:
$repositories === [] and throw new \RuntimeException('No relevant repository found.');
$context->repoConfig = \array_shift($repositories);
$repository = $this->repositoryProvider->getByConfig($context->repoConfig);

$this->logger->debug('Trying to load from repo `%s`', $repository->getName());

try {
await(coroutine($this->processRepository($repository, $context)));
} catch (\Throwable $e) {
$this->logger->exception($e);
yield;
goto start;
} finally {
$repository instanceof Destroyable and $repository->destroy();
}

return $context->file;
});
};
return $task;

return new DownloadTask(
software: $software,
onProgress: $onProgress,
handler: $handler,
);
}

/**
Expand Down Expand Up @@ -130,22 +138,23 @@ private function processRelease(ReleaseInterface $asset, DownloadContext $contex
};
}

/**
* @return \Closure(): \SplFileObject
*/
private function processAsset(AssetInterface $asset, DownloadContext $context): \Closure
{
return function () use ($asset, $context): void {
return function () use ($asset, $context): \SplFileObject {
// Create a file
$temp = $this->getTempDirectory() . '/' . $asset->getName();
$temp = $this->getTempDirectory() . DIRECTORY_SEPARATOR . $asset->getName();
$file = new \SplFileObject($temp, 'wb+');

$this->logger->info('Downloading into ' . $temp);
$this->logger->debug('Downloading into ' . $temp);

await(coroutine(
(static function () use ($asset, $context, $file): void {
$generator = $asset->download(
static fn(int $dlNow, int $dlSize, array $info) => ($context->onProgress)(
new Progress(
step: 1,
steps: 2,
total: $dlSize,
current: $dlNow,
message: 'downloading...',
Expand All @@ -162,8 +171,7 @@ private function processAsset(AssetInterface $asset, DownloadContext $context):
throw $e;
}));

// todo Unpack
$this->logger->info('Downloaded into ' . $temp);
return $context->file = $file;
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/Module/Downloader/Internal/DownloadContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Internal\DLoad\Module\Downloader\Internal;

use Internal\DLoad\Module\Common\Config\Destination;
use Internal\DLoad\Module\Common\Config\Embed\Repository;
use Internal\DLoad\Module\Common\Config\Embed\Software;
use Internal\DLoad\Module\Downloader\Progress;
Expand All @@ -13,14 +12,15 @@ final class DownloadContext
{
/** Current repository config */
public Repository $repoConfig;
/** Downloaded file */
public \SplFileObject $file;

/**
* @param \Closure(Progress): mixed $onProgress Callback to report progress.
* Exception thrown in this callback will stop and revert the task.
*/
public function __construct(
public readonly Software $software,
public readonly Destination $destination,
public readonly \Closure $onProgress,
) {}
}
2 changes: 0 additions & 2 deletions src/Module/Downloader/Progress.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
final class Progress
{
public function __construct(
public readonly int $step = 0,
public readonly int $steps = 1,
public readonly int $total = 100,
public readonly int $current = 0,
public readonly string $message = '',
Expand Down
10 changes: 0 additions & 10 deletions src/Module/Downloader/Task.php

This file was deleted.

22 changes: 22 additions & 0 deletions src/Module/Downloader/Task/DownloadTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Internal\DLoad\Module\Downloader\Task;

use Internal\DLoad\Module\Common\Config\Embed\Software;
use React\Promise\PromiseInterface;

final class DownloadTask
{
/**
* @param \Closure(Progress): mixed $onProgress Callback to report progress.
* Exception thrown in this callback will stop and revert the task.
* @param \Closure(): PromiseInterface<\SplFileObject> $handler
*/
public function __construct(
public readonly Software $software,
public readonly \Closure $onProgress,
public readonly \Closure $handler,
) {}
}
5 changes: 3 additions & 2 deletions src/Module/Repository/Internal/GitHub/GitHubRelease.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ public function getConfig(): string

public function destroy(): void
{
$this->assets === null or \array_walk($this->assets, static fn(object $asset) =>
$asset instanceof Destroyable and $asset->destroy());
$this->assets === null or $this->assets->map(
static fn(object $asset) => $asset instanceof Destroyable and $asset->destroy(),
);

unset($this->assets, $this->repository, $this->client);
}
Expand Down
5 changes: 3 additions & 2 deletions src/Module/Repository/Internal/GitHub/GitHubRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ public function getName(): string

public function destroy(): void
{
$this->releases === null or \array_walk($this->releases, static fn(object $release) =>
$release instanceof Destroyable and $release->destroy());
$this->releases === null or $this->releases->map(
static fn(object $release) => $release instanceof Destroyable and $release->destroy(),
);

unset($this->releases, $this->client);
}
Expand Down

0 comments on commit 670bcfd

Please sign in to comment.