Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 7 additions & 19 deletions lib/Migration/FixBackgroundJobs.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,16 @@

namespace OCA\Mail\Migration;

use OCA\Mail\BackgroundJob\PreviewEnhancementProcessingJob;
use OCA\Mail\BackgroundJob\QuotaJob;
use OCA\Mail\BackgroundJob\RepairSyncJob;
use OCA\Mail\BackgroundJob\SyncJob;
use OCA\Mail\BackgroundJob\TrainImportanceClassifierJob;
use OCA\Mail\Db\MailAccountMapper;
use OCP\BackgroundJob\IJobList;
use OCA\Mail\Service\AccountService;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;

class FixBackgroundJobs implements IRepairStep {
/** @var IJobList */
private $jobList;
/** @var MailAccountMapper */
private $mapper;

public function __construct(IJobList $jobList, MailAccountMapper $mapper) {
$this->jobList = $jobList;
$this->mapper = $mapper;
public function __construct(
private MailAccountMapper $mapper,
private AccountService $accountService,
) {
}

#[\Override]
Expand All @@ -43,13 +34,10 @@ public function run(IOutput $output) {

$output->startProgress(count($accounts));
foreach ($accounts as $account) {
$this->jobList->add(SyncJob::class, ['accountId' => $account->getId()]);
$this->jobList->add(RepairSyncJob::class, ['accountId' => $account->getId()]);
$this->jobList->add(TrainImportanceClassifierJob::class, ['accountId' => $account->getId()]);
$this->jobList->add(PreviewEnhancementProcessingJob::class, ['accountId' => $account->getId()]);
$this->jobList->add(QuotaJob::class, ['accountId' => $account->getId()]);
$this->accountService->scheduleBackgroundJobs($account->getId());
$output->advance();
}

$output->finishProgress();
}
}
37 changes: 31 additions & 6 deletions lib/Service/AccountService.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCA\Mail\AppInfo\Application;
use OCA\Mail\BackgroundJob\PreviewEnhancementProcessingJob;
use OCA\Mail\BackgroundJob\QuotaJob;
use OCA\Mail\BackgroundJob\RepairSyncJob;
use OCA\Mail\BackgroundJob\SyncJob;
use OCA\Mail\BackgroundJob\TrainImportanceClassifierJob;
use OCA\Mail\Db\MailAccount;
Expand All @@ -23,6 +24,7 @@
use OCA\Mail\IMAP\IMAPClientFactory;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJob;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use function array_map;
Expand Down Expand Up @@ -53,7 +55,7 @@ public function __construct(
IJobList $jobList,
IMAPClientFactory $imapClientFactory,
private readonly IConfig $config,
private readonly ITimeFactory $time,
private readonly ITimeFactory $timeFactory,
) {
$this->mapper = $mapper;
$this->aliasesService = $aliasesService;
Expand Down Expand Up @@ -176,17 +178,14 @@ public function save(MailAccount $newAccount): MailAccount {
$newAccount = $this->mapper->save($newAccount);

// Insert background jobs for this account
$this->jobList->add(SyncJob::class, ['accountId' => $newAccount->getId()]);
$this->jobList->add(TrainImportanceClassifierJob::class, ['accountId' => $newAccount->getId()]);
$this->jobList->add(PreviewEnhancementProcessingJob::class, ['accountId' => $newAccount->getId()]);
$this->jobList->add(QuotaJob::class, ['accountId' => $newAccount->getId()]);
$this->scheduleBackgroundJobs($newAccount->getId());

// Set initial heartbeat
$this->config->setUserValue(
$newAccount->getUserId(),
Application::APP_ID,
'ui-heartbeat',
(string)$this->time->getTime(),
(string)$this->timeFactory->getTime(),
);

return $newAccount;
Expand Down Expand Up @@ -235,4 +234,30 @@ public function testAccountConnection(string $currentUserId, int $accountId) :bo
return false;
}
}

public function scheduleBackgroundJobs(int $accountId): void {
$arguments = ['accountId' => $accountId];

$now = $this->timeFactory->getTime();
$this->scheduleBackgroundJob(SyncJob::class, $now, $arguments);
$this->scheduleBackgroundJob(TrainImportanceClassifierJob::class, $now, $arguments);
$this->scheduleBackgroundJob(PreviewEnhancementProcessingJob::class, $now, $arguments);
$this->scheduleBackgroundJob(QuotaJob::class, $now, $arguments);

$inThreeDays = $now + (3 * 86400);
$this->scheduleBackgroundJob(RepairSyncJob::class, $inThreeDays, $arguments);
}

/**
* IJobList::add() / IJobList::scheduleAfter() resets last_run, last_check, and reserved_at if the job exists.
* To avoid unwanted resets (e.g. when enabling debug mode), we check first if the job is already present.
*
* @param class-string<IJob> $job
* @param mixed $argument The serializable argument to be passed to $job->run() when the job is executed
*/
private function scheduleBackgroundJob(string $job, int $runAfter, mixed $argument = null): void {
if (!$this->jobList->has($job, $argument)) {
$this->jobList->scheduleAfter($job, $runAfter, $argument);
}
}
}
9 changes: 7 additions & 2 deletions lib/Service/Provisioning/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use OCA\Mail\Db\ProvisioningMapper;
use OCA\Mail\Db\TagMapper;
use OCA\Mail\Exception\ValidationException;
use OCA\Mail\Service\AccountService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\ICacheFactory;
Expand Down Expand Up @@ -56,15 +57,18 @@ class Manager {
/** @var ICacheFactory */
private $cacheFactory;

public function __construct(IUserManager $userManager,
public function __construct(
IUserManager $userManager,
ProvisioningMapper $provisioningMapper,
MailAccountMapper $mailAccountMapper,
ICrypto $crypto,
ILDAPProviderFactory $ldapProviderFactory,
AliasMapper $aliasMapper,
LoggerInterface $logger,
TagMapper $tagMapper,
ICacheFactory $cacheFactory) {
ICacheFactory $cacheFactory,
private AccountService $accountService,
) {
$this->userManager = $userManager;
$this->provisioningMapper = $provisioningMapper;
$this->mailAccountMapper = $mailAccountMapper;
Expand Down Expand Up @@ -211,6 +215,7 @@ public function provisionSingleUser(array $provisionings, IUser $user): bool {
$this->updateAccount($user, $mailAccount, $provisioning)
);

$this->accountService->scheduleBackgroundJobs($mailAccount->getId());
$this->tagMapper->createDefaultTags($mailAccount);
}

Expand Down
36 changes: 30 additions & 6 deletions tests/Unit/Service/AccountServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use ChristophWurst\Nextcloud\Testing\TestCase;
use Horde_Imap_Client_Socket;
use OCA\Mail\Account;
use OCA\Mail\BackgroundJob\QuotaJob;
use OCA\Mail\BackgroundJob\SyncJob;
use OCA\Mail\Db\MailAccount;
use OCA\Mail\Db\MailAccountMapper;
use OCA\Mail\Exception\ClientException;
Expand Down Expand Up @@ -163,24 +165,31 @@ public function testDeleteByAccountId() {
}

public function testSave() {
$account = new MailAccount();
$account->setUserId('user1');
$mailAccount = new MailAccount();
$mailAccount->setId(1000);
$mailAccount->setUserId('user1');

$this->mapper->expects($this->once())
->method('save')
->with($account)
->with($mailAccount)
->will($this->returnArgument(0));

$this->time->expects(self::once())
$this->time->expects(self::exactly(2))
->method('getTime')
->willReturn(1755850409);

$this->jobList->method('has')
->willReturn(false);
$this->jobList->expects($this->exactly(5))
->method('scheduleAfter');

$this->config->expects(self::once())
->method('setUserValue')
->with('user1', 'mail', 'ui-heartbeat', 1755850409);

$actual = $this->accountService->save($account);
$actual = $this->accountService->save($mailAccount);

$this->assertEquals($account, $actual);
$this->assertEquals($mailAccount, $actual);
}

public function testUpdateSignature() {
Expand Down Expand Up @@ -228,4 +237,19 @@ public function testAccountsSuccesfulConnection() {
$connected = $this->accountService->testAccountConnection($this->user, $accountId);
$this->assertTrue($connected);
}

public function testScheduleBackgroundJobs(): void {
$mailAccountId = 1000;
$this->time->expects(self::once())
->method('getTime')
->willReturn(1755850409);
$this->jobList->method('has')
->willReturnCallback(function ($job) {
return $job === SyncJob::class || $job === QuotaJob::class;
});
$this->jobList->expects($this->exactly(3))
->method('scheduleAfter');

$this->accountService->scheduleBackgroundJobs($mailAccountId);
}
}
Loading