From 228db07a97ae9c58d1af57244efbf1f9a715a7f4 Mon Sep 17 00:00:00 2001 From: Robert Lemke Date: Tue, 19 Feb 2019 16:32:50 +0100 Subject: [PATCH] Optimize memory usage for updateResourceMetadata --- Classes/Command/GcsCommandController.php | 61 ++++++++++++++++++------ Classes/GcsTarget.php | 21 -------- Classes/StorageFactory.php | 2 +- 3 files changed, 48 insertions(+), 36 deletions(-) diff --git a/Classes/Command/GcsCommandController.php b/Classes/Command/GcsCommandController.php index 28fc0c4..86b4224 100644 --- a/Classes/Command/GcsCommandController.php +++ b/Classes/Command/GcsCommandController.php @@ -11,11 +11,16 @@ * source code. */ +use Doctrine\DBAL\FetchMode; +use Doctrine\ORM\EntityManagerInterface; use Flownative\Google\CloudStorage\Exception; use Flownative\Google\CloudStorage\GcsTarget; use Flownative\Google\CloudStorage\StorageFactory; +use Google\Cloud\Core\Exception\NotFoundException; +use Google\Cloud\Core\Exception\ServiceException; use Neos\Flow\Annotations as Flow; use Neos\Flow\Cli\CommandController; +use Neos\Flow\Persistence\PersistenceManagerInterface; use Neos\Flow\ResourceManagement\ResourceManager; use Neos\Flow\ResourceManagement\Storage\StorageObject; @@ -38,6 +43,12 @@ final class GcsCommandController extends CommandController */ protected $resourceManager; + /** + * @Flow\Inject(lazy=false) + * @var EntityManagerInterface + */ + protected $entityManager; + /** * Checks the connection * @@ -46,7 +57,7 @@ final class GcsCommandController extends CommandController * @param string $bucket The bucket which is used for trying to upload and retrieve some test data * @return void */ - public function connectCommand(string $bucket) + public function connectCommand(string $bucket): void { try { $storageClient = $this->storageFactory->create(); @@ -86,10 +97,10 @@ public function connectCommand(string $bucket) * * @param string $collection Name of the collection to publish */ - public function republishCommand(string $collection = 'persistent') + public function republishCommand(string $collection = 'persistent'): void { $collectionName = $collection; - $collection = $this->resourceManager->getCollection($collection); + $collection = $this->resourceManager->getCollection($collectionName); if (!$collection) { $this->outputLine('The collection %s does not exist.', [$collectionName]); exit(1); @@ -132,8 +143,9 @@ public function republishCommand(string $collection = 'persistent') * the same bucket. * * @param string $collection Name of the collection to publish + * @throws \Doctrine\DBAL\DBALException */ - public function updateResourceMetadataCommand(string $collection = 'persistent') + public function updateResourceMetadataCommand(string $collection = 'persistent'): void { $collectionName = $collection; $collection = $this->resourceManager->getCollection($collection); @@ -151,17 +163,38 @@ public function updateResourceMetadataCommand(string $collection = 'persistent') $this->outputLine(); $this->outputLine('Updating metadata for resources in bucket %s ...', [$target->getBucketName()]); $this->outputLine(); + + try { - foreach ($collection->getObjects() as $object) { - /** @var StorageObject $object */ - $resource = $this->resourceManager->getResourceBySha1($object->getSha1()); - if ($resource) { - try { - $target->updateResourceMetadata($resource); - $this->outputLine(' ✅ %s %s ', [$resource->getSha1(), $resource->getFilename()]); - } catch (Exception $exception) { - $this->outputLine(' ❌ %s %s', [$resource->getSha1(), $exception->getMessage()]); - } + $storageClient = $this->storageFactory->create(); + } catch (\Exception $e) { + $this->outputLine('%s', [$e->getMessage()]); + exit(1); + } + + $targetBucket = $storageClient->bucket($target->getBucketName()); + $targetKeyPrefix = $target->getKeyPrefix(); + $queryResult = $this->entityManager->getConnection()->executeQuery( + 'SELECT sha1, filename, mediatype FROM neos_flow_resourcemanagement_persistentresource AS r WHERE collectionname = :collectionName ORDER BY sha1', + [ + 'collectionName' => $collectionName + ] + ); + + try { + $previousSha1 = null; + while ($resourceRecord = $queryResult->fetch(FetchMode::ASSOCIATIVE)) { + if ($resourceRecord['sha1'] === $previousSha1) { + continue; + } + $previousSha1 = $resourceRecord['sha1']; + + try { + $object = $targetBucket->object($targetKeyPrefix . $resourceRecord['sha1']); + $object->update(['contentType' => $resourceRecord['mediatype']]); + $this->outputLine(' ✅ %s %s ', [$resourceRecord['sha1'], $resourceRecord['filename']]); + } catch (ServiceException | NotFoundException $exception) { + $this->outputLine(' ❌ %s %s', [$resourceRecord['sha1'], $resourceRecord['filename']]); } } } catch (\Exception $e) { diff --git a/Classes/GcsTarget.php b/Classes/GcsTarget.php index 4afba34..f929f85 100644 --- a/Classes/GcsTarget.php +++ b/Classes/GcsTarget.php @@ -424,27 +424,6 @@ public function publishResource(PersistentResource $resource, CollectionInterfac } } - /** - * Updates the metadata (currently content type) of a resource object already stored in this target - * - * @param PersistentResource $resource - * @throws \Flownative\Google\CloudStorage\Exception - */ - public function updateResourceMetadata(PersistentResource $resource) - { - try { - $targetBucket = $this->storageClient->bucket($this->bucketName); - } catch (NotFoundException $exception) { - throw new \Flownative\Google\CloudStorage\Exception(sprintf('Failed retrieving bucket information for "%s".', $this->bucketName), 1538462744); - } - try { - $object = $targetBucket->object($this->getKeyPrefix() . $resource->getSha1()); - $object->update(['contentType' => $resource->getMediaType()]); - } catch (ServiceException | NotFoundException $exception) { - throw new \Flownative\Google\CloudStorage\Exception(sprintf('Resource "%s" (%s) not found in bucket %s.', $resource->getSha1(), $resource->getFilename(), $this->bucketName), 1538462744); - } - } - /** * Unpublishes the given persistent resource * diff --git a/Classes/StorageFactory.php b/Classes/StorageFactory.php index 9a0d32d..bb83991 100644 --- a/Classes/StorageFactory.php +++ b/Classes/StorageFactory.php @@ -34,7 +34,7 @@ class StorageFactory protected $environment; /** - * Creates a new Storage instance and authenticates agains the Google API + * Creates a new Storage instance and authenticates against the Google API * * @param string $credentialsProfileName * @return \Google\Cloud\Storage\StorageClient