Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
fix(dav): Limit number of UPDATES for sync token created_at
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 <[email protected]>
  • Loading branch information
ChristophWurst committed Jun 19, 2024
commit 169eedabf94504ce126c2221a96791967c2b3ec1
29 changes: 28 additions & 1 deletion apps/dav/lib/Migration/Version1025Date20240308063933.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace OCA\DAV\Migration;

use Closure;
use OCP\AppFramework\Services\IAppConfig;
use OCP\DB\ISchemaWrapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\Types;
Expand All @@ -19,10 +20,13 @@

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

/**
Expand Down Expand Up @@ -50,7 +54,22 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
}

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

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OCP\AppFramework\Services\IAppConfig::getAppValue has been marked as deprecated

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();

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OCP\DB\IResult::fetchColumn has been marked as deprecated
$oldestIdResult->closeCursor();

$qb = $this->db->getQueryBuilder();

$update = $qb->update($tableName)
Expand All @@ -59,7 +78,15 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array
$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);
}
}
Expand Down