Signed-off-by: Carl Schwan <carl@carlschwan.eu>tags/v25.0.0beta3
* @package OCA\FederatedFileSharing\BackgroundJob | * @package OCA\FederatedFileSharing\BackgroundJob | ||||
*/ | */ | ||||
class RetryJob extends Job { | class RetryJob extends Job { | ||||
/** @var bool */ | |||||
private $retainJob = true; | |||||
/** @var Notifications */ | |||||
private $notifications; | |||||
private bool $retainJob = true; | |||||
private Notifications $notifications; | |||||
/** @var int max number of attempts to send the request */ | /** @var int max number of attempts to send the request */ | ||||
private $maxTry = 20; | |||||
private int $maxTry = 20; | |||||
/** @var int how much time should be between two tries (10 minutes) */ | /** @var int how much time should be between two tries (10 minutes) */ | ||||
private $interval = 600; | |||||
private int $interval = 600; | |||||
public function __construct(Notifications $notifications, | public function __construct(Notifications $notifications, | ||||
ITimeFactory $time) { | ITimeFactory $time) { | ||||
} | } | ||||
/** | /** | ||||
* run the job, then remove it from the jobList | |||||
* | |||||
* @param IJobList $jobList | |||||
* @param ILogger|null $logger | |||||
* Run the job, then remove it from the jobList | |||||
*/ | */ | ||||
public function execute(IJobList $jobList, ILogger $logger = null) { | |||||
public function start(IJobList $jobList): void { | |||||
if ($this->shouldRun($this->argument)) { | if ($this->shouldRun($this->argument)) { | ||||
parent::execute($jobList, $logger); | |||||
parent::start($jobList); | |||||
$jobList->remove($this, $this->argument); | $jobList->remove($this, $this->argument); | ||||
if ($this->retainJob) { | if ($this->retainJob) { | ||||
$this->reAddJob($jobList, $this->argument); | $this->reAddJob($jobList, $this->argument); | ||||
} | } | ||||
/** | /** | ||||
* re-add background job with new arguments | |||||
* | |||||
* @param IJobList $jobList | |||||
* @param array $argument | |||||
* Re-add background job with new arguments | |||||
*/ | */ | ||||
protected function reAddJob(IJobList $jobList, array $argument) { | |||||
protected function reAddJob(IJobList $jobList, array $argument): void { | |||||
$jobList->add(RetryJob::class, | $jobList->add(RetryJob::class, | ||||
[ | [ | ||||
'remote' => $argument['remote'], | 'remote' => $argument['remote'], | ||||
} | } | ||||
/** | /** | ||||
* test if it is time for the next run | |||||
* | |||||
* @param array $argument | |||||
* @return bool | |||||
* Test if it is time for the next run | |||||
*/ | */ | ||||
protected function shouldRun(array $argument) { | |||||
protected function shouldRun(array $argument): bool { | |||||
$lastRun = (int)$argument['lastRun']; | $lastRun = (int)$argument['lastRun']; | ||||
return (($this->time->getTime() - $lastRun) > $this->interval); | return (($this->time->getTime() - $lastRun) > $this->interval); | ||||
} | } |
use OCP\Http\Client\IClient; | use OCP\Http\Client\IClient; | ||||
use OCP\Http\Client\IClientService; | use OCP\Http\Client\IClientService; | ||||
use OCP\Http\Client\IResponse; | use OCP\Http\Client\IResponse; | ||||
use OCP\ILogger; | |||||
use OCP\IURLGenerator; | use OCP\IURLGenerator; | ||||
use OCP\OCS\IDiscoveryService; | use OCP\OCS\IDiscoveryService; | ||||
use Psr\Log\LoggerInterface; | use Psr\Log\LoggerInterface; | ||||
private LoggerInterface $logger; | private LoggerInterface $logger; | ||||
protected bool $retainJob = false; | protected bool $retainJob = false; | ||||
private string $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret'; | private string $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret'; | ||||
/** 30 day = 2592000sec */ | /** 30 day = 2592000sec */ | ||||
private int $maxLifespan = 2592000; | private int $maxLifespan = 2592000; | ||||
} | } | ||||
/** | /** | ||||
* run the job, then remove it from the joblist | |||||
* | |||||
* @param IJobList $jobList | |||||
* @param ILogger|null $logger | |||||
* Run the job, then remove it from the joblist | |||||
*/ | */ | ||||
public function execute(IJobList $jobList, ILogger $logger = null) { | |||||
public function start(IJobList $jobList): void { | |||||
$target = $this->argument['url']; | $target = $this->argument['url']; | ||||
// only execute if target is still in the list of trusted domains | // only execute if target is still in the list of trusted domains | ||||
if ($this->trustedServers->isTrustedServer($target)) { | if ($this->trustedServers->isTrustedServer($target)) { | ||||
$this->parentExecute($jobList, $logger); | |||||
$this->parentStart($jobList); | |||||
} | } | ||||
$jobList->remove($this, $this->argument); | $jobList->remove($this, $this->argument); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Call execute() method of parent | |||||
* | |||||
* @param IJobList $jobList | |||||
* @param ILogger $logger | |||||
*/ | |||||
protected function parentExecute($jobList, $logger = null) { | |||||
parent::execute($jobList, $logger); | |||||
protected function parentStart(IJobList $jobList): void { | |||||
parent::start($jobList); | |||||
} | } | ||||
protected function run($argument) { | protected function run($argument) { | ||||
$status = -1; // There is no status code if we could not connect | $status = -1; // There is no status code if we could not connect | ||||
$this->logger->info('Could not connect to ' . $target, [ | $this->logger->info('Could not connect to ' . $target, [ | ||||
'exception' => $e, | 'exception' => $e, | ||||
'app' => 'federation', | |||||
]); | ]); | ||||
} catch (\Throwable $e) { | } catch (\Throwable $e) { | ||||
$status = Http::STATUS_INTERNAL_SERVER_ERROR; | $status = Http::STATUS_INTERNAL_SERVER_ERROR; | ||||
$this->logger->error($e->getMessage(), [ | $this->logger->error($e->getMessage(), [ | ||||
'app' => 'federation', | |||||
'exception' => $e, | 'exception' => $e, | ||||
]); | ]); | ||||
} | } | ||||
); | ); | ||||
} else { | } else { | ||||
$this->logger->error( | $this->logger->error( | ||||
'remote server "' . $target . '"" does not return a valid shared secret. Received data: ' . $body, | |||||
['app' => 'federation'] | |||||
'remote server "' . $target . '"" does not return a valid shared secret. Received data: ' . $body, | |||||
['app' => 'federation'] | |||||
); | ); | ||||
$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE); | $this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* re-add background job | |||||
* Re-add background job | |||||
* | * | ||||
* @param array $argument | * @param array $argument | ||||
*/ | */ | ||||
protected function reAddJob(array $argument): void { | protected function reAddJob(array $argument): void { | ||||
$url = $argument['url']; | $url = $argument['url']; | ||||
$created = isset($argument['created']) ? (int)$argument['created'] : $this->time->getTime(); | |||||
$created = $argument['created'] ?? $this->time->getTime(); | |||||
$token = $argument['token']; | $token = $argument['token']; | ||||
$this->jobList->add( | $this->jobList->add( | ||||
GetSharedSecret::class, | GetSharedSecret::class, |
/** @var \PHPUnit\Framework\MockObject\MockObject|ITimeFactory */ | /** @var \PHPUnit\Framework\MockObject\MockObject|ITimeFactory */ | ||||
private $timeFactory; | private $timeFactory; | ||||
/** @var GetSharedSecret */ | |||||
private $getSharedSecret; | |||||
private GetSharedSecret $getSharedSecret; | |||||
protected function setUp(): void { | protected function setUp(): void { | ||||
parent::setUp(); | parent::setUp(); | ||||
* @param bool $isTrustedServer | * @param bool $isTrustedServer | ||||
* @param bool $retainBackgroundJob | * @param bool $retainBackgroundJob | ||||
*/ | */ | ||||
public function testExecute($isTrustedServer, $retainBackgroundJob) { | |||||
public function testExecute(bool $isTrustedServer, bool $retainBackgroundJob): void { | |||||
/** @var GetSharedSecret |\PHPUnit\Framework\MockObject\MockObject $getSharedSecret */ | /** @var GetSharedSecret |\PHPUnit\Framework\MockObject\MockObject $getSharedSecret */ | ||||
$getSharedSecret = $this->getMockBuilder('OCA\Federation\BackgroundJob\GetSharedSecret') | |||||
$getSharedSecret = $this->getMockBuilder(GetSharedSecret::class) | |||||
->setConstructorArgs( | ->setConstructorArgs( | ||||
[ | [ | ||||
$this->httpClientService, | $this->httpClientService, | ||||
$this->discoverService, | $this->discoverService, | ||||
$this->timeFactory | $this->timeFactory | ||||
] | ] | ||||
)->setMethods(['parentExecute'])->getMock(); | |||||
)->setMethods(['parentStart'])->getMock(); | |||||
$this->invokePrivate($getSharedSecret, 'argument', [['url' => 'url', 'token' => 'token']]); | $this->invokePrivate($getSharedSecret, 'argument', [['url' => 'url', 'token' => 'token']]); | ||||
$this->trustedServers->expects($this->once())->method('isTrustedServer') | $this->trustedServers->expects($this->once())->method('isTrustedServer') | ||||
->with('url')->willReturn($isTrustedServer); | ->with('url')->willReturn($isTrustedServer); | ||||
if ($isTrustedServer) { | if ($isTrustedServer) { | ||||
$getSharedSecret->expects($this->once())->method('parentExecute'); | |||||
$getSharedSecret->expects($this->once())->method('parentStart'); | |||||
} else { | } else { | ||||
$getSharedSecret->expects($this->never())->method('parentExecute'); | |||||
$getSharedSecret->expects($this->never())->method('parentStart'); | |||||
} | } | ||||
$this->invokePrivate($getSharedSecret, 'retainJob', [$retainBackgroundJob]); | $this->invokePrivate($getSharedSecret, 'retainJob', [$retainBackgroundJob]); | ||||
$this->jobList->expects($this->once())->method('remove'); | $this->jobList->expects($this->once())->method('remove'); |
namespace OCA\Files\BackgroundJob; | namespace OCA\Files\BackgroundJob; | ||||
use OC\Files\Utils\Scanner; | use OC\Files\Utils\Scanner; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\TimedJob; | |||||
use OCP\DB\QueryBuilder\IQueryBuilder; | use OCP\DB\QueryBuilder\IQueryBuilder; | ||||
use OCP\EventDispatcher\IEventDispatcher; | use OCP\EventDispatcher\IEventDispatcher; | ||||
use OCP\IConfig; | use OCP\IConfig; | ||||
* | * | ||||
* @package OCA\Files\BackgroundJob | * @package OCA\Files\BackgroundJob | ||||
*/ | */ | ||||
class ScanFiles extends \OC\BackgroundJob\TimedJob { | |||||
/** @var IConfig */ | |||||
private $config; | |||||
/** @var IEventDispatcher */ | |||||
private $dispatcher; | |||||
class ScanFiles extends TimedJob { | |||||
private IConfig $config; | |||||
private IEventDispatcher $dispatcher; | |||||
private LoggerInterface $logger; | private LoggerInterface $logger; | ||||
private $connection; | |||||
private IDBConnection $connection; | |||||
/** Amount of users that should get scanned per execution */ | /** Amount of users that should get scanned per execution */ | ||||
public const USERS_PER_SESSION = 500; | public const USERS_PER_SESSION = 500; | ||||
IConfig $config, | IConfig $config, | ||||
IEventDispatcher $dispatcher, | IEventDispatcher $dispatcher, | ||||
LoggerInterface $logger, | LoggerInterface $logger, | ||||
IDBConnection $connection | |||||
IDBConnection $connection, | |||||
ITimeFactory $time | |||||
) { | ) { | ||||
parent::__construct($time); | |||||
// Run once per 10 minutes | // Run once per 10 minutes | ||||
$this->setInterval(60 * 10); | $this->setInterval(60 * 10); | ||||
$this->connection = $connection; | $this->connection = $connection; | ||||
} | } | ||||
/** | |||||
* @param string $user | |||||
*/ | |||||
protected function runScanner(string $user) { | |||||
protected function runScanner(string $user): void { | |||||
try { | try { | ||||
$scanner = new Scanner( | $scanner = new Scanner( | ||||
$user, | $user, | ||||
->andWhere($query->expr()->gt('parent', $query->createNamedParameter(-1, IQueryBuilder::PARAM_INT))) | ->andWhere($query->expr()->gt('parent', $query->createNamedParameter(-1, IQueryBuilder::PARAM_INT))) | ||||
->setMaxResults(1); | ->setMaxResults(1); | ||||
return $query->execute()->fetchOne(); | |||||
return $query->executeQuery()->fetchOne(); | |||||
} | } | ||||
/** | /** |
use OC\Files\Mount\MountPoint; | use OC\Files\Mount\MountPoint; | ||||
use OC\Files\Storage\Temporary; | use OC\Files\Storage\Temporary; | ||||
use OCA\Files\BackgroundJob\ScanFiles; | use OCA\Files\BackgroundJob\ScanFiles; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\EventDispatcher\IEventDispatcher; | use OCP\EventDispatcher\IEventDispatcher; | ||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\IUser; | use OCP\IUser; | ||||
$dispatcher, | $dispatcher, | ||||
$logger, | $logger, | ||||
$connection, | $connection, | ||||
$this->createMock(ITimeFactory::class) | |||||
]) | ]) | ||||
->setMethods(['runScanner']) | ->setMethods(['runScanner']) | ||||
->getMock(); | ->getMock(); |
use OCA\Files_Trashbin\Expiration; | use OCA\Files_Trashbin\Expiration; | ||||
use OCA\Files_Trashbin\Helper; | use OCA\Files_Trashbin\Helper; | ||||
use OCA\Files_Trashbin\Trashbin; | use OCA\Files_Trashbin\Trashbin; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\TimedJob; | |||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\IUser; | use OCP\IUser; | ||||
use OCP\IUserManager; | use OCP\IUserManager; | ||||
class ExpireTrash extends \OC\BackgroundJob\TimedJob { | |||||
class ExpireTrash extends TimedJob { | |||||
private IConfig $config; | |||||
private Expiration $expiration; | |||||
private IUserManager $userManager; | |||||
/** @var IConfig */ | |||||
private $config; | |||||
/** | |||||
* @var Expiration | |||||
*/ | |||||
private $expiration; | |||||
/** | |||||
* @var IUserManager | |||||
*/ | |||||
private $userManager; | |||||
public function __construct(IConfig $config = null, | |||||
IUserManager $userManager = null, | |||||
Expiration $expiration = null) { | |||||
public function __construct( | |||||
IConfig $config, | |||||
IUserManager $userManager, | |||||
Expiration $expiration, | |||||
ITimeFactory $time | |||||
) { | |||||
parent::__construct($time); | |||||
// Run once per 30 minutes | // Run once per 30 minutes | ||||
$this->setInterval(60 * 30); | $this->setInterval(60 * 30); | ||||
if ($config === null || $expiration === null || $userManager === null) { | |||||
$this->fixDIForJobs(); | |||||
} else { | |||||
$this->config = $config; | |||||
$this->userManager = $userManager; | |||||
$this->expiration = $expiration; | |||||
} | |||||
} | |||||
protected function fixDIForJobs() { | |||||
/** @var Application $application */ | |||||
$application = \OC::$server->query(Application::class); | |||||
$this->config = $application->getContainer()->get(IConfig::class); | |||||
$this->userManager = \OC::$server->getUserManager(); | |||||
$this->expiration = $application->getContainer()->query('Expiration'); | |||||
$this->config = $config; | |||||
$this->userManager = $userManager; | |||||
$this->expiration = $expiration; | |||||
} | } | ||||
/** | /** | ||||
/** | /** | ||||
* Act on behalf on trash item owner | * Act on behalf on trash item owner | ||||
* @param string $user | |||||
* @return boolean | |||||
*/ | */ | ||||
protected function setupFS($user) { | |||||
protected function setupFS(string $user): bool { | |||||
\OC_Util::tearDownFS(); | \OC_Util::tearDownFS(); | ||||
\OC_Util::setupFS($user); | \OC_Util::setupFS($user); | ||||
use OCA\Files_Trashbin\BackgroundJob\ExpireTrash; | use OCA\Files_Trashbin\BackgroundJob\ExpireTrash; | ||||
use OCA\Files_Trashbin\Expiration; | use OCA\Files_Trashbin\Expiration; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\IJobList; | use OCP\BackgroundJob\IJobList; | ||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\ILogger; | |||||
use OCP\IUserManager; | use OCP\IUserManager; | ||||
use PHPUnit\Framework\MockObject\MockObject; | use PHPUnit\Framework\MockObject\MockObject; | ||||
use Test\TestCase; | use Test\TestCase; | ||||
use Psr\Log\LoggerInterface; | |||||
class ExpireTrashTest extends TestCase { | class ExpireTrashTest extends TestCase { | ||||
/** @var IConfig|MockObject */ | /** @var IConfig|MockObject */ | ||||
/** @var IJobList|MockObject */ | /** @var IJobList|MockObject */ | ||||
private $jobList; | private $jobList; | ||||
/** @var ILogger|MockObject */ | |||||
/** @var LoggerInterface|MockObject */ | |||||
private $logger; | private $logger; | ||||
/** @var ITimeFactory|MockObject */ | |||||
private $time; | |||||
protected function setUp(): void { | protected function setUp(): void { | ||||
parent::setUp(); | parent::setUp(); | ||||
$this->expiration = $this->createMock(Expiration::class); | $this->expiration = $this->createMock(Expiration::class); | ||||
$this->jobList = $this->createMock(IJobList::class); | $this->jobList = $this->createMock(IJobList::class); | ||||
$this->logger = $this->createMock(ILogger::class); | $this->logger = $this->createMock(ILogger::class); | ||||
$this->time = $this->createMock(ITimeFactory::class); | |||||
$this->jobList->expects($this->once()) | $this->jobList->expects($this->once()) | ||||
->method('setLastRun'); | ->method('setLastRun'); | ||||
$this->expiration->expects($this->never()) | $this->expiration->expects($this->never()) | ||||
->method('getMaxAgeAsTimestamp'); | ->method('getMaxAgeAsTimestamp'); | ||||
$job = new ExpireTrash($this->config, $this->userManager, $this->expiration); | |||||
$job->execute($this->jobList, $this->logger); | |||||
$job = new ExpireTrash($this->config, $this->userManager, $this->expiration, $this->time); | |||||
$job->start($this->jobList); | |||||
} | } | ||||
} | } |
use OCA\Files_Versions\Expiration; | use OCA\Files_Versions\Expiration; | ||||
use OCA\Files_Versions\Storage; | use OCA\Files_Versions\Storage; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\TimedJob; | |||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\IUser; | use OCP\IUser; | ||||
use OCP\IUserManager; | use OCP\IUserManager; | ||||
class ExpireVersions extends \OC\BackgroundJob\TimedJob { | |||||
class ExpireVersions extends TimedJob { | |||||
public const ITEMS_PER_SESSION = 1000; | public const ITEMS_PER_SESSION = 1000; | ||||
/** @var IConfig */ | |||||
private $config; | |||||
private IConfig $config; | |||||
private Expiration $expiration; | |||||
private IUserManager $userManager; | |||||
/** | |||||
* @var Expiration | |||||
*/ | |||||
private $expiration; | |||||
/** | |||||
* @var IUserManager | |||||
*/ | |||||
private $userManager; | |||||
public function __construct(IConfig $config, IUserManager $userManager, Expiration $expiration) { | |||||
public function __construct(IConfig $config, IUserManager $userManager, Expiration $expiration, ITimeFactory $time) { | |||||
parent::__construct($time); | |||||
// Run once per 30 minutes | // Run once per 30 minutes | ||||
$this->setInterval(60 * 30); | $this->setInterval(60 * 30); | ||||
/** | /** | ||||
* Act on behalf on trash item owner | * Act on behalf on trash item owner | ||||
* @param string $user | |||||
* @return boolean | |||||
*/ | */ | ||||
protected function setupFS($user) { | |||||
protected function setupFS(string $user): bool { | |||||
\OC_Util::tearDownFS(); | \OC_Util::tearDownFS(); | ||||
\OC_Util::setupFS($user); | \OC_Util::setupFS($user); | ||||
use OCA\Files_Versions\BackgroundJob\ExpireVersions; | use OCA\Files_Versions\BackgroundJob\ExpireVersions; | ||||
use OCA\Files_Versions\Expiration; | use OCA\Files_Versions\Expiration; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\IJobList; | use OCP\BackgroundJob\IJobList; | ||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\ILogger; | use OCP\ILogger; | ||||
/** @var IJobList|MockObject */ | /** @var IJobList|MockObject */ | ||||
private $jobList; | private $jobList; | ||||
/** @var ILogger|MockObject */ | |||||
private $logger; | |||||
protected function setUp(): void { | protected function setUp(): void { | ||||
parent::setUp(); | parent::setUp(); | ||||
$this->userManager = $this->createMock(IUserManager::class); | $this->userManager = $this->createMock(IUserManager::class); | ||||
$this->expiration = $this->createMock(Expiration::class); | $this->expiration = $this->createMock(Expiration::class); | ||||
$this->jobList = $this->createMock(IJobList::class); | $this->jobList = $this->createMock(IJobList::class); | ||||
$this->logger = $this->createMock(ILogger::class); | |||||
$this->jobList->expects($this->once()) | $this->jobList->expects($this->once()) | ||||
->method('setLastRun'); | ->method('setLastRun'); | ||||
$this->expiration->expects($this->never()) | $this->expiration->expects($this->never()) | ||||
->method('getMaxAgeAsTimestamp'); | ->method('getMaxAgeAsTimestamp'); | ||||
$job = new ExpireVersions($this->config, $this->userManager, $this->expiration); | |||||
$job->execute($this->jobList, $this->logger); | |||||
$job = new ExpireVersions($this->config, $this->userManager, $this->expiration, $this->createMock(ITimeFactory::class)); | |||||
$job->start($this->jobList); | |||||
} | } | ||||
} | } |
use OCP\IUserManager; | use OCP\IUserManager; | ||||
class RetryJob extends Job { | class RetryJob extends Job { | ||||
/** @var IClientService */ | |||||
private $clientService; | |||||
/** @var string */ | |||||
private $lookupServer; | |||||
/** @var IConfig */ | |||||
private $config; | |||||
/** @var IUserManager */ | |||||
private $userManager; | |||||
/** @var IAccountManager */ | |||||
private $accountManager; | |||||
/** @var Signer */ | |||||
private $signer; | |||||
/** @var int */ | |||||
protected $retries = 0; | |||||
/** @var bool */ | |||||
protected $retainJob = false; | |||||
private IClientService $clientService; | |||||
private string $lookupServer; | |||||
private IConfig $config; | |||||
private IUserManager $userManager; | |||||
private IAccountManager $accountManager; | |||||
private Signer $signer; | |||||
protected int $retries = 0; | |||||
protected bool $retainJob = false; | |||||
/** | /** | ||||
* @param ITimeFactory $time | * @param ITimeFactory $time | ||||
} | } | ||||
/** | /** | ||||
* run the job, then remove it from the jobList | |||||
* | |||||
* @param IJobList $jobList | |||||
* @param ILogger|null $logger | |||||
* Run the job, then remove it from the jobList | |||||
*/ | */ | ||||
public function execute(IJobList $jobList, ILogger $logger = null): void { | |||||
public function start(IJobList $jobList): void { | |||||
if (!isset($this->argument['userId'])) { | if (!isset($this->argument['userId'])) { | ||||
// Old background job without user id, just drop it. | // Old background job without user id, just drop it. | ||||
$jobList->remove($this, $this->argument); | $jobList->remove($this, $this->argument); | ||||
return; | return; | ||||
} | } | ||||
$this->retries = (int) $this->config->getUserValue($this->argument['userId'], 'lookup_server_connector', 'update_retries', 0); | |||||
$this->retries = (int) $this->config->getUserValue($this->argument['userId'], 'lookup_server_connector', 'update_retries', '0'); | |||||
if ($this->shouldRemoveBackgroundJob()) { | if ($this->shouldRemoveBackgroundJob()) { | ||||
$jobList->remove($this, $this->argument); | $jobList->remove($this, $this->argument); | ||||
} | } | ||||
if ($this->shouldRun()) { | if ($this->shouldRun()) { | ||||
parent::execute($jobList, $logger); | |||||
parent::start($jobList); | |||||
if (!$this->retainJob) { | if (!$this->retainJob) { | ||||
$jobList->remove($this, $this->argument); | $jobList->remove($this, $this->argument); | ||||
} | } | ||||
* - no valid lookup server URL given | * - no valid lookup server URL given | ||||
* - lookup server was disabled by the admin | * - lookup server was disabled by the admin | ||||
* - max retries are reached (set to 5) | * - max retries are reached (set to 5) | ||||
* | |||||
* @return bool | |||||
*/ | */ | ||||
protected function shouldRemoveBackgroundJob(): bool { | protected function shouldRemoveBackgroundJob(): bool { | ||||
return $this->config->getSystemValueBool('has_internet_connection', true) === false || | return $this->config->getSystemValueBool('has_internet_connection', true) === false || |
*/ | */ | ||||
namespace OCA\User_LDAP\Jobs; | namespace OCA\User_LDAP\Jobs; | ||||
use OC\BackgroundJob\TimedJob; | |||||
use OC\ServerNotAvailableException; | use OC\ServerNotAvailableException; | ||||
use OCA\User_LDAP\AccessFactory; | use OCA\User_LDAP\AccessFactory; | ||||
use OCA\User_LDAP\Configuration; | use OCA\User_LDAP\Configuration; | ||||
use OCA\User_LDAP\LDAP; | use OCA\User_LDAP\LDAP; | ||||
use OCA\User_LDAP\Mapping\UserMapping; | use OCA\User_LDAP\Mapping\UserMapping; | ||||
use OCA\User_LDAP\User\Manager; | use OCA\User_LDAP\User\Manager; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\TimedJob; | |||||
use OCP\IAvatarManager; | use OCP\IAvatarManager; | ||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\IDBConnection; | use OCP\IDBConnection; | ||||
/** @var AccessFactory */ | /** @var AccessFactory */ | ||||
protected $accessFactory; | protected $accessFactory; | ||||
public function __construct(Manager $userManager) { | |||||
public function __construct(Manager $userManager, ITimeFactory $time) { | |||||
parent::__construct($time); | |||||
$this->userManager = $userManager; | $this->userManager = $userManager; | ||||
$this->setInterval( | $this->setInterval( | ||||
\OC::$server->getConfig()->getAppValue( | \OC::$server->getConfig()->getAppValue( | ||||
/** | /** | ||||
* "fixes" DI | * "fixes" DI | ||||
* | |||||
* @param array $argument | |||||
*/ | */ | ||||
public function setArgument($argument) { | public function setArgument($argument) { | ||||
if (isset($argument['config'])) { | if (isset($argument['config'])) { |
use OCA\User_LDAP\LDAP; | use OCA\User_LDAP\LDAP; | ||||
use OCA\User_LDAP\Mapping\UserMapping; | use OCA\User_LDAP\Mapping\UserMapping; | ||||
use OCA\User_LDAP\User\Manager; | use OCA\User_LDAP\User\Manager; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\IAvatarManager; | use OCP\IAvatarManager; | ||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\IDBConnection; | use OCP\IDBConnection; | ||||
'accessFactory' => $this->accessFactory, | 'accessFactory' => $this->accessFactory, | ||||
]; | ]; | ||||
$this->sync = new Sync($this->userManager); | |||||
$this->sync = new Sync($this->userManager, $this->createMock(ITimeFactory::class)); | |||||
} | } | ||||
public function intervalDataProvider() { | public function intervalDataProvider() { |
*/ | */ | ||||
namespace OC\Core\BackgroundJobs; | namespace OC\Core\BackgroundJobs; | ||||
use OC\BackgroundJob\QueuedJob; | |||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\QueuedJob; | |||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use Psr\Log\LoggerInterface; | use Psr\Log\LoggerInterface; | ||||
protected IConfig $config; | protected IConfig $config; | ||||
protected LoggerInterface $log; | protected LoggerInterface $log; | ||||
public function __construct(IConfig $config, LoggerInterface $log) { | |||||
public function __construct(IConfig $config, LoggerInterface $log, ITimeFactory $time) { | |||||
parent::__construct($time); | |||||
$this->config = $config; | $this->config = $config; | ||||
$this->log = $log; | $this->log = $log; | ||||
} | } |
*/ | */ | ||||
namespace OC\Core\BackgroundJobs; | namespace OC\Core\BackgroundJobs; | ||||
use OC\BackgroundJob\QueuedJob; | |||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\QueuedJob; | |||||
use OCP\Files\Folder; | use OCP\Files\Folder; | ||||
use OCP\Files\IRootFolder; | use OCP\Files\IRootFolder; | ||||
use OCP\Files\NotFoundException; | use OCP\Files\NotFoundException; | ||||
private IUserManager $userManager; | private IUserManager $userManager; | ||||
private IRootFolder $rootFolder; | private IRootFolder $rootFolder; | ||||
public function __construct(IConfig $config, IUserManager $userManager, IRootFolder $rootFolder) { | |||||
public function __construct(IConfig $config, IUserManager $userManager, IRootFolder $rootFolder, ITimeFactory $time) { | |||||
parent::__construct($time); | |||||
$this->config = $config; | $this->config = $config; | ||||
$this->userManager = $userManager; | $this->userManager = $userManager; | ||||
$this->rootFolder = $rootFolder; | $this->rootFolder = $rootFolder; |
*/ | */ | ||||
namespace OC\Core\BackgroundJobs; | namespace OC\Core\BackgroundJobs; | ||||
use OC\BackgroundJob\QueuedJob; | |||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\QueuedJob; | |||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\IUser; | use OCP\IUser; | ||||
use OCP\IUserManager; | use OCP\IUserManager; | ||||
protected IConfig $config; | protected IConfig $config; | ||||
private IUserManager $userManager; | private IUserManager $userManager; | ||||
public function __construct(IConfig $config, IUserManager $userManager) { | |||||
public function __construct(IConfig $config, IUserManager $userManager, ITimeFactory $time) { | |||||
parent::__construct($time); | |||||
$this->config = $config; | $this->config = $config; | ||||
$this->userManager = $userManager; | $this->userManager = $userManager; | ||||
} | } |
} | } | ||||
} | } | ||||
public function start(IJobList $jobList): void { | |||||
$this->execute($jobList); | |||||
} | |||||
abstract protected function run($argument); | abstract protected function run($argument); | ||||
public function setId(int $id) { | public function setId(int $id) { |
/** | /** | ||||
* @deprecated internal class, use \OCP\BackgroundJob\QueuedJob | * @deprecated internal class, use \OCP\BackgroundJob\QueuedJob | ||||
*/ | */ | ||||
class QueuedJob extends \OC\BackgroundJob\QueuedJob { | |||||
class QueuedJob extends \OCP\BackgroundJob\QueuedJob { | |||||
public function run($argument) { | public function run($argument) { | ||||
$class = $argument['klass']; | $class = $argument['klass']; | ||||
$method = $argument['method']; | $method = $argument['method']; |
/** | /** | ||||
* @deprecated internal class, use \OCP\BackgroundJob\QueuedJob | * @deprecated internal class, use \OCP\BackgroundJob\QueuedJob | ||||
*/ | */ | ||||
class RegularJob extends \OC\BackgroundJob\Job { | |||||
class RegularJob extends \OCP\BackgroundJob\Job { | |||||
public function run($argument) { | public function run($argument) { | ||||
try { | try { | ||||
if (is_callable($argument)) { | if (is_callable($argument)) { |
*/ | */ | ||||
namespace OC\Command; | namespace OC\Command; | ||||
use OC\BackgroundJob\QueuedJob; | |||||
use OCP\BackgroundJob\QueuedJob; | |||||
class CallableJob extends QueuedJob { | class CallableJob extends QueuedJob { | ||||
protected function run($serializedCallable) { | protected function run($serializedCallable) { |
*/ | */ | ||||
namespace OC\Command; | namespace OC\Command; | ||||
use OC\BackgroundJob\QueuedJob; | |||||
use OCP\BackgroundJob\QueuedJob; | |||||
use Laravel\SerializableClosure\SerializableClosure as LaravelClosure; | use Laravel\SerializableClosure\SerializableClosure as LaravelClosure; | ||||
use Opis\Closure\SerializableClosure as OpisClosure; | use Opis\Closure\SerializableClosure as OpisClosure; | ||||
*/ | */ | ||||
namespace OC\Command; | namespace OC\Command; | ||||
use OC\BackgroundJob\QueuedJob; | |||||
use OCP\BackgroundJob\QueuedJob; | |||||
use OCP\Command\ICommand; | use OCP\Command\ICommand; | ||||
/** | /** |
* For more professional log management set the 'logfile' config to a different | * For more professional log management set the 'logfile' config to a different | ||||
* location and manage that with your own tools. | * location and manage that with your own tools. | ||||
*/ | */ | ||||
class Rotate extends \OC\BackgroundJob\Job { | |||||
class Rotate extends \OCP\BackgroundJob\Job { | |||||
use RotationTrait; | use RotationTrait; | ||||
public function run($dummy) { | public function run($dummy) { |
*/ | */ | ||||
namespace OC\Migration; | namespace OC\Migration; | ||||
use OC\BackgroundJob\JobList; | |||||
use OC\BackgroundJob\TimedJob; | |||||
use OC\NeedsUpdateException; | use OC\NeedsUpdateException; | ||||
use OC\Repair; | use OC\Repair; | ||||
use OC_App; | use OC_App; | ||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\BackgroundJob\IJobList; | use OCP\BackgroundJob\IJobList; | ||||
use OCP\ILogger; | |||||
use OCP\BackgroundJob\TimedJob; | |||||
use Psr\Log\LoggerInterface; | use Psr\Log\LoggerInterface; | ||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | use Symfony\Component\EventDispatcher\EventDispatcherInterface; | ||||
* @package OC\Migration | * @package OC\Migration | ||||
*/ | */ | ||||
class BackgroundRepair extends TimedJob { | class BackgroundRepair extends TimedJob { | ||||
private IJobList $jobList; | |||||
private LoggerInterface $logger; | |||||
private EventDispatcherInterface $dispatcher; | |||||
/** @var IJobList */ | |||||
private $jobList; | |||||
/** @var ILogger */ | |||||
private $logger; | |||||
/** @var EventDispatcherInterface */ | |||||
private $dispatcher; | |||||
public function __construct(EventDispatcherInterface $dispatcher) { | |||||
public function __construct(EventDispatcherInterface $dispatcher, ITimeFactory $time, LoggerInterface $logger, IJobList $jobList) { | |||||
parent::__construct($time); | |||||
$this->dispatcher = $dispatcher; | $this->dispatcher = $dispatcher; | ||||
} | |||||
/** | |||||
* run the job, then remove it from the job list | |||||
* | |||||
* @param JobList $jobList | |||||
* @param ILogger|null $logger | |||||
*/ | |||||
public function execute($jobList, ILogger $logger = null) { | |||||
// add an interval of 15 mins | |||||
$this->setInterval(15 * 60); | |||||
$this->jobList = $jobList; | |||||
$this->logger = $logger; | $this->logger = $logger; | ||||
parent::execute($jobList, $logger); | |||||
$this->jobList = $jobList; | |||||
$this->setInterval(15 * 60); | |||||
} | } | ||||
/** | /** | ||||
try { | try { | ||||
$repair->addStep($step); | $repair->addStep($step); | ||||
} catch (\Exception $ex) { | } catch (\Exception $ex) { | ||||
$this->logger->logException($ex, [ | |||||
'app' => 'migration' | |||||
$this->logger->error($ex->getMessage(), [ | |||||
'app' => 'migration', | |||||
'exception' => $ex, | |||||
]); | ]); | ||||
// remove the job - we can never execute it | // remove the job - we can never execute it |
use OCP\AppFramework\Utility\ITimeFactory; | use OCP\AppFramework\Utility\ITimeFactory; | ||||
use OCP\IConfig; | use OCP\IConfig; | ||||
use OCP\ILogger; | |||||
use OCP\IUserManager; | use OCP\IUserManager; | ||||
use OCP\BackgroundJob\IJobList; | |||||
use OCP\BackgroundJob\Job; | |||||
use OCP\Security\VerificationToken\InvalidTokenException; | use OCP\Security\VerificationToken\InvalidTokenException; | ||||
use OCP\Security\VerificationToken\IVerificationToken; | use OCP\Security\VerificationToken\IVerificationToken; | ||||
class CleanUpJob extends \OCP\BackgroundJob\Job { | |||||
/** @var int */ | |||||
protected $runNotBefore; | |||||
/** @var string */ | |||||
protected $userId; | |||||
/** @var string */ | |||||
protected $subject; | |||||
/** @var string */ | |||||
protected $pwdPrefix; | |||||
/** @var IConfig */ | |||||
private $config; | |||||
/** @var IVerificationToken */ | |||||
private $verificationToken; | |||||
/** @var IUserManager */ | |||||
private $userManager; | |||||
class CleanUpJob extends Job { | |||||
protected ?int $runNotBefore = null; | |||||
protected ?string $userId = null; | |||||
protected ?string $subject = null; | |||||
protected ?string $pwdPrefix = null; | |||||
private IConfig $config; | |||||
private IVerificationToken $verificationToken; | |||||
private IUserManager $userManager; | |||||
public function __construct(ITimeFactory $time, IConfig $config, IVerificationToken $verificationToken, IUserManager $userManager) { | public function __construct(ITimeFactory $time, IConfig $config, IVerificationToken $verificationToken, IUserManager $userManager) { | ||||
parent::__construct($time); | parent::__construct($time); | ||||
} | } | ||||
} | } | ||||
public function execute($jobList, ILogger $logger = null) { | |||||
public function start(IJobList $jobList): void { | |||||
if ($this->time->getTime() >= $this->runNotBefore) { | if ($this->time->getTime() >= $this->runNotBefore) { | ||||
$jobList->remove($this, $this->argument); | $jobList->remove($this, $this->argument); | ||||
parent::execute($jobList, $logger); | |||||
parent::start($jobList); | |||||
} | } | ||||
} | } | ||||
} | } |
use OCP\AppFramework\Utility\ITimeFactory; | use OCP\AppFramework\Utility\ITimeFactory; | ||||
use OCP\ILogger; | use OCP\ILogger; | ||||
use Psr\Log\LoggerInterface; | |||||
/** | /** | ||||
* Base class for background jobs | * Base class for background jobs |
/** | /** | ||||
* Run the job, then remove it from the joblist | * Run the job, then remove it from the joblist | ||||
* | * | ||||
* @since 15.0.0 | |||||
* @since 25.0.0 | |||||
*/ | */ | ||||
final public function start(IJobList $jobList): void { | final public function start(IJobList $jobList): void { | ||||
$jobList->remove($this, $this->argument); | $jobList->remove($this, $this->argument); |
public function add($job, $argument = null): void { | public function add($job, $argument = null): void { | ||||
if (is_string($job)) { | if (is_string($job)) { | ||||
/** @var IJob $job */ | /** @var IJob $job */ | ||||
$job = new $job; | |||||
$job = \OCP\Server::get($job); | |||||
} | } | ||||
$job->setArgument($argument); | $job->setArgument($argument); | ||||
if (!$this->has($job, null)) { | if (!$this->has($job, null)) { |
use OC\Migration\BackgroundRepair; | use OC\Migration\BackgroundRepair; | ||||
use OC\NeedsUpdateException; | use OC\NeedsUpdateException; | ||||
use OCP\ILogger; | |||||
use OCP\AppFramework\Utility\ITimeFactory; | |||||
use OCP\Migration\IOutput; | use OCP\Migration\IOutput; | ||||
use OCP\Migration\IRepairStep; | use OCP\Migration\IRepairStep; | ||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | use Symfony\Component\EventDispatcher\EventDispatcherInterface; | ||||
use Symfony\Component\EventDispatcher\GenericEvent; | use Symfony\Component\EventDispatcher\GenericEvent; | ||||
use Test\TestCase; | use Test\TestCase; | ||||
use Psr\Log\LoggerInterface; | |||||
class TestRepairStep implements IRepairStep { | class TestRepairStep implements IRepairStep { | ||||
/** @var BackgroundRepair|\PHPUnit\Framework\MockObject\MockObject */ | /** @var BackgroundRepair|\PHPUnit\Framework\MockObject\MockObject */ | ||||
private $job; | private $job; | ||||
/** @var ILogger|\PHPUnit\Framework\MockObject\MockObject */ | |||||
/** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ | |||||
private $logger; | private $logger; | ||||
/** @var EventDispatcherInterface|\PHPUnit\Framework\MockObject\MockObject $dispatcher */ | /** @var EventDispatcherInterface|\PHPUnit\Framework\MockObject\MockObject $dispatcher */ | ||||
private $dispatcher; | private $dispatcher; | ||||
/** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject $dispatcher */ | |||||
private $time; | |||||
protected function setUp(): void { | protected function setUp(): void { | ||||
parent::setUp(); | parent::setUp(); | ||||
$this->jobList = $this->getMockBuilder('OC\BackgroundJob\JobList') | $this->jobList = $this->getMockBuilder('OC\BackgroundJob\JobList') | ||||
->disableOriginalConstructor() | ->disableOriginalConstructor() | ||||
->getMock(); | ->getMock(); | ||||
$this->logger = $this->getMockBuilder(ILogger::class) | |||||
$this->logger = $this->getMockBuilder(LoggerInterface::class) | |||||
->disableOriginalConstructor() | ->disableOriginalConstructor() | ||||
->getMock(); | ->getMock(); | ||||
$this->dispatcher = $this->createMock(EventDispatcherInterface::class); | $this->dispatcher = $this->createMock(EventDispatcherInterface::class); | ||||
$this->time = $this->createMock(ITimeFactory::class); | |||||
$this->time->method('getTime') | |||||
->willReturn(999999); | |||||
$this->job = $this->getMockBuilder(BackgroundRepair::class) | $this->job = $this->getMockBuilder(BackgroundRepair::class) | ||||
->setConstructorArgs([$this->dispatcher]) | |||||
->setConstructorArgs([$this->dispatcher, $this->time, $this->logger, $this->jobList]) | |||||
->setMethods(['loadApp']) | ->setMethods(['loadApp']) | ||||
->getMock(); | ->getMock(); | ||||
} | } | ||||
public function testNoArguments() { | public function testNoArguments() { | ||||
$this->jobList->expects($this->once())->method('remove'); | $this->jobList->expects($this->once())->method('remove'); | ||||
$this->job->execute($this->jobList); | |||||
$this->job->start($this->jobList); | |||||
} | } | ||||
public function testAppUpgrading() { | public function testAppUpgrading() { | ||||
'app' => 'test', | 'app' => 'test', | ||||
'step' => 'j' | 'step' => 'j' | ||||
]); | ]); | ||||
$this->job->execute($this->jobList); | |||||
$this->job->start($this->jobList); | |||||
} | } | ||||
public function testUnknownStep() { | public function testUnknownStep() { | ||||
$this->dispatcher->expects($this->never())->method('dispatch'); | $this->dispatcher->expects($this->never())->method('dispatch'); | ||||
$this->jobList->expects($this->once())->method('remove'); | $this->jobList->expects($this->once())->method('remove'); | ||||
$this->logger->expects($this->once())->method('logException'); | |||||
$this->logger->expects($this->once())->method('error'); | |||||
$this->job->setArgument([ | $this->job->setArgument([ | ||||
'app' => 'test', | 'app' => 'test', | ||||
'step' => 'j' | 'step' => 'j' | ||||
]); | ]); | ||||
$this->job->execute($this->jobList, $this->logger); | |||||
$this->job->start($this->jobList); | |||||
} | } | ||||
public function testWorkingStep() { | public function testWorkingStep() { | ||||
'app' => 'test', | 'app' => 'test', | ||||
'step' => '\Test\Migration\TestRepairStep' | 'step' => '\Test\Migration\TestRepairStep' | ||||
]); | ]); | ||||
$this->job->execute($this->jobList, $this->logger); | |||||
$this->job->start($this->jobList); | |||||
} | } | ||||
} | } |