Skip to content

Commit

Permalink
Merge branch 'main' of github.com:utopia-php/database into null-bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
fogelito committed Oct 19, 2023
2 parents 8aeaea3 + 591cadb commit ff0612c
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 151 deletions.
12 changes: 6 additions & 6 deletions composer.lock

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

46 changes: 22 additions & 24 deletions src/Database/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ abstract class Adapter
*/
protected array $metadata = [];

protected static ?int $timeout = null;

/**
* @param string $key
* @param mixed $value
Expand Down Expand Up @@ -205,7 +203,12 @@ public function before(string $event, string $name = '', ?callable $callback = n
if (!isset($this->transformations[$event])) {
$this->transformations[$event] = [];
}
$this->transformations[$event][$name] = $callback;

if (\is_null($callback)) {
unset($this->transformations[$event][$name]);
} else {
$this->transformations[$event][$name] = $callback;
}

return $this;
}
Expand Down Expand Up @@ -458,11 +461,10 @@ abstract public function deleteDocument(string $collection, string $id): bool;
* @param array<string> $orderTypes
* @param array<string, mixed> $cursor
* @param string $cursorDirection
* @param int|null $timeout
*
* @return array<Document>
*/
abstract public function find(string $collection, array $queries = [], ?int $limit = 25, ?int $offset = null, array $orderAttributes = [], array $orderTypes = [], array $cursor = [], string $cursorDirection = Database::CURSOR_AFTER, ?int $timeout = null): array;
abstract public function find(string $collection, array $queries = [], ?int $limit = 25, ?int $offset = null, array $orderAttributes = [], array $orderTypes = [], array $cursor = [], string $cursorDirection = Database::CURSOR_AFTER): array;

/**
* Sum an attribute
Expand All @@ -474,7 +476,7 @@ abstract public function find(string $collection, array $queries = [], ?int $lim
*
* @return int|float
*/
abstract public function sum(string $collection, string $attribute, array $queries = [], ?int $max = null, ?int $timeout = null): float|int;
abstract public function sum(string $collection, string $attribute, array $queries = [], ?int $max = null): float|int;

/**
* Count Documents
Expand All @@ -485,7 +487,7 @@ abstract public function sum(string $collection, string $attribute, array $queri
*
* @return int
*/
abstract public function count(string $collection, array $queries = [], ?int $max = null, ?int $timeout = null): int;
abstract public function count(string $collection, array $queries = [], ?int $max = null): int;

/**
* Get Collection Size
Expand Down Expand Up @@ -745,32 +747,28 @@ abstract public function getMaxIndexLength(): int;
* Set a global timeout for database queries in milliseconds.
*
* This function allows you to set a maximum execution time for all database
* queries executed using the library. Once this timeout is set, any database
* query that takes longer than the specified time will be automatically
* terminated by the library, and an appropriate error or exception will be
* raised to handle the timeout condition.
* queries executed using the library, or a specific event specified by the
* event parameter. Once this timeout is set, any database query that takes
* longer than the specified time will be automatically terminated by the library,
* and an appropriate error or exception will be raised to handle the timeout condition.
*
* @param int $milliseconds The timeout value in milliseconds for database queries.
* @param string $event The event the timeout should fire fore
* @return void
*
* @throws \Exception The provided timeout value must be greater than or equal to 0.
*/
public static function setTimeout(int $milliseconds): void
{
if ($milliseconds <= 0) {
throw new DatabaseException('Timeout must be greater than 0');
}
self::$timeout = $milliseconds;
}
* @throws Exception The provided timeout value must be greater than or equal to 0.
*/
abstract public function setTimeout(int $milliseconds, string $event = Database::EVENT_ALL): void;

/**
* Clears a global timeout for database queries.
*
* @param string $event
* @return void
*
*/
public static function clearTimeout(): void
*/
public function clearTimeout(string $event): void
{
self::$timeout = null;
// Clear existing callback
$this->before($event, 'timeout', null);
}
}
62 changes: 29 additions & 33 deletions src/Database/Adapter/MariaDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
use Exception;
use PDO;
use PDOException;
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Exception\Timeout;
use Utopia\Database\Exception as DatabaseException;
use Utopia\Database\Exception\Duplicate as DuplicateException;
use Utopia\Database\Exception\Timeout as TimeoutException;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;

Expand Down Expand Up @@ -641,7 +641,7 @@ public function deleteIndex(string $collection, string $id): bool
* @return Document
* @throws Exception
* @throws PDOException
* @throws Duplicate
* @throws DuplicateException
*/
public function createDocument(string $collection, Document $document): Document
{
Expand Down Expand Up @@ -736,7 +736,7 @@ public function createDocument(string $collection, Document $document): Document
switch ($e->getCode()) {
case 1062:
case 23000:
throw new Duplicate('Duplicated document: ' . $e->getMessage());
throw new DuplicateException('Duplicated document: ' . $e->getMessage());

default:
throw $e;
Expand All @@ -758,7 +758,7 @@ public function createDocument(string $collection, Document $document): Document
* @return Document
* @throws Exception
* @throws PDOException
* @throws Duplicate
* @throws DuplicateException
*/
public function updateDocument(string $collection, Document $document): Document
{
Expand Down Expand Up @@ -939,7 +939,7 @@ public function updateDocument(string $collection, Document $document): Document
switch ($e->getCode()) {
case 1062:
case 23000:
throw new Duplicate('Duplicated document: ' . $e->getMessage());
throw new DuplicateException('Duplicated document: ' . $e->getMessage());

default:
throw $e;
Expand Down Expand Up @@ -1058,12 +1058,11 @@ public function deleteDocument(string $collection, string $id): bool
* @param array<string> $orderTypes
* @param array<string, mixed> $cursor
* @param string $cursorDirection
* @param int|null $timeout
* @return array<Document>
* @throws DatabaseException
* @throws Timeout
* @throws TimeoutException
*/
public function find(string $collection, array $queries = [], ?int $limit = 25, ?int $offset = null, array $orderAttributes = [], array $orderTypes = [], array $cursor = [], string $cursorDirection = Database::CURSOR_AFTER, ?int $timeout = null): array
public function find(string $collection, array $queries = [], ?int $limit = 25, ?int $offset = null, array $orderAttributes = [], array $orderTypes = [], array $cursor = [], string $cursorDirection = Database::CURSOR_AFTER): array
{
$name = $this->filter($collection);
$roles = Authorization::getRoles();
Expand Down Expand Up @@ -1173,11 +1172,8 @@ public function find(string $collection, array $queries = [], ?int $limit = 25,

$sql = $this->trigger(Database::EVENT_DOCUMENT_FIND, $sql);

if ($timeout || static::$timeout) {
$sql = $this->setTimeoutForQuery($sql, $timeout ? $timeout : static::$timeout);
}

$stmt = $this->getPDO()->prepare($sql);

foreach ($queries as $query) {
$this->bindConditionValue($stmt, $query);
}
Expand Down Expand Up @@ -1257,7 +1253,7 @@ public function find(string $collection, array $queries = [], ?int $limit = 25,
* @throws Exception
* @throws PDOException
*/
public function count(string $collection, array $queries = [], ?int $max = null, ?int $timeout = null): int
public function count(string $collection, array $queries = [], ?int $max = null): int
{
$name = $this->filter($collection);
$roles = Authorization::getRoles();
Expand Down Expand Up @@ -1287,11 +1283,8 @@ public function count(string $collection, array $queries = [], ?int $max = null,

$sql = $this->trigger(Database::EVENT_DOCUMENT_COUNT, $sql);

if ($timeout || self::$timeout) {
$sql = $this->setTimeoutForQuery($sql, $timeout ? $timeout : self::$timeout);
}

$stmt = $this->getPDO()->prepare($sql);

foreach ($queries as $query) {
$this->bindConditionValue($stmt, $query);
}
Expand Down Expand Up @@ -1322,7 +1315,7 @@ public function count(string $collection, array $queries = [], ?int $max = null,
* @throws Exception
* @throws PDOException
*/
public function sum(string $collection, string $attribute, array $queries = [], ?int $max = null, ?int $timeout = null): int|float
public function sum(string $collection, string $attribute, array $queries = [], ?int $max = null): int|float
{
$name = $this->filter($collection);
$roles = Authorization::getRoles();
Expand Down Expand Up @@ -1352,10 +1345,6 @@ public function sum(string $collection, string $attribute, array $queries = [],

$sql = $this->trigger(Database::EVENT_DOCUMENT_SUM, $sql);

if ($timeout || self::$timeout) {
$sql = $this->setTimeoutForQuery($sql, $timeout ? $timeout : self::$timeout);
}

$stmt = $this->getPDO()->prepare($sql);

foreach ($queries as $query) {
Expand Down Expand Up @@ -1583,35 +1572,42 @@ public function getSupportForTimeouts(): bool
}

/**
* Returns Max Execution Time
* @param string $sql
* Set max execution time
* @param int $milliseconds
* @return string
* @param string $event
* @return void
* @throws DatabaseException
*/
protected function setTimeoutForQuery(string $sql, int $milliseconds): string
public function setTimeout(int $milliseconds, string $event = Database::EVENT_ALL): void
{
if (!$this->getSupportForTimeouts()) {
return $sql;
return;
}
if ($milliseconds <= 0) {
throw new DatabaseException('Timeout must be greater than 0');
}

$seconds = $milliseconds / 1000;
return "SET STATEMENT max_statement_time = {$seconds} FOR " . $sql;

$this->before($event, 'timeout', function ($sql) use ($seconds) {
return "SET STATEMENT max_statement_time = {$seconds} FOR " . $sql;
});
}

/**
* @param PDOException $e
* @throws Timeout
* @throws TimeoutException
*/
protected function processException(PDOException $e): void
{
// Regular PDO
if ($e->getCode() === '70100' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 1969) {
throw new Timeout($e->getMessage());
throw new TimeoutException($e->getMessage());
}

// PDOProxy switches errorInfo PDOProxy.php line 64
if ($e->getCode() === 1969 && isset($e->errorInfo[0]) && $e->errorInfo[0] === '70100') {
throw new Timeout($e->getMessage());
throw new TimeoutException($e->getMessage());
}

throw $e;
Expand Down
Loading

0 comments on commit ff0612c

Please sign in to comment.