Skip to content

Commit 45a0834

Browse files
committed
feat(files_trashbin): Refactor expire background job to support parallel run
- Follow-up of #51600 The original PR introduced the possibility to continue an `ExpireTrash` job by saving the offset. This was to prevent having to start over the whole user list when the job crashed or was killed. But on big instances, one process is not enough to go through all the users in a timely manner. Supporting parallel run allows covering more ground faster. This PR introduced this possibility. We are now storing the offset right away to allow another parallel job to pick up the task at that point. We are arbitrarily cutting the user list in chunk of 10 to not drastically overflow the 30 minutes time limit. Signed-off-by: Louis Chemineau <louis@chmn.me>
1 parent 14f7982 commit 45a0834

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed

apps/files_trashbin/lib/BackgroundJob/ExpireTrash.php

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
namespace OCA\Files_Trashbin\BackgroundJob;
88

9+
use OC\Files\SetupManager;
910
use OC\Files\View;
1011
use OCA\Files_Trashbin\Expiration;
1112
use OCA\Files_Trashbin\Helper;
@@ -17,16 +18,18 @@
1718
use Psr\Log\LoggerInterface;
1819

1920
class ExpireTrash extends TimedJob {
21+
private const THIRTY_MINUTES = 30 * 60;
22+
2023
public function __construct(
2124
private IAppConfig $appConfig,
2225
private IUserManager $userManager,
2326
private Expiration $expiration,
2427
private LoggerInterface $logger,
28+
private SetupManager $setupManager,
2529
ITimeFactory $time,
2630
) {
2731
parent::__construct($time);
28-
// Run once per 30 minutes
29-
$this->setInterval(60 * 30);
32+
$this->setInterval(self::THIRTY_MINUTES);
3033
}
3134

3235
protected function run($argument) {
@@ -40,44 +43,43 @@ protected function run($argument) {
4043
return;
4144
}
4245

43-
$stopTime = time() + 60 * 30; // Stops after 30 minutes.
44-
$offset = $this->appConfig->getValueInt('files_trashbin', 'background_job_expire_trash_offset', 0);
45-
$users = $this->userManager->getSeenUsers($offset);
46+
$stopTime = time() + self::THIRTY_MINUTES;
47+
48+
do {
49+
$this->appConfig->clearCache();
50+
$offset = $this->appConfig->getValueInt('files_trashbin', 'background_job_expire_trash_offset', 0);
51+
$this->appConfig->setValueInt('files_trashbin', 'background_job_expire_trash_offset', $offset + 10);
52+
53+
$users = $this->userManager->getLastLoggedInUsers(10, $offset);
4654

47-
foreach ($users as $user) {
48-
try {
49-
$uid = $user->getUID();
50-
if (!$this->setupFS($uid)) {
51-
continue;
55+
foreach ($users as $uid) {
56+
try {
57+
if ($this->setupFS($uid)) {
58+
$dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
59+
Trashbin::deleteExpiredFiles($dirContent, $uid);
60+
}
61+
} catch (\Throwable $e) {
62+
$this->logger->error('Error while expiring trashbin for user ' . $uid, ['exception' => $e]);
5263
}
53-
$dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
54-
Trashbin::deleteExpiredFiles($dirContent, $uid);
55-
} catch (\Throwable $e) {
56-
$this->logger->error('Error while expiring trashbin for user ' . $user->getUID(), ['exception' => $e]);
64+
65+
$this->setupManager->tearDown();
5766
}
5867

59-
$offset++;
68+
} while (time() < $stopTime && count($users) === 10);
6069

61-
if ($stopTime < time()) {
62-
$this->appConfig->setValueInt('files_trashbin', 'background_job_expire_trash_offset', $offset);
63-
\OC_Util::tearDownFS();
64-
return;
65-
}
70+
if (count($users) < 10) {
71+
$this->appConfig->setValueInt('files_trashbin', 'background_job_expire_trash_offset', 0);
6672
}
67-
68-
$this->appConfig->setValueInt('files_trashbin', 'background_job_expire_trash_offset', 0);
69-
\OC_Util::tearDownFS();
7073
}
7174

7275
/**
7376
* Act on behalf on trash item owner
7477
*/
75-
protected function setupFS(string $user): bool {
76-
\OC_Util::tearDownFS();
77-
\OC_Util::setupFS($user);
78+
protected function setupFS(string $uid): bool {
79+
$this->setupManager->setupForUser($this->userManager->get($uid));
7880

7981
// Check if this user has a trashbin directory
80-
$view = new View('/' . $user);
82+
$view = new View('/' . $uid);
8183
if (!$view->is_dir('/files_trashbin/files')) {
8284
return false;
8385
}

0 commit comments

Comments
 (0)