Skip to content

Commit c08a9af

Browse files
author
Mohammed Karim
committed
CacheFactory will attempt to initialize $backup handler and finally 'dummy' handler if $adapter->initialize() throws a CriticalError.
RedisHandler throws a CriticalError if there is an issue connecting to Redis.
1 parent b5c5a94 commit c08a9af

2 files changed

Lines changed: 44 additions & 10 deletions

File tree

system/Cache/CacheFactory.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
namespace CodeIgniter\Cache;
4040

4141
use CodeIgniter\Cache\Exceptions\CacheException;
42+
use CodeIgniter\Exceptions\CriticalError;
4243

4344
/**
4445
* Class Cache
@@ -93,7 +94,20 @@ public static function getHandler($config, string $handler = null, string $backu
9394
}
9495
}
9596

96-
$adapter->initialize();
97+
// If $adapter->initialization throws a CriticalError exception, we will attempt to
98+
// use the $backup handler, if that also fails, we resort to the dummy handler.
99+
try
100+
{
101+
$adapter->initialize();
102+
}
103+
catch (CriticalError $e)
104+
{
105+
// log the fact that an exception occurred as well what handler we resorting to
106+
log_message('critical', $e->getMessage() . ' Resorting to using ' . $backup . ' handler.');
107+
108+
// get the next best cache handler (or dummy if the $backup also fails)
109+
$adapter = self::getHandler($config, $backup, 'dummy');
110+
}
97111

98112
return $adapter;
99113
}

system/Cache/Handlers/RedisHandler.php

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
namespace CodeIgniter\Cache\Handlers;
4040

4141
use CodeIgniter\Cache\CacheInterface;
42+
use CodeIgniter\Exceptions\CriticalError;
4243

4344
/**
4445
* Redis cache handler
@@ -116,19 +117,38 @@ public function initialize()
116117
$config = $this->config;
117118

118119
$this->redis = new \Redis();
119-
if (! $this->redis->connect($config['host'], ($config['host'][0] === '/' ? 0 : $config['port']), $config['timeout']))
120-
{
121-
log_message('error', 'Cache: Redis connection failed. Check your configuration.');
122-
}
123120

124-
if (isset($config['password']) && ! $this->redis->auth($config['password']))
121+
// Try to connect to Redis, if an issue occurs throw a CriticalError exception,
122+
// so that the CacheFactory can attempt to initiate the next cache handler.
123+
try
125124
{
126-
log_message('error', 'Cache: Redis authentication failed.');
125+
// Note:: If Redis is your primary cache choice, and it is "offline", every page load will end up been delayed by the timeout duration.
126+
// I feel like some sort of temporary flag should be set, to indicate that we think Redis is "offline", allowing us to bypass the timeout for a set period of time.
127+
128+
if (! $this->redis->connect($config['host'], ($config['host'][0] === '/' ? 0 : $config['port']), $config['timeout']))
129+
{
130+
// Note:: I'm unsure if log_message() is necessary, however I'm not 100% comfortable removing it.
131+
log_message('error', 'Cache: Redis connection failed. Check your configuration.');
132+
throw new CriticalError('Cache: Redis connection failed. Check your configuration.');
133+
}
134+
135+
if (isset($config['password']) && ! $this->redis->auth($config['password']))
136+
{
137+
log_message('error', 'Cache: Redis authentication failed.');
138+
throw new CriticalError('Cache: Redis authentication failed.');
139+
}
140+
141+
if (isset($config['database']) && ! $this->redis->select($config['database']))
142+
{
143+
log_message('error', 'Cache: Redis select database failed.');
144+
throw new CriticalError('Cache: Redis select database failed.');
145+
}
127146
}
128-
129-
if (isset($config['database']) && ! $this->redis->select($config['database']))
147+
catch (\RedisException $e)
130148
{
131-
log_message('error', 'Cache: Redis select database failed.');
149+
// $this->redis->connect() can sometimes throw a RedisException.
150+
// We need to these to a CriticalError exception and throw it.
151+
throw new CriticalError('Cache: RedisException occurred with message (' . $e->getMessage() . ').');
132152
}
133153
}
134154

0 commit comments

Comments
 (0)