From ad37636952d6d2243c1069124b88fa463ddca56a Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 7 May 2026 18:15:55 +0530 Subject: [PATCH] Use separate cache circuit breakers per pool --- app/cli.php | 7 +++++-- app/init/resources.php | 14 +++++++------- app/realtime.php | 19 +++++++++++-------- src/Appwrite/Cache/CircuitBreakerFactory.php | 3 ++- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/app/cli.php b/app/cli.php index f9e12da4d2..21d3280cdb 100644 --- a/app/cli.php +++ b/app/cli.php @@ -74,10 +74,13 @@ $container->set('cache', function ($pools, Telemetry $telemetry) { $adapters = []; foreach ($list as $value) { - $adapters[] = new CachePool($pools->get($value)); + $adapters[] = new CircuitBreakerCache( + new CachePool($pools->get($value)), + CircuitBreakerFactory::create($telemetry, "cache.{$value}") + ); } - return new Cache(new CircuitBreakerCache(new Sharding($adapters), CircuitBreakerFactory::create($telemetry))); + return new Cache(new Sharding($adapters)); }, ['pools', 'telemetry']); $container->set('pools', function (Registry $register) { diff --git a/app/init/resources.php b/app/init/resources.php index 977a4a2147..a989a92459 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -16,7 +16,6 @@ use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; -use Utopia\CircuitBreaker\CircuitBreaker; use Utopia\Config\Config; use Utopia\Console; use Utopia\Database\Adapter\Pool as DatabasePool; @@ -187,21 +186,22 @@ $container->set('getLogsDB', function (Group $pools, Cache $cache, Authorization $container->set('telemetry', fn () => new NoTelemetry()); -$container->set('breakerForCache', fn (Telemetry $telemetry): CircuitBreaker => CircuitBreakerFactory::create($telemetry), ['telemetry']); - -$container->set('cache', function (Group $pools, CircuitBreaker $breaker, Telemetry $telemetry) { +$container->set('cache', function (Group $pools, Telemetry $telemetry) { $list = Config::getParam('pools-cache', []); $adapters = []; foreach ($list as $value) { - $adapters[] = new CachePool($pools->get($value)); + $adapters[] = new CircuitBreakerCache( + new CachePool($pools->get($value)), + CircuitBreakerFactory::create($telemetry, "cache.{$value}") + ); } - $cache = new Cache(new CircuitBreakerCache(new Sharding($adapters), $breaker)); + $cache = new Cache(new Sharding($adapters)); $cache->setTelemetry($telemetry); return $cache; -}, ['pools', 'breakerForCache', 'telemetry']); +}, ['pools', 'telemetry']); $container->set('redis', function () { $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); diff --git a/app/realtime.php b/app/realtime.php index 870e8dc220..b12e24c60a 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -177,23 +177,26 @@ if (!function_exists('getCache')) { $list = Config::getParam('pools-cache', []); $adapters = []; - foreach ($list as $value) { - $adapters[] = new CachePool($pools->get($value)); - } + static $breakers = []; + static $telemetry = null; + static $telemetryResolved = false; - static $breaker = null; - - if ($breaker === null) { + if (!$telemetryResolved) { try { $telemetry = $register->get('telemetry'); } catch (\Throwable) { $telemetry = null; } - $breaker = CircuitBreakerFactory::create($telemetry); + $telemetryResolved = true; } - return $ctx['cache'] = new Cache(new CircuitBreakerCache(new Sharding($adapters), $breaker)); + foreach ($list as $value) { + $breakers[$value] ??= CircuitBreakerFactory::create($telemetry, "cache.{$value}"); + $adapters[] = new CircuitBreakerCache(new CachePool($pools->get($value)), $breakers[$value]); + } + + return $ctx['cache'] = new Cache(new Sharding($adapters)); } } diff --git a/src/Appwrite/Cache/CircuitBreakerFactory.php b/src/Appwrite/Cache/CircuitBreakerFactory.php index 5c587c97ee..6eeae313b0 100644 --- a/src/Appwrite/Cache/CircuitBreakerFactory.php +++ b/src/Appwrite/Cache/CircuitBreakerFactory.php @@ -11,12 +11,13 @@ class CircuitBreakerFactory private const TIMEOUT = 30; private const SUCCESS_THRESHOLD = 2; - public static function create(?Telemetry $telemetry = null): CircuitBreaker + public static function create(?Telemetry $telemetry = null, string $cacheKey = 'cache'): CircuitBreaker { return new CircuitBreaker( threshold: self::THRESHOLD, timeout: self::TIMEOUT, successThreshold: self::SUCCESS_THRESHOLD, + cacheKey: $cacheKey, telemetry: $telemetry, ); }