| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- <?php
- namespace App\Service\Cron\Job;
- use App\Entity\Core\File;
- use App\Enum\Core\FileHostEnum;
- use App\Enum\Core\FileStatusEnum;
- use App\Repository\Core\FileRepository;
- use App\Service\Cron\BaseCronJob;
- use App\Service\File\Storage\LocalStorage;
- use App\Service\Utils\DatesUtils;
- use Doctrine\DBAL\Connection;
- use Doctrine\ORM\QueryBuilder;
- use JetBrains\PhpStorm\Pure;
- /**
- * Cronjob that delete temporary files older than N days.
- *
- * >>> ot:cron run clean-temp-files --preview
- * >>> ot:cron run clean-temp-files
- */
- class CleanTempFiles extends BaseCronJob
- {
- /**
- * Delay before removing a temporary file (in days).
- */
- private const DELETE_OLDER_THAN = 60;
- #[Pure]
- public function __construct(
- private Connection $connection,
- private FileRepository $fileRepository,
- private LocalStorage $storage,
- ) {
- parent::__construct();
- }
- /**
- * Preview the result of the execution, without actually deleting anything.
- *
- * @throws \Exception
- */
- public function preview(): void
- {
- $maxDate = DatesUtils::new();
- $maxDate->sub(new \DateInterval('P'.self::DELETE_OLDER_THAN.'D'));
- $files = $this->listFilesToDelete($maxDate);
- $total = count($files);
- $this->ui->print($total.' temporary files to be removed');
- $this->ui->print('> Printing the first and last 50 :');
- $i = 0;
- foreach ($files as $file) {
- ++$i;
- if ($i > 50 && ($total - $i) > 50) {
- continue;
- }
- if (($total - $i) === 50) {
- $this->ui->print(' (...)');
- }
- $this->ui->print(' * '.$file->getPath());
- }
- }
- /**
- * Proceed to the deletion of the files and the purge of the DB.
- *
- * @throws \Exception
- */
- public function execute(): void
- {
- $maxDate = DatesUtils::new();
- $maxDate->sub(new \DateInterval('P'.self::DELETE_OLDER_THAN.'D'));
- $files = $this->listFilesToDelete($maxDate);
- $this->logger->info(count($files).' temporary files to be removed');
- $this->deleteFiles($files);
- }
- /**
- * List the files to delete in the DB.
- *
- * @return array<File>
- *
- * @throws \Exception
- */
- protected function listFilesToDelete(\DateTime $maxDate): array
- {
- $this->ui->print('List temporary files created before '.$maxDate->format('c'));
- $queryBuilder = $this->fileRepository->createQueryBuilder('f');
- $queryBuilder->select();
- $this->getQueryConditions($queryBuilder, $maxDate);
- return $queryBuilder->getQuery()->getResult();
- }
- /**
- * Delete the files.
- *
- * @param array<File> $files
- */
- protected function deleteFiles(array $files): void
- {
- $total = count($files);
- $this->logger->info($total.' temporary files to be removed');
- $this->connection->setAutoCommit(false);
- $queryBuilder = $this->fileRepository->createQueryBuilder('f');
- $this->logger->info('Deleting files...');
- $i = 0;
- $deleted = 0;
- $this->ui->progress(0, $total);
- foreach ($files as $file) {
- $this->connection->beginTransaction();
- $this->ui->progress($i, $total);
- ++$i;
- try {
- // Delete from disk
- $this->storage->hardDelete($file);
- // Remove from DB
- $queryBuilder->delete()->where('f.id = :id')->setParameter('id', $file->getId());
- $this->connection->commit();
- ++$deleted;
- } catch (\RuntimeException|\InvalidArgumentException $e) {
- // Non blocking errors
- $this->connection->rollback();
- $this->logger->error('ERROR : '.$e->getMessage());
- } catch (\Exception $exception) {
- $this->connection->rollback();
- throw $exception;
- }
- }
- $this->logger->info($deleted.' files deleted');
- }
- protected function getQueryConditions(QueryBuilder $queryBuilder, \DateTime $maxDate): void
- {
- $queryBuilder
- ->andWhere(
- $queryBuilder->expr()->orX(
- $queryBuilder->expr()->eq('f.isTemporaryFile', ':temporaryTrue'),
- $queryBuilder->expr()->eq('f.status', ':status')
- )
- )
- ->andWhere($queryBuilder->expr()->eq('f.host', ':host'))
- ->andWhere(
- $queryBuilder->expr()->orX(
- $queryBuilder->expr()->lt('f.createDate', ':maxDate'),
- $queryBuilder->expr()->isNull('f.createDate')
- )
- )
- ->setParameter('temporaryTrue', true)
- ->setParameter('host', FileHostEnum::AP2I)
- ->setParameter('status', FileStatusEnum::DELETED)
- ->setParameter('maxDate', $maxDate->format('Y-m-d'))
- ;
- }
- }
|