Skip to content

Commit

Permalink
Merge branch '0.53.x' of github.com:utopia-php/database into connecti…
Browse files Browse the repository at this point in the history
…on-id
  • Loading branch information
fogelito committed Nov 6, 2024
2 parents 2041770 + 07e3e5a commit 13eb1db
Show file tree
Hide file tree
Showing 12 changed files with 414 additions and 58 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"ext-mbstring": "*",
"php": ">=8.3",
"utopia-php/framework": "0.33.*",
"utopia-php/cache": "0.10.*",
"utopia-php/cache": "0.11.*",
"utopia-php/mongo": "0.3.*"
},
"require-dev": {
Expand Down
22 changes: 11 additions & 11 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ services:
build:
context: .
args:
DEBUG: false
DEBUG: true
networks:
- database
volumes:
Expand Down
39 changes: 30 additions & 9 deletions src/Database/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Timeout as TimeoutException;
use Utopia\Database\Exception\Transaction as TransactionException;

abstract class Adapter
{
Expand Down Expand Up @@ -315,16 +316,36 @@ public function inTransaction(): bool
*/
public function withTransaction(callable $callback): mixed
{
$this->startTransaction();

try {
$result = $callback();
$this->commitTransaction();
return $result;
} catch (\Throwable $e) {
$this->rollbackTransaction();
throw $e;
for ($attempts = 0; $attempts < 3; $attempts++) {
try {
$this->startTransaction();
$result = $callback();
$this->commitTransaction();
return $result;
} catch (\Throwable $action) {
try {
$this->rollbackTransaction();
} catch (\Throwable $rollback) {
if ($attempts < 2) {
\usleep(5000); // 5ms
continue;
}

$this->inTransaction = 0;
throw $rollback;
}

if ($attempts < 2) {
\usleep(5000); // 5ms
continue;
}

$this->inTransaction = 0;
throw $action;
}
}

throw new TransactionException('Failed to execute transaction');
}

/**
Expand Down
55 changes: 55 additions & 0 deletions src/Database/Adapter/Postgres.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Timeout as TimeoutException;
use Utopia\Database\Exception\Transaction as TransactionException;
use Utopia\Database\Exception\Truncate as TruncateException;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
Expand All @@ -26,6 +27,60 @@ class Postgres extends SQL
* 4. Full-text search is different - to_tsvector() and to_tsquery()
*/

/**
* @inheritDoc
*/
public function startTransaction(): bool
{
try {
if ($this->inTransaction === 0) {
if ($this->getPDO()->inTransaction()) {
$this->getPDO()->rollBack();
} else {
// If no active transaction, this has no effect.
$this->getPDO()->prepare('ROLLBACK')->execute();
}

$result = $this->getPDO()->beginTransaction();
} else {
$result = true;
}
} 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 $result;
}

/**
* @inheritDoc
*/
public function rollbackTransaction(): bool
{
if ($this->inTransaction === 0) {
return false;
}

try {
$result = $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;
}

/**
* Returns Max Execution Time
* @param int $milliseconds
Expand Down
34 changes: 23 additions & 11 deletions src/Database/Adapter/SQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Exception\Transaction as TransactionException;
use Utopia\Database\Query;

abstract class SQL extends Adapter
Expand Down Expand Up @@ -36,18 +37,21 @@ public function startTransaction(): bool
if ($this->inTransaction === 0) {
if ($this->getPDO()->inTransaction()) {
$this->getPDO()->rollBack();
} else {
// If no active transaction, this has no effect.
$this->getPDO()->prepare('ROLLBACK')->execute();
}

$result = $this->getPDO()->beginTransaction();
} else {
$result = true;
$result = $this->getPDO()->exec('SAVEPOINT transaction' . $this->inTransaction);
}
} catch (PDOException $e) {
throw new DatabaseException('Failed to start transaction: ' . $e->getMessage(), $e->getCode(), $e);
throw new TransactionException('Failed to start transaction: ' . $e->getMessage(), $e->getCode(), $e);
}

if (!$result) {
throw new DatabaseException('Failed to start transaction');
throw new TransactionException('Failed to start transaction');
}

$this->inTransaction++;
Expand All @@ -67,16 +71,20 @@ public function commitTransaction(): bool
return true;
}

if (!$this->getPDO()->inTransaction()) {
$this->inTransaction = 0;
return false;
}

try {
$result = $this->getPDO()->commit();
$this->inTransaction = 0;
} catch (PDOException $e) {
throw new DatabaseException('Failed to commit transaction: ' . $e->getMessage(), $e->getCode(), $e);
} finally {
$this->inTransaction--;
throw new TransactionException('Failed to commit transaction: ' . $e->getMessage(), $e->getCode(), $e);
}

if (!$result) {
throw new DatabaseException('Failed to commit transaction');
throw new TransactionException('Failed to commit transaction');
}

return $result;
Expand All @@ -92,15 +100,19 @@ public function rollbackTransaction(): bool
}

try {
$result = $this->getPDO()->rollBack();
if ($this->inTransaction > 1) {
$result = $this->getPDO()->exec('ROLLBACK TO transaction' . ($this->inTransaction - 1));
$this->inTransaction--;
} else {
$result = $this->getPDO()->rollBack();
$this->inTransaction = 0;
}
} catch (PDOException $e) {
throw new DatabaseException('Failed to rollback transaction: ' . $e->getMessage(), $e->getCode(), $e);
} finally {
$this->inTransaction = 0;
}

if (!$result) {
throw new DatabaseException('Failed to rollback transaction');
throw new TransactionException('Failed to rollback transaction');
}

return $result;
Expand Down
31 changes: 31 additions & 0 deletions src/Database/Adapter/SQLite.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\NotFound as NotFoundException;
use Utopia\Database\Exception\Timeout as TimeoutException;
use Utopia\Database\Exception\Transaction as TransactionException;
use Utopia\Database\Helpers\ID;

/**
Expand All @@ -30,6 +31,36 @@
*/
class SQLite extends MariaDB
{
/**
* @inheritDoc
*/
public function startTransaction(): bool
{
try {
if ($this->inTransaction === 0) {
if ($this->getPDO()->inTransaction()) {
$this->getPDO()->rollBack();
}

$result = $this->getPDO()->beginTransaction();
} else {
$result = $this->getPDO()
->prepare('SAVEPOINT transaction' . $this->inTransaction)
->execute();
}
} 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 $result;
}

/**
* Check if Database exists
* Optionally check if collection exists in Database
Expand Down
Loading

0 comments on commit 13eb1db

Please sign in to comment.