Skip to content

Commit

Permalink
Fix PhpStorm inspections.
Browse files Browse the repository at this point in the history
  • Loading branch information
colinmollenhour committed Jan 18, 2023
1 parent 6bc6f63 commit 3fc3e91
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 121 deletions.
122 changes: 66 additions & 56 deletions Cm/Cache/Backend/Redis.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,20 @@ protected function getClientOptions($options = array())
$clientOptions->forceStandalone = isset($options['force_standalone']) && $options['force_standalone'];
$clientOptions->connectRetries = isset($options['connect_retries']) ? (int) $options['connect_retries'] : self::DEFAULT_CONNECT_RETRIES;
$clientOptions->readTimeout = isset($options['read_timeout']) ? (float) $options['read_timeout'] : null;
$clientOptions->password = isset($options['password']) ? $options['password'] : null;
$clientOptions->username = isset($options['username']) ? $options['username'] : null;
$clientOptions->password = $options['password'] ?? null;
$clientOptions->username = $options['username'] ?? null;
$clientOptions->database = isset($options['database']) ? (int) $options['database'] : 0;
$clientOptions->persistent = isset($options['persistent']) ? $options['persistent'] : '';
$clientOptions->timeout = isset($options['timeout']) ? $options['timeout'] : self::DEFAULT_CONNECT_TIMEOUT;
$clientOptions->persistent = $options['persistent'] ?? '';
$clientOptions->timeout = $options['timeout'] ?? self::DEFAULT_CONNECT_TIMEOUT;
return $clientOptions;
}

/**
* Construct Zend_Cache Redis backend
* @param array $options
* @throws Zend_Cache_Exception
* @throws CredisException
* @noinspection PhpMissingParentConstructorInspection
*/
public function __construct($options = array())
{
Expand Down Expand Up @@ -210,7 +212,7 @@ public function __construct($options = array())

$this->_redis = $redisMaster;
break 2;
} catch (\Exception $e) {
} catch (Exception $e) {
unset($sentinelClient);
$exception = $e;
}
Expand All @@ -225,16 +227,16 @@ public function __construct($options = array())
$slaves = $sentinel->getSlaveClients($sentinelMaster);
if ($slaves) {
if ($options['load_from_slaves'] == 2) {
array_push($slaves, $this->_redis); // Also send reads to the master
$slaves[] = $this->_redis; // Also send reads to the master
}
$slaveSelect = isset($options['slave_select_callable']) && is_callable($options['slave_select_callable']) ? $options['slave_select_callable'] : null;
if ($slaveSelect) {
$slave = $slaveSelect($slaves, $this->_redis);
} else {
$slaveKey = array_rand($slaves, 1);
$slaveKey = array_rand($slaves);
$slave = $slaves[$slaveKey]; /* @var $slave Credis_Client */
}
if ($slave instanceof Credis_Client && $slave != $this->_redis) {
if ($slave instanceof Credis_Client && $slave !== $this->_redis) {
try {
$this->_applyClientOptions($slave, true);
$this->_slave = $slave;
Expand All @@ -255,7 +257,7 @@ public function __construct($options = array())

// Direct connection to single Redis server and optional slaves
else {
$port = isset($options['port']) ? $options['port'] : 6379;
$port = $options['port'] ?? 6379;
$this->_redis = new Credis_Client($options['server'], $port, $this->_clientOptions->timeout, $this->_clientOptions->persistent);
$this->_applyClientOptions($this->_redis);

Expand All @@ -268,7 +270,7 @@ public function __construct($options = array())
$clientOptions = $this->getClientOptions($options['load_from_slave'] + $options);
$totalServers = 2;
} else { // Multiple slaves
$slaveKey = array_rand($options['load_from_slave'], 1);
$slaveKey = array_rand($options['load_from_slave']);
$slave = $options['load_from_slave'][$slaveKey];
$server = $slave['server'];
$port = $slave['port'];
Expand All @@ -283,15 +285,15 @@ public function __construct($options = array())
// If multiple addresses are given, split and choose a random one
if (strpos($server, ',') !== false) {
$slaves = preg_split('/\s*,\s*/', $server, -1, PREG_SPLIT_NO_EMPTY);
$slaveKey = array_rand($slaves, 1);
$slaveKey = array_rand($slaves);
$server = $slaves[$slaveKey];
$port = null;
$totalServers = count($slaves) + 1;
} else {
$totalServers = 2;
}
}
// Skip setting up slave if master is not write only and it is randomly chosen to be the read server
// Skip setting up slave if master is not write only, and it is randomly chosen to be the read server
$masterWriteOnly = isset($options['master_write_only']) ? (int) $options['master_write_only'] : false;
if (is_string($server) && $server && ! (!$masterWriteOnly && rand(1, $totalServers) === 1)) {
try {
Expand Down Expand Up @@ -341,15 +343,15 @@ public function __construct($options = array())
} elseif (function_exists('lz4_compress')) {
$version = phpversion("lz4");
if (version_compare($version, "0.3.0") < 0) {
$this->_compressTags = $this->_compressTags > 1 ? true : false;
$this->_compressData = $this->_compressData > 1 ? true : false;
$this->_compressTags = $this->_compressTags > 1;
$this->_compressData = $this->_compressData > 1;
}
$this->_compressionLib = 'l4z';
} elseif (function_exists('zstd_compress')) {
$version = phpversion("zstd");
if (version_compare($version, "0.4.13") < 0) {
$this->_compressTags = $this->_compressTags > 1 ? true : false;
$this->_compressData = $this->_compressData > 1 ? true : false;
$this->_compressTags = $this->_compressTags > 1;
$this->_compressData = $this->_compressData > 1;
}
$this->_compressionLib = 'zstd';
} elseif (function_exists('lzf_compress')) {
Expand Down Expand Up @@ -396,6 +398,10 @@ public function __construct($options = array())
* Apply common configuration to client instances.
*
* @param Credis_Client $client
* @param bool $forceSelect
* @param null|stdClass $clientOptions
* @throws CredisException
* @throws Zend_Cache_Exception
*/
protected function _applyClientOptions(Credis_Client $client, $forceSelect = false, $clientOptions = null)
{
Expand Down Expand Up @@ -428,8 +434,10 @@ protected function _applyClientOptions(Credis_Client $client, $forceSelect = fal
}

/**
* @deprecated - Previously this setup an instance of Credis_Cluster but this class was not complete or flawed
* @param $options
* @throws CredisException
* @throws Zend_Cache_Exception
* @deprecated - Previously this setup an instance of Credis_Cluster but this class was not complete or flawed
*/
protected function _setupReadWriteCluster($options)
{
Expand All @@ -442,22 +450,22 @@ protected function _setupReadWriteCluster($options)
$this->_redis = new Credis_Client(
$masterNode['host'],
$masterNode['port'],
isset($masterNode['timeout']) ? $masterNode['timeout'] : 2.5,
isset($masterNode['persistent']) ? $masterNode['persistent'] : ''
$masterNode['timeout'] ?? 2.5,
$masterNode['persistent'] ?? ''
);
$this->_applyClientOptions($this->_redis);
break;
}
}

if (!empty($options['cluster']['slave'])) {
$slaveKey = array_rand($options['cluster']['slave'], 1);
$slaveKey = array_rand($options['cluster']['slave']);
$slave = $options['cluster']['slave'][$slaveKey];
$this->_slave = new Credis_Client(
$slave['host'],
$slave['port'],
isset($slave['timeout']) ? $slave['timeout'] : 2.5,
isset($slave['persistent']) ? $slave['persistent'] : ''
$slave['timeout'] ?? 2.5,
$slave['persistent'] ?? ''
);
$this->_applyClientOptions($this->_redis, true);
}
Expand All @@ -469,6 +477,7 @@ protected function _setupReadWriteCluster($options)
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @return bool|string
* @throws CredisException
*/
public function load($id, $doNotTestCacheValidity = false)
{
Expand Down Expand Up @@ -531,17 +540,17 @@ public function test($id)
{
// Don't use slave for this since `test` is usually used for locking
$mtime = $this->_redis->hGet(self::PREFIX_KEY.$id, self::FIELD_MTIME);
return ($mtime ? $mtime : false);
return ($mtime ? (int)$mtime : false);
}

/**
* Get the life time
* Get the lifetime
*
* if $specificLifetime is not false, the given specific life time is used
* if $specificLifetime is not false, the given specific lifetime is used
* else, the global lifetime is used
*
* @param int $specificLifetime
* @return int Cache life time
* @return int Cache lifetime
*/
public function getLifetime($specificLifetime)
{
Expand Down Expand Up @@ -714,31 +723,17 @@ public function remove($id)

$result = $this->_redis->exec();

return isset($result[0]) ? (bool)$result[0] : false;
return isset($result[0]) && (bool)$result[0];
}

/**
* @param array $tags
* @throws Zend_Cache_Exception
*/
protected function _removeByNotMatchingTags($tags)
{
$ids = $this->getIdsNotMatchingTags($tags);
if ($ids) {
$ids = array_chunk($ids, $this->_removeChunkSize);
foreach ($ids as $idsChunk) {
$this->_redis->pipeline()->multi();

// Remove data
$this->_redis->unlink($this->_preprocessIds($idsChunk));

// Remove ids from list of all ids
if ($this->_notMatchingTags) {
$this->_redis->sRem(self::SET_IDS, $idsChunk);
}

$this->_redis->exec();
}
}
$this->_removeByIds($ids);
}

/**
Expand All @@ -747,6 +742,14 @@ protected function _removeByNotMatchingTags($tags)
protected function _removeByMatchingTags($tags)
{
$ids = $this->getIdsMatchingTags($tags);
$this->_removeByIds($ids);
}

/**
* @param array $ids
*/
protected function _removeByIds($ids)
{
if ($ids) {
$ids = array_chunk($ids, $this->_removeChunkSize);
foreach ($ids as $idsChunk) {
Expand Down Expand Up @@ -804,7 +807,7 @@ protected function _removeByMatchingAnyTags($tags)

if ($ids) {
$ids = array_chunk($ids, $this->_removeChunkSize);
foreach ($ids as $index => $idsChunk) {
foreach ($ids as $idsChunk) {
// Remove data
$this->_redis->unlink($this->_preprocessIds($idsChunk));

Expand Down Expand Up @@ -946,10 +949,10 @@ protected function _collectGarbage()
unset($expired);
}

// TODO
// Clean up global list of ids for ids with no tag
if ($this->_notMatchingTags) {
// TODO
}
// if ($this->_notMatchingTags) {
// }
}

/**
Expand Down Expand Up @@ -1041,9 +1044,9 @@ public function setDirectives($directives)
* Mainly a workaround for the issues that arise due to the fact that
* Magento's Enterprise_PageCache module doesn't set any expiry.
*
* @param int $specificLifetime
* @param string $id
* @return int Cache life time
* @param int $lifetime
* @param string $id
* @return int Cache lifetime
*/
protected function _getAutoExpiringLifetime($lifetime, $id)
{
Expand Down Expand Up @@ -1127,6 +1130,7 @@ public function getIdsMatchingTags($tags = array())
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
* @throws Zend_Cache_Exception
*/
public function getIdsNotMatchingTags($tags = array())
{
Expand Down Expand Up @@ -1180,15 +1184,17 @@ public function getInfo()
*/
public function getFillingPercentage()
{
$maxMem = $this->_redis->config('GET', 'maxmemory');
try {
$maxMem = $this->_redis->config('GET', 'maxmemory');
} catch (CredisException $e) {
throw new Zend_Cache_Exception($e->getMessage(), 0, $e);
}
if (0 == (int) $maxMem['maxmemory']) {
return 1;
}
$info = $this->_redis->info();
return (int) round(
($info['used_memory']/$maxMem['maxmemory']*100),
0,
PHP_ROUND_HALF_UP
($info['used_memory']/$maxMem['maxmemory']*100)
);
}

Expand All @@ -1200,13 +1206,17 @@ public function getFillingPercentage()
*/
public function getHitMissPercentage()
{
$info = $this->_redis->info();
try {
$info = $this->_redis->info();
} catch (CredisException $e) {
throw new Zend_Cache_Exception($e->getMessage(), 0, $e);
}
$hits = $info['keyspace_hits'];
$misses = $info['keyspace_misses'];
$total = $misses+$hits;
$percentage = 0;
if ($total > 0) {
$percentage = round($hits*100/$total, 0);
$percentage = round($hits*100/$total);
}
return $percentage;
}
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Works with any Zend Framework project including all versions of Magento!

- Uses the [phpredis PECL extension](https://github.com/nicolasff/phpredis) for best performance (requires **master** branch or tagged version newer than Aug 19 2011).
- Falls back to standalone PHP if phpredis isn't available using the [Credis](https://github.com/colinmollenhour/credis) library.
- Tagging is fully supported, implemented using the Redis "set" and "hash" datatypes for efficient tag management.
- Tagging is fully supported, implemented using the Redis "set" and "hash" data types for efficient tag management.
- Key expiration is handled automatically by Redis.
- Supports unix socket connection for even better performance on a single machine.
- Supports configurable compression for memory savings. Can choose between gzip, lzf and snappy and can change configuration without flushing cache.
Expand Down Expand Up @@ -182,9 +182,9 @@ to read from rather than using md5 hash of the keys.

# TUNING

- The recommended "maxmemory-policy" is "volatile-lru". All tag metadata is non-volatile so it is
- The recommended "maxmemory-policy" is "volatile-lru". All tag metadata is non-volatile, so it is
recommended to use key expirations unless non-volatile keys are absolutely necessary so that tag
data cannot get evicted. So, be sure that the "maxmemory" is high enough to accommodate all of
data cannot get evicted. So, be sure that the "maxmemory" is high enough to accommodate all
the tag data and non-volatile data with enough room left for the volatile key data as well.
- Automatic cleaning is optional and not recommended since it is slow and uses lots of memory.
- Occasional (e.g. once a day) garbage collection is recommended if the entire cache is infrequently cleared and
Expand All @@ -201,8 +201,8 @@ to read from rather than using md5 hash of the keys.
- Enable persistent connections. Make sure that if you have multiple configurations connecting the persistent
string is unique for each configuration so that "select" commands don't cause conflicts.
- Increase your server's `lua-time-limit` if you are getting "BUSY" errors. This setting can also cause Redis Sentinel
to invoke failovers when you would probably prefer to let the Lua script finish and have clients wait a little longer.
- Use the `stats.php` script to inspect your cache to find oversized or wasteful cache tags.
to invoke fail-overs when you would probably prefer to let the Lua script finish and have clients wait a little longer.
- Use the `stats.php` script to inspect your cache to find over-sized or wasteful cache tags.

### Example Garbage Collection Script (Magento)

Expand Down
Loading

0 comments on commit 3fc3e91

Please sign in to comment.