aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/private/Files/Cache/Cache.php30
-rw-r--r--lib/public/AppFramework/Db/TTransactional.php6
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 ]);
}
}