]> source.dussan.org Git - nextcloud-server.git/commitdiff
fix(dav): Limit number of UPDATES for sync token created_at 45990/head
authorChristoph Wurst <christoph@winzerhof-wurst.at>
Wed, 19 Jun 2024 10:30:32 +0000 (12:30 +0200)
committerbackportbot[bot] <backportbot[bot]@users.noreply.github.com>
Wed, 19 Jun 2024 16:07:37 +0000 (16:07 +0000)
Address book and calendar sync tokens have a created_at column in 26+
and we need to assign a current timestamp to the existing data at
upgrade so the data isn't cleaned up immediately. Updating the full
table is expensive and fails on clustered setups that limit transaction
size. We don't need a timestamp for the oldest rows so we can skip
updating them.

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
apps/dav/lib/Migration/Version1025Date20240308063933.php

index a75fc85eccc39f87cdee771b8bb15e69020d795b..e30a9ea02921f9ac1eed31ef05469168c2956fe8 100644 (file)
@@ -27,6 +27,7 @@ declare(strict_types=1);
 namespace OCA\DAV\Migration;
 
 use Closure;
+use OCP\AppFramework\Services\IAppConfig;
 use OCP\DB\ISchemaWrapper;
 use OCP\DB\QueryBuilder\IQueryBuilder;
 use OCP\DB\Types;
@@ -36,10 +37,13 @@ use OCP\Migration\SimpleMigrationStep;
 
 class Version1025Date20240308063933 extends SimpleMigrationStep {
 
+       private IAppConfig $appConfig;
        private IDBConnection $db;
 
-       public function __construct(IDBConnection $db) {
+       public function __construct(IAppConfig $appConfig,
+               IDBConnection $db) {
                $this->db = $db;
+               $this->appConfig = $appConfig;
        }
 
        /**
@@ -67,7 +71,22 @@ class Version1025Date20240308063933 extends SimpleMigrationStep {
        }
 
        public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options): void {
+               // The threshold is higher than the default of \OCA\DAV\BackgroundJob\PruneOutdatedSyncTokensJob
+               // but small enough to fit into a cluster transaction size.
+               // For a 50k users instance that would still keep 10 changes on average.
+               $limit = max(1, (int) $this->appConfig->getAppValue('totalNumberOfSyncTokensToKeep', '500000'));
+
                foreach (['addressbookchanges', 'calendarchanges'] as $tableName) {
+                       $thresholdSelect = $this->db->getQueryBuilder();
+                       $thresholdSelect->select('id')
+                               ->from($tableName)
+                               ->orderBy('id', 'desc')
+                               ->setFirstResult($limit)
+                               ->setMaxResults(1);
+                       $oldestIdResult = $thresholdSelect->executeQuery();
+                       $oldestId = $oldestIdResult->fetchColumn();
+                       $oldestIdResult->closeCursor();
+
                        $qb = $this->db->getQueryBuilder();
 
                        $update = $qb->update($tableName)
@@ -76,7 +95,15 @@ class Version1025Date20240308063933 extends SimpleMigrationStep {
                                        $qb->expr()->eq('created_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)),
                                );
 
+                       // If there is a lot of data we only set timestamp for the most recent rows
+                       // because the rest will be deleted by \OCA\DAV\BackgroundJob\PruneOutdatedSyncTokensJob
+                       // anyway.
+                       if ($oldestId !== false) {
+                               $update->andWhere($qb->expr()->gt('id', $qb->createNamedParameter($oldestId, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT));
+                       }
+
                        $updated = $update->executeStatement();
+
                        $output->debug('Added a default creation timestamp to ' . $updated . ' rows in ' . $tableName);
                }
        }