Skip to content

Commit

Permalink
Add command for refreshing stored resources
Browse files Browse the repository at this point in the history
  • Loading branch information
RandyCupic committed Oct 15, 2023
1 parent 46eac9d commit ae769f3
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 0 deletions.
149 changes: 149 additions & 0 deletions bundle/Command/RefreshStoredResourcesCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

declare(strict_types=1);

namespace Netgen\Bundle\RemoteMediaBundle\Command;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectRepository;
use Netgen\RemoteMedia\API\ProviderInterface;
use Netgen\RemoteMedia\API\Search\Query;
use Netgen\RemoteMedia\API\Values\RemoteResource;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

use function array_key_exists;
use function array_map;
use function count;

use const PHP_EOL;

final class RefreshStoredResourcesCommand extends Command
{
private ObjectRepository $resourceRepository;

private ProgressBar $progressBar;

/** @var \Netgen\RemoteMedia\API\Values\RemoteResource[] */
private array $resourcesToDelete;

public function __construct(
EntityManagerInterface $entityManager,
private ProviderInterface $provider,
) {
$this->resourceRepository = $entityManager->getRepository(RemoteResource::class);

parent::__construct();
}

protected function configure(): void
{
$this
->setName('netgen:remote_media:refresh')
->setDescription('This command will refresh all stored resources in the database with newest data. WARNING: this might consume API rate limits.')
->addOption('batch-size', 'bs', InputOption::VALUE_OPTIONAL, 'Size of batch', 500)
->addOption('delete', 'd', InputOption::VALUE_NONE, 'Force deleting resources that are not found on remote.');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$limit = $input->getOption('batch-size');
$delete = $input->getOption('delete');
$offset = 0;

$this->progressBar = new ProgressBar($output, $this->resourceRepository->count([]));
$this->progressBar->start();

$this->resourcesToDelete = [];

do {
$resources = $this->getBatch($limit, $offset);

$this->refreshResources($resources);

$offset += $limit;
} while (count($resources) > 0);

$this->progressBar->finish();

if (count($this->resourcesToDelete) > 0 && $delete === false) {
$output->writeln(PHP_EOL . 'There are ' . count($this->resourcesToDelete) . ' resources no longer existing on remote. Use --delete to delete them.');

return Command::SUCCESS;
}

if (count($this->resourcesToDelete) > 0 && $delete === true) {
$output->writeln(PHP_EOL . 'Deleting resources that are no longer on remote:');

$progressBar = new ProgressBar($output, count($this->resourcesToDelete));
$progressBar->start();

foreach ($this->resourcesToDelete as $resource) {
$this->provider->remove($resource);
$progressBar->advance();
}

$progressBar->finish();
}

return Command::SUCCESS;
}

/**
* @return \Netgen\RemoteMedia\API\Values\RemoteResource[]
*/
private function getBatch(int $limit, int $offset): array
{
return $this->resourceRepository->findBy([], null, $limit, $offset);
}

/**
* @param \Netgen\RemoteMedia\API\Values\RemoteResource[] $resources
*/
private function refreshResources(array $resources): void
{
$remoteIds = array_map(
static fn (RemoteResource $resource): string => $resource->getRemoteId(),
$resources,
);

$remoteResources = $this->getRemoteBatch($remoteIds);

foreach ($resources as $resource) {
if (!array_key_exists($resource->getRemoteId(), $remoteResources)) {
$this->resourcesToDelete[] = $resource;

$this->progressBar->advance();

continue;
}

$remoteResource = $remoteResources[$resource->getRemoteId()];

$this->provider->store($resource->refresh($remoteResource));
$this->progressBar->advance();
}
}

/**
* @param string[] $remoteIds
*
* @return array<string, \Netgen\RemoteMedia\API\Values\RemoteResource>
*/
private function getRemoteBatch(array $remoteIds): array
{
$query = Query::fromRemoteIds($remoteIds);

$searchResult = $this->provider->search($query);

$resources = [];
foreach ($searchResult->getResources() as $resource) {
$resources[$resource->getRemoteId()] = $resource;
}

return $resources;
}
}
8 changes: 8 additions & 0 deletions bundle/Resources/config/services/commands.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
services:
netgen_remote_media.command.refresh_stored_resources:
class: Netgen\Bundle\RemoteMediaBundle\Command\RefreshStoredResourcesCommand
arguments:
- "@doctrine.orm.entity_manager"
- "@netgen_remote_media.provider"
tags:
- { name: console.command }

netgen_remote_media.command.api_usage:
class: Netgen\Bundle\RemoteMediaBundle\Command\ShowApiUsageCommand
arguments:
Expand Down

0 comments on commit ae769f3

Please sign in to comment.