mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-06 23:04:58 +00:00
Add cron job for removing expired stored objects
Introduced `RemoveExpiredStoredObjectCronJob` to automate the deletion of expired stored objects every 7 days. Enhanced associated tests and updated relevant interfaces and classes to support the new cron job functionality.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\DocStoreBundle\Service\StoredObjectCleaner;
|
||||
|
||||
use Chill\DocStoreBundle\Repository\StoredObjectRepositoryInterface;
|
||||
use Chill\MainBundle\Cron\CronJobInterface;
|
||||
use Chill\MainBundle\Entity\CronJobExecution;
|
||||
use Symfony\Component\Clock\ClockInterface;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
|
||||
/**
|
||||
* Represents a cron job that removes expired stored objects.
|
||||
*
|
||||
* This cronjob is executed every 7days, to remove expired stored object. For every
|
||||
* expired stored object, every version is sent to message bus for async deletion.
|
||||
*/
|
||||
final class RemoveExpiredStoredObjectCronJob implements CronJobInterface
|
||||
{
|
||||
public const string KEY = 'remove-expired-stored-object';
|
||||
|
||||
private const string LAST_DELETED_KEY = 'last-deleted-stored-object-id';
|
||||
|
||||
public function __construct(
|
||||
private readonly ClockInterface $clock,
|
||||
private readonly MessageBusInterface $messageBus,
|
||||
private readonly StoredObjectRepositoryInterface $storedObjectRepository
|
||||
) {}
|
||||
|
||||
public function canRun(?CronJobExecution $cronJobExecution): bool
|
||||
{
|
||||
if (null === $cronJobExecution) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->clock->now() >= $cronJobExecution->getLastEnd()->add(new \DateInterval('P7D'));
|
||||
}
|
||||
|
||||
public function getKey(): string
|
||||
{
|
||||
return self::KEY;
|
||||
}
|
||||
|
||||
public function run(array $lastExecutionData): ?array
|
||||
{
|
||||
$lastDeleted = $lastExecutionData[self::LAST_DELETED_KEY] ?? 0;
|
||||
|
||||
foreach ($this->storedObjectRepository->findByExpired($this->clock->now()) as $storedObject) {
|
||||
foreach ($storedObject->getVersions() as $version) {
|
||||
$this->messageBus->dispatch(new RemoveOldVersionMessage($version->getId()));
|
||||
}
|
||||
$lastDeleted = max($lastDeleted, $storedObject->getId());
|
||||
}
|
||||
|
||||
return [self::LAST_DELETED_KEY => $lastDeleted];
|
||||
}
|
||||
}
|
@@ -11,13 +11,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\DocStoreBundle\Service\StoredObjectCleaner;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\DocStoreBundle\Exception\StoredObjectManagerException;
|
||||
use Chill\DocStoreBundle\Repository\StoredObjectVersionRepository;
|
||||
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Clock\ClockInterface;
|
||||
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
|
||||
|
||||
/**
|
||||
* Class RemoveOldVersionMessageHandler.
|
||||
*
|
||||
* This class is responsible for handling the RemoveOldVersionMessage. It implements the MessageHandlerInterface.
|
||||
* It removes old versions of stored objects based on certain conditions.
|
||||
*
|
||||
* If a StoredObject is a candidate for deletion (is expired and no more version stored), it is also removed from the
|
||||
* database.
|
||||
*/
|
||||
final readonly class RemoveOldVersionMessageHandler implements MessageHandlerInterface
|
||||
{
|
||||
private const LOG_PREFIX = '[RemoveOldVersionMessageHandler] ';
|
||||
@@ -27,6 +38,7 @@ final readonly class RemoveOldVersionMessageHandler implements MessageHandlerInt
|
||||
private LoggerInterface $logger,
|
||||
private EntityManagerInterface $entityManager,
|
||||
private StoredObjectManagerInterface $storedObjectManager,
|
||||
private ClockInterface $clock,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -37,6 +49,7 @@ 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]);
|
||||
@@ -44,8 +57,13 @@ final readonly class RemoveOldVersionMessageHandler implements MessageHandlerInt
|
||||
}
|
||||
|
||||
$this->storedObjectManager->delete($storedObjectVersion);
|
||||
|
||||
// to ensure an immediate deletion
|
||||
$this->entityManager->remove($storedObjectVersion);
|
||||
|
||||
if (StoredObject::canBeDeleted($this->clock->now(), $storedObject)) {
|
||||
$this->entityManager->remove($storedObject);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
// clear the entity manager for future usage
|
||||
|
@@ -226,9 +226,11 @@ final class StoredObjectManager implements StoredObjectManagerInterface
|
||||
|
||||
try {
|
||||
$response = $this->client->request('DELETE', $signedUrl->url);
|
||||
if (Response::HTTP_NO_CONTENT !== $response->getStatusCode()) {
|
||||
if (! (Response::HTTP_NO_CONTENT === $response->getStatusCode() || Response::HTTP_NOT_FOUND === $response->getStatusCode())) {
|
||||
throw StoredObjectManagerException::invalidStatusCode($response->getStatusCode());
|
||||
}
|
||||
|
||||
$storedObjectVersion->getStoredObject()->removeVersion($storedObjectVersion);
|
||||
} catch (TransportExceptionInterface $exception) {
|
||||
throw StoredObjectManagerException::errorDuringHttpRequest($exception);
|
||||
}
|
||||
|
@@ -39,7 +39,9 @@ interface StoredObjectManagerInterface
|
||||
public function read(StoredObject|StoredObjectVersion $document): string;
|
||||
|
||||
/**
|
||||
* Set the content of a StoredObject.
|
||||
* Register the content of a new version for the StoredObject.
|
||||
*
|
||||
* The manager is also responsible for registering a version in the StoredObject, and return this version.
|
||||
*
|
||||
* @param StoredObject $document the document
|
||||
* @param string $clearContent The content to store in clear
|
||||
@@ -52,6 +54,11 @@ interface StoredObjectManagerInterface
|
||||
public function write(StoredObject $document, string $clearContent, ?string $contentType = null): StoredObjectVersion;
|
||||
|
||||
/**
|
||||
* Remove a version from the storage.
|
||||
*
|
||||
* This method is also responsible for removing the version from the StoredObject (using @see{StoredObject::removeVersion})
|
||||
* in case of success.
|
||||
*
|
||||
* @throws StoredObjectManagerException
|
||||
*/
|
||||
public function delete(StoredObjectVersion $storedObjectVersion): void;
|
||||
|
Reference in New Issue
Block a user