From 669b967899527e341a8580164695e66544fd1733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 10 Sep 2024 12:06:09 +0200 Subject: [PATCH] Enhance object version removal to exclude point-in-time versions Add a check to exclude versions associated with points in time before deleting old object versions. This ensures that such versions are not mistakenly removed, providing greater data integrity. Updated tests and repository methods accordingly. --- .../Repository/StoredObjectVersionRepository.php | 4 +++- .../StoredObjectCleaner/RemoveOldVersionCronJob.php | 2 +- .../RemoveOldVersionMessageHandler.php | 8 +++++++- .../Repository/StoredObjectVersionRepositoryTest.php | 2 +- .../StoredObjectCleaner/RemoveOldVersionCronJobTest.php | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Bundle/ChillDocStoreBundle/Repository/StoredObjectVersionRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/StoredObjectVersionRepository.php index 1ab9b9edd..60ea07420 100644 --- a/src/Bundle/ChillDocStoreBundle/Repository/StoredObjectVersionRepository.php +++ b/src/Bundle/ChillDocStoreBundle/Repository/StoredObjectVersionRepository.php @@ -62,7 +62,7 @@ class StoredObjectVersionRepository implements ObjectRepository * * @return iterable returns an iterable with the IDs of the versions */ - public function findIdsByVersionsOlderThanDateAndNotLastVersion(\DateTimeImmutable $beforeDate): iterable + public function findIdsByVersionsOlderThanDateAndNotLastVersionAndNotPointInTime(\DateTimeImmutable $beforeDate): iterable { $results = $this->connection->executeQuery( self::QUERY_FIND_IDS_BY_VERSIONS_OLDER_THAN_DATE_AND_NOT_LAST_VERSION, @@ -83,6 +83,8 @@ class StoredObjectVersionRepository implements ObjectRepository sov.createdat < ?::timestamp AND sov.version < (SELECT MAX(sub_sov.version) FROM chill_doc.stored_object_version sub_sov WHERE sub_sov.stored_object_id = sov.stored_object_id) + AND + NOT EXISTS (SELECT 1 FROM chill_doc.stored_object_point_in_time sub_poi WHERE sub_poi.stored_object_version_id = sov.id) SQL; public function getClassName(): string diff --git a/src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionCronJob.php b/src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionCronJob.php index d190a4e45..d2494266b 100644 --- a/src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionCronJob.php +++ b/src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionCronJob.php @@ -50,7 +50,7 @@ final readonly class RemoveOldVersionCronJob implements CronJobInterface $deleteBeforeDate = $this->clock->now()->sub(new \DateInterval(self::KEEP_INTERVAL)); $maxDeleted = $lastExecutionData[self::LAST_DELETED_KEY] ?? 0; - foreach ($this->storedObjectVersionRepository->findIdsByVersionsOlderThanDateAndNotLastVersion($deleteBeforeDate) as $id) { + foreach ($this->storedObjectVersionRepository->findIdsByVersionsOlderThanDateAndNotLastVersionAndNotPointInTime($deleteBeforeDate) as $id) { $this->messageBus->dispatch(new RemoveOldVersionMessage($id)); $maxDeleted = max($maxDeleted, $id); } diff --git a/src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionMessageHandler.php b/src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionMessageHandler.php index 69c9f283d..ea3e37be7 100644 --- a/src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionMessageHandler.php +++ b/src/Bundle/ChillDocStoreBundle/Service/StoredObjectCleaner/RemoveOldVersionMessageHandler.php @@ -18,6 +18,7 @@ use Chill\DocStoreBundle\Service\StoredObjectManagerInterface; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Clock\ClockInterface; +use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; /** @@ -49,13 +50,18 @@ final readonly class RemoveOldVersionMessageHandler implements MessageHandlerInt $this->logger->info(self::LOG_PREFIX.'Received one message', ['storedObjectVersionId' => $message->storedObjectVersionId]); $storedObjectVersion = $this->storedObjectVersionRepository->find($message->storedObjectVersionId); - $storedObject = $storedObjectVersion->getStoredObject(); if (null === $storedObjectVersion) { $this->logger->error(self::LOG_PREFIX.'StoredObjectVersion not found in database', ['storedObjectVersionId' => $message->storedObjectVersionId]); throw new \RuntimeException('StoredObjectVersion not found with id '.$message->storedObjectVersionId); } + if ($storedObjectVersion->hasPointInTimes()) { + throw new UnrecoverableMessageHandlingException('the stored object version is now associated with a point in time'); + } + + $storedObject = $storedObjectVersion->getStoredObject(); + $this->storedObjectManager->delete($storedObjectVersion); // to ensure an immediate deletion $this->entityManager->remove($storedObjectVersion); diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Service/Repository/StoredObjectVersionRepositoryTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Service/Repository/StoredObjectVersionRepositoryTest.php index ace122bea..4b134a1fb 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Service/Repository/StoredObjectVersionRepositoryTest.php +++ b/src/Bundle/ChillDocStoreBundle/Tests/Service/Repository/StoredObjectVersionRepositoryTest.php @@ -35,7 +35,7 @@ class StoredObjectVersionRepositoryTest extends KernelTestCase $repository = new StoredObjectVersionRepository($this->entityManager); // get old version, to get a chance to get one - $actual = $repository->findIdsByVersionsOlderThanDateAndNotLastVersion(new \DateTimeImmutable('1970-01-01')); + $actual = $repository->findIdsByVersionsOlderThanDateAndNotLastVersionAndNotPointInTime(new \DateTimeImmutable('1970-01-01')); self::assertIsIterable($actual); self::assertContainsOnly('int', $actual); diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectCleaner/RemoveOldVersionCronJobTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectCleaner/RemoveOldVersionCronJobTest.php index 937253c81..df75eea93 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectCleaner/RemoveOldVersionCronJobTest.php +++ b/src/Bundle/ChillDocStoreBundle/Tests/Service/StoredObjectCleaner/RemoveOldVersionCronJobTest.php @@ -46,7 +46,7 @@ class RemoveOldVersionCronJobTest extends KernelTestCase $clock = new MockClock(new \DateTimeImmutable('2024-01-01 00:00:00', new \DateTimeZone('+00:00'))); $repository = $this->createMock(StoredObjectVersionRepository::class); $repository->expects($this->once()) - ->method('findIdsByVersionsOlderThanDateAndNotLastVersion') + ->method('findIdsByVersionsOlderThanDateAndNotLastVersionAndNotPointInTime') ->with(new \DateTime('2023-10-03 00:00:00', new \DateTimeZone('+00:00'))) ->willReturnCallback(function ($arg) { yield 1;