From a5b8017628c3dd8713d10ede9a9a0d3629a8ec06 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 17 Dec 2024 15:13:32 +0900 Subject: [PATCH 01/20] Add cache fallback into DB library --- Dockerfile | 2 + composer.lock | 169 +++++++++++++++-------------- docker-compose.yml | 2 + src/Database/Database.php | 19 +++- tests/e2e/Adapter/Base.php | 41 +++++++ tests/e2e/Adapter/MariaDBTest.php | 13 ++- tests/e2e/Adapter/MirrorTest.php | 27 +++-- tests/e2e/Adapter/MongoDBTest.php | 13 ++- tests/e2e/Adapter/MySQLTest.php | 14 ++- tests/e2e/Adapter/PostgresTest.php | 13 ++- tests/e2e/Adapter/SQLiteTest.php | 12 +- 11 files changed, 210 insertions(+), 115 deletions(-) diff --git a/Dockerfile b/Dockerfile index 405656e47..22ecf2532 100755 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,8 @@ RUN \ git \ brotli-dev \ linux-headers \ + docker-cli \ + docker-cli-compose \ && docker-php-ext-install opcache pgsql pdo_mysql pdo_pgsql \ && apk del postgresql-dev \ && rm -rf /var/cache/apk/* diff --git a/composer.lock b/composer.lock index d08a958c7..bc490a4b5 100644 --- a/composer.lock +++ b/composer.lock @@ -149,16 +149,16 @@ }, { "name": "google/protobuf", - "version": "v4.28.3", + "version": "v4.29.1", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100" + "reference": "6042b5483f8029e42473faeb8ef75ba266278381" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/c5c311e0f3d89928251ac5a2f0e3db283612c100", - "reference": "c5c311e0f3d89928251ac5a2f0e3db283612c100", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/6042b5483f8029e42473faeb8ef75ba266278381", + "reference": "6042b5483f8029e42473faeb8ef75ba266278381", "shasum": "" }, "require": { @@ -187,9 +187,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.28.3" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.29.1" }, - "time": "2024-10-22T22:27:17+00:00" + "time": "2024-12-03T22:07:45+00:00" }, { "name": "jean85/pretty-package-versions", @@ -465,16 +465,16 @@ }, { "name": "open-telemetry/api", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" + "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/542064815d38a6df55af7957cd6f1d7d967c99c6", - "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", + "reference": "04c85a1e41a3d59fa9bdc801a5de1df6624b95ed", "shasum": "" }, "require": { @@ -488,13 +488,13 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.1.x-dev" - }, "spi": { "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" ] + }, + "branch-alias": { + "dev-main": "1.1.x-dev" } }, "autoload": { @@ -531,7 +531,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2024-10-15T22:42:37+00:00" + "time": "2024-11-16T04:32:30+00:00" }, { "name": "open-telemetry/context", @@ -758,13 +758,13 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.0.x-dev" - }, "spi": { "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" ] + }, + "branch-alias": { + "dev-main": "1.0.x-dev" } }, "autoload": { @@ -1391,16 +1391,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -1438,7 +1438,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -1454,30 +1454,31 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/http-client", - "version": "v7.1.8", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a" + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", - "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", + "url": "https://api.github.com/repos/symfony/http-client/zipball/ff4df2b68d1c67abb9fef146e6540ea16b58d99e", + "reference": "ff4df2b68d1c67abb9fef146e6540ea16b58d99e", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", + "symfony/http-client-contracts": "~3.4.4|^3.5.2", "symfony/service-contracts": "^2.5|^3" }, "conflict": { + "amphp/amp": "<2.5", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -1488,14 +1489,14 @@ "symfony/http-client-implementation": "3.0" }, "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", + "amphp/http-client": "^4.2.1|^5.0", + "amphp/http-tunnel": "^1.0|^2.0", "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", + "symfony/amphp-http-client-meta": "^1.0|^2.0", "symfony/dependency-injection": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/messenger": "^6.4|^7.0", @@ -1532,7 +1533,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.8" + "source": "https://github.com/symfony/http-client/tree/v7.2.1" }, "funding": [ { @@ -1548,20 +1549,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:40:27+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.0", + "version": "v3.5.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", "shasum": "" }, "require": { @@ -1569,12 +1570,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -1610,7 +1611,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" }, "funding": [ { @@ -1626,7 +1627,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-12-07T08:49:48+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -1654,8 +1655,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1728,8 +1729,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1808,8 +1809,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1866,16 +1867,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -1929,7 +1930,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -1945,7 +1946,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "tbachert/spi", @@ -1974,10 +1975,10 @@ }, "type": "composer-plugin", "extra": { + "class": "Nevay\\SPI\\Composer\\Plugin", "branch-alias": { "dev-main": "0.2.x-dev" }, - "class": "Nevay\\SPI\\Composer\\Plugin", "plugin-optional": true }, "autoload": { @@ -2097,16 +2098,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.14", + "version": "0.33.15", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "45a5a2db3602fa054096f378482c7da9936f5850" + "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/45a5a2db3602fa054096f378482c7da9936f5850", - "reference": "45a5a2db3602fa054096f378482c7da9936f5850", + "url": "https://api.github.com/repos/utopia-php/http/zipball/83b0628900c2c53e8c3efbf069f3e13050295edc", + "reference": "83b0628900c2c53e8c3efbf069f3e13050295edc", "shasum": "" }, "require": { @@ -2138,9 +2139,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.14" + "source": "https://github.com/utopia-php/http/tree/0.33.15" }, - "time": "2024-11-20T12:39:10+00:00" + "time": "2024-12-10T13:07:04+00:00" }, { "name": "utopia-php/mongo", @@ -2389,16 +2390,16 @@ }, { "name": "laravel/pint", - "version": "v1.18.2", + "version": "v1.18.3", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64" + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64", - "reference": "f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64", + "url": "https://api.github.com/repos/laravel/pint/zipball/cef51821608239040ab841ad6e1c6ae502ae3026", + "reference": "cef51821608239040ab841ad6e1c6ae502ae3026", "shasum": "" }, "require": { @@ -2409,13 +2410,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.64.0", - "illuminate/view": "^10.48.20", - "larastan/larastan": "^2.9.8", + "friendsofphp/php-cs-fixer": "^3.65.0", + "illuminate/view": "^10.48.24", + "larastan/larastan": "^2.9.11", "laravel-zero/framework": "^10.4.0", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.35.1" + "nunomaduro/termwind": "^1.17.0", + "pestphp/pest": "^2.36.0" }, "bin": [ "builds/pint" @@ -2451,7 +2452,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-11-20T09:33:46+00:00" + "time": "2024-11-26T15:34:00+00:00" }, { "name": "myclabs/deep-copy", @@ -2723,16 +2724,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.11", + "version": "1.12.12", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "0d1fc20a962a91be578bcfe7cf939e6e1a2ff733" + "reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0d1fc20a962a91be578bcfe7cf939e6e1a2ff733", - "reference": "0d1fc20a962a91be578bcfe7cf939e6e1a2ff733", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0", + "reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0", "shasum": "" }, "require": { @@ -2777,7 +2778,7 @@ "type": "github" } ], - "time": "2024-11-17T14:08:01+00:00" + "time": "2024-11-28T22:13:23+00:00" }, { "name": "phpunit/php-code-coverage", @@ -3100,16 +3101,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.21", + "version": "9.6.22", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa" + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", - "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", "shasum": "" }, "require": { @@ -3120,7 +3121,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", + "myclabs/deep-copy": "^1.12.1", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=7.3", @@ -3183,7 +3184,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.21" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" }, "funding": [ { @@ -3199,7 +3200,7 @@ "type": "tidelift" } ], - "time": "2024-09-19T10:50:18+00:00" + "time": "2024-12-05T13:48:26+00:00" }, { "name": "rregeer/phpunit-coverage-check", diff --git a/docker-compose.yml b/docker-compose.yml index 953b69838..c49290aaf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,8 @@ services: - ./dev:/usr/src/code/dev - ./phpunit.xml:/usr/src/code/phpunit.xml - ./dev/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini + - /var/run/docker.sock:/var/run/docker.sock + - ./docker-compose.yml:/usr/src/code/docker-compose.yml adminer: image: adminer diff --git a/src/Database/Database.php b/src/Database/Database.php index 730c37581..f185852ad 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -4,6 +4,7 @@ use Exception; use Utopia\Cache\Cache; +use Utopia\CLI\Console; use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Conflict as ConflictException; @@ -2956,7 +2957,14 @@ public function getDocument(string $collection, string $id, array $queries = [], $documentCacheHash .= ':' . \md5(\implode($selections)); } - if ($cache = $this->cache->load($documentCacheKey, self::TTL, $documentCacheHash)) { + try { + $cache = $this->cache->load($documentCacheKey, self::TTL, $documentCacheHash); + } catch (Exception $e) { + Console::warning('Warning: Failed to get document from cache: ' . $e->getMessage()); + $cache = null; + } + + if ($cache) { $document = new Document($cache); if ($collection->getId() !== self::METADATA) { @@ -5321,8 +5329,13 @@ public function purgeCachedDocument(string $collectionId, string $id): bool $collectionKey = $this->cacheName . '-cache-' . $this->getNamespace() . ':' . $this->adapter->getTenant() . ':collection:' . $collectionId; $documentKey = $collectionKey . ':' . $id; - $this->cache->purge($collectionKey, $documentKey); - $this->cache->purge($documentKey); + try { + $this->cache->purge($collectionKey, $documentKey); + $this->cache->purge($documentKey); + } catch (Exception $e) { + Console::warning('Warning: Failed to purge cache: ' . $e->getMessage()); + return false; + } return true; } diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 19ca3602d..e57acd241 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -5,6 +5,8 @@ use Exception; use PHPUnit\Framework\TestCase; use Throwable; +use Utopia\CLI\CLI; +use Utopia\CLI\Console; use Utopia\Database\Adapter\SQL; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -70,6 +72,10 @@ public function setUp(): void public function tearDown(): void { Authorization::setDefaultStatus(true); + + $stdout = ''; + $stderr = ''; + Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker start', "", $stdout, $stderr); } protected string $testDatabase = 'utopiaTests'; @@ -17102,6 +17108,41 @@ public function testUpdateDocumentsRelationships(): void } } + public function testRedisFallback(): void + { + Authorization::cleanRoles(); + Authorization::setRole(Role::any()->toString()); + $database = static::getDatabase(); + + $stdout = ''; + $stderr = ''; + Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker stop', "", $stdout, $stderr); + + $database->createCollection('testRedisFallback', attributes: [ + new Document([ + '$id' => ID::custom('string'), + 'type' => Database::VAR_STRING, + 'size' => 767, + 'required' => true, + ]) + ], permissions: [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()) + ]); + + $database->createDocument('testRedisFallback', new Document([ + '$id' => 'doc1', + 'string' => 'textđź“ť', + ])); + + $database->createIndex('testRedisFallback', 'index1', Database::INDEX_KEY, ['string']); + + // Bring backup Redis + Console::execute('cd /usr/src/code && docker compose up redis -d', "", $stdout, $stderr); + } + public function testEvents(): void { Authorization::skip(function () { diff --git a/tests/e2e/Adapter/MariaDBTest.php b/tests/e2e/Adapter/MariaDBTest.php index 32d8c0c0c..e3b12726d 100644 --- a/tests/e2e/Adapter/MariaDBTest.php +++ b/tests/e2e/Adapter/MariaDBTest.php @@ -4,6 +4,7 @@ use PDO; use Redis; +use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\MariaDB; @@ -41,10 +42,14 @@ public static function getDatabase(bool $fresh = false): Database $dbPass = 'password'; $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $dbPass, MariaDB::getPDOAttributes()); - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); + try { + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); + } catch (\Exception $e) { + $cache = new Cache(new None()); + } $database = new Database(new MariaDB($pdo), $cache); $database diff --git a/tests/e2e/Adapter/MirrorTest.php b/tests/e2e/Adapter/MirrorTest.php index a3d457624..9bf26db45 100644 --- a/tests/e2e/Adapter/MirrorTest.php +++ b/tests/e2e/Adapter/MirrorTest.php @@ -4,6 +4,7 @@ use PDO; use Redis; +use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\MariaDB; @@ -45,10 +46,15 @@ protected static function getDatabase(bool $fresh = false): Mirror $dbPass = 'password'; $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $dbPass, MariaDB::getPDOAttributes()); - $redis = new Redis(); - $redis->connect('redis'); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); + + try { + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); + } catch (\Exception $e) { + $cache = new Cache(new None()); + } self::$sourcePdo = $pdo; self::$source = new Database(new MariaDB($pdo), $cache); @@ -59,10 +65,15 @@ protected static function getDatabase(bool $fresh = false): Mirror $mirrorPass = 'password'; $mirrorPdo = new PDO("mysql:host={$mirrorHost};port={$mirrorPort};charset=utf8mb4", $mirrorUser, $mirrorPass, MariaDB::getPDOAttributes()); - $mirrorRedis = new Redis(); - $mirrorRedis->connect('redis-mirror'); - $mirrorRedis->flushAll(); - $mirrorCache = new Cache(new RedisAdapter($mirrorRedis)); + + try { + $mirrorRedis = new Redis(); + $mirrorRedis->connect('redis-mirror'); + $mirrorRedis->flushAll(); + $mirrorCache = new Cache(new RedisAdapter($mirrorRedis)); + } catch (\Exception $e) { + $mirrorCache = new Cache(new None()); + } self::$destinationPdo = $mirrorPdo; self::$destination = new Database(new MariaDB($mirrorPdo), $mirrorCache); diff --git a/tests/e2e/Adapter/MongoDBTest.php b/tests/e2e/Adapter/MongoDBTest.php index e582aef59..fe8552e4e 100644 --- a/tests/e2e/Adapter/MongoDBTest.php +++ b/tests/e2e/Adapter/MongoDBTest.php @@ -4,6 +4,7 @@ use Exception; use Redis; +use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\Mongo; @@ -35,10 +36,14 @@ public static function getDatabase(): Database return self::$database; } - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); + try { + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); + } catch (\Exception $e) { + $cache = new Cache(new None()); + } $schema = 'utopiaTests'; // same as $this->testDatabase $client = new Client( diff --git a/tests/e2e/Adapter/MySQLTest.php b/tests/e2e/Adapter/MySQLTest.php index 369958f07..9943f00a5 100644 --- a/tests/e2e/Adapter/MySQLTest.php +++ b/tests/e2e/Adapter/MySQLTest.php @@ -4,6 +4,7 @@ use PDO; use Redis; +use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\MySQL; @@ -42,11 +43,14 @@ public static function getDatabase(): Database $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $dbPass, MySQL::getPDOAttributes()); - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - - $cache = new Cache(new RedisAdapter($redis)); + try { + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); + } catch (\Exception $e) { + $cache = new Cache(new None()); + } $database = new Database(new MySQL($pdo), $cache); $database diff --git a/tests/e2e/Adapter/PostgresTest.php b/tests/e2e/Adapter/PostgresTest.php index 62977c913..274e4897a 100644 --- a/tests/e2e/Adapter/PostgresTest.php +++ b/tests/e2e/Adapter/PostgresTest.php @@ -4,6 +4,7 @@ use PDO; use Redis; +use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\Postgres; @@ -40,10 +41,14 @@ public static function getDatabase(): Database $dbPass = 'password'; $pdo = new PDO("pgsql:host={$dbHost};port={$dbPort};", $dbUser, $dbPass, Postgres::getPDOAttributes()); - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); + try { + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); + } catch (\Exception $e) { + $cache = new Cache(new None()); + } $database = new Database(new Postgres($pdo), $cache); $database diff --git a/tests/e2e/Adapter/SQLiteTest.php b/tests/e2e/Adapter/SQLiteTest.php index 87676b7f5..b453b65bf 100644 --- a/tests/e2e/Adapter/SQLiteTest.php +++ b/tests/e2e/Adapter/SQLiteTest.php @@ -4,6 +4,7 @@ use PDO; use Redis; +use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\SQLite; @@ -45,9 +46,14 @@ public static function getDatabase(): Database //$dsn = 'memory'; // Overwrite for fast tests $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); - $redis = new Redis(); - $redis->connect('redis'); - $redis->flushAll(); + try { + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); + } catch (\Exception $e) { + $cache = new Cache(new None()); + } $cache = new Cache(new RedisAdapter($redis)); From c19a7f3237f1b91f5a239d47b4a5ecb6a19c3433 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 17 Dec 2024 15:16:48 +0900 Subject: [PATCH 02/20] Run Linter --- tests/e2e/Adapter/Base.php | 1 - tests/e2e/Adapter/MirrorTest.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index e57acd241..9910e170a 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -5,7 +5,6 @@ use Exception; use PHPUnit\Framework\TestCase; use Throwable; -use Utopia\CLI\CLI; use Utopia\CLI\Console; use Utopia\Database\Adapter\SQL; use Utopia\Database\Database; diff --git a/tests/e2e/Adapter/MirrorTest.php b/tests/e2e/Adapter/MirrorTest.php index 9bf26db45..eb26f8872 100644 --- a/tests/e2e/Adapter/MirrorTest.php +++ b/tests/e2e/Adapter/MirrorTest.php @@ -46,7 +46,7 @@ protected static function getDatabase(bool $fresh = false): Mirror $dbPass = 'password'; $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $dbPass, MariaDB::getPDOAttributes()); - + try { $redis = new Redis(); $redis->connect('redis', 6379); From 748fcd39e04b1684952a3e2cf4bd438c2ade4611 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 18 Dec 2024 11:14:36 +0900 Subject: [PATCH 03/20] Cover all cache calls, fix PHPStan --- src/Database/Database.php | 49 +++++++++++++++++++++++++------- tests/e2e/Adapter/Base.php | 3 ++ tests/e2e/Adapter/SQLiteTest.php | 2 -- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index f185852ad..ae1b47709 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1133,7 +1133,11 @@ public function delete(?string $database = null): bool 'deleted' => $deleted ]); - $this->cache->flush(); + try { + $this->cache->flush(); + } catch (Exception $e) { + Console::warning('Failed to flush cache: ' . $e->getMessage()); + } return $deleted; } @@ -3027,21 +3031,35 @@ public function getDocument(string $collection, string $id, array $queries = [], foreach ($this->map as $key => $value) { [$k, $v] = \explode('=>', $key); $ck = $this->cacheName . '-cache-' . $this->getNamespace() . ':' . $this->adapter->getTenant() . ':map:' . $k; - $cache = $this->cache->load($ck, self::TTL, $ck); + + try { + $cache = $this->cache->load($ck, self::TTL, $ck); + } catch (Exception $e) { + Console::warning('Failed to load document from cache: ' . $e->getMessage()); + $cache = []; + } if (empty($cache)) { $cache = []; } if (!\in_array($v, $cache)) { $cache[] = $v; - $this->cache->save($ck, $cache, $ck); + try { + $this->cache->save($ck, $cache, $ck); + } catch (Exception $e) { + Console::warning('Failed to save document to cache: ' . $e->getMessage()); + } } } // Don't save to cache if it's part of a relationship if (!$hasTwoWayRelationship && empty($relationships)) { - $this->cache->save($documentCacheKey, $document->getArrayCopy(), $documentCacheHash); - // Add document reference to the collection key - $this->cache->save($collectionCacheKey, 'empty', $documentCacheKey); + try { + $this->cache->save($documentCacheKey, $document->getArrayCopy(), $documentCacheHash); + // Add document reference to the collection key + $this->cache->save($collectionCacheKey, 'empty', $documentCacheKey); + } catch (Exception $e) { + Console::warning('Failed to save document to cache: ' . $e->getMessage()); + } } // Remove internal attributes if not queried for select query @@ -5307,9 +5325,14 @@ public function deleteDocuments(string $collection, array $queries = [], int $ba public function purgeCachedCollection(string $collectionId): bool { $collectionKey = $this->cacheName . '-cache-' . $this->getNamespace() . ':' . $this->adapter->getTenant() . ':collection:' . $collectionId; - $documentKeys = $this->cache->list($collectionKey); - foreach ($documentKeys as $documentKey) { - $this->cache->purge($documentKey); + try { + $documentKeys = $this->cache->list($collectionKey); + foreach ($documentKeys as $documentKey) { + $this->cache->purge($documentKey); + } + } catch (Exception $e) { + Console::warning('Warning: Failed to purge cached collection: ' . $e->getMessage()); + return false; } return true; @@ -6036,7 +6059,13 @@ private function purgeRelatedDocuments(Document $collection, string $id): void } $key = $this->cacheName . '-cache-' . $this->getNamespace() . ':map:' . $collection->getId() . ':' . $id; - $cache = $this->cache->load($key, self::TTL, $key); + try { + $cache = $this->cache->load($key, self::TTL, $key); + } catch (Exception $e) { + Console::warning('Warning: Failed to load cache: ' . $e->getMessage()); + return; + } + if (!empty($cache)) { foreach ($cache as $v) { list($collectionId, $documentId) = explode(':', $v); diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 9910e170a..d85ff32b1 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17137,9 +17137,12 @@ public function testRedisFallback(): void ])); $database->createIndex('testRedisFallback', 'index1', Database::INDEX_KEY, ['string']); + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); // Bring backup Redis Console::execute('cd /usr/src/code && docker compose up redis -d', "", $stdout, $stderr); + + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); } public function testEvents(): void diff --git a/tests/e2e/Adapter/SQLiteTest.php b/tests/e2e/Adapter/SQLiteTest.php index b453b65bf..4a00b1c87 100644 --- a/tests/e2e/Adapter/SQLiteTest.php +++ b/tests/e2e/Adapter/SQLiteTest.php @@ -55,8 +55,6 @@ public static function getDatabase(): Database $cache = new Cache(new None()); } - $cache = new Cache(new RedisAdapter($redis)); - $database = new Database(new SQLite($pdo), $cache); $database ->setDatabase('utopiaTests') From e34ed7e7e028994e99a113921291acd6b10ad9c8 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 18 Dec 2024 11:18:29 +0900 Subject: [PATCH 04/20] Run Linter, correctly bring up docker containers --- src/Database/Database.php | 2 +- tests/e2e/Adapter/Base.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index ae1b47709..2b31fdada 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -3031,7 +3031,7 @@ public function getDocument(string $collection, string $id, array $queries = [], foreach ($this->map as $key => $value) { [$k, $v] = \explode('=>', $key); $ck = $this->cacheName . '-cache-' . $this->getNamespace() . ':' . $this->adapter->getTenant() . ':map:' . $k; - + try { $cache = $this->cache->load($ck, self::TTL, $ck); } catch (Exception $e) { diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index d85ff32b1..179a244b9 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17140,7 +17140,8 @@ public function testRedisFallback(): void $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); // Bring backup Redis - Console::execute('cd /usr/src/code && docker compose up redis -d', "", $stdout, $stderr); + Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker start', "", $stdout, $stderr); + sleep(2); $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); } From 3dff9adeb9d841d07b316a4811a919dae94b9b1c Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 13 Jan 2025 10:44:11 +0900 Subject: [PATCH 05/20] Make cache throw on write but fallback on read --- src/Database/Database.php | 50 ++++++++++++++------------------------ tests/e2e/Adapter/Base.php | 35 +++++++++++++++++++++----- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 2b31fdada..0ee628ed8 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1133,11 +1133,7 @@ public function delete(?string $database = null): bool 'deleted' => $deleted ]); - try { - $this->cache->flush(); - } catch (Exception $e) { - Console::warning('Failed to flush cache: ' . $e->getMessage()); - } + $this->cache->flush(); return $deleted; } @@ -3977,6 +3973,9 @@ public function updateDocument(string $collection, string $id, Document $documen $this->adapter->updateDocument($collection->getId(), $id, $document); + $this->purgeRelatedDocuments($collection, $id); + $this->purgeCachedDocument($collection->getId(), $id); + return $document; }); @@ -3986,8 +3985,6 @@ public function updateDocument(string $collection, string $id, Document $documen $document = $this->decode($collection, $document); - $this->purgeRelatedDocuments($collection, $id); - $this->purgeCachedDocument($collection->getId(), $id); $this->trigger(self::EVENT_DOCUMENT_UPDATE, $document); return $document; @@ -4787,11 +4784,13 @@ public function deleteDocument(string $collection, string $id): bool $document = $this->silent(fn () => $this->deleteDocumentRelationships($collection, $document)); } - return $this->adapter->deleteDocument($collection->getId(), $id); - }); + $result = $this->adapter->deleteDocument($collection->getId(), $id); - $this->purgeRelatedDocuments($collection, $id); - $this->purgeCachedDocument($collection->getId(), $id); + $this->purgeRelatedDocuments($collection, $id); + $this->purgeCachedDocument($collection->getId(), $id); + + return $result; + }); $this->trigger(self::EVENT_DOCUMENT_DELETE, $document); @@ -5325,14 +5324,10 @@ public function deleteDocuments(string $collection, array $queries = [], int $ba public function purgeCachedCollection(string $collectionId): bool { $collectionKey = $this->cacheName . '-cache-' . $this->getNamespace() . ':' . $this->adapter->getTenant() . ':collection:' . $collectionId; - try { - $documentKeys = $this->cache->list($collectionKey); - foreach ($documentKeys as $documentKey) { - $this->cache->purge($documentKey); - } - } catch (Exception $e) { - Console::warning('Warning: Failed to purge cached collection: ' . $e->getMessage()); - return false; + + $documentKeys = $this->cache->list($collectionKey); + foreach ($documentKeys as $documentKey) { + $this->cache->purge($documentKey); } return true; @@ -5352,13 +5347,8 @@ public function purgeCachedDocument(string $collectionId, string $id): bool $collectionKey = $this->cacheName . '-cache-' . $this->getNamespace() . ':' . $this->adapter->getTenant() . ':collection:' . $collectionId; $documentKey = $collectionKey . ':' . $id; - try { - $this->cache->purge($collectionKey, $documentKey); - $this->cache->purge($documentKey); - } catch (Exception $e) { - Console::warning('Warning: Failed to purge cache: ' . $e->getMessage()); - return false; - } + $this->cache->purge($collectionKey, $documentKey); + $this->cache->purge($documentKey); return true; } @@ -6059,12 +6049,8 @@ private function purgeRelatedDocuments(Document $collection, string $id): void } $key = $this->cacheName . '-cache-' . $this->getNamespace() . ':map:' . $collection->getId() . ':' . $id; - try { - $cache = $this->cache->load($key, self::TTL, $key); - } catch (Exception $e) { - Console::warning('Warning: Failed to load cache: ' . $e->getMessage()); - return; - } + + $cache = $this->cache->load($key, self::TTL, $key); if (!empty($cache)) { foreach ($cache as $v) { diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 179a244b9..b67d11cf1 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17107,16 +17107,13 @@ public function testUpdateDocumentsRelationships(): void } } - public function testRedisFallback(): void + public function testCacheFallback(): void { Authorization::cleanRoles(); Authorization::setRole(Role::any()->toString()); $database = static::getDatabase(); - $stdout = ''; - $stderr = ''; - Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker stop', "", $stdout, $stderr); - + // Write mock data $database->createCollection('testRedisFallback', attributes: [ new Document([ '$id' => ID::custom('string'), @@ -17139,9 +17136,35 @@ public function testRedisFallback(): void $database->createIndex('testRedisFallback', 'index1', Database::INDEX_KEY, ['string']); $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + // Bring down Redis + $stdout = ''; + $stderr = ''; + Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker stop', "", $stdout, $stderr); + + // Check we can read data still + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + $this->assertFalse(($database->getDocument('testRedisFallback', 'doc1'))->isEmpty()); + + // Check we cannot modify data + try { + $database->updateDocument('testRedisFallback', 'doc1', new Document([ + 'string' => 'textđź“ť updated', + ])); + $this->fail('Failed to throw exception'); + } catch (\Throwable $e) { + $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); + } + + try { + $database->deleteDocument('testRedisFallback', 'doc1'); + $this->fail('Failed to throw exception'); + } catch (\Throwable $e) { + $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); + } + // Bring backup Redis Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker start', "", $stdout, $stderr); - sleep(2); + sleep(5); $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); } From 1aad32eb6e3fb25955b8f2a92cb93d8f2cc43587 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 14 Jan 2025 16:07:19 +0900 Subject: [PATCH 06/20] Address Comments --- tests/e2e/Adapter/Base.php | 4 ---- tests/e2e/Adapter/MariaDBTest.php | 14 +++++--------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index b67d11cf1..8c7f9e634 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -71,10 +71,6 @@ public function setUp(): void public function tearDown(): void { Authorization::setDefaultStatus(true); - - $stdout = ''; - $stderr = ''; - Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker start', "", $stdout, $stderr); } protected string $testDatabase = 'utopiaTests'; diff --git a/tests/e2e/Adapter/MariaDBTest.php b/tests/e2e/Adapter/MariaDBTest.php index e3b12726d..c60f08c0e 100644 --- a/tests/e2e/Adapter/MariaDBTest.php +++ b/tests/e2e/Adapter/MariaDBTest.php @@ -4,7 +4,6 @@ use PDO; use Redis; -use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\MariaDB; @@ -42,14 +41,11 @@ public static function getDatabase(bool $fresh = false): Database $dbPass = 'password'; $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $dbPass, MariaDB::getPDOAttributes()); - try { - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); - } catch (\Exception $e) { - $cache = new Cache(new None()); - } + + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); $database = new Database(new MariaDB($pdo), $cache); $database From 94e9e521eabe815c4ef8511accffd0a820f29f1c Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 14 Jan 2025 16:16:25 +0900 Subject: [PATCH 07/20] Run LInter --- tests/e2e/Adapter/Base.php | 90 +++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 290875bf7..83711e8ba 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17179,55 +17179,55 @@ public function testCacheFallback(): void 'type' => Database::VAR_STRING, 'size' => 767, 'required' => true, - ]) - ], permissions: [ - Permission::read(Role::any()), - Permission::create(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()) - ]); + ]) + ], permissions: [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()) + ]); - $database->createDocument('testRedisFallback', new Document([ - '$id' => 'doc1', - 'string' => 'textđź“ť', + $database->createDocument('testRedisFallback', new Document([ + '$id' => 'doc1', + 'string' => 'textđź“ť', + ])); + + $database->createIndex('testRedisFallback', 'index1', Database::INDEX_KEY, ['string']); + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + + // Bring down Redis + $stdout = ''; + $stderr = ''; + Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker stop', "", $stdout, $stderr); + + // Check we can read data still + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + $this->assertFalse(($database->getDocument('testRedisFallback', 'doc1'))->isEmpty()); + + // Check we cannot modify data + try { + $database->updateDocument('testRedisFallback', 'doc1', new Document([ + 'string' => 'textđź“ť updated', ])); - - $database->createIndex('testRedisFallback', 'index1', Database::INDEX_KEY, ['string']); - $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); - - // Bring down Redis - $stdout = ''; - $stderr = ''; - Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker stop', "", $stdout, $stderr); - - // Check we can read data still - $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); - $this->assertFalse(($database->getDocument('testRedisFallback', 'doc1'))->isEmpty()); - - // Check we cannot modify data - try { - $database->updateDocument('testRedisFallback', 'doc1', new Document([ - 'string' => 'textđź“ť updated', - ])); - $this->fail('Failed to throw exception'); - } catch (\Throwable $e) { - $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); - } - - try { - $database->deleteDocument('testRedisFallback', 'doc1'); - $this->fail('Failed to throw exception'); - } catch (\Throwable $e) { - $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); - } - - // Bring backup Redis - Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker start', "", $stdout, $stderr); - sleep(5); - - $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + $this->fail('Failed to throw exception'); + } catch (\Throwable $e) { + $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); + } + + try { + $database->deleteDocument('testRedisFallback', 'doc1'); + $this->fail('Failed to throw exception'); + } catch (\Throwable $e) { + $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); } + // Bring backup Redis + Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker start', "", $stdout, $stderr); + sleep(5); + + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + } + public function testNestedQueryValidation(): void { $this->getDatabase()->createCollection(__FUNCTION__, [ From c296c599c3fc541f2aa4be3c58d36970b25d34b3 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 16 Jan 2025 15:54:06 +0900 Subject: [PATCH 08/20] Update tests --- tests/e2e/Adapter/Base.php | 124 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 83711e8ba..68404c44c 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17166,68 +17166,6 @@ public function testUpdateDocumentsRelationships(): void } } - public function testCacheFallback(): void - { - Authorization::cleanRoles(); - Authorization::setRole(Role::any()->toString()); - $database = static::getDatabase(); - - // Write mock data - $database->createCollection('testRedisFallback', attributes: [ - new Document([ - '$id' => ID::custom('string'), - 'type' => Database::VAR_STRING, - 'size' => 767, - 'required' => true, - ]) - ], permissions: [ - Permission::read(Role::any()), - Permission::create(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()) - ]); - - $database->createDocument('testRedisFallback', new Document([ - '$id' => 'doc1', - 'string' => 'textđź“ť', - ])); - - $database->createIndex('testRedisFallback', 'index1', Database::INDEX_KEY, ['string']); - $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); - - // Bring down Redis - $stdout = ''; - $stderr = ''; - Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker stop', "", $stdout, $stderr); - - // Check we can read data still - $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); - $this->assertFalse(($database->getDocument('testRedisFallback', 'doc1'))->isEmpty()); - - // Check we cannot modify data - try { - $database->updateDocument('testRedisFallback', 'doc1', new Document([ - 'string' => 'textđź“ť updated', - ])); - $this->fail('Failed to throw exception'); - } catch (\Throwable $e) { - $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); - } - - try { - $database->deleteDocument('testRedisFallback', 'doc1'); - $this->fail('Failed to throw exception'); - } catch (\Throwable $e) { - $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); - } - - // Bring backup Redis - Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker start', "", $stdout, $stderr); - sleep(5); - - $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); - } - public function testNestedQueryValidation(): void { $this->getDatabase()->createCollection(__FUNCTION__, [ @@ -17377,4 +17315,66 @@ public function testEvents(): void $database->delete('hellodb'); }); } + + public function testCacheFallback(): void + { + Authorization::cleanRoles(); + Authorization::setRole(Role::any()->toString()); + $database = static::getDatabase(); + + // Write mock data + $database->createCollection('testRedisFallback', attributes: [ + new Document([ + '$id' => ID::custom('string'), + 'type' => Database::VAR_STRING, + 'size' => 767, + 'required' => true, + ]) + ], permissions: [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()) + ]); + + $database->createDocument('testRedisFallback', new Document([ + '$id' => 'doc1', + 'string' => 'textđź“ť', + ])); + + $database->createIndex('testRedisFallback', 'index1', Database::INDEX_KEY, ['string']); + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + + // Bring down Redis + $stdout = ''; + $stderr = ''; + Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker stop', "", $stdout, $stderr); + + // Check we can read data still + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + $this->assertFalse(($database->getDocument('testRedisFallback', 'doc1'))->isEmpty()); + + // Check we cannot modify data + try { + $database->updateDocument('testRedisFallback', 'doc1', new Document([ + 'string' => 'textđź“ť updated', + ])); + $this->fail('Failed to throw exception'); + } catch (\Throwable $e) { + $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); + } + + try { + $database->deleteDocument('testRedisFallback', 'doc1'); + $this->fail('Failed to throw exception'); + } catch (\Throwable $e) { + $this->assertEquals('Redis server redis:6379 went away', $e->getMessage()); + } + + // Bring backup Redis + Console::execute('docker ps -a --filter "name=utopia-redis" --format "{{.Names}}" | xargs -r docker start', "", $stdout, $stderr); + sleep(5); + + $this->assertCount(1, $database->find('testRedisFallback', [Query::equal('string', ['textđź“ť'])])); + } } From 4d75c5d2cd7cadaeba4cfcc70598de638f998720 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 20 Jan 2025 13:46:14 +0900 Subject: [PATCH 09/20] Fix tests failing because of events --- tests/e2e/Adapter/Base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 68404c44c..e6cbb93fa 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17320,7 +17320,7 @@ public function testCacheFallback(): void { Authorization::cleanRoles(); Authorization::setRole(Role::any()->toString()); - $database = static::getDatabase(); + $database = static::getDatabase(true); // Write mock data $database->createCollection('testRedisFallback', attributes: [ From daa1bee5a2d9881d4c2a13d8342742a3bebca210 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 20 Jan 2025 14:17:35 +0900 Subject: [PATCH 10/20] Readd fresh parameter to tests --- tests/e2e/Adapter/Base.php | 2 +- tests/e2e/Adapter/MongoDBTest.php | 4 ++-- tests/e2e/Adapter/MySQLTest.php | 4 ++-- tests/e2e/Adapter/PostgresTest.php | 4 ++-- tests/e2e/Adapter/SQLiteTest.php | 4 ++-- tests/e2e/Adapter/SharedTables/MongoDBTest.php | 4 ++-- tests/e2e/Adapter/SharedTables/MySQLTest.php | 4 ++-- tests/e2e/Adapter/SharedTables/PostgresTest.php | 4 ++-- tests/e2e/Adapter/SharedTables/SQLiteTest.php | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index e6cbb93fa..ecf5931bf 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -41,7 +41,7 @@ abstract class Base extends TestCase /** * @return Database */ - abstract protected static function getDatabase(): Database; + abstract protected static function getDatabase(bool $fresh = false): Database; /** * @param string $collection diff --git a/tests/e2e/Adapter/MongoDBTest.php b/tests/e2e/Adapter/MongoDBTest.php index fe8552e4e..68c46e81b 100644 --- a/tests/e2e/Adapter/MongoDBTest.php +++ b/tests/e2e/Adapter/MongoDBTest.php @@ -30,9 +30,9 @@ public static function getAdapterName(): string * @return Database * @throws Exception */ - public static function getDatabase(): Database + public static function getDatabase(bool $fresh = false): Database { - if (!is_null(self::$database)) { + if (!is_null(self::$database) && !$fresh) { return self::$database; } diff --git a/tests/e2e/Adapter/MySQLTest.php b/tests/e2e/Adapter/MySQLTest.php index 9943f00a5..4ef4b5d50 100644 --- a/tests/e2e/Adapter/MySQLTest.php +++ b/tests/e2e/Adapter/MySQLTest.php @@ -30,9 +30,9 @@ public static function getAdapterName(): string /** * @return Database */ - public static function getDatabase(): Database + public static function getDatabase(bool $fresh = false): Database { - if (!is_null(self::$database)) { + if (!is_null(self::$database) && !$fresh) { return self::$database; } diff --git a/tests/e2e/Adapter/PostgresTest.php b/tests/e2e/Adapter/PostgresTest.php index 274e4897a..32c30779c 100644 --- a/tests/e2e/Adapter/PostgresTest.php +++ b/tests/e2e/Adapter/PostgresTest.php @@ -29,9 +29,9 @@ public static function getAdapterName(): string /** * @reture Adapter */ - public static function getDatabase(): Database + public static function getDatabase(bool $fresh = false): Database { - if (!is_null(self::$database)) { + if (!is_null(self::$database) && !$fresh) { return self::$database; } diff --git a/tests/e2e/Adapter/SQLiteTest.php b/tests/e2e/Adapter/SQLiteTest.php index 4a00b1c87..f88564953 100644 --- a/tests/e2e/Adapter/SQLiteTest.php +++ b/tests/e2e/Adapter/SQLiteTest.php @@ -30,9 +30,9 @@ public static function getAdapterName(): string /** * @return Database */ - public static function getDatabase(): Database + public static function getDatabase(bool $fresh = false): Database { - if (!is_null(self::$database)) { + if (!is_null(self::$database) && !$fresh) { return self::$database; } diff --git a/tests/e2e/Adapter/SharedTables/MongoDBTest.php b/tests/e2e/Adapter/SharedTables/MongoDBTest.php index 7d41bb711..2dc5c11d1 100644 --- a/tests/e2e/Adapter/SharedTables/MongoDBTest.php +++ b/tests/e2e/Adapter/SharedTables/MongoDBTest.php @@ -30,9 +30,9 @@ public static function getAdapterName(): string * @return Database * @throws Exception */ - public static function getDatabase(): Database + public static function getDatabase(bool $fresh = false): Database { - if (!is_null(self::$database)) { + if (!is_null(self::$database) && !$fresh) { return self::$database; } diff --git a/tests/e2e/Adapter/SharedTables/MySQLTest.php b/tests/e2e/Adapter/SharedTables/MySQLTest.php index e56a2ba51..8cba87474 100644 --- a/tests/e2e/Adapter/SharedTables/MySQLTest.php +++ b/tests/e2e/Adapter/SharedTables/MySQLTest.php @@ -30,9 +30,9 @@ public static function getAdapterName(): string /** * @return Database */ - public static function getDatabase(): Database + public static function getDatabase(bool $fresh = false): Database { - if (!is_null(self::$database)) { + if (!is_null(self::$database) && !$fresh) { return self::$database; } diff --git a/tests/e2e/Adapter/SharedTables/PostgresTest.php b/tests/e2e/Adapter/SharedTables/PostgresTest.php index 8319311d5..a6127bef5 100644 --- a/tests/e2e/Adapter/SharedTables/PostgresTest.php +++ b/tests/e2e/Adapter/SharedTables/PostgresTest.php @@ -29,9 +29,9 @@ public static function getAdapterName(): string /** * @reture Adapter */ - public static function getDatabase(): Database + public static function getDatabase(bool $fresh = false): Database { - if (!is_null(self::$database)) { + if (!is_null(self::$database) && !$fresh) { return self::$database; } diff --git a/tests/e2e/Adapter/SharedTables/SQLiteTest.php b/tests/e2e/Adapter/SharedTables/SQLiteTest.php index daa39d6be..60a35367e 100644 --- a/tests/e2e/Adapter/SharedTables/SQLiteTest.php +++ b/tests/e2e/Adapter/SharedTables/SQLiteTest.php @@ -30,9 +30,9 @@ public static function getAdapterName(): string /** * @return Database */ - public static function getDatabase(): Database + public static function getDatabase(bool $fresh = false): Database { - if (!is_null(self::$database)) { + if (!is_null(self::$database) && !$fresh) { return self::$database; } From e145a8a0bc583e4b05dfe257dacdf7de0651e6e0 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 27 Jan 2025 12:33:06 +0900 Subject: [PATCH 11/20] Fix Double Event Execution --- src/Database/Database.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 20d8e3a3f..38ba5b14b 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -4021,7 +4021,6 @@ public function updateDocument(string $collection, string $id, Document $documen $document = $this->decode($collection, $document); - $this->purgeCachedDocument($collection->getId(), $id); $this->trigger(self::EVENT_DOCUMENT_UPDATE, $document); return $document; From a42b88447263482ae1d261eba16f8a6d39834110 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 27 Jan 2025 15:42:40 +0900 Subject: [PATCH 12/20] Fix tests --- tests/e2e/Adapter/MirrorTest.php | 12 ++++-------- tests/e2e/Adapter/MongoDBTest.php | 13 ++++--------- tests/e2e/Adapter/MySQLTest.php | 13 ++++--------- tests/e2e/Adapter/PostgresTest.php | 13 ++++--------- tests/e2e/Adapter/SQLiteTest.php | 13 ++++--------- 5 files changed, 20 insertions(+), 44 deletions(-) diff --git a/tests/e2e/Adapter/MirrorTest.php b/tests/e2e/Adapter/MirrorTest.php index eb26f8872..bdeb46e1c 100644 --- a/tests/e2e/Adapter/MirrorTest.php +++ b/tests/e2e/Adapter/MirrorTest.php @@ -47,14 +47,10 @@ protected static function getDatabase(bool $fresh = false): Mirror $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $dbPass, MariaDB::getPDOAttributes()); - try { - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); - } catch (\Exception $e) { - $cache = new Cache(new None()); - } + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); self::$sourcePdo = $pdo; self::$source = new Database(new MariaDB($pdo), $cache); diff --git a/tests/e2e/Adapter/MongoDBTest.php b/tests/e2e/Adapter/MongoDBTest.php index 68c46e81b..a7e8eb7fa 100644 --- a/tests/e2e/Adapter/MongoDBTest.php +++ b/tests/e2e/Adapter/MongoDBTest.php @@ -4,7 +4,6 @@ use Exception; use Redis; -use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\Mongo; @@ -36,14 +35,10 @@ public static function getDatabase(bool $fresh = false): Database return self::$database; } - try { - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); - } catch (\Exception $e) { - $cache = new Cache(new None()); - } + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); $schema = 'utopiaTests'; // same as $this->testDatabase $client = new Client( diff --git a/tests/e2e/Adapter/MySQLTest.php b/tests/e2e/Adapter/MySQLTest.php index 4ef4b5d50..cd32df297 100644 --- a/tests/e2e/Adapter/MySQLTest.php +++ b/tests/e2e/Adapter/MySQLTest.php @@ -4,7 +4,6 @@ use PDO; use Redis; -use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\MySQL; @@ -43,14 +42,10 @@ public static function getDatabase(bool $fresh = false): Database $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $dbPass, MySQL::getPDOAttributes()); - try { - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); - } catch (\Exception $e) { - $cache = new Cache(new None()); - } + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); $database = new Database(new MySQL($pdo), $cache); $database diff --git a/tests/e2e/Adapter/PostgresTest.php b/tests/e2e/Adapter/PostgresTest.php index 32c30779c..8f05a1fed 100644 --- a/tests/e2e/Adapter/PostgresTest.php +++ b/tests/e2e/Adapter/PostgresTest.php @@ -4,7 +4,6 @@ use PDO; use Redis; -use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\Postgres; @@ -41,14 +40,10 @@ public static function getDatabase(bool $fresh = false): Database $dbPass = 'password'; $pdo = new PDO("pgsql:host={$dbHost};port={$dbPort};", $dbUser, $dbPass, Postgres::getPDOAttributes()); - try { - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); - } catch (\Exception $e) { - $cache = new Cache(new None()); - } + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); $database = new Database(new Postgres($pdo), $cache); $database diff --git a/tests/e2e/Adapter/SQLiteTest.php b/tests/e2e/Adapter/SQLiteTest.php index f88564953..67f3b1f0e 100644 --- a/tests/e2e/Adapter/SQLiteTest.php +++ b/tests/e2e/Adapter/SQLiteTest.php @@ -4,7 +4,6 @@ use PDO; use Redis; -use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\SQLite; @@ -46,14 +45,10 @@ public static function getDatabase(bool $fresh = false): Database //$dsn = 'memory'; // Overwrite for fast tests $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); - try { - $redis = new Redis(); - $redis->connect('redis', 6379); - $redis->flushAll(); - $cache = new Cache(new RedisAdapter($redis)); - } catch (\Exception $e) { - $cache = new Cache(new None()); - } + $redis = new Redis(); + $redis->connect('redis', 6379); + $redis->flushAll(); + $cache = new Cache(new RedisAdapter($redis)); $database = new Database(new SQLite($pdo), $cache); $database From 1653b807e8488fb84d8e892ac782a12bf7454745 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 27 Jan 2025 16:06:20 +0900 Subject: [PATCH 13/20] Get SQLite working --- src/Database/Adapter/SQLite.php | 2 +- tests/e2e/Adapter/SQLiteTest.php | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Database/Adapter/SQLite.php b/src/Database/Adapter/SQLite.php index 88b57e590..d22b7f694 100644 --- a/src/Database/Adapter/SQLite.php +++ b/src/Database/Adapter/SQLite.php @@ -224,7 +224,7 @@ public function createCollection(string $name, array $attributes = [], array $in if (!($e instanceof Duplicate)) { $this->getPDO() - ->prepare("DROP TABLE IF EXISTS {$this->getSQLTable($id)}, {$this->getSQLTable($id . '_perms')};") + ->prepare("DROP TABLE IF EXISTS {$this->getSQLTable($id)}; DROP TABLE IF EXISTS {$this->getSQLTable($id . '_perms')};") ->execute(); } diff --git a/tests/e2e/Adapter/SQLiteTest.php b/tests/e2e/Adapter/SQLiteTest.php index 67f3b1f0e..483881821 100644 --- a/tests/e2e/Adapter/SQLiteTest.php +++ b/tests/e2e/Adapter/SQLiteTest.php @@ -33,18 +33,22 @@ public static function getDatabase(bool $fresh = false): Database { if (!is_null(self::$database) && !$fresh) { return self::$database; + } elseif (!is_null(self::$pdo) && $fresh) { + // We want to reuse PDO because referencing the same file results in read-only access + self::$database = null; + $pdo = self::$pdo; + } else { + $db = __DIR__."/database.sql"; + + if (file_exists($db)) { + unlink($db); + } + + $dsn = $db; + //$dsn = 'memory'; // Overwrite for fast tests + $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); } - $db = __DIR__."/database.sql"; - - if (file_exists($db)) { - unlink($db); - } - - $dsn = $db; - //$dsn = 'memory'; // Overwrite for fast tests - $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); - $redis = new Redis(); $redis->connect('redis', 6379); $redis->flushAll(); From ee9f9c2164fd855574a55d509c29f83a086aab36 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 4 Feb 2025 10:38:57 +0900 Subject: [PATCH 14/20] Remove Mongo support and remove fresh functionality and instead use flushEvents --- src/Database/Adapter.php | 7 +++++ src/Database/Adapter/Mongo.php | 10 +++++++ src/Database/Adapter/SQL.php | 10 +++++++ src/Database/Database.php | 14 ++++++++++ tests/e2e/Adapter/Base.php | 10 +++++-- tests/e2e/Adapter/MirrorTest.php | 15 ++++------ tests/e2e/Adapter/MongoDBTest.php | 4 +-- tests/e2e/Adapter/MySQLTest.php | 4 +-- tests/e2e/Adapter/PostgresTest.php | 4 +-- tests/e2e/Adapter/SQLiteTest.php | 28 ++++++++----------- tests/e2e/Adapter/SharedTables/SQLiteTest.php | 25 +++++++++++------ 11 files changed, 89 insertions(+), 42 deletions(-) diff --git a/src/Database/Adapter.php b/src/Database/Adapter.php index c9cbbdecc..c20409f56 100644 --- a/src/Database/Adapter.php +++ b/src/Database/Adapter.php @@ -900,6 +900,13 @@ abstract public function getSupportForCastIndexArray(): bool; */ abstract public function getSupportForUpserts(): bool; + /** + * Is Cache Fallback supported? + * + * @return bool + */ + abstract public function getSupportForCacheFallback(): bool; + /** * Get current attribute count from collection document * diff --git a/src/Database/Adapter/Mongo.php b/src/Database/Adapter/Mongo.php index c5f0522af..acc2a9728 100644 --- a/src/Database/Adapter/Mongo.php +++ b/src/Database/Adapter/Mongo.php @@ -1800,6 +1800,16 @@ public function getSupportForGetConnectionId(): bool return false; } + /** + * Is cache fallback supported? + * + * @return bool + */ + public function getSupportForCacheFallback(): bool + { + return false; + } + /** * Is get schema attributes supported? * diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index ae05e3d9b..1dcf6b3f3 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -402,6 +402,16 @@ public function getSupportForGetConnectionId(): bool return true; } + /** + * Is cache fallback supported? + * + * @return bool + */ + public function getSupportForCacheFallback(): bool + { + return true; + } + /** * Get current attribute count from collection document * diff --git a/src/Database/Database.php b/src/Database/Database.php index 38ba5b14b..21de5df3e 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -458,6 +458,20 @@ public function on(string $event, string $name, callable $callback): static return $this; } + /** + * Clear all listeners, should only be used for testing. + * + * @return static + */ + public function flushListeners(): static + { + $this->listeners = [ + '*' => [], + ]; + + return $this; + } + /** * Add a transformation to be applied to a query string before an event occurs * diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 161a8e9b4..291491d2f 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -41,7 +41,7 @@ abstract class Base extends TestCase /** * @return Database */ - abstract protected static function getDatabase(bool $fresh = false): Database; + abstract protected static function getDatabase(): Database; /** * @param string $collection @@ -17689,9 +17689,15 @@ public function testEvents(): void public function testCacheFallback(): void { + if (!static::getDatabase()->getAdapter()->getSupportForCacheFallback()) { + $this->expectNotToPerformAssertions(); + return; + } + Authorization::cleanRoles(); Authorization::setRole(Role::any()->toString()); - $database = static::getDatabase(true); + $database = static::getDatabase(); + $database->flushListeners(); // Write mock data $database->createCollection('testRedisFallback', attributes: [ diff --git a/tests/e2e/Adapter/MirrorTest.php b/tests/e2e/Adapter/MirrorTest.php index bdeb46e1c..e0e6fad35 100644 --- a/tests/e2e/Adapter/MirrorTest.php +++ b/tests/e2e/Adapter/MirrorTest.php @@ -4,7 +4,6 @@ use PDO; use Redis; -use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; use Utopia\Database\Adapter\MariaDB; @@ -48,7 +47,7 @@ protected static function getDatabase(bool $fresh = false): Mirror $pdo = new PDO("mysql:host={$dbHost};port={$dbPort};charset=utf8mb4", $dbUser, $dbPass, MariaDB::getPDOAttributes()); $redis = new Redis(); - $redis->connect('redis', 6379); + $redis->connect('redis'); $redis->flushAll(); $cache = new Cache(new RedisAdapter($redis)); @@ -62,14 +61,10 @@ protected static function getDatabase(bool $fresh = false): Mirror $mirrorPdo = new PDO("mysql:host={$mirrorHost};port={$mirrorPort};charset=utf8mb4", $mirrorUser, $mirrorPass, MariaDB::getPDOAttributes()); - try { - $mirrorRedis = new Redis(); - $mirrorRedis->connect('redis-mirror'); - $mirrorRedis->flushAll(); - $mirrorCache = new Cache(new RedisAdapter($mirrorRedis)); - } catch (\Exception $e) { - $mirrorCache = new Cache(new None()); - } + $mirrorRedis = new Redis(); + $mirrorRedis->connect('redis-mirror'); + $mirrorRedis->flushAll(); + $mirrorCache = new Cache(new RedisAdapter($mirrorRedis)); self::$destinationPdo = $mirrorPdo; self::$destination = new Database(new MariaDB($mirrorPdo), $mirrorCache); diff --git a/tests/e2e/Adapter/MongoDBTest.php b/tests/e2e/Adapter/MongoDBTest.php index a7e8eb7fa..e582aef59 100644 --- a/tests/e2e/Adapter/MongoDBTest.php +++ b/tests/e2e/Adapter/MongoDBTest.php @@ -29,9 +29,9 @@ public static function getAdapterName(): string * @return Database * @throws Exception */ - public static function getDatabase(bool $fresh = false): Database + public static function getDatabase(): Database { - if (!is_null(self::$database) && !$fresh) { + if (!is_null(self::$database)) { return self::$database; } diff --git a/tests/e2e/Adapter/MySQLTest.php b/tests/e2e/Adapter/MySQLTest.php index cd32df297..0f72d0136 100644 --- a/tests/e2e/Adapter/MySQLTest.php +++ b/tests/e2e/Adapter/MySQLTest.php @@ -29,9 +29,9 @@ public static function getAdapterName(): string /** * @return Database */ - public static function getDatabase(bool $fresh = false): Database + public static function getDatabase(): Database { - if (!is_null(self::$database) && !$fresh) { + if (!is_null(self::$database)) { return self::$database; } diff --git a/tests/e2e/Adapter/PostgresTest.php b/tests/e2e/Adapter/PostgresTest.php index 8f05a1fed..62977c913 100644 --- a/tests/e2e/Adapter/PostgresTest.php +++ b/tests/e2e/Adapter/PostgresTest.php @@ -28,9 +28,9 @@ public static function getAdapterName(): string /** * @reture Adapter */ - public static function getDatabase(bool $fresh = false): Database + public static function getDatabase(): Database { - if (!is_null(self::$database) && !$fresh) { + if (!is_null(self::$database)) { return self::$database; } diff --git a/tests/e2e/Adapter/SQLiteTest.php b/tests/e2e/Adapter/SQLiteTest.php index 483881821..0dd1b0073 100644 --- a/tests/e2e/Adapter/SQLiteTest.php +++ b/tests/e2e/Adapter/SQLiteTest.php @@ -29,26 +29,22 @@ public static function getAdapterName(): string /** * @return Database */ - public static function getDatabase(bool $fresh = false): Database + public static function getDatabase(): Database { - if (!is_null(self::$database) && !$fresh) { + if (!is_null(self::$database)) { return self::$database; - } elseif (!is_null(self::$pdo) && $fresh) { - // We want to reuse PDO because referencing the same file results in read-only access - self::$database = null; - $pdo = self::$pdo; - } else { - $db = __DIR__."/database.sql"; - - if (file_exists($db)) { - unlink($db); - } - - $dsn = $db; - //$dsn = 'memory'; // Overwrite for fast tests - $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); } + $db = __DIR__."/database.sql"; + + if (file_exists($db)) { + unlink($db); + } + + $dsn = $db; + //$dsn = 'memory'; // Overwrite for fast tests + $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); + $redis = new Redis(); $redis->connect('redis', 6379); $redis->flushAll(); diff --git a/tests/e2e/Adapter/SharedTables/SQLiteTest.php b/tests/e2e/Adapter/SharedTables/SQLiteTest.php index 60a35367e..393859d32 100644 --- a/tests/e2e/Adapter/SharedTables/SQLiteTest.php +++ b/tests/e2e/Adapter/SharedTables/SQLiteTest.php @@ -34,17 +34,26 @@ public static function getDatabase(bool $fresh = false): Database { if (!is_null(self::$database) && !$fresh) { return self::$database; - } + } elseif (!is_null(self::$pdo) && $fresh) { + // We want to reuse PDO because referencing the same file results in read-only access + self::$database->silent(function () { + self::$database->delete(); + }); - $db = __DIR__."/database.sql"; + self::$database = null; + $pdo = self::$pdo; + } else { - if (file_exists($db)) { - unlink($db); - } + $db = __DIR__."/database.sql"; - $dsn = $db; - //$dsn = 'memory'; // Overwrite for fast tests - $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); + if (file_exists($db)) { + unlink($db); + } + + $dsn = $db; + //$dsn = 'memory'; // Overwrite for fast tests + $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); + } $redis = new Redis(); $redis->connect('redis'); From 490f0d35ac1dffc9f86081931b31283bdb38e446 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 4 Feb 2025 10:46:36 +0900 Subject: [PATCH 15/20] Remove fresh functionality --- .../e2e/Adapter/SharedTables/MongoDBTest.php | 4 +-- tests/e2e/Adapter/SharedTables/MySQLTest.php | 4 +-- .../e2e/Adapter/SharedTables/PostgresTest.php | 4 +-- tests/e2e/Adapter/SharedTables/SQLiteTest.php | 29 +++++++------------ 4 files changed, 16 insertions(+), 25 deletions(-) diff --git a/tests/e2e/Adapter/SharedTables/MongoDBTest.php b/tests/e2e/Adapter/SharedTables/MongoDBTest.php index 2dc5c11d1..7d41bb711 100644 --- a/tests/e2e/Adapter/SharedTables/MongoDBTest.php +++ b/tests/e2e/Adapter/SharedTables/MongoDBTest.php @@ -30,9 +30,9 @@ public static function getAdapterName(): string * @return Database * @throws Exception */ - public static function getDatabase(bool $fresh = false): Database + public static function getDatabase(): Database { - if (!is_null(self::$database) && !$fresh) { + if (!is_null(self::$database)) { return self::$database; } diff --git a/tests/e2e/Adapter/SharedTables/MySQLTest.php b/tests/e2e/Adapter/SharedTables/MySQLTest.php index 8cba87474..e56a2ba51 100644 --- a/tests/e2e/Adapter/SharedTables/MySQLTest.php +++ b/tests/e2e/Adapter/SharedTables/MySQLTest.php @@ -30,9 +30,9 @@ public static function getAdapterName(): string /** * @return Database */ - public static function getDatabase(bool $fresh = false): Database + public static function getDatabase(): Database { - if (!is_null(self::$database) && !$fresh) { + if (!is_null(self::$database)) { return self::$database; } diff --git a/tests/e2e/Adapter/SharedTables/PostgresTest.php b/tests/e2e/Adapter/SharedTables/PostgresTest.php index a6127bef5..8319311d5 100644 --- a/tests/e2e/Adapter/SharedTables/PostgresTest.php +++ b/tests/e2e/Adapter/SharedTables/PostgresTest.php @@ -29,9 +29,9 @@ public static function getAdapterName(): string /** * @reture Adapter */ - public static function getDatabase(bool $fresh = false): Database + public static function getDatabase(): Database { - if (!is_null(self::$database) && !$fresh) { + if (!is_null(self::$database)) { return self::$database; } diff --git a/tests/e2e/Adapter/SharedTables/SQLiteTest.php b/tests/e2e/Adapter/SharedTables/SQLiteTest.php index 393859d32..daa39d6be 100644 --- a/tests/e2e/Adapter/SharedTables/SQLiteTest.php +++ b/tests/e2e/Adapter/SharedTables/SQLiteTest.php @@ -30,31 +30,22 @@ public static function getAdapterName(): string /** * @return Database */ - public static function getDatabase(bool $fresh = false): Database + public static function getDatabase(): Database { - if (!is_null(self::$database) && !$fresh) { + if (!is_null(self::$database)) { return self::$database; - } elseif (!is_null(self::$pdo) && $fresh) { - // We want to reuse PDO because referencing the same file results in read-only access - self::$database->silent(function () { - self::$database->delete(); - }); - - self::$database = null; - $pdo = self::$pdo; - } else { - - $db = __DIR__."/database.sql"; + } - if (file_exists($db)) { - unlink($db); - } + $db = __DIR__."/database.sql"; - $dsn = $db; - //$dsn = 'memory'; // Overwrite for fast tests - $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); + if (file_exists($db)) { + unlink($db); } + $dsn = $db; + //$dsn = 'memory'; // Overwrite for fast tests + $pdo = new PDO("sqlite:" . $dsn, null, null, SQLite::getPDOAttributes()); + $redis = new Redis(); $redis->connect('redis'); $redis->flushAll(); From d5f738d3909272c3d69a237bf581958ecadd562a Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 4 Feb 2025 10:50:36 +0900 Subject: [PATCH 16/20] Move listener flushing to event tests --- tests/e2e/Adapter/Base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 291491d2f..1995c00a7 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17684,6 +17684,7 @@ public function testEvents(): void $database->deleteAttribute($collectionId, 'attr1'); $database->deleteCollection($collectionId); $database->delete('hellodb'); + $database->flushListeners(); }); } @@ -17697,7 +17698,6 @@ public function testCacheFallback(): void Authorization::cleanRoles(); Authorization::setRole(Role::any()->toString()); $database = static::getDatabase(); - $database->flushListeners(); // Write mock data $database->createCollection('testRedisFallback', attributes: [ From 69f2260e90d83b8851f94ba50e8ab0a87c547e8a Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 4 Feb 2025 12:18:39 +0900 Subject: [PATCH 17/20] Fix mirror adapter flushing listeners --- src/Database/Mirror.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Database/Mirror.php b/src/Database/Mirror.php index 92cdae23c..08fb04fb5 100644 --- a/src/Database/Mirror.php +++ b/src/Database/Mirror.php @@ -952,4 +952,21 @@ protected function logError(string $action, \Throwable $err): void $callback($action, $err); } } + + /** + * Clear all listeners, should only be used for testing. + * + * @return static + */ + public function flushListeners(): static + { + $this->listeners = [ + '*' => [], + ]; + + $this->source->flushListeners(); + $this->destination->flushListeners(); + + return $this; + } } From a0014dee25c0d0f5f5b9b7dc9122c51d72d2f76a Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 4 Feb 2025 14:22:12 +0900 Subject: [PATCH 18/20] Address Comments --- src/Database/Adapter.php | 2 +- src/Database/Adapter/Mongo.php | 2 +- src/Database/Adapter/SQL.php | 2 +- src/Database/Database.php | 66 ++++++++-------------------------- src/Database/Mirror.php | 19 +--------- tests/e2e/Adapter/Base.php | 6 ++-- 6 files changed, 22 insertions(+), 75 deletions(-) diff --git a/src/Database/Adapter.php b/src/Database/Adapter.php index c20409f56..12b74513b 100644 --- a/src/Database/Adapter.php +++ b/src/Database/Adapter.php @@ -905,7 +905,7 @@ abstract public function getSupportForUpserts(): bool; * * @return bool */ - abstract public function getSupportForCacheFallback(): bool; + abstract public function getSupportForCacheSkipOnFailure(): bool; /** * Get current attribute count from collection document diff --git a/src/Database/Adapter/Mongo.php b/src/Database/Adapter/Mongo.php index acc2a9728..b35add565 100644 --- a/src/Database/Adapter/Mongo.php +++ b/src/Database/Adapter/Mongo.php @@ -1805,7 +1805,7 @@ public function getSupportForGetConnectionId(): bool * * @return bool */ - public function getSupportForCacheFallback(): bool + public function getSupportForCacheSkipOnFailure(): bool { return false; } diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index 1dcf6b3f3..eb44467e9 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -407,7 +407,7 @@ public function getSupportForGetConnectionId(): bool * * @return bool */ - public function getSupportForCacheFallback(): bool + public function getSupportForCacheSkipOnFailure(): bool { return true; } diff --git a/src/Database/Database.php b/src/Database/Database.php index 21de5df3e..b99f07c49 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -442,14 +442,20 @@ function (?string $value) { /** * Add listener to events + * Passing a null $callback will remove the listener * * @param string $event * @param string $name - * @param callable $callback + * @param ?callable $callback * @return static */ - public function on(string $event, string $name, callable $callback): static + public function on(string $event, string $name, ?callable $callback): static { + if (empty($callback)) { + unset($this->listeners[$event][$name]); + return $this; + } + if (!isset($this->listeners[$event])) { $this->listeners[$event] = []; } @@ -458,20 +464,6 @@ public function on(string $event, string $name, callable $callback): static return $this; } - /** - * Clear all listeners, should only be used for testing. - * - * @return static - */ - public function flushListeners(): static - { - $this->listeners = [ - '*' => [], - ]; - - return $this; - } - /** * Add a transformation to be applied to a query string before an event occurs * @@ -3062,46 +3054,16 @@ public function getDocument(string $collection, string $id, array $queries = [], $attribute['type'] === Database::VAR_RELATIONSHIP ); - $hasTwoWayRelationship = false; - foreach ($relationships as $relationship) { - if ($relationship['options']['twoWay']) { - $hasTwoWayRelationship = true; - break; - } - } - - /** - * Bug with function purity in PHPStan means it thinks $this->map is always empty - * @phpstan-ignore-next-line - */ - foreach ($this->map as $key => $value) { - [$k, $v] = \explode('=>', $key); - $ck = $this->cacheName . '-cache-' . $this->getNamespace() . ':' . $this->adapter->getTenant() . ':map:' . $k; - - try { - $cache = $this->cache->load($ck, self::TTL, $ck); - } catch (Exception $e) { - Console::warning('Failed to load document from cache: ' . $e->getMessage()); - $cache = []; - } - if (empty($cache)) { - $cache = []; - } - if (!\in_array($v, $cache)) { - $cache[] = $v; - try { - $this->cache->save($ck, $cache, $ck); - } catch (Exception $e) { - Console::warning('Failed to save document to cache: ' . $e->getMessage()); - } - } - } + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => + $attribute['type'] === Database::VAR_RELATIONSHIP + ); // Don't save to cache if it's part of a relationship - if (!$hasTwoWayRelationship && empty($relationships)) { + if (empty($relationships)) { try { $this->cache->save($documentCacheKey, $document->getArrayCopy(), $documentCacheHash); - // Add document reference to the collection key $this->cache->save($collectionCacheKey, 'empty', $documentCacheKey); } catch (Exception $e) { Console::warning('Failed to save document to cache: ' . $e->getMessage()); diff --git a/src/Database/Mirror.php b/src/Database/Mirror.php index 08fb04fb5..6ac448b22 100644 --- a/src/Database/Mirror.php +++ b/src/Database/Mirror.php @@ -157,7 +157,7 @@ public function disableValidation(): static return $this; } - public function on(string $event, string $name, callable $callback): static + public function on(string $event, string $name, ?callable $callback): static { $this->source->on($event, $name, $callback); @@ -952,21 +952,4 @@ protected function logError(string $action, \Throwable $err): void $callback($action, $err); } } - - /** - * Clear all listeners, should only be used for testing. - * - * @return static - */ - public function flushListeners(): static - { - $this->listeners = [ - '*' => [], - ]; - - $this->source->flushListeners(); - $this->destination->flushListeners(); - - return $this; - } } diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 1995c00a7..4dd8ae92d 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17684,13 +17684,15 @@ public function testEvents(): void $database->deleteAttribute($collectionId, 'attr1'); $database->deleteCollection($collectionId); $database->delete('hellodb'); - $database->flushListeners(); + + // Remove all listeners + $database->on(Database::EVENT_ALL, 'test', null); }); } public function testCacheFallback(): void { - if (!static::getDatabase()->getAdapter()->getSupportForCacheFallback()) { + if (!static::getDatabase()->getAdapter()->getSupportForCacheSkipOnFailure()) { $this->expectNotToPerformAssertions(); return; } From 8363f6dc030400fe85286144ee67d02da5e33ccb Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 4 Feb 2025 14:23:18 +0900 Subject: [PATCH 19/20] Change $cache to $cached --- src/Database/Database.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index b99f07c49..e82a097ca 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -3000,14 +3000,14 @@ public function getDocument(string $collection, string $id, array $queries = [], } try { - $cache = $this->cache->load($documentCacheKey, self::TTL, $documentCacheHash); + $cached = $this->cache->load($documentCacheKey, self::TTL, $documentCacheHash); } catch (Exception $e) { Console::warning('Warning: Failed to get document from cache: ' . $e->getMessage()); - $cache = null; + $cached = null; } - if ($cache) { - $document = new Document($cache); + if ($cached) { + $document = new Document($cached); if ($collection->getId() !== self::METADATA) { if (!$validator->isValid([ From fc8964e622f9fd4ae478f93d88fd5829729b3be3 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 4 Feb 2025 14:36:06 +0900 Subject: [PATCH 20/20] Address Comments --- src/Database/Adapter/SQLite.php | 10 +--------- src/Database/Database.php | 6 ------ tests/e2e/Adapter/Base.php | 1 + 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/Database/Adapter/SQLite.php b/src/Database/Adapter/SQLite.php index d22b7f694..930562c7c 100644 --- a/src/Database/Adapter/SQLite.php +++ b/src/Database/Adapter/SQLite.php @@ -220,15 +220,7 @@ public function createCollection(string $name, array $attributes = [], array $in $this->createIndex("{$id}_perms", '_index_2', Database::INDEX_KEY, ['_permission', '_type'], [], []); } catch (PDOException $e) { - $e = $this->processException($e); - - if (!($e instanceof Duplicate)) { - $this->getPDO() - ->prepare("DROP TABLE IF EXISTS {$this->getSQLTable($id)}; DROP TABLE IF EXISTS {$this->getSQLTable($id . '_perms')};") - ->execute(); - } - - throw $e; + throw $this->processException($e); } return true; } diff --git a/src/Database/Database.php b/src/Database/Database.php index e82a097ca..872cff833 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -3054,12 +3054,6 @@ public function getDocument(string $collection, string $id, array $queries = [], $attribute['type'] === Database::VAR_RELATIONSHIP ); - $relationships = \array_filter( - $collection->getAttribute('attributes', []), - fn ($attribute) => - $attribute['type'] === Database::VAR_RELATIONSHIP - ); - // Don't save to cache if it's part of a relationship if (empty($relationships)) { try { diff --git a/tests/e2e/Adapter/Base.php b/tests/e2e/Adapter/Base.php index 4dd8ae92d..d35891f0c 100644 --- a/tests/e2e/Adapter/Base.php +++ b/tests/e2e/Adapter/Base.php @@ -17687,6 +17687,7 @@ public function testEvents(): void // Remove all listeners $database->on(Database::EVENT_ALL, 'test', null); + $database->on(Database::EVENT_ALL, 'should-not-execute', null); }); }