diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index d2648c2db637c..faf17a109b24d 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -893,6 +893,7 @@ 'OC\\Repair\\NC13\\AddLogRotateJob' => $baseDir . '/lib/private/Repair/NC13/AddLogRotateJob.php', 'OC\\Repair\\NC13\\RepairInvalidPaths' => $baseDir . '/lib/private/Repair/NC13/RepairInvalidPaths.php', 'OC\\Repair\\NC14\\AddPreviewBackgroundCleanupJob' => $baseDir . '/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php', + 'OC\\Repair\\NC14\\RepairPendingCronJobs' => $baseDir . '/lib/private/Repair/NC14/RepairPendingCronJobs.php', 'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\Owncloud\\DropAccountTermsTable' => $baseDir . '/lib/private/Repair/Owncloud/DropAccountTermsTable.php', 'OC\\Repair\\Owncloud\\SaveAccountsTableData' => $baseDir . '/lib/private/Repair/Owncloud/SaveAccountsTableData.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 4a2580fe757f9..a8d748137e881 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -923,6 +923,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Repair\\NC13\\AddLogRotateJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC13/AddLogRotateJob.php', 'OC\\Repair\\NC13\\RepairInvalidPaths' => __DIR__ . '/../../..' . '/lib/private/Repair/NC13/RepairInvalidPaths.php', 'OC\\Repair\\NC14\\AddPreviewBackgroundCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php', + 'OC\\Repair\\NC14\\RepairPendingCronJobs' => __DIR__ . '/../../..' . '/lib/private/Repair/NC14/RepairPendingCronJobs.php', 'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\Owncloud\\DropAccountTermsTable' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/DropAccountTermsTable.php', 'OC\\Repair\\Owncloud\\SaveAccountsTableData' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/SaveAccountsTableData.php', diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php index a926194e9dff5..fab608cf16496 100644 --- a/lib/private/BackgroundJob/JobList.php +++ b/lib/private/BackgroundJob/JobList.php @@ -180,12 +180,14 @@ public function getAll() { * get the next job in the list * * @return IJob|null + * @suppress SqlInjectionChecker */ public function getNext() { $query = $this->connection->getQueryBuilder(); $query->select('*') ->from('jobs') ->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT))) + ->andWhere($query->expr()->lte('last_checked', $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT))) ->orderBy('last_checked', 'ASC') ->setMaxResults(1); @@ -214,6 +216,14 @@ public function getNext() { $job = $this->buildJob($row); if ($job === null) { + // set the last_checked to 12h in the future to not check failing jobs all over again + $reset = $this->connection->getQueryBuilder(); + $reset->update('jobs') + ->set('reserved_at', $reset->expr()->literal(0, IQueryBuilder::PARAM_INT)) + ->set('last_checked', $reset->createNamedParameter($this->timeFactory->getTime() + 12 * 3600, IQueryBuilder::PARAM_INT)) + ->where($reset->expr()->eq('id', $reset->createNamedParameter($row['id'], IQueryBuilder::PARAM_INT))); + $reset->execute(); + // Background job from disabled app, try again. return $this->getNext(); } diff --git a/lib/private/Repair.php b/lib/private/Repair.php index 78a60392219c0..ad9662ca1d7e0 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -38,6 +38,7 @@ use OC\Repair\NC11\FixMountStorages; use OC\Repair\NC13\AddLogRotateJob; use OC\Repair\NC14\AddPreviewBackgroundCleanupJob; +use OC\Repair\NC14\RepairPendingCronJobs; use OC\Repair\OldGroupMembershipShares; use OC\Repair\Owncloud\DropAccountTermsTable; use OC\Repair\Owncloud\SaveAccountsTableData; @@ -137,6 +138,7 @@ public static function getRepairSteps() { new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OC::$server->query(SCSSCacher::class), \OC::$server->query(JSCombiner::class)), new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()), new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()), + new RepairPendingCronJobs(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), ]; } diff --git a/lib/private/Repair/NC14/RepairPendingCronJobs.php b/lib/private/Repair/NC14/RepairPendingCronJobs.php new file mode 100644 index 0000000000000..a8ca2c75e89e1 --- /dev/null +++ b/lib/private/Repair/NC14/RepairPendingCronJobs.php @@ -0,0 +1,77 @@ + + * + * @author Morris Jobke + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ + +namespace OC\Repair\NC14; + +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class RepairPendingCronJobs implements IRepairStep { + const MAX_ROWS = 1000; + + /** @var IDBConnection */ + private $connection; + /** @var IConfig */ + private $config; + + public function __construct(IDBConnection $connection, IConfig $config) { + $this->connection = $connection; + $this->config = $config; + } + + + public function getName() { + return 'Repair pending cron jobs'; + } + + private function shouldRun() { + $versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0'); + + return version_compare($versionFromBeforeUpdate, '14.0.0.9', '<'); + } + + /** + * @suppress SqlInjectionChecker + */ + private function repair() { + $reset = $this->connection->getQueryBuilder(); + $reset->update('jobs') + ->set('reserved_at', $reset->expr()->literal(0, IQueryBuilder::PARAM_INT)) + ->where($reset->expr()->neq('reserved_at', $reset->expr()->literal(0, IQueryBuilder::PARAM_INT))); + + return $reset->execute(); + } + + public function run(IOutput $output) { + if ($this->shouldRun()) { + $count = $this->repair(); + + $output->info('Repaired ' . $count . ' pending cron job(s).'); + } else { + $output->info('No need to repair pending cron jobs.'); + } + } +} diff --git a/lib/private/Updater.php b/lib/private/Updater.php index 02b3138f30fe0..4098d1b767d72 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -111,10 +111,14 @@ public function upgrade() { $this->emit('\OC\Updater', 'maintenanceEnabled'); } - $this->waitForCronToFinish(); - $installedVersion = $this->config->getSystemValue('version', '0.0.0'); $currentVersion = implode('.', \OCP\Util::getVersion()); + + // see https://github.com/nextcloud/server/issues/9992 for potential problem + if (version_compare($installedVersion, '14.0.0.9', '>=')) { + $this->waitForCronToFinish(); + } + $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core')); $success = true; diff --git a/version.php b/version.php index 13501453cc640..93a2001444e1d 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(14, 0, 0, 8); +$OC_Version = array(14, 0, 0, 9); // The human readable string $OC_VersionString = '14.0.0 alpha';