From 914be48e25be005c99c3c5581abf41ef335ab2b0 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Mon, 2 Feb 2026 18:25:24 +0000 Subject: [PATCH 1/4] fix: add null check for cache adapter --- app/init/registers.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/init/registers.php b/app/init/registers.php index 50d6a99380..402729246c 100644 --- a/app/init/registers.php +++ b/app/init/registers.php @@ -318,8 +318,11 @@ $register->set('pools', function () { default => null }; - $adapter->setMaxRetries(CACHE_RECONNECT_MAX_RETRIES); - $adapter->setRetryDelay(CACHE_RECONNECT_RETRY_DELAY); + if ($adapter !== null) { + $adapter->setMaxRetries(CACHE_RECONNECT_MAX_RETRIES); + $adapter->setRetryDelay(CACHE_RECONNECT_RETRY_DELAY); + } + return $adapter; default: throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation."); From 255098ed9c9e746ecaa891afbb2caa4683948270 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Mon, 2 Feb 2026 18:36:16 +0000 Subject: [PATCH 2/4] use env vars for cache reconnection tests --- tests/e2e/Services/Health/CacheTest.php | 27 +++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/e2e/Services/Health/CacheTest.php b/tests/e2e/Services/Health/CacheTest.php index d47105cd6e..3ba63f4d22 100644 --- a/tests/e2e/Services/Health/CacheTest.php +++ b/tests/e2e/Services/Health/CacheTest.php @@ -5,9 +5,22 @@ namespace Tests\E2E\Services\Health; use Redis; use Utopia\Cache\Adapter\Redis as RedisAdapter; use Utopia\Cache\Cache; +use Utopia\System\System; class CacheTest extends HealthBase { + private static string $redisHost; + private static int $redisPort; + private static string $redisContainer; + + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + self::$redisHost = System::getEnv('_APP_REDIS_HOST', 'redis'); + self::$redisPort = (int) System::getEnv('_APP_REDIS_PORT', '6379'); + self::$redisContainer = System::getEnv('_APP_REDIS_CONTAINER', 'appwrite-redis'); + } + public function testCacheSuccess(): void { $response = $this->callGet('/health/cache'); @@ -21,7 +34,7 @@ class CacheTest extends HealthBase public function testCacheReconnect(): void { $redis = new Redis(); - $redis->connect('redis', 6379); + $redis->connect(self::$redisHost, self::$redisPort); $cache = new Cache( (new RedisAdapter($redis)) ->setMaxRetries(CACHE_RECONNECT_MAX_RETRIES) @@ -30,7 +43,8 @@ class CacheTest extends HealthBase $cache->save('test:reconnect', 'reconnect', 'test:reconnect'); - $stopCmd = 'docker ps -a --filter "name=appwrite-redis" --format "{{.Names}}" | xargs -r docker stop'; + $container = self::$redisContainer; + $stopCmd = "docker ps -a --filter \"name={$container}\" --format \"{{.Names}}\" | xargs -r docker stop"; exec($stopCmd . ' 2>&1', $output, $exitCode); $this->assertEquals(0, $exitCode, "Docker stop failed: $stopCmd\nOutput: " . implode("\n", $output)); sleep(1); @@ -43,7 +57,7 @@ class CacheTest extends HealthBase } } finally { $output = []; - $startCmd = 'docker ps -a --filter "name=appwrite-redis" --format "{{.Names}}" | xargs -r docker start'; + $startCmd = "docker ps -a --filter \"name={$container}\" --format \"{{.Names}}\" | xargs -r docker start"; exec($startCmd . ' 2>&1', $output, $exitCode); $this->assertEquals(0, $exitCode, "Docker start failed: $startCmd\nOutput: " . implode("\n", $output)); } @@ -61,7 +75,7 @@ class CacheTest extends HealthBase public function testCacheReconnectPersistent(): void { $redis = new Redis(); - $redis->pconnect('redis', 6379); + $redis->pconnect(self::$redisHost, self::$redisPort); $cache = new Cache( (new RedisAdapter($redis)) ->setMaxRetries(CACHE_RECONNECT_MAX_RETRIES) @@ -70,7 +84,8 @@ class CacheTest extends HealthBase $cache->save('test:reconnect_persistent', 'reconnect_persistent', 'test:reconnect_persistent'); - $stopCmd = 'docker ps -a --filter "name=appwrite-redis" --format "{{.Names}}" | xargs -r docker stop'; + $container = self::$redisContainer; + $stopCmd = "docker ps -a --filter \"name={$container}\" --format \"{{.Names}}\" | xargs -r docker stop"; exec($stopCmd . ' 2>&1', $output, $exitCode); $this->assertEquals(0, $exitCode, "Docker stop failed: $stopCmd\nOutput: " . implode("\n", $output)); sleep(1); @@ -83,7 +98,7 @@ class CacheTest extends HealthBase } } finally { $output = []; - $startCmd = 'docker ps -a --filter "name=appwrite-redis" --format "{{.Names}}" | xargs -r docker start'; + $startCmd = "docker ps -a --filter \"name={$container}\" --format \"{{.Names}}\" | xargs -r docker start"; exec($startCmd . ' 2>&1', $output, $exitCode); $this->assertEquals(0, $exitCode, "Docker start failed: $startCmd\nOutput: " . implode("\n", $output)); } From 8117ab9542425da5b9ee913b8f1378065a6f66d2 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Mon, 2 Feb 2026 19:07:50 +0000 Subject: [PATCH 3/4] simplify CacheTest to match other Health tests --- tests/e2e/Services/Health/CacheTest.php | 96 ------------------------- 1 file changed, 96 deletions(-) diff --git a/tests/e2e/Services/Health/CacheTest.php b/tests/e2e/Services/Health/CacheTest.php index 3ba63f4d22..0b825b2dba 100644 --- a/tests/e2e/Services/Health/CacheTest.php +++ b/tests/e2e/Services/Health/CacheTest.php @@ -2,25 +2,8 @@ namespace Tests\E2E\Services\Health; -use Redis; -use Utopia\Cache\Adapter\Redis as RedisAdapter; -use Utopia\Cache\Cache; -use Utopia\System\System; - class CacheTest extends HealthBase { - private static string $redisHost; - private static int $redisPort; - private static string $redisContainer; - - public static function setUpBeforeClass(): void - { - parent::setUpBeforeClass(); - self::$redisHost = System::getEnv('_APP_REDIS_HOST', 'redis'); - self::$redisPort = (int) System::getEnv('_APP_REDIS_PORT', '6379'); - self::$redisContainer = System::getEnv('_APP_REDIS_CONTAINER', 'appwrite-redis'); - } - public function testCacheSuccess(): void { $response = $this->callGet('/health/cache'); @@ -30,83 +13,4 @@ class CacheTest extends HealthBase $this->assertLessThan(100, $response['body']['statuses'][0]['ping']); $this->assertEquals('pass', $response['body']['statuses'][0]['status']); } - - public function testCacheReconnect(): void - { - $redis = new Redis(); - $redis->connect(self::$redisHost, self::$redisPort); - $cache = new Cache( - (new RedisAdapter($redis)) - ->setMaxRetries(CACHE_RECONNECT_MAX_RETRIES) - ->setRetryDelay(CACHE_RECONNECT_RETRY_DELAY) - ); - - $cache->save('test:reconnect', 'reconnect', 'test:reconnect'); - - $container = self::$redisContainer; - $stopCmd = "docker ps -a --filter \"name={$container}\" --format \"{{.Names}}\" | xargs -r docker stop"; - exec($stopCmd . ' 2>&1', $output, $exitCode); - $this->assertEquals(0, $exitCode, "Docker stop failed: $stopCmd\nOutput: " . implode("\n", $output)); - sleep(1); - - try { - try { - $cache->load('test:reconnect', 5); - $this->fail('Redis connection should have failed'); - } catch (\RedisException $e) { - } - } finally { - $output = []; - $startCmd = "docker ps -a --filter \"name={$container}\" --format \"{{.Names}}\" | xargs -r docker start"; - exec($startCmd . ' 2>&1', $output, $exitCode); - $this->assertEquals(0, $exitCode, "Docker start failed: $startCmd\nOutput: " . implode("\n", $output)); - } - - $this->assertEventually(function () use ($cache) { - $this->assertEquals('reconnect', $cache->save('test:reconnect', 'reconnect', 'test:reconnect')); - $this->assertEquals('reconnect', $cache->load('test:reconnect', 5)); - return true; - }, 10000, 1000); - } - - /** - * @depends testCacheReconnect - */ - public function testCacheReconnectPersistent(): void - { - $redis = new Redis(); - $redis->pconnect(self::$redisHost, self::$redisPort); - $cache = new Cache( - (new RedisAdapter($redis)) - ->setMaxRetries(CACHE_RECONNECT_MAX_RETRIES) - ->setRetryDelay(CACHE_RECONNECT_RETRY_DELAY) - ); - - $cache->save('test:reconnect_persistent', 'reconnect_persistent', 'test:reconnect_persistent'); - - $container = self::$redisContainer; - $stopCmd = "docker ps -a --filter \"name={$container}\" --format \"{{.Names}}\" | xargs -r docker stop"; - exec($stopCmd . ' 2>&1', $output, $exitCode); - $this->assertEquals(0, $exitCode, "Docker stop failed: $stopCmd\nOutput: " . implode("\n", $output)); - sleep(1); - - try { - try { - $cache->load('test:reconnect_persistent', 5); - $this->fail('Redis connection should have failed'); - } catch (\RedisException $e) { - } - } finally { - $output = []; - $startCmd = "docker ps -a --filter \"name={$container}\" --format \"{{.Names}}\" | xargs -r docker start"; - exec($startCmd . ' 2>&1', $output, $exitCode); - $this->assertEquals(0, $exitCode, "Docker start failed: $startCmd\nOutput: " . implode("\n", $output)); - } - - $this->assertEventually(function () use ($cache) { - $this->assertEquals('reconnect_persistent', $cache->save('test:reconnect_persistent', 'reconnect_persistent', 'test:reconnect_persistent')); - $this->assertEquals('reconnect_persistent', $cache->load('test:reconnect_persistent', 5)); - return true; - }, 10000, 1000); - } } From cbe7ce7269a41ebbf301762266dbc323c390bde9 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Mon, 2 Feb 2026 21:47:46 +0000 Subject: [PATCH 4/4] fix merge conflict in composer.lock --- composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index 562ffefe70..10e68b7f63 100644 --- a/composer.lock +++ b/composer.lock @@ -9052,7 +9052,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": {