diff --git a/src/Database/Adapter.php b/src/Database/Adapter.php index 54bf57e63..1f2e8e306 100644 --- a/src/Database/Adapter.php +++ b/src/Database/Adapter.php @@ -4,7 +4,12 @@ use Exception; use Utopia\Database\Exception as DatabaseException; +use Utopia\Database\Exception\Authorization as AuthorizationException; +use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Duplicate as DuplicateException; +use Utopia\Database\Exception\Limit as LimitException; +use Utopia\Database\Exception\Relationship as RelationshipException; +use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Exception\Timeout as TimeoutException; use Utopia\Database\Exception\Transaction as TransactionException; @@ -371,7 +376,10 @@ public function inTransaction(): bool */ public function withTransaction(callable $callback): mixed { - for ($attempts = 0; $attempts < 3; $attempts++) { + $sleep = 50_000; // 50 milliseconds + $retries = 2; + + for ($attempts = 0; $attempts <= $retries; $attempts++) { try { $this->startTransaction(); $result = $callback(); @@ -380,9 +388,22 @@ public function withTransaction(callable $callback): mixed } catch (\Throwable $action) { try { $this->rollbackTransaction(); + + if ( + $action instanceof DuplicateException || + $action instanceof RestrictedException || + $action instanceof AuthorizationException || + $action instanceof RelationshipException || + $action instanceof ConflictException || + $action instanceof LimitException + ) { + $this->inTransaction = 0; + throw $action; + } + } catch (\Throwable $rollback) { - if ($attempts < 2) { - \usleep(5000); // 5ms + if ($attempts < $retries) { + \usleep($sleep * ($attempts + 1)); continue; } @@ -390,8 +411,8 @@ public function withTransaction(callable $callback): mixed throw $rollback; } - if ($attempts < 2) { - \usleep(5000); // 5ms + if ($attempts < $retries) { + \usleep($sleep * ($attempts + 1)); continue; } diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index c81f3d6fb..a62385275 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -13,7 +13,6 @@ use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Transaction as TransactionException; use Utopia\Database\Query; -use Utopia\Database\Validator\Spatial; abstract class SQL extends Adapter { @@ -66,19 +65,17 @@ public function startTransaction(): bool $this->getPDO()->prepare('ROLLBACK')->execute(); } - $result = $this->getPDO()->beginTransaction(); + $this->getPDO()->beginTransaction(); + } else { - $result = $this->getPDO()->exec('SAVEPOINT transaction' . $this->inTransaction); + $this->getPDO()->exec('SAVEPOINT transaction' . $this->inTransaction); } } catch (PDOException $e) { throw new TransactionException('Failed to start transaction: ' . $e->getMessage(), $e->getCode(), $e); } - if (!$result) { - throw new TransactionException('Failed to start transaction'); - } - $this->inTransaction++; + return true; } @@ -124,21 +121,17 @@ public function rollbackTransaction(): bool try { if ($this->inTransaction > 1) { - $result = $this->getPDO()->exec('ROLLBACK TO transaction' . ($this->inTransaction - 1)); + $this->getPDO()->exec('ROLLBACK TO transaction' . ($this->inTransaction - 1)); $this->inTransaction--; } else { - $result = $this->getPDO()->rollBack(); + $this->getPDO()->rollBack(); $this->inTransaction = 0; } } catch (PDOException $e) { throw new DatabaseException('Failed to rollback transaction: ' . $e->getMessage(), $e->getCode(), $e); } - if (!$result) { - throw new TransactionException('Failed to rollback transaction'); - } - - return $result; + return true; } /**