mirror of
https://github.com/nextcloud/server.git
synced 2026-02-18 18:28:50 -05:00
feat(preview): Expire previews
Signed-off-by: provokateurin <kate@provokateurin.de>
This commit is contained in:
parent
1a5679b176
commit
fe9e43c165
9 changed files with 96 additions and 4 deletions
|
|
@ -10,7 +10,7 @@ $nextcloudDir = dirname(__DIR__);
|
|||
return (require __DIR__ . '/rector-shared.php')
|
||||
->withPaths([
|
||||
$nextcloudDir . '/build/rector-strict.php',
|
||||
// TODO: Add more files. The entry above is just there to stop rector from complaining about the fact that it ran without checking any files.
|
||||
$nextcloudDir . '/core/BackgroundJobs/ExpirePreviewsJob.php',
|
||||
])
|
||||
->withPreparedSets(
|
||||
deadCode: true,
|
||||
|
|
|
|||
|
|
@ -2917,4 +2917,12 @@ $CONFIG = [
|
|||
'fe80::/10',
|
||||
'10.0.0.1',
|
||||
],
|
||||
|
||||
/**
|
||||
* Delete previews older than a certain number of days to reduce storage usage.
|
||||
* Less than one day is not allowed, so set it to 0 to disable the deletion.
|
||||
*
|
||||
* Defaults to ``0``.
|
||||
*/
|
||||
'preview_expiration_days' => 0,
|
||||
];
|
||||
|
|
|
|||
38
core/BackgroundJobs/ExpirePreviewsJob.php
Normal file
38
core/BackgroundJobs/ExpirePreviewsJob.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OC\Core\BackgroundJobs;
|
||||
|
||||
use OC\Preview\PreviewService;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\IJob;
|
||||
use OCP\BackgroundJob\TimedJob;
|
||||
use OCP\IConfig;
|
||||
|
||||
class ExpirePreviewsJob extends TimedJob {
|
||||
public function __construct(
|
||||
ITimeFactory $time,
|
||||
private readonly IConfig $config,
|
||||
private readonly PreviewService $service,
|
||||
) {
|
||||
parent::__construct($time);
|
||||
|
||||
$this->setTimeSensitivity(IJob::TIME_INSENSITIVE);
|
||||
$this->setInterval(60 * 60 * 24);
|
||||
}
|
||||
|
||||
protected function run(mixed $argument): void {
|
||||
$days = $this->config->getSystemValueInt('preview_expiration_days');
|
||||
if ($days <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->service->deleteExpiredPreviews($days);
|
||||
}
|
||||
}
|
||||
|
|
@ -1309,6 +1309,7 @@ return array(
|
|||
'OC\\Core\\BackgroundJobs\\BackgroundCleanupUpdaterBackupsJob' => $baseDir . '/core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php',
|
||||
'OC\\Core\\BackgroundJobs\\CheckForUserCertificates' => $baseDir . '/core/BackgroundJobs/CheckForUserCertificates.php',
|
||||
'OC\\Core\\BackgroundJobs\\CleanupLoginFlowV2' => $baseDir . '/core/BackgroundJobs/CleanupLoginFlowV2.php',
|
||||
'OC\\Core\\BackgroundJobs\\ExpirePreviewsJob' => $baseDir . '/core/BackgroundJobs/ExpirePreviewsJob.php',
|
||||
'OC\\Core\\BackgroundJobs\\GenerateMetadataJob' => $baseDir . '/core/BackgroundJobs/GenerateMetadataJob.php',
|
||||
'OC\\Core\\BackgroundJobs\\LookupServerSendCheckBackgroundJob' => $baseDir . '/core/BackgroundJobs/LookupServerSendCheckBackgroundJob.php',
|
||||
'OC\\Core\\BackgroundJobs\\PreviewMigrationJob' => $baseDir . '/core/BackgroundJobs/PreviewMigrationJob.php',
|
||||
|
|
|
|||
|
|
@ -1350,6 +1350,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OC\\Core\\BackgroundJobs\\BackgroundCleanupUpdaterBackupsJob' => __DIR__ . '/../../..' . '/core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php',
|
||||
'OC\\Core\\BackgroundJobs\\CheckForUserCertificates' => __DIR__ . '/../../..' . '/core/BackgroundJobs/CheckForUserCertificates.php',
|
||||
'OC\\Core\\BackgroundJobs\\CleanupLoginFlowV2' => __DIR__ . '/../../..' . '/core/BackgroundJobs/CleanupLoginFlowV2.php',
|
||||
'OC\\Core\\BackgroundJobs\\ExpirePreviewsJob' => __DIR__ . '/../../..' . '/core/BackgroundJobs/ExpirePreviewsJob.php',
|
||||
'OC\\Core\\BackgroundJobs\\GenerateMetadataJob' => __DIR__ . '/../../..' . '/core/BackgroundJobs/GenerateMetadataJob.php',
|
||||
'OC\\Core\\BackgroundJobs\\LookupServerSendCheckBackgroundJob' => __DIR__ . '/../../..' . '/core/BackgroundJobs/LookupServerSendCheckBackgroundJob.php',
|
||||
'OC\\Core\\BackgroundJobs\\PreviewMigrationJob' => __DIR__ . '/../../..' . '/core/BackgroundJobs/PreviewMigrationJob.php',
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace OC\Preview\Db;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeImmutable;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\QBMapper;
|
||||
use OCP\DB\Exception;
|
||||
|
|
@ -26,6 +28,7 @@ class PreviewMapper extends QBMapper {
|
|||
private const TABLE_NAME = 'previews';
|
||||
private const LOCATION_TABLE_NAME = 'preview_locations';
|
||||
private const VERSION_TABLE_NAME = 'preview_versions';
|
||||
public const MAX_CHUNK_SIZE = 1000;
|
||||
|
||||
public function __construct(
|
||||
IDBConnection $db,
|
||||
|
|
@ -204,11 +207,16 @@ class PreviewMapper extends QBMapper {
|
|||
/**
|
||||
* @return \Generator<Preview>
|
||||
*/
|
||||
public function getPreviews(string $lastId, int $limit = 1000): \Generator {
|
||||
public function getPreviews(string $lastId, int $limit = self::MAX_CHUNK_SIZE, ?int $maxAgeDays = null): \Generator {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$this->joinLocation($qb)
|
||||
->where($qb->expr()->gt('p.id', $qb->createNamedParameter($lastId)))
|
||||
->setMaxResults($limit);
|
||||
|
||||
if ($maxAgeDays !== null) {
|
||||
$qb->andWhere($qb->expr()->lt('mtime', $qb->createNamedParameter((new DateTimeImmutable())->sub(new DateInterval('P' . $maxAgeDays . 'D'))->getTimestamp(), IQueryBuilder::PARAM_INT)));
|
||||
}
|
||||
|
||||
return $this->yieldEntities($qb);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class PreviewService {
|
|||
public function deleteAll(): void {
|
||||
$lastId = '0';
|
||||
while (true) {
|
||||
$previews = $this->previewMapper->getPreviews($lastId, 1000);
|
||||
$previews = $this->previewMapper->getPreviews($lastId, PreviewMapper::MAX_CHUNK_SIZE);
|
||||
$i = 0;
|
||||
|
||||
// FIXME: Should we use transaction here? Du to the I/O created when
|
||||
|
|
@ -124,7 +124,7 @@ class PreviewService {
|
|||
$lastId = $preview->getId();
|
||||
}
|
||||
|
||||
if ($i !== 1000) {
|
||||
if ($i !== PreviewMapper::MAX_CHUNK_SIZE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -137,4 +137,37 @@ class PreviewService {
|
|||
public function getAvailablePreviews(array $fileIds): array {
|
||||
return $this->previewMapper->getAvailablePreviews($fileIds);
|
||||
}
|
||||
|
||||
public function deleteExpiredPreviews(int $maxAgeDays): void {
|
||||
$lastId = '0';
|
||||
$startTime = time();
|
||||
while (true) {
|
||||
try {
|
||||
$this->connection->beginTransaction();
|
||||
|
||||
$previews = $this->previewMapper->getPreviews($lastId, PreviewMapper::MAX_CHUNK_SIZE, $maxAgeDays);
|
||||
$i = 0;
|
||||
foreach ($previews as $preview) {
|
||||
$this->deletePreview($preview);
|
||||
$i++;
|
||||
$lastId = $preview->getId();
|
||||
}
|
||||
|
||||
$this->connection->commit();
|
||||
|
||||
if ($i !== PreviewMapper::MAX_CHUNK_SIZE) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->connection->commit();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// Stop if execution time is more than one hour.
|
||||
if (time() - $startTime > 3600) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use InvalidArgumentException;
|
|||
use OC\AppFramework\Bootstrap\Coordinator;
|
||||
use OC\Authentication\Token\PublicKeyTokenProvider;
|
||||
use OC\Authentication\Token\TokenCleanupJob;
|
||||
use OC\Core\BackgroundJobs\ExpirePreviewsJob;
|
||||
use OC\Core\BackgroundJobs\GenerateMetadataJob;
|
||||
use OC\Core\BackgroundJobs\PreviewMigrationJob;
|
||||
use OC\Log\Rotate;
|
||||
|
|
@ -526,6 +527,7 @@ class Setup {
|
|||
$jobList->add(CleanupDeletedUsers::class);
|
||||
$jobList->add(GenerateMetadataJob::class);
|
||||
$jobList->add(PreviewMigrationJob::class);
|
||||
$jobList->add(ExpirePreviewsJob::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
phpVersion="8.2"
|
||||
>
|
||||
<projectFiles>
|
||||
<file name="core/BackgroundJobs/ExpirePreviewsJob.php"/>
|
||||
<ignoreFiles>
|
||||
<directory name="apps/**/composer"/>
|
||||
<directory name="apps/**/tests"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue