diff options
-rw-r--r-- | lib/private/Files/Cache/Cache.php | 30 | ||||
-rw-r--r-- | lib/public/AppFramework/Db/TTransactional.php | 6 |
2 files changed, 12 insertions, 24 deletions
diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 8f0f962a3b7..a08c39ef302 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -46,6 +46,7 @@ use OC\Files\Search\SearchComparison; use OC\Files\Search\SearchQuery; use OC\Files\Storage\Wrapper\Encryption; use OC\SystemConfig; +use OCP\AppFramework\Db\TTransactional; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\CacheEntryInsertedEvent; @@ -81,6 +82,9 @@ class Cache implements ICache { MoveFromCacheTrait::moveFromCache as moveFromCacheFallback; } + use TTransactional; + + /** * @var array partial data for the cache */ @@ -715,29 +719,9 @@ class Cache implements ICache { $query->set('encrypted', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)); } - // Retry transaction in case of RetryableException like deadlocks. - // Retry up to 4 times because we should receive up to 4 concurrent requests from the frontend - $retryLimit = 4; - for ($i = 1; $i <= $retryLimit; $i++) { - try { - $this->connection->beginTransaction(); - $query->executeStatement(); - break; - } catch (\OC\DatabaseException $e) { - $this->connection->rollBack(); - throw $e; - } catch (RetryableException $e) { - // Simply throw if we already retried 4 times. - if ($i === $retryLimit) { - throw $e; - } - - $this->connection->rollBack(); - - // Sleep a bit to give some time to the other transaction to finish. - usleep(100 * 1000 * $i); - } - } + // Retry the transaction in case of RetryableException like deadlocks. + // Retry up to 4 times because we should receive up to 4 concurrent requests from the frontend. + $this->atomicRetry(fn () => $query->executeStatement(), $this->connection, 4, 100 * 1000); } else { $this->connection->beginTransaction(); } diff --git a/lib/public/AppFramework/Db/TTransactional.php b/lib/public/AppFramework/Db/TTransactional.php index 56daef1d62a..a52df671a92 100644 --- a/lib/public/AppFramework/Db/TTransactional.php +++ b/lib/public/AppFramework/Db/TTransactional.php @@ -82,6 +82,7 @@ trait TTransactional { * @psalm-param callable():T $fn * @param IDBConnection $db * @param int $maxRetries + * @param int<0, \max> $sleep - sleep time in microseconds between retries * * @return mixed the result of the passed callable * @psalm-return T @@ -91,7 +92,7 @@ trait TTransactional { * * @since 27.0.0 */ - protected function atomicRetry(callable $fn, IDBConnection $db, int $maxRetries = 3): mixed { + protected function atomicRetry(callable $fn, IDBConnection $db, int $maxRetries = 3, int $sleep = 0): mixed { for ($i = 0; $i < $maxRetries; $i++) { try { return $this->atomic($fn, $db); @@ -99,6 +100,9 @@ trait TTransactional { if (!$e->isRetryable() || $i === ($maxRetries - 1)) { throw $e; } + + usleep($sleep * $i); + logger('core')->warning('Retrying operation after retryable exception.', [ 'exception' => $e ]); } } |