Skip to content

Commit b0c929d

Browse files
committed
Wait for cron to finish before running upgrade command
* fixes #9562 Signed-off-by: Morris Jobke <hey@morrisjobke.de>
1 parent 0f84351 commit b0c929d

5 files changed

Lines changed: 55 additions & 11 deletions

File tree

core/Command/Upgrade.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ protected function execute(InputInterface $input, OutputInterface $output) {
9999
$this->config,
100100
\OC::$server->getIntegrityCodeChecker(),
101101
$this->logger,
102-
$this->installer
102+
$this->installer,
103+
\OC::$server->getJobList()
103104
);
104105

105106
$dispatcher = \OC::$server->getEventDispatcher();
@@ -191,6 +192,9 @@ protected function execute(InputInterface $input, OutputInterface $output) {
191192
$updater->listen('\OC\Updater', 'maintenanceActive', function () use($output) {
192193
$output->writeln('<info>Maintenance mode is kept active</info>');
193194
});
195+
$updater->listen('\OC\Updater', 'waitForCronToFinish', function () use($output) {
196+
$output->writeln('<info>Waiting for cron to finish (checks again in 5 seconds)...</info>');
197+
});
194198
$updater->listen('\OC\Updater', 'updateEnd',
195199
function ($success) use($output, $self) {
196200
if ($success) {

core/ajax/update.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ public function handleRepairFeedback($event) {
119119
$config,
120120
\OC::$server->getIntegrityCodeChecker(),
121121
$logger,
122-
\OC::$server->query(\OC\Installer::class)
122+
\OC::$server->query(\OC\Installer::class),
123+
\OC::$server->getJobList()
123124
);
124125
$incompatibleApps = [];
125126

@@ -152,6 +153,9 @@ public function handleRepairFeedback($event) {
152153
$updater->listen('\OC\Updater', 'maintenanceActive', function () use ($eventSource, $l) {
153154
$eventSource->send('success', (string)$l->t('Maintenance mode is kept active'));
154155
});
156+
$updater->listen('\OC\Updater', 'waitForCronToFinish', function () use ($eventSource, $l) {
157+
$eventSource->send('success', (string)$l->t('Waiting for cron to finish (checks again in 5 seconds)...'));
158+
});
155159
$updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($eventSource, $l) {
156160
$eventSource->send('success', (string)$l->t('Updating database schema'));
157161
});

lib/private/BackgroundJob/JobList.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,4 +333,25 @@ public function setExecutionTime(IJob $job, $timeTaken) {
333333
->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
334334
$query->execute();
335335
}
336+
337+
/**
338+
* checks if a job is still running (reserved_at time is smaller than 12 hours ago)
339+
*
340+
* @return bool
341+
*/
342+
public function isAnyJobRunning(): bool {
343+
$query = $this->connection->getQueryBuilder();
344+
$query->select('*')
345+
->from('jobs')
346+
->where($query->expr()->gt('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - 12 * 3600, IQueryBuilder::PARAM_INT)))
347+
->setMaxResults(1);
348+
$result = $query->execute();
349+
$row = $result->fetch();
350+
$result->closeCursor();
351+
352+
if ($row) {
353+
return true;
354+
}
355+
return false;
356+
}
336357
}

lib/private/Updater.php

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
use OC\Hooks\BasicEmitter;
3939
use OC\IntegrityCheck\Checker;
4040
use OC_App;
41+
use OCP\BackgroundJob\IJobList;
4142
use OCP\IConfig;
4243
use OCP\ILogger;
4344
use OCP\Util;
@@ -66,6 +67,9 @@ class Updater extends BasicEmitter {
6667
/** @var Installer */
6768
private $installer;
6869

70+
/** @var IJobList */
71+
private $jobList;
72+
6973
private $logLevelNames = [
7074
0 => 'Debug',
7175
1 => 'Info',
@@ -74,20 +78,16 @@ class Updater extends BasicEmitter {
7478
4 => 'Fatal',
7579
];
7680

77-
/**
78-
* @param IConfig $config
79-
* @param Checker $checker
80-
* @param ILogger $log
81-
* @param Installer $installer
82-
*/
8381
public function __construct(IConfig $config,
8482
Checker $checker,
85-
ILogger $log = null,
86-
Installer $installer) {
83+
ILogger $log,
84+
Installer $installer,
85+
IJobList $jobList) {
8786
$this->log = $log;
8887
$this->config = $config;
8988
$this->checker = $checker;
9089
$this->installer = $installer;
90+
$this->jobList = $jobList;
9191
}
9292

9393
/**
@@ -111,6 +111,8 @@ public function upgrade() {
111111
$this->emit('\OC\Updater', 'maintenanceEnabled');
112112
}
113113

114+
$this->waitForCronToFinish();
115+
114116
$installedVersion = $this->config->getSystemValue('version', '0.0.0');
115117
$currentVersion = implode('.', \OCP\Util::getVersion());
116118
$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
@@ -604,6 +606,12 @@ private function logAllEvents() {
604606
});
605607

606608
}
609+
private function waitForCronToFinish() {
610+
while ($this->jobList->isAnyJobRunning()) {
611+
$this->emit('\OC\Updater', 'waitForCronToFinish');
612+
sleep(5);
613+
}
614+
}
607615

608616
}
609617

tests/lib/UpdaterTest.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
use OC\Installer;
2626
use OC\Updater;
27+
use OCP\BackgroundJob\IJobList;
2728
use OCP\IConfig;
2829
use OCP\ILogger;
2930
use OC\IntegrityCheck\Checker;
@@ -39,6 +40,8 @@ class UpdaterTest extends TestCase {
3940
private $checker;
4041
/** @var Installer|\PHPUnit_Framework_MockObject_MockObject */
4142
private $installer;
43+
/** @var IJobList|\PHPUnit_Framework_MockObject_MockObject */
44+
private $jobList;
4245

4346
public function setUp() {
4447
parent::setUp();
@@ -54,12 +57,16 @@ public function setUp() {
5457
$this->installer = $this->getMockBuilder(Installer::class)
5558
->disableOriginalConstructor()
5659
->getMock();
60+
$this->jobList = $this->getMockBuilder(IJobList::class)
61+
->disableOriginalConstructor()
62+
->getMock();
5763

5864
$this->updater = new Updater(
5965
$this->config,
6066
$this->checker,
6167
$this->logger,
62-
$this->installer
68+
$this->installer,
69+
$this->jobList
6370
);
6471
}
6572

0 commit comments

Comments
 (0)