Skip to content

Commit

Permalink
Adding background:queue commands: status and delete
Browse files Browse the repository at this point in the history
  • Loading branch information
DeepDiver1975 authored and phil-davis committed Apr 3, 2019
1 parent d445ab4 commit b57f68b
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 5 deletions.
65 changes: 65 additions & 0 deletions core/Command/Background/Queue/Delete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @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 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\Output\OutputInterface;

class Delete extends Command {

/** @var \OCP\BackgroundJob\IJobList */
private $jobList;

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

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');
}

/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$id = $input->getArgument('id');

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

$this->jobList->removeById($id);
$output->writeln('Job has been deleted.');
return 0;
}
}
60 changes: 60 additions & 0 deletions core/Command/Background/Queue/Status.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @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 OCP\BackgroundJob\IJob;
use OCP\BackgroundJob\IJobList;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Status extends Command {

/** @var \OCP\BackgroundJob\IJobList */
private $jobList;

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

protected function configure() {
$this
->setName('background:queue:status')
->setDescription('List queue status');
}

/**
* @param InputInterface $input
* @param OutputInterface $output
* @return void
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$t = new Table($output);
$t->setHeaders(['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()]);
});
$t->render();
}
}
2 changes: 2 additions & 0 deletions core/register_command.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
$application->add(new OC\Core\Command\Background\Cron(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Background\WebCron(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Background\Ajax(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Background\Queue\Status(\OC::$server->getJobList()));
$application->add(new OC\Core\Command\Background\Queue\Delete(\OC::$server->getJobList()));

$application->add(new OC\Core\Command\Config\App\DeleteConfig(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Config\App\GetConfig(\OC::$server->getConfig()));
Expand Down
1 change: 0 additions & 1 deletion db_structure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,6 @@
<default></default>
<notnull>false</notnull>
</field>

<field>
<!-- timestamp when the job was checked if it needs execution the last time -->
<name>last_checked</name>
Expand Down
26 changes: 22 additions & 4 deletions lib/private/BackgroundJob/JobList.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public function remove($job, $argument = null) {
/**
* @param int $id
*/
protected function removeById($id) {
public function removeById($id) {
$query = $this->connection->getQueryBuilder();
$query->delete('jobs')
->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
Expand Down Expand Up @@ -305,9 +305,7 @@ public function getLastJob() {
}

/**
* set the lastRun of $job to now
*
* @param IJob $job
* @inheritdoc
*/
public function setLastRun($job) {
$query = $this->connection->getQueryBuilder();
Expand All @@ -324,4 +322,24 @@ public function setExecutionTime($job, $timeTaken) {
->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
$query->execute();
}

/**
* @inheritdoc
*/
public function listJobs(\Closure $callback) {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from('jobs');
$result = $query->execute();

while ($row = $result->fetch()) {
$job = $this->buildJob($row);
if ($job) {
if ($callback($job) === false) {
break;
}
}
}
$result->closeCursor();
}
}
15 changes: 15 additions & 0 deletions lib/public/BackgroundJob/IJobList.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,19 @@ public function setLastRun($job);
* @since 10.0.0
*/
public function setExecutionTime($job, $timeTaken);

/**
* iterate over all jobs in the queue
*
* @return void
* @since 10.0.9
*/
public function listJobs(\Closure $callback);

/**
* remove a specific job by id
* @return void
* @since 10.0.9
*/
public function removeById($id);
}
72 changes: 72 additions & 0 deletions tests/Core/Command/Background/Queue/DeleteTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2017, 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 Tests\Core\Command\Background\Queue;

use OC\Core\Command\Background\Queue\Delete;
use OCP\BackgroundJob\IJobList;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;

/**
* Class DeleteTest
*
* @group DB
*/
class DeleteTest extends TestCase {

/** @var CommandTester */
private $commandTester;
/** @var IJobList */
private $jobList;

public function setUp() {
parent::setUp();

$this->jobList = $this->createMock(IJobList::class);
$this->jobList->expects($this->any())->method('getById')
->willReturnCallback(function ($id) {
return ($id !== '666') ? true : null;
});

$command = new Delete($this->jobList);
$this->commandTester = new CommandTester($command);
}

/**
* @dataProvider providesJobIds
* @param $jobId
* @param $expectedOutput
*/
public function testCommandInput($jobId, $expectedOutput) {
$input = ['id' => $jobId];
$this->commandTester->execute($input);
$output = $this->commandTester->getDisplay();
$this->assertContains($expectedOutput, $output);
}

public function providesJobIds() {
return [
['666', 'Job with id <666> is not known.'],
['1', 'Job has been deleted.'],
];
}
}
72 changes: 72 additions & 0 deletions tests/Core/Command/Background/Queue/StatusTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2017, 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 Tests\Core\Command\Background\Queue;

use OC\BackgroundJob\Legacy\RegularJob;
use OC\Core\Command\Background\Queue\Status;
use OCP\BackgroundJob\IJobList;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;

/**
* Class StatusTest
*
* @group DB
*/
class StatusTest extends TestCase {

/** @var CommandTester */
private $commandTester;
/** @var IJobList */
private $jobList;

public function setUp() {
parent::setUp();

$this->jobList = $this->createMock(IJobList::class);
$this->jobList->expects($this->any())->method('listJobs')
->willReturnCallback(function (\Closure $callBack) {
$job = new RegularJob();
$job->setId(666);
$callBack($job);
});

$command = new Status($this->jobList);
$command->setApplication(new Application());
$this->commandTester = new CommandTester($command);
}

public function testCommandInput() {
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
$expected = <<<EOS
+-----+------------------------------------+---------------------------+---------------+
| Id | Job | Last run | Job Arguments |
+-----+------------------------------------+---------------------------+---------------+
| 666 | OC\BackgroundJob\Legacy\RegularJob | 1970-01-01T00:00:00+00:00 | |
+-----+------------------------------------+---------------------------+---------------+
EOS;

$this->assertContains($expected, $output);
}
}

0 comments on commit b57f68b

Please sign in to comment.