Skip to content

Commit

Permalink
Add background:execute occ command for running cron jobs manually
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Needham committed Jun 12, 2018
1 parent 7909d43 commit 3f7a790
Show file tree
Hide file tree
Showing 9 changed files with 352 additions and 8 deletions.
6 changes: 3 additions & 3 deletions core/Command/Background/Queue/Delete.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ protected function configure() {
$this
->setName('background:queue:delete')
->setDescription('Delete a job from the queue')
->addArgument('id', InputArgument::REQUIRED, 'id of the job to be deleted');
->addArgument('Job ID', InputArgument::REQUIRED, 'ID of the job to be deleted');
}

/**
Expand All @@ -50,11 +50,11 @@ protected function configure() {
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$id = $input->getArgument('id');
$id = $input->getArgument('Job ID');

$job = $this->jobList->getById($id);
if ($job === null) {
$output->writeln("Job with id <$id> is not known.");
$output->writeln("Job with ID <$id> is not known.");
return 1;
}

Expand Down
97 changes: 97 additions & 0 deletions core/Command/Background/Queue/Execute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php
/**
* @author Tom Needham <[email protected]>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OC\Core\Command\Background\Queue;

use OC\BackgroundJob\TimedJob;
use OC\Log\CommandLogger;
use OCP\BackgroundJob\IJobList;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class Execute extends Command {

/**
* @var IJobList
*/
protected $jobList;

/**
* @param IJobList $jobList
*/
public function __construct(IJobList $jobList) {
$this->jobList = $jobList;
parent::__construct();
}

protected function configure() {
$this
->setName('background:queue:execute')
->setDescription("Run a single background job from the queue")
->addArgument('Job ID', InputArgument::REQUIRED, 'ID of the job to run')
->addOption('force', 'f', InputOption::VALUE_NONE, 'Force run the job even if within timing interval');
}

/**
* @param InputInterface $input
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output) {
// Get the job to run
$jobId = $input->getArgument('Job ID');
// Try to find the job
$job = $this->jobList->getById($jobId);
if($job === null) {
$output->writeln("<error>Job not found</error>");
return 1;
}

$jobClass = \get_class($job);
$output->writeln("<info>Found job: $jobClass with ID $jobId</info>");

$start = \time();

// Run the job if not reserved
$logger = new \OC\Log(new CommandLogger($output), \OC::$server->getSystemConfig());

if($job instanceof TimedJob && $input->getOption('force')) {
// Force the execution to ignore the interval
$output->writeln('<info>Forcing run, resetting last run value to 0</info>');
$job->setLastRun(0);
}

$output->writeln('<info>Running job...</info>');

$job->execute($this->jobList, $logger);

$duration = \time() - $start;

$output->writeln("<info>Finished in $duration seconds</info>");
$this->jobList->setLastJob($job);
$this->jobList->setExecutionTime($job, $duration);

return 0;
}
}
2 changes: 1 addition & 1 deletion core/Command/Background/Queue/Status.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected function configure() {
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$t = new Table($output);
$t->setHeaders(['Id', 'Job', 'Last run', 'Job Arguments']);
$t->setHeaders(['Job ID', 'Job', 'Last Run', 'Job Arguments']);
$this->jobList->listJobs(function (IJob $job) use ($t) {
$t->addRow([$job->getId(), \get_class($job), \date('c', $job->getLastRun()), $job->getArgument()]);
});
Expand Down
3 changes: 2 additions & 1 deletion core/register_command.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
$application->add(new OC\Core\Command\User\Setting(\OC::$server->getUserManager(), \OC::$server->getConfig(), \OC::$server->getDatabaseConnection()));
$application->add(new OC\Core\Command\User\Modify(\OC::$server->getUserManager(), \OC::$server->getMailer()));
$application->add(new OC\Core\Command\User\SyncBackend(\OC::$server->getAccountMapper(), \OC::$server->getConfig(), \OC::$server->getUserManager(), \OC::$server->getLogger()));
$application->add(new \OC\Core\Command\User\Inactive(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\Inactive(\OC::$server->getUserManager()));

$application->add(new OC\Core\Command\Group\Add(\OC::$server->getGroupManager()));
$application->add(new OC\Core\Command\Group\Delete(\OC::$server->getGroupManager()));
Expand All @@ -162,6 +162,7 @@
$application->add(new OC\Core\Command\Security\ImportCertificate(\OC::$server->getCertificateManager(null)));
$application->add(new OC\Core\Command\Security\RemoveCertificate(\OC::$server->getCertificateManager(null)));
$application->add(new OC\Core\Command\Security\ListRoutes(\OC::$server->getRouter()));
$application->add(new OC\Core\Command\Background\Queue\Execute(\OC::$server->getJobList()));
} else {
$application->add(new OC\Core\Command\Maintenance\Install(\OC::$server->getConfig()));
}
24 changes: 21 additions & 3 deletions lib/private/BackgroundJob/Job.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,39 @@ abstract class Job implements IJob {
* @param ILogger $logger
*/
public function execute($jobList, ILogger $logger = null) {
if ($logger === null) {
$logger = \OC::$server->getLogger();
}

$jobList->setLastRun($this);
try {
//storing job start time
$jobStartTime = \time();

\OCP\Util::writeLog('cron', 'Started background job of class : ' . \get_class($this) . ' with arguments : ' . \print_r($this->argument, true), \OCP\Util::DEBUG);
$logger->debug(
'Started background job of class : {class} with arguments : {arguments}',
[
'app' => 'cron',
'class' => \get_class($this),
'arguments' => \print_r($this->argument, true)
]
);

$this->run($this->argument);

//storing job end time
$jobEndTime = \time();
$timeTaken = $jobEndTime - $jobStartTime;

\OCP\Util::writeLog('cron', "Finished background job, the job took : $timeTaken seconds, " .
"this job is an instance of class : " . \get_class($this) . ' with arguments : ' . \print_r($this->argument, true), \OCP\Util::DEBUG);
$logger->debug(
'Finished background job, the job took : {timeTaken} seconds, this job is an instance of class : {class} with arguments : {arguments}',
[
'app' => 'cron',
'timeTaken' => $timeTaken,
'class' => \get_class($this),
'arguments' => \print_r($this->argument, true)
]
);

$jobList->setExecutionTime($this, $timeTaken);
} catch (\Exception $e) {
Expand Down
1 change: 1 addition & 0 deletions lib/private/BackgroundJob/JobList.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ private function buildJob($row) {
$job->setId($row['id']);
$job->setLastRun($row['last_run']);
$job->setArgument(\json_decode($row['argument'], true));

return $job;
} catch (AutoloadNotAllowedException $e) {
// job is from a disabled app, ignore
Expand Down
22 changes: 22 additions & 0 deletions lib/private/BackgroundJob/TimedJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,29 @@ public function setInterval($interval) {
*/
public function execute($jobList, ILogger $logger = null) {
if ((\time() - $this->lastRun) > $this->interval) {
if($logger !== null) {
$id = $this->getId();
$class = \get_class($this);
$lastRun = $this->getLastRun();
$interval = $this->interval;
$logger->debug(
"Running job with id $id and class $class. Last run $lastRun and interval $interval",
['app' => 'cron']
);
}
parent::execute($jobList, $logger);
} else {
if($logger !== null) {
$id = $this->getId();
$class = \get_class($this);
$lastRun = $this->getLastRun();
$interval = $this->interval;
$diff = $this->interval - (\time() - $this->lastRun);
$logger->debug(
"Job with id $id and class $class not running due to interval. Last run $lastRun and interval $interval. Wait $diff seconds.",
['app' => 'cron']
);
}
}
}
}
Loading

0 comments on commit 3f7a790

Please sign in to comment.