Skip to content

Commit

Permalink
Merge pull request #3030 from nextcloud/feat/spread-expiry
Browse files Browse the repository at this point in the history
  • Loading branch information
skjnldsv authored Jul 16, 2024
2 parents cd6b855 + 929f840 commit 920b1cf
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 6 deletions.
6 changes: 5 additions & 1 deletion lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
use OCP\Files\IMimeTypeLoader;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IAppConfig;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
Expand Down Expand Up @@ -196,8 +197,11 @@ public function register(IRegistrationContext $context): void {
$context->registerService(\OCA\GroupFolders\BackgroundJob\ExpireGroupVersions::class, function (ContainerInterface $c) {
if (interface_exists(\OCA\Files_Versions\Versions\IVersionBackend::class)) {
return new ExpireGroupVersionsJob(
$c->get(ITimeFactory::class),
$c->get(GroupVersionsExpireManager::class),
$c->get(ITimeFactory::class)
$c->get(IAppConfig::class),
$c->get(FolderManager::class),
$c->get(LoggerInterface::class),
);
}

Expand Down
53 changes: 48 additions & 5 deletions lib/BackgroundJob/ExpireGroupVersions.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,23 @@

namespace OCA\GroupFolders\BackgroundJob;

use OCA\GroupFolders\AppInfo\Application;
use OCA\GroupFolders\Folder\FolderManager;
use OCA\GroupFolders\Versions\GroupVersionsExpireManager;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\TimedJob;
use OCP\IAppConfig;
use Psr\Log\LoggerInterface;

class ExpireGroupVersions extends TimedJob {
private GroupVersionsExpireManager $expireManager;

public function __construct(GroupVersionsExpireManager $expireManager, ITimeFactory $timeFactory) {
parent::__construct($timeFactory);
public function __construct(
ITimeFactory $time,
private GroupVersionsExpireManager $expireManager,
private IAppConfig $appConfig,
private FolderManager $folderManager,
private LoggerInterface $logger,
) {
parent::__construct($time);

// Run once per hour
$this->setInterval(60 * 60);
Expand All @@ -42,7 +50,42 @@ public function __construct(GroupVersionsExpireManager $expireManager, ITimeFact
$this->expireManager = $expireManager;
}

/**
* Expiring groupfolder versions can be quite expensive.
* We need to limit the amount of folders we expire per run.
*/
protected function run($argument) {
$this->expireManager->expireAll();
$lastFolder = $this->appConfig->getValueInt(Application::APP_ID, 'cron_last_folder_index', 0);
$folders = $this->folderManager->getAllFolders();

$folderCount = count($folders);
$currentRunHour = (int)date('G', $this->time->getTime());

// Calculate folders to process in the remaining hours, ensure at least one folder is processed
$toDo = max(1, (int)ceil(($folderCount - $lastFolder) / (24 - $currentRunHour)));

// If there are no folders, we don't need to do anything
if ($folderCount === 0) {
$this->logger->debug('No folders to expire', ['app' => 'cron']);
return;
}

// If we would go over the end of the list, wrap around
if ($lastFolder >= $folderCount) {
$lastFolder = 0;
}

// Save the updated folder index BEFORE processing the folders
$this->appConfig->setValueInt(Application::APP_ID, 'cron_last_folder_index', $lastFolder + $toDo);

// Determine the set of folders to process
$folderSet = array_slice($folders, $lastFolder, $toDo);
$folderIDs = array_map(function ($folder) {
return $folder['id'];
}, $folderSet);

// Log and start the expiration process
$this->logger->debug('Expiring versions for ' . count($folderSet) . ' folders', ['app' => 'cron', 'folders' => $folderIDs]);
$this->expireManager->expireFolders($folderSet);
}
}
7 changes: 7 additions & 0 deletions lib/Versions/GroupVersionsExpireManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public function expireAll(): void {
}
}

public function expireFolders(array $folders): void {
foreach ($folders as $folder) {
$this->emit(self::class, 'enterFolder', [$folder]);
$this->expireFolder($folder);
}
}

/**
* @param array{acl: bool, groups: array<array-key, array<array-key, int|string>>, id: int, mount_point: mixed, quota: int, size: 0} $folder
*/
Expand Down

0 comments on commit 920b1cf

Please sign in to comment.