diff --git a/Dockerfile b/Dockerfile index f3f281f43..44df6dba4 100755 --- a/Dockerfile +++ b/Dockerfile @@ -20,8 +20,8 @@ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN \ apk update \ && apk add --no-cache postgresql-libs postgresql-dev make automake autoconf gcc g++ \ - && pecl install mongodb \ - && docker-php-ext-enable mongodb \ + && pecl install mongodb redis \ + && docker-php-ext-enable mongodb redis \ && docker-php-ext-install opcache pgsql pdo_mysql pdo_pgsql \ && rm -rf /var/cache/apk/* diff --git a/README.md b/README.md index 2b3a91064..71486a7ce 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,8 @@ Some examples to help you get started. use PDO; use Utopia\Database\Database; use Utopia\Database\Adapter\MariaDB; +use Utopia\Cache\Cache; +use Utopia\Cache\Adapter\None as NoCache; $dbHost = 'mariadb'; $dbPort = '3306'; @@ -71,7 +73,9 @@ $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ]); -$database = new Database(new MariaDB($pdo)); +$cache = new Cache(new NoCache()); + +$database = new Database(new MariaDB($pdo), $cache); $database->setNamespace('myscope'); $database->create(); // Creates a new schema named `myscope` diff --git a/composer.json b/composer.json index 085230290..870f363d5 100755 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "php": ">=7.1", "ext-pdo": "*", "utopia-php/framework": "0.*.*", - "utopia-php/cache": "0.3.*", + "utopia-php/cache": "0.4.0", "mongodb/mongodb": "1.8.0" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 3327487b3..2bf15be73 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dea2465791a58ea901b688ea9eae5b72", + "content-hash": "fa7d9c6d206e196d739c246ce67aac67", "packages": [ { "name": "composer/package-versions-deprecated", @@ -287,16 +287,16 @@ }, { "name": "utopia-php/cache", - "version": "0.3.0", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/utopia-php/cache.git", - "reference": "e6b8b99d445c4bba5f51857e3d2a3c39a42d73a2" + "reference": "81c7806e13091a9d585ad9bba57fae625a2cf26c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/cache/zipball/e6b8b99d445c4bba5f51857e3d2a3c39a42d73a2", - "reference": "e6b8b99d445c4bba5f51857e3d2a3c39a42d73a2", + "url": "https://api.github.com/repos/utopia-php/cache/zipball/81c7806e13091a9d585ad9bba57fae625a2cf26c", + "reference": "81c7806e13091a9d585ad9bba57fae625a2cf26c", "shasum": "" }, "require": { @@ -334,9 +334,9 @@ ], "support": { "issues": "https://github.com/utopia-php/cache/issues", - "source": "https://github.com/utopia-php/cache/tree/0.3.0" + "source": "https://github.com/utopia-php/cache/tree/0.4.0" }, - "time": "2021-04-20T21:37:21+00:00" + "time": "2021-04-22T14:28:14+00:00" }, { "name": "utopia-php/framework", diff --git a/docker-compose.yml b/docker-compose.yml index fb1bdc1ed..71e36278c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -67,5 +67,11 @@ services: MYSQL_PASSWORD: password MYSQL_TCP_PORT: 3307 + redis: + image: redis:6.0-alpine + container_name: redis + networks: + - database + networks: database: \ No newline at end of file diff --git a/src/Database/Database.php b/src/Database/Database.php index f9b176b9c..ad0d43bfc 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -7,6 +7,7 @@ use Utopia\Database\Validator\Structure; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Structure as StructureException; +use Utopia\Cache\Cache; class Database { @@ -36,11 +37,19 @@ class Database // Collections const COLLECTIONS = 'collections'; + // Cache + const TTL = 60 * 60 * 24; // 24 hours + /** * @var Adapter */ protected $adapter; + /** + * @var Cache + */ + protected $cache; + /** * Parent Collection * Defines the structure for both system and custom collections @@ -90,10 +99,12 @@ class Database /** * @param Adapter $adapter + * @param Cache $cache */ - public function __construct(Adapter $adapter) + public function __construct(Adapter $adapter, Cache $cache) { $this->adapter = $adapter; + $this->cache = $cache; self::addFilter('json', function($value) { @@ -440,7 +451,26 @@ public function getDocument(string $collection, string $id): Document } $collection = $this->getCollection($collection); - $document = $this->adapter->getDocument($collection->getId(), $id); + $document = null; + $cache = null; + + // TODO@kodumbeats Check if returned cache id matches request + if ($cache = $this->cache->load($id, self::TTL)) { + $document = new Document($cache); + $validator = new Authorization($document, self::PERMISSION_READ); + + if (!$validator->isValid($document->getRead()) && $collection->getId() !== self::COLLECTIONS) { // Check if user has read access to this document + return new Document(); + } + + if($document->isEmpty()) { + return $document; + } + + return $document; + } + + $document = $this->adapter->getDocument($collection->getId(), $id); $document->setAttribute('$collection', $collection->getId()); @@ -457,6 +487,8 @@ public function getDocument(string $collection, string $id): Document $document = $this->casting($collection, $document); $document = $this->decode($collection, $document); + $this->cache->save($id, $document->getArrayCopy()); // save to cache after fetching from db + return $document; } @@ -544,9 +576,11 @@ public function updateDocument(string $collection, string $id, Document $documen } $document = $this->adapter->updateDocument($collection->getId(), $document); - $document = $this->decode($collection, $document); + $this->cache->purge($id); + $this->cache->save($document->getId(), $document->getArrayCopy()); + return $document; } @@ -568,6 +602,8 @@ public function deleteDocument(string $collection, string $id): bool throw new AuthorizationException($validator->getDescription()); } + $this->cache->purge($id); + return $this->adapter->deleteDocument($collection, $id); } diff --git a/src/Database/Document.php b/src/Database/Document.php index efed817c7..69127fab7 100644 --- a/src/Database/Document.php +++ b/src/Database/Document.php @@ -32,19 +32,19 @@ public function __construct(array $input = []) throw new Exception('$write permission must be of type array'); } - foreach ($input as $key => &$value) { - if (\is_array($value)) { - if ((isset($value['$id']) || isset($value['$collection']))) { - $input[$key] = new self($value); - } else { - foreach ($value as $childKey => $child) { - if ((isset($child['$id']) || isset($child['$collection'])) && (!$child instanceof self)) { - $value[$childKey] = new self($child); - } - } - } - } - } + // foreach ($input as $key => &$value) { + // if (\is_array($value)) { + // if ((isset($value['$id']) || isset($value['$collection']))) { + // $input[$key] = new self($value); + // } else { + // foreach ($value as $childKey => $child) { + // if ((isset($child['$id']) || isset($child['$collection'])) && (!$child instanceof self)) { + // $value[$childKey] = new self($child); + // } + // } + // } + // } + // } parent::__construct($input); } diff --git a/tests/Database/Adapter/MariaDBTest.php b/tests/Database/Adapter/MariaDBTest.php index 4a01997c5..27dac6fb5 100644 --- a/tests/Database/Adapter/MariaDBTest.php +++ b/tests/Database/Adapter/MariaDBTest.php @@ -3,8 +3,11 @@ namespace Utopia\Tests\Adapter; use PDO; +use Redis; use Utopia\Database\Database; use Utopia\Database\Adapter\MariaDB; +use Utopia\Cache\Cache; +use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Tests\Base; class MariaDBTest extends Base @@ -15,7 +18,7 @@ class MariaDBTest extends Base static $database = null; /** - * @reture Adapter + * @return Adapter */ static function getDatabase(): Database { @@ -36,7 +39,12 @@ static function getDatabase(): Database PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ]); - $database = new Database(new MariaDB($pdo)); + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); + + $database = new Database(new MariaDB($pdo), $cache); $database->setNamespace('myapp_'.uniqid()); return self::$database = $database;