From 6612e709e30cea3eff2c984cabdccb84ed6c0a32 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Tue, 17 Dec 2024 16:25:03 -0400 Subject: [PATCH 01/11] feat: add the getKeysByPattern method --- ProcessMaker/Cache/CacheABC.php | 62 ++++++++++++++++ tests/Feature/Cache/CacheABCTest.php | 107 +++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 ProcessMaker/Cache/CacheABC.php create mode 100644 tests/Feature/Cache/CacheABCTest.php diff --git a/ProcessMaker/Cache/CacheABC.php b/ProcessMaker/Cache/CacheABC.php new file mode 100644 index 0000000000..74db515f3b --- /dev/null +++ b/ProcessMaker/Cache/CacheABC.php @@ -0,0 +1,62 @@ +connection = config('cache.default'); + $this->prefix = config('cache.prefix'); + } + + /** + * Retrieve an array of cache keys that match a specific pattern. + * + * @param string $pattern The pattern to match. + * + * @return array An array of cache keys that match the pattern. + */ + public function getKeysByPattern(string $pattern): array + { + if (!in_array($this->connection, self::AVAILABLE_CONNECTIONS)) { + throw new Exception('`getKeysByPattern` method only supports Redis connections.'); + } + + try { + // Get all keys + $keys = Redis::connection($this->connection)->keys($this->prefix . '*'); + // Filter keys by pattern + return array_filter($keys, fn ($key) => preg_match('/' . $pattern . '/', $key)); + } catch (Exception $e) { + Log::info('CacheABC' . $e->getMessage()); + } + + return []; + } +} diff --git a/tests/Feature/Cache/CacheABCTest.php b/tests/Feature/Cache/CacheABCTest.php new file mode 100644 index 0000000000..a923bd385c --- /dev/null +++ b/tests/Feature/Cache/CacheABCTest.php @@ -0,0 +1,107 @@ +set('cache.default', 'redis'); + } + + protected function tearDown(): void + { + config()->set('cache.default', 'array'); + + parent::tearDown(); + } + + public function testGetKeysByPatternWithValidConnectionAndMatchingKeys() + { + $this->cacheABC = $this->getMockForAbstractClass(CacheABC::class); + + $pattern = 'test-pattern'; + $prefix = config('cache.prefix'); + $keys = [$prefix . ':test-pattern:1', $prefix . ':test-pattern:2']; + + Redis::shouldReceive('connection') + ->with('redis') + ->andReturnSelf(); + + Redis::shouldReceive('keys') + ->with($prefix . '*') + ->andReturn($keys); + + $result = $this->cacheABC->getKeysByPattern($pattern); + + $this->assertCount(2, $result); + $this->assertEquals($keys, $result); + } + + public function testGetKeysByPatternWithValidConnectionAndNoMatchingKeys() + { + $this->cacheABC = $this->getMockForAbstractClass(CacheABC::class); + + $pattern = 'non-matching-pattern'; + $prefix = config('cache.prefix'); + $keys = [$prefix . ':test-pattern:1', $prefix . ':test-pattern:2']; + + Redis::shouldReceive('connection') + ->with('redis') + ->andReturnSelf(); + + Redis::shouldReceive('keys') + ->with($prefix . '*') + ->andReturn($keys); + + $result = $this->cacheABC->getKeysByPattern($pattern); + + $this->assertCount(0, $result); + } + + public function testGetKeysByPatternWithInvalidConnection() + { + config()->set('cache.default', 'array'); + + $this->cacheABC = $this->getMockForAbstractClass(CacheABC::class); + + $this->expectException(Exception::class); + $this->expectExceptionMessage('`getKeysByPattern` method only supports Redis connections.'); + + $this->cacheABC->getKeysByPattern('pattern'); + } + + public function testGetKeysByPatternWithExceptionDuringKeyRetrieval() + { + $this->cacheABC = $this->getMockForAbstractClass(CacheABC::class); + + $pattern = 'test-pattern'; + $prefix = config('cache.prefix'); + + Redis::shouldReceive('connection') + ->with('redis') + ->andReturnSelf(); + + Redis::shouldReceive('keys') + ->with($prefix . '*') + ->andThrow(new Exception('Redis error')); + + Log::shouldReceive('info') + ->with('CacheABC' . 'Redis error') + ->once(); + + $result = $this->cacheABC->getKeysByPattern($pattern); + + $this->assertCount(0, $result); + } +} From af794c93aaf793883190b9c20604b97048fbaf41 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Tue, 17 Dec 2024 16:27:32 -0400 Subject: [PATCH 02/11] feat: enhance SettingCacheManager to extend CacheABC and improve cache driver handling --- .../Cache/Settings/SettingCacheManager.php | 44 ++++++++++--------- tests/Feature/Cache/SettingCacheTest.php | 9 +++- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/ProcessMaker/Cache/Settings/SettingCacheManager.php b/ProcessMaker/Cache/Settings/SettingCacheManager.php index 3ace2bc469..40767f5ee0 100644 --- a/ProcessMaker/Cache/Settings/SettingCacheManager.php +++ b/ProcessMaker/Cache/Settings/SettingCacheManager.php @@ -3,37 +3,47 @@ namespace ProcessMaker\Cache\Settings; use Illuminate\Cache\CacheManager; +use Illuminate\Cache\Repository; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Redis; +use ProcessMaker\Cache\CacheABC; use ProcessMaker\Cache\CacheInterface; -class SettingCacheManager implements CacheInterface +class SettingCacheManager extends CacheABC implements CacheInterface { const DEFAULT_CACHE_DRIVER = 'cache_settings'; - protected CacheManager $cacheManager; + protected Repository $cacheManager; public function __construct(CacheManager $cacheManager) { - $driver = $this->determineCacheDriver(); + parent::__construct(); - $this->cacheManager = $cacheManager; - $this->cacheManager->store($driver); + $this->setCacheDriver($cacheManager); } /** - * Determine the cache driver to use. + * Determine and set the cache driver to use. * - * @return string + * @param CacheManager $cacheManager + * + * @return void */ - private function determineCacheDriver(): string + private function setCacheDriver(CacheManager $cacheManager): void { $defaultCache = config('cache.default'); - if (in_array($defaultCache, ['redis', 'cache_settings'])) { - return self::DEFAULT_CACHE_DRIVER; + $isAvailableConnection = in_array($defaultCache, self::AVAILABLE_CONNECTIONS); + + if ($isAvailableConnection) { + $defaultCache = self::DEFAULT_CACHE_DRIVER; } - return $defaultCache; + $this->cacheManager = $cacheManager->store($defaultCache); + + if ($isAvailableConnection) { + $this->connection = $this->cacheManager->connection()->getName(); + $this->prefix = $this->cacheManager->getPrefix(); + } } /** @@ -140,22 +150,16 @@ public function clear(): bool */ public function clearBy(string $pattern): void { - $defaultDriver = $this->cacheManager->getDefaultDriver(); - - if ($defaultDriver !== 'cache_settings') { + if ($this->connection !== 'cache_settings') { throw new SettingCacheException('The cache driver must be Redis.'); } try { - // get the connection name from the cache manager - $connection = $this->cacheManager->connection()->getName(); - // Get all keys - $keys = Redis::connection($connection)->keys($this->cacheManager->getPrefix() . '*'); // Filter keys by pattern - $matchedKeys = array_filter($keys, fn ($key) => preg_match('/' . $pattern . '/', $key)); + $matchedKeys = $this->getKeysByPattern($pattern); if (!empty($matchedKeys)) { - Redis::connection($connection)->del($matchedKeys); + Redis::connection($this->connection)->del($matchedKeys); } } catch (\Exception $e) { Log::error('SettingCacheException' . $e->getMessage()); diff --git a/tests/Feature/Cache/SettingCacheTest.php b/tests/Feature/Cache/SettingCacheTest.php index 3016ab3867..56dd28d170 100644 --- a/tests/Feature/Cache/SettingCacheTest.php +++ b/tests/Feature/Cache/SettingCacheTest.php @@ -192,8 +192,13 @@ public function testClearByPatternWithFailedDeletion() \SettingCache::set('test_pattern:1', 1); \SettingCache::set('test_pattern:2', 2); + // Set up the expectation for the connection method + Redis::shouldReceive('connection') + ->with('cache_settings') + ->andReturnSelf(); + Redis::shouldReceive('keys') - ->with('*settings:*') + ->with('settings:*') ->andReturn($keys); Redis::shouldReceive('del') @@ -210,7 +215,7 @@ public function testTryClearByPatternWithNonRedisDriver() { config()->set('cache.default', 'array'); - $this->expectException(SettingCacheException::class); + $this->expectException(\Exception::class); $this->expectExceptionMessage('The cache driver must be Redis.'); \SettingCache::clearBy('pattern'); From aec1487cb4c6d9da9ee7141c012c294c39cd5237 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Tue, 17 Dec 2024 17:01:32 -0400 Subject: [PATCH 03/11] feat: add console command to clear settings cache --- .../Console/Commands/CacheSettingClear.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 ProcessMaker/Console/Commands/CacheSettingClear.php diff --git a/ProcessMaker/Console/Commands/CacheSettingClear.php b/ProcessMaker/Console/Commands/CacheSettingClear.php new file mode 100644 index 0000000000..0aade4ef09 --- /dev/null +++ b/ProcessMaker/Console/Commands/CacheSettingClear.php @@ -0,0 +1,30 @@ + Date: Tue, 17 Dec 2024 17:21:56 -0400 Subject: [PATCH 04/11] refactor: rename CacheABC to CacheManagerBase --- .../{CacheABC.php => CacheManagerBase.php} | 2 +- .../Cache/Settings/SettingCacheManager.php | 4 ++-- ...heABCTest.php => CacheManagerBaseTest.php} | 22 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) rename ProcessMaker/Cache/{CacheABC.php => CacheManagerBase.php} (97%) rename tests/Feature/Cache/{CacheABCTest.php => CacheManagerBaseTest.php} (75%) diff --git a/ProcessMaker/Cache/CacheABC.php b/ProcessMaker/Cache/CacheManagerBase.php similarity index 97% rename from ProcessMaker/Cache/CacheABC.php rename to ProcessMaker/Cache/CacheManagerBase.php index 74db515f3b..80552bfdf0 100644 --- a/ProcessMaker/Cache/CacheABC.php +++ b/ProcessMaker/Cache/CacheManagerBase.php @@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Redis; -abstract class CacheABC +abstract class CacheManagerBase { /** * The cache connection. diff --git a/ProcessMaker/Cache/Settings/SettingCacheManager.php b/ProcessMaker/Cache/Settings/SettingCacheManager.php index 40767f5ee0..b5ae641a3e 100644 --- a/ProcessMaker/Cache/Settings/SettingCacheManager.php +++ b/ProcessMaker/Cache/Settings/SettingCacheManager.php @@ -6,10 +6,10 @@ use Illuminate\Cache\Repository; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Redis; -use ProcessMaker\Cache\CacheABC; use ProcessMaker\Cache\CacheInterface; +use ProcessMaker\Cache\CacheManagerBase; -class SettingCacheManager extends CacheABC implements CacheInterface +class SettingCacheManager extends CacheManagerBase implements CacheInterface { const DEFAULT_CACHE_DRIVER = 'cache_settings'; diff --git a/tests/Feature/Cache/CacheABCTest.php b/tests/Feature/Cache/CacheManagerBaseTest.php similarity index 75% rename from tests/Feature/Cache/CacheABCTest.php rename to tests/Feature/Cache/CacheManagerBaseTest.php index a923bd385c..12d106d982 100644 --- a/tests/Feature/Cache/CacheABCTest.php +++ b/tests/Feature/Cache/CacheManagerBaseTest.php @@ -5,12 +5,12 @@ use Exception; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Redis; -use ProcessMaker\Cache\CacheABC; +use ProcessMaker\Cache\CacheManagerBase; use Tests\TestCase; -class CacheABCTest extends TestCase +class CacheManagerBaseTest extends TestCase { - protected $cacheABC; + protected $cacheManagerBase; protected function setUp(): void { @@ -28,7 +28,7 @@ protected function tearDown(): void public function testGetKeysByPatternWithValidConnectionAndMatchingKeys() { - $this->cacheABC = $this->getMockForAbstractClass(CacheABC::class); + $this->cacheManagerBase = $this->getMockForAbstractClass(CacheManagerBase::class); $pattern = 'test-pattern'; $prefix = config('cache.prefix'); @@ -42,7 +42,7 @@ public function testGetKeysByPatternWithValidConnectionAndMatchingKeys() ->with($prefix . '*') ->andReturn($keys); - $result = $this->cacheABC->getKeysByPattern($pattern); + $result = $this->cacheManagerBase->getKeysByPattern($pattern); $this->assertCount(2, $result); $this->assertEquals($keys, $result); @@ -50,7 +50,7 @@ public function testGetKeysByPatternWithValidConnectionAndMatchingKeys() public function testGetKeysByPatternWithValidConnectionAndNoMatchingKeys() { - $this->cacheABC = $this->getMockForAbstractClass(CacheABC::class); + $this->cacheManagerBase = $this->getMockForAbstractClass(CacheManagerBase::class); $pattern = 'non-matching-pattern'; $prefix = config('cache.prefix'); @@ -64,7 +64,7 @@ public function testGetKeysByPatternWithValidConnectionAndNoMatchingKeys() ->with($prefix . '*') ->andReturn($keys); - $result = $this->cacheABC->getKeysByPattern($pattern); + $result = $this->cacheManagerBase->getKeysByPattern($pattern); $this->assertCount(0, $result); } @@ -73,17 +73,17 @@ public function testGetKeysByPatternWithInvalidConnection() { config()->set('cache.default', 'array'); - $this->cacheABC = $this->getMockForAbstractClass(CacheABC::class); + $this->cacheManagerBase = $this->getMockForAbstractClass(CacheManagerBase::class); $this->expectException(Exception::class); $this->expectExceptionMessage('`getKeysByPattern` method only supports Redis connections.'); - $this->cacheABC->getKeysByPattern('pattern'); + $this->cacheManagerBase->getKeysByPattern('pattern'); } public function testGetKeysByPatternWithExceptionDuringKeyRetrieval() { - $this->cacheABC = $this->getMockForAbstractClass(CacheABC::class); + $this->cacheManagerBase = $this->getMockForAbstractClass(CacheManagerBase::class); $pattern = 'test-pattern'; $prefix = config('cache.prefix'); @@ -100,7 +100,7 @@ public function testGetKeysByPatternWithExceptionDuringKeyRetrieval() ->with('CacheABC' . 'Redis error') ->once(); - $result = $this->cacheABC->getKeysByPattern($pattern); + $result = $this->cacheManagerBase->getKeysByPattern($pattern); $this->assertCount(0, $result); } From df09a430d794005a424b94d618cc6ffe0ac99da6 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Tue, 17 Dec 2024 18:26:31 -0400 Subject: [PATCH 05/11] fix(cr): introduce CacheManagerException and update error handling in CacheManagerBase --- ProcessMaker/Cache/CacheManagerBase.php | 4 ++-- ProcessMaker/Cache/CacheManagerException.php | 9 +++++++++ ProcessMaker/Cache/Settings/SettingCacheManager.php | 2 ++ tests/Feature/Cache/CacheManagerBaseTest.php | 5 +++-- tests/Feature/Cache/SettingCacheTest.php | 2 +- 5 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 ProcessMaker/Cache/CacheManagerException.php diff --git a/ProcessMaker/Cache/CacheManagerBase.php b/ProcessMaker/Cache/CacheManagerBase.php index 80552bfdf0..17f8cd4cf2 100644 --- a/ProcessMaker/Cache/CacheManagerBase.php +++ b/ProcessMaker/Cache/CacheManagerBase.php @@ -45,7 +45,7 @@ public function __construct() public function getKeysByPattern(string $pattern): array { if (!in_array($this->connection, self::AVAILABLE_CONNECTIONS)) { - throw new Exception('`getKeysByPattern` method only supports Redis connections.'); + throw new CacheManagerException('`getKeysByPattern` method only supports Redis connections.'); } try { @@ -54,7 +54,7 @@ public function getKeysByPattern(string $pattern): array // Filter keys by pattern return array_filter($keys, fn ($key) => preg_match('/' . $pattern . '/', $key)); } catch (Exception $e) { - Log::info('CacheABC' . $e->getMessage()); + Log::info('CacheManagerBase: ' . $e->getMessage()); } return []; diff --git a/ProcessMaker/Cache/CacheManagerException.php b/ProcessMaker/Cache/CacheManagerException.php new file mode 100644 index 0000000000..e0352c28f7 --- /dev/null +++ b/ProcessMaker/Cache/CacheManagerException.php @@ -0,0 +1,9 @@ + ' . $defaultCache); $isAvailableConnection = in_array($defaultCache, self::AVAILABLE_CONNECTIONS); if ($isAvailableConnection) { @@ -150,6 +151,7 @@ public function clear(): bool */ public function clearBy(string $pattern): void { + dump('connection' . $this->connection); if ($this->connection !== 'cache_settings') { throw new SettingCacheException('The cache driver must be Redis.'); } diff --git a/tests/Feature/Cache/CacheManagerBaseTest.php b/tests/Feature/Cache/CacheManagerBaseTest.php index 12d106d982..b051663f0b 100644 --- a/tests/Feature/Cache/CacheManagerBaseTest.php +++ b/tests/Feature/Cache/CacheManagerBaseTest.php @@ -6,6 +6,7 @@ use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Redis; use ProcessMaker\Cache\CacheManagerBase; +use ProcessMaker\Cache\CacheManagerException; use Tests\TestCase; class CacheManagerBaseTest extends TestCase @@ -75,7 +76,7 @@ public function testGetKeysByPatternWithInvalidConnection() $this->cacheManagerBase = $this->getMockForAbstractClass(CacheManagerBase::class); - $this->expectException(Exception::class); + $this->expectException(CacheManagerException::class); $this->expectExceptionMessage('`getKeysByPattern` method only supports Redis connections.'); $this->cacheManagerBase->getKeysByPattern('pattern'); @@ -97,7 +98,7 @@ public function testGetKeysByPatternWithExceptionDuringKeyRetrieval() ->andThrow(new Exception('Redis error')); Log::shouldReceive('info') - ->with('CacheABC' . 'Redis error') + ->with('CacheManagerBase: ' . 'Redis error') ->once(); $result = $this->cacheManagerBase->getKeysByPattern($pattern); diff --git a/tests/Feature/Cache/SettingCacheTest.php b/tests/Feature/Cache/SettingCacheTest.php index 56dd28d170..17b8066468 100644 --- a/tests/Feature/Cache/SettingCacheTest.php +++ b/tests/Feature/Cache/SettingCacheTest.php @@ -215,7 +215,7 @@ public function testTryClearByPatternWithNonRedisDriver() { config()->set('cache.default', 'array'); - $this->expectException(\Exception::class); + $this->expectException(SettingCacheException::class); $this->expectExceptionMessage('The cache driver must be Redis.'); \SettingCache::clearBy('pattern'); From 379c687471bffd53eecdc2101fb24573bea93752 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Wed, 18 Dec 2024 09:17:00 -0400 Subject: [PATCH 06/11] fix: improve cache driver handling --- .../Cache/Settings/SettingCacheManager.php | 34 ++++++++++--------- tests/Feature/Cache/SettingCacheTest.php | 2 ++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/ProcessMaker/Cache/Settings/SettingCacheManager.php b/ProcessMaker/Cache/Settings/SettingCacheManager.php index d3a66f61e9..b7e26d9cc8 100644 --- a/ProcessMaker/Cache/Settings/SettingCacheManager.php +++ b/ProcessMaker/Cache/Settings/SettingCacheManager.php @@ -19,7 +19,18 @@ public function __construct(CacheManager $cacheManager) { parent::__construct(); - $this->setCacheDriver($cacheManager); + // $this->setCacheDriver($cacheManager); + $driver = $this->setCacheDriver(); + + $this->cacheManager = $cacheManager->store($driver); + + if (in_array($driver, ['redis', 'cache_settings'])) { + $this->connection = $this->cacheManager->connection()->getName(); + } else { + $this->connection = $driver; + } + + $this->prefix = $this->cacheManager->getPrefix(); } /** @@ -27,24 +38,15 @@ public function __construct(CacheManager $cacheManager) * * @param CacheManager $cacheManager * - * @return void + * @return string */ - private function setCacheDriver(CacheManager $cacheManager): void + private function setCacheDriver(): string { $defaultCache = config('cache.default'); - dump('$defaultCache => ' . $defaultCache); - $isAvailableConnection = in_array($defaultCache, self::AVAILABLE_CONNECTIONS); - - if ($isAvailableConnection) { - $defaultCache = self::DEFAULT_CACHE_DRIVER; - } - - $this->cacheManager = $cacheManager->store($defaultCache); - - if ($isAvailableConnection) { - $this->connection = $this->cacheManager->connection()->getName(); - $this->prefix = $this->cacheManager->getPrefix(); + if (in_array($defaultCache, ['redis', 'cache_settings'])) { + return self::DEFAULT_CACHE_DRIVER; } + return $defaultCache; } /** @@ -151,7 +153,7 @@ public function clear(): bool */ public function clearBy(string $pattern): void { - dump('connection' . $this->connection); + dump('connection -> ' . $this->connection); if ($this->connection !== 'cache_settings') { throw new SettingCacheException('The cache driver must be Redis.'); } diff --git a/tests/Feature/Cache/SettingCacheTest.php b/tests/Feature/Cache/SettingCacheTest.php index 17b8066468..4075f5bd60 100644 --- a/tests/Feature/Cache/SettingCacheTest.php +++ b/tests/Feature/Cache/SettingCacheTest.php @@ -142,6 +142,8 @@ public function testGetSettingByNotExistingKey() public function testClearByPattern() { + config()->set('cache.default', 'cache_settings'); + \SettingCache::set('password-policies.users_can_change', 1); \SettingCache::set('password-policies.numbers', 2); \SettingCache::set('password-policies.uppercase', 3); From 48f0e56971fbbf6313158b69b8e50b3cd658e67b Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Wed, 18 Dec 2024 12:56:58 -0400 Subject: [PATCH 07/11] refactor: update SettingCacheManager --- .../Cache/Settings/SettingCacheManager.php | 39 ++++++++++++------- tests/Feature/Cache/SettingCacheTest.php | 2 + 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/ProcessMaker/Cache/Settings/SettingCacheManager.php b/ProcessMaker/Cache/Settings/SettingCacheManager.php index b7e26d9cc8..2dc0b11696 100644 --- a/ProcessMaker/Cache/Settings/SettingCacheManager.php +++ b/ProcessMaker/Cache/Settings/SettingCacheManager.php @@ -17,10 +17,8 @@ class SettingCacheManager extends CacheManagerBase implements CacheInterface public function __construct(CacheManager $cacheManager) { - parent::__construct(); - - // $this->setCacheDriver($cacheManager); - $driver = $this->setCacheDriver(); + $this->setCacheDriver($cacheManager); + /* $driver = $this->setCacheDriver(); $this->cacheManager = $cacheManager->store($driver); @@ -30,23 +28,37 @@ public function __construct(CacheManager $cacheManager) $this->connection = $driver; } - $this->prefix = $this->cacheManager->getPrefix(); + $this->prefix = $this->cacheManager->getPrefix(); */ } - /** - * Determine and set the cache driver to use. - * - * @param CacheManager $cacheManager - * - * @return string - */ - private function setCacheDriver(): string + + /* private function setCacheDriver(): string { $defaultCache = config('cache.default'); if (in_array($defaultCache, ['redis', 'cache_settings'])) { return self::DEFAULT_CACHE_DRIVER; } return $defaultCache; + } */ + + private function setCacheDriver(CacheManager $cacheManager): void + { + $defaultCache = config('cache.default'); + $isAvailableConnection = in_array($defaultCache, self::AVAILABLE_CONNECTIONS); + + if ($isAvailableConnection) { + $defaultCache = self::DEFAULT_CACHE_DRIVER; + } + + $this->cacheManager = $cacheManager->store($defaultCache); + + if ($isAvailableConnection) { + $this->connection = $this->cacheManager->connection()->getName(); + } else { + $this->connection = $defaultCache; + } + + $this->prefix = $this->cacheManager->getPrefix(); } /** @@ -154,6 +166,7 @@ public function clear(): bool public function clearBy(string $pattern): void { dump('connection -> ' . $this->connection); + if ($this->connection !== 'cache_settings') { throw new SettingCacheException('The cache driver must be Redis.'); } diff --git a/tests/Feature/Cache/SettingCacheTest.php b/tests/Feature/Cache/SettingCacheTest.php index 4075f5bd60..5c13e9a6d9 100644 --- a/tests/Feature/Cache/SettingCacheTest.php +++ b/tests/Feature/Cache/SettingCacheTest.php @@ -144,6 +144,8 @@ public function testClearByPattern() { config()->set('cache.default', 'cache_settings'); + dump('default cache ->> ' . config('cache.default')); + \SettingCache::set('password-policies.users_can_change', 1); \SettingCache::set('password-policies.numbers', 2); \SettingCache::set('password-policies.uppercase', 3); From 0218c1cf4e46fa574ccf0a9aad274a6f59d2c0eb Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Wed, 18 Dec 2024 14:11:35 -0400 Subject: [PATCH 08/11] refactor: simplify cache driver handling --- .../Cache/Settings/SettingCacheManager.php | 61 ++++++++----------- tests/Feature/Cache/SettingCacheTest.php | 4 -- 2 files changed, 24 insertions(+), 41 deletions(-) diff --git a/ProcessMaker/Cache/Settings/SettingCacheManager.php b/ProcessMaker/Cache/Settings/SettingCacheManager.php index 2dc0b11696..1540c20468 100644 --- a/ProcessMaker/Cache/Settings/SettingCacheManager.php +++ b/ProcessMaker/Cache/Settings/SettingCacheManager.php @@ -13,51 +13,36 @@ class SettingCacheManager extends CacheManagerBase implements CacheInterface { const DEFAULT_CACHE_DRIVER = 'cache_settings'; + protected CacheManager $manager; + protected Repository $cacheManager; public function __construct(CacheManager $cacheManager) { - $this->setCacheDriver($cacheManager); - /* $driver = $this->setCacheDriver(); - - $this->cacheManager = $cacheManager->store($driver); + $this->manager = $cacheManager; - if (in_array($driver, ['redis', 'cache_settings'])) { - $this->connection = $this->cacheManager->connection()->getName(); - } else { - $this->connection = $driver; - } - - $this->prefix = $this->cacheManager->getPrefix(); */ + $this->setCacheDriver(); } - - /* private function setCacheDriver(): string - { - $defaultCache = config('cache.default'); - if (in_array($defaultCache, ['redis', 'cache_settings'])) { - return self::DEFAULT_CACHE_DRIVER; - } - return $defaultCache; - } */ - - private function setCacheDriver(CacheManager $cacheManager): void + /** + * Determine and set the cache driver to use. + * + * @param CacheManager $cacheManager + * + * @return void + */ + private function setCacheDriver(): void { $defaultCache = config('cache.default'); $isAvailableConnection = in_array($defaultCache, self::AVAILABLE_CONNECTIONS); - if ($isAvailableConnection) { - $defaultCache = self::DEFAULT_CACHE_DRIVER; - } - - $this->cacheManager = $cacheManager->store($defaultCache); - - if ($isAvailableConnection) { - $this->connection = $this->cacheManager->connection()->getName(); - } else { - $this->connection = $defaultCache; - } - + // Set the cache driver to use + $cacheDriver = $isAvailableConnection ? self::DEFAULT_CACHE_DRIVER : $defaultCache; + // Store the cache driver + $this->cacheManager = $this->manager->store($cacheDriver); + // Store the cache connection + $this->connection = $isAvailableConnection ? $this->manager->getDefaultDriver() : $defaultCache; + // Store the cache prefix $this->prefix = $this->cacheManager->getPrefix(); } @@ -165,9 +150,9 @@ public function clear(): bool */ public function clearBy(string $pattern): void { - dump('connection -> ' . $this->connection); + $defaultDriver = $this->manager->getDefaultDriver(); - if ($this->connection !== 'cache_settings') { + if ($defaultDriver !== 'cache_settings') { throw new SettingCacheException('The cache driver must be Redis.'); } @@ -176,11 +161,13 @@ public function clearBy(string $pattern): void $matchedKeys = $this->getKeysByPattern($pattern); if (!empty($matchedKeys)) { - Redis::connection($this->connection)->del($matchedKeys); + Redis::connection($defaultDriver)->del($matchedKeys); } } catch (\Exception $e) { Log::error('SettingCacheException' . $e->getMessage()); + dump('exception => ' . $e->getMessage()); + throw new SettingCacheException('Failed to delete keys.'); } } diff --git a/tests/Feature/Cache/SettingCacheTest.php b/tests/Feature/Cache/SettingCacheTest.php index 5c13e9a6d9..17b8066468 100644 --- a/tests/Feature/Cache/SettingCacheTest.php +++ b/tests/Feature/Cache/SettingCacheTest.php @@ -142,10 +142,6 @@ public function testGetSettingByNotExistingKey() public function testClearByPattern() { - config()->set('cache.default', 'cache_settings'); - - dump('default cache ->> ' . config('cache.default')); - \SettingCache::set('password-policies.users_can_change', 1); \SettingCache::set('password-policies.numbers', 2); \SettingCache::set('password-policies.uppercase', 3); From 5f4c607eb13a93aa7ac87128f0a6790e31f1ea16 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Wed, 18 Dec 2024 16:26:08 -0400 Subject: [PATCH 09/11] feat: enhance getKeysByPattern method to accept a connection --- ProcessMaker/Cache/CacheManagerBase.php | 15 ++++++++++++++- .../Cache/Settings/SettingCacheManager.php | 2 +- .../Console/Commands/CacheSettingClear.php | 2 ++ tests/Feature/Cache/SettingCacheTest.php | 11 +++-------- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/ProcessMaker/Cache/CacheManagerBase.php b/ProcessMaker/Cache/CacheManagerBase.php index 17f8cd4cf2..ec593ad80b 100644 --- a/ProcessMaker/Cache/CacheManagerBase.php +++ b/ProcessMaker/Cache/CacheManagerBase.php @@ -39,21 +39,34 @@ public function __construct() * Retrieve an array of cache keys that match a specific pattern. * * @param string $pattern The pattern to match. + * @param string|null $connection The cache connection to use. * * @return array An array of cache keys that match the pattern. */ - public function getKeysByPattern(string $pattern): array + public function getKeysByPattern(string $pattern, string $connection = null, string $prefix = null): array { + if ($connection) { + $this->connection = $connection; + } + + if ($prefix) { + $this->prefix = $prefix; + } + if (!in_array($this->connection, self::AVAILABLE_CONNECTIONS)) { throw new CacheManagerException('`getKeysByPattern` method only supports Redis connections.'); } + dump('getKeysByPattern prefix => ' . $this->connection . ' - ' . $this->prefix); + try { // Get all keys $keys = Redis::connection($this->connection)->keys($this->prefix . '*'); + dump('getKeysByPattern keys => ' . json_encode($keys)); // Filter keys by pattern return array_filter($keys, fn ($key) => preg_match('/' . $pattern . '/', $key)); } catch (Exception $e) { + dump('getKeysByPattern => ' . $e->getMessage()); Log::info('CacheManagerBase: ' . $e->getMessage()); } diff --git a/ProcessMaker/Cache/Settings/SettingCacheManager.php b/ProcessMaker/Cache/Settings/SettingCacheManager.php index 1540c20468..452691551c 100644 --- a/ProcessMaker/Cache/Settings/SettingCacheManager.php +++ b/ProcessMaker/Cache/Settings/SettingCacheManager.php @@ -158,7 +158,7 @@ public function clearBy(string $pattern): void try { // Filter keys by pattern - $matchedKeys = $this->getKeysByPattern($pattern); + $matchedKeys = $this->getKeysByPattern($pattern, $defaultDriver, $this->manager->getPrefix()); if (!empty($matchedKeys)) { Redis::connection($defaultDriver)->del($matchedKeys); diff --git a/ProcessMaker/Console/Commands/CacheSettingClear.php b/ProcessMaker/Console/Commands/CacheSettingClear.php index 0aade4ef09..86afc59556 100644 --- a/ProcessMaker/Console/Commands/CacheSettingClear.php +++ b/ProcessMaker/Console/Commands/CacheSettingClear.php @@ -26,5 +26,7 @@ class CacheSettingClear extends Command public function handle() { \SettingCache::clear(); + + $this->info('Settings cache cleared.'); } } diff --git a/tests/Feature/Cache/SettingCacheTest.php b/tests/Feature/Cache/SettingCacheTest.php index 17b8066468..43353a39ef 100644 --- a/tests/Feature/Cache/SettingCacheTest.php +++ b/tests/Feature/Cache/SettingCacheTest.php @@ -243,24 +243,19 @@ public function testClearOnlySettings() \SettingCache::set('password-policies.users_can_change', 1); \SettingCache::set('password-policies.numbers', 2); - config()->set('cache.default', 'array'); - Cache::put('password-policies.uppercase', 3); + Cache::store('file')->put('password-policies.uppercase', 3); - config()->set('cache.default', 'cache_settings'); $this->assertEquals(1, \SettingCache::get('password-policies.users_can_change')); $this->assertEquals(2, \SettingCache::get('password-policies.numbers')); - config()->set('cache.default', 'array'); - $this->assertEquals(3, Cache::get('password-policies.uppercase')); + $this->assertEquals(3, Cache::store('file')->get('password-policies.uppercase')); - config()->set('cache.default', 'cache_settings'); \SettingCache::clear(); $this->assertNull(\SettingCache::get('password-policies.users_can_change')); $this->assertNull(\SettingCache::get('password-policies.numbers')); - config()->set('cache.default', 'array'); - $this->assertEquals(3, Cache::get('password-policies.uppercase')); + $this->assertEquals(3, Cache::store('file')->get('password-policies.uppercase')); } public function testInvalidateOnSaved() From 77994afd8945643c936cfc867aafae950ed2d52d Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Thu, 19 Dec 2024 09:15:55 -0400 Subject: [PATCH 10/11] fix: update SettingCacheTest to use Cache facade for consistency --- tests/Feature/Cache/SettingCacheTest.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/Feature/Cache/SettingCacheTest.php b/tests/Feature/Cache/SettingCacheTest.php index 43353a39ef..7dd066371a 100644 --- a/tests/Feature/Cache/SettingCacheTest.php +++ b/tests/Feature/Cache/SettingCacheTest.php @@ -142,22 +142,22 @@ public function testGetSettingByNotExistingKey() public function testClearByPattern() { - \SettingCache::set('password-policies.users_can_change', 1); - \SettingCache::set('password-policies.numbers', 2); - \SettingCache::set('password-policies.uppercase', 3); + Cache::store('cache_settings')->put('password-policies.users_can_change', 1); + Cache::store('cache_settings')->put('password-policies.numbers', 2); + Cache::store('cache_settings')->put('password-policies.uppercase', 3); Cache::put('session-control.ip_restriction', 0); - $this->assertEquals(1, \SettingCache::get('password-policies.users_can_change')); - $this->assertEquals(2, \SettingCache::get('password-policies.numbers')); - $this->assertEquals(3, \SettingCache::get('password-policies.uppercase')); + $this->assertEquals(1, Cache::store('cache_settings')->get('password-policies.users_can_change')); + $this->assertEquals(2, Cache::store('cache_settings')->get('password-policies.numbers')); + $this->assertEquals(3, Cache::store('cache_settings')->get('password-policies.uppercase')); $pattern = 'password-policies'; \SettingCache::clearBy($pattern); - $this->assertNull(\SettingCache::get('password-policies.users_can_change')); - $this->assertNull(\SettingCache::get('password-policies.numbers')); - $this->assertNull(\SettingCache::get('password-policies.uppercase')); + $this->assertNull(Cache::store('cache_settings')->get('password-policies.users_can_change')); + $this->assertNull(Cache::store('cache_settings')->get('password-policies.numbers')); + $this->assertNull(Cache::store('cache_settings')->get('password-policies.uppercase')); } public function testClearByPatternRemainUnmatched() From 626adf10bd76b1a96bac9c443f02c0ba9bb125a3 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Thu, 19 Dec 2024 10:06:37 -0400 Subject: [PATCH 11/11] fix: clean code --- ProcessMaker/Cache/CacheManagerBase.php | 36 ++++--------------- .../Cache/Settings/SettingCacheManager.php | 9 ++--- tests/Feature/Cache/SettingCacheTest.php | 24 ++++++------- 3 files changed, 20 insertions(+), 49 deletions(-) diff --git a/ProcessMaker/Cache/CacheManagerBase.php b/ProcessMaker/Cache/CacheManagerBase.php index ec593ad80b..f7545504e3 100644 --- a/ProcessMaker/Cache/CacheManagerBase.php +++ b/ProcessMaker/Cache/CacheManagerBase.php @@ -8,20 +8,6 @@ abstract class CacheManagerBase { - /** - * The cache connection. - * - * @var string - */ - protected string $connection; - - /** - * The cache prefix. - * - * @var string - */ - protected string $prefix; - /** * The available cache connections. * @@ -29,12 +15,6 @@ abstract class CacheManagerBase */ protected const AVAILABLE_CONNECTIONS = ['redis', 'cache_settings']; - public function __construct() - { - $this->connection = config('cache.default'); - $this->prefix = config('cache.prefix'); - } - /** * Retrieve an array of cache keys that match a specific pattern. * @@ -45,28 +25,24 @@ public function __construct() */ public function getKeysByPattern(string $pattern, string $connection = null, string $prefix = null): array { - if ($connection) { - $this->connection = $connection; + if (!$connection) { + $connection = config('cache.default'); } - if ($prefix) { - $this->prefix = $prefix; + if (!$prefix) { + $prefix = config('cache.prefix'); } - if (!in_array($this->connection, self::AVAILABLE_CONNECTIONS)) { + if (!in_array($connection, self::AVAILABLE_CONNECTIONS)) { throw new CacheManagerException('`getKeysByPattern` method only supports Redis connections.'); } - dump('getKeysByPattern prefix => ' . $this->connection . ' - ' . $this->prefix); - try { // Get all keys - $keys = Redis::connection($this->connection)->keys($this->prefix . '*'); - dump('getKeysByPattern keys => ' . json_encode($keys)); + $keys = Redis::connection($connection)->keys($prefix . '*'); // Filter keys by pattern return array_filter($keys, fn ($key) => preg_match('/' . $pattern . '/', $key)); } catch (Exception $e) { - dump('getKeysByPattern => ' . $e->getMessage()); Log::info('CacheManagerBase: ' . $e->getMessage()); } diff --git a/ProcessMaker/Cache/Settings/SettingCacheManager.php b/ProcessMaker/Cache/Settings/SettingCacheManager.php index 452691551c..1d967ee65f 100644 --- a/ProcessMaker/Cache/Settings/SettingCacheManager.php +++ b/ProcessMaker/Cache/Settings/SettingCacheManager.php @@ -40,10 +40,6 @@ private function setCacheDriver(): void $cacheDriver = $isAvailableConnection ? self::DEFAULT_CACHE_DRIVER : $defaultCache; // Store the cache driver $this->cacheManager = $this->manager->store($cacheDriver); - // Store the cache connection - $this->connection = $isAvailableConnection ? $this->manager->getDefaultDriver() : $defaultCache; - // Store the cache prefix - $this->prefix = $this->cacheManager->getPrefix(); } /** @@ -157,8 +153,9 @@ public function clearBy(string $pattern): void } try { + $prefix = $this->manager->getPrefix(); // Filter keys by pattern - $matchedKeys = $this->getKeysByPattern($pattern, $defaultDriver, $this->manager->getPrefix()); + $matchedKeys = $this->getKeysByPattern($pattern, $defaultDriver, $prefix); if (!empty($matchedKeys)) { Redis::connection($defaultDriver)->del($matchedKeys); @@ -166,8 +163,6 @@ public function clearBy(string $pattern): void } catch (\Exception $e) { Log::error('SettingCacheException' . $e->getMessage()); - dump('exception => ' . $e->getMessage()); - throw new SettingCacheException('Failed to delete keys.'); } } diff --git a/tests/Feature/Cache/SettingCacheTest.php b/tests/Feature/Cache/SettingCacheTest.php index 7dd066371a..2f34d50784 100644 --- a/tests/Feature/Cache/SettingCacheTest.php +++ b/tests/Feature/Cache/SettingCacheTest.php @@ -162,24 +162,24 @@ public function testClearByPattern() public function testClearByPatternRemainUnmatched() { - \SettingCache::set('session-control.ip_restriction', 0); - \SettingCache::set('password-policies.users_can_change', 1); - \SettingCache::set('password-policies.numbers', 2); - \SettingCache::set('password-policies.uppercase', 3); + Cache::store('cache_settings')->put('session-control.ip_restriction', 0); + Cache::store('cache_settings')->put('password-policies.users_can_change', 1); + Cache::store('cache_settings')->put('password-policies.numbers', 2); + Cache::store('cache_settings')->put('password-policies.uppercase', 3); - $this->assertEquals(0, \SettingCache::get('session-control.ip_restriction')); - $this->assertEquals(1, \SettingCache::get('password-policies.users_can_change')); - $this->assertEquals(2, \SettingCache::get('password-policies.numbers')); - $this->assertEquals(3, \SettingCache::get('password-policies.uppercase')); + $this->assertEquals(0, Cache::store('cache_settings')->get('session-control.ip_restriction')); + $this->assertEquals(1, Cache::store('cache_settings')->get('password-policies.users_can_change')); + $this->assertEquals(2, Cache::store('cache_settings')->get('password-policies.numbers')); + $this->assertEquals(3, Cache::store('cache_settings')->get('password-policies.uppercase')); $pattern = 'password-policies'; \SettingCache::clearBy($pattern); - $this->assertEquals(0, \SettingCache::get('session-control.ip_restriction')); - $this->assertNull(\SettingCache::get('password-policies.users_can_change')); - $this->assertNull(\SettingCache::get('password-policies.numbers')); - $this->assertNull(\SettingCache::get('password-policies.uppercase')); + $this->assertEquals(0, Cache::store('cache_settings')->get('session-control.ip_restriction')); + $this->assertNull(Cache::store('cache_settings')->get('password-policies.users_can_change')); + $this->assertNull(Cache::store('cache_settings')->get('password-policies.numbers')); + $this->assertNull(Cache::store('cache_settings')->get('password-policies.uppercase')); } public function testClearByPatternWithFailedDeletion()