diff --git a/.gitignore b/.gitignore index 6caf5b1..9e2f056 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .basedir vendor composer.lock +/.php-cs-fixer.cache diff --git a/Cm/Cache/Backend/Redis.php b/Cm/Cache/Backend/Redis.php index 6ba83d8..023cee7 100644 --- a/Cm/Cache/Backend/Redis.php +++ b/Cm/Cache/Backend/Redis.php @@ -38,7 +38,6 @@ */ class Cm_Cache_Backend_Redis extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface { - const SET_IDS = 'zc:ids'; const SET_TAGS = 'zc:tags'; @@ -63,7 +62,7 @@ class Cm_Cache_Backend_Redis extends Zend_Cache_Backend implements Zend_Cache_Ba protected $_redis; /** @var bool */ - protected $_notMatchingTags = FALSE; + protected $_notMatchingTags = false; /** @var int */ protected $_lifetimelimit = self::MAX_LIFETIME; /* Redis backend limit */ @@ -145,9 +144,9 @@ protected function getClientOptions($options = array()) $clientOptions = new stdClass(); $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->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->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; @@ -161,67 +160,68 @@ protected function getClientOptions($options = array()) */ public function __construct($options = array()) { - if ( empty($options['server']) && empty($options['cluster'])) { + if (empty($options['server']) && empty($options['cluster'])) { Zend_Cache::throwException('Redis \'server\' not specified.'); } $this->_clientOptions = $this->getClientOptions($options); // If 'sentinel_master' is specified then server is actually sentinel and master address should be fetched from server. - $sentinelMaster = empty($options['sentinel_master']) ? NULL : $options['sentinel_master']; + $sentinelMaster = empty($options['sentinel_master']) ? null : $options['sentinel_master']; if ($sentinelMaster) { $sentinelClientOptions = isset($options['sentinel']) && is_array($options['sentinel']) ? $this->getClientOptions($options['sentinel'] + $options) : $this->_clientOptions; $servers = preg_split('/\s*,\s*/', trim($options['server']), -1, PREG_SPLIT_NO_EMPTY); - $sentinel = NULL; - $exception = NULL; - for ($i = 0; $i <= $sentinelClientOptions->connectRetries; $i++) // Try each sentinel in round-robin fashion - foreach ($servers as $server) { - try { - $sentinelClient = new Credis_Client($server, NULL, $sentinelClientOptions->timeout, $sentinelClientOptions->persistent); - $sentinelClient->forceStandalone(); - $sentinelClient->setMaxConnectRetries(0); - if ($sentinelClientOptions->readTimeout) { - $sentinelClient->setReadTimeout($sentinelClientOptions->readTimeout); - } - if ($sentinelClientOptions->password) { - $sentinelClient->auth($sentinelClientOptions->password) or Zend_Cache::throwException('Unable to authenticate with the redis sentinel.'); - } - $sentinel = new Credis_Sentinel($sentinelClient); - $sentinel - ->setClientTimeout($this->_clientOptions->timeout) - ->setClientPersistent($this->_clientOptions->persistent); - $redisMaster = $sentinel->getMasterClient($sentinelMaster); - $this->_applyClientOptions($redisMaster); - - // Verify connected server is actually master as per Sentinel client spec - if ( ! empty($options['sentinel_master_verify'])) { - $roleData = $redisMaster->role(); - if ( ! $roleData || $roleData[0] != 'master') { - usleep(100000); // Sleep 100ms and try again - $redisMaster = $sentinel->getMasterClient($sentinelMaster); - $this->_applyClientOptions($redisMaster); + $sentinel = null; + $exception = null; + for ($i = 0; $i <= $sentinelClientOptions->connectRetries; $i++) { // Try each sentinel in round-robin fashion + foreach ($servers as $server) { + try { + $sentinelClient = new Credis_Client($server, null, $sentinelClientOptions->timeout, $sentinelClientOptions->persistent); + $sentinelClient->forceStandalone(); + $sentinelClient->setMaxConnectRetries(0); + if ($sentinelClientOptions->readTimeout) { + $sentinelClient->setReadTimeout($sentinelClientOptions->readTimeout); + } + if ($sentinelClientOptions->password) { + $sentinelClient->auth($sentinelClientOptions->password) or Zend_Cache::throwException('Unable to authenticate with the redis sentinel.'); + } + $sentinel = new Credis_Sentinel($sentinelClient); + $sentinel + ->setClientTimeout($this->_clientOptions->timeout) + ->setClientPersistent($this->_clientOptions->persistent); + $redisMaster = $sentinel->getMasterClient($sentinelMaster); + $this->_applyClientOptions($redisMaster); + + // Verify connected server is actually master as per Sentinel client spec + if (! empty($options['sentinel_master_verify'])) { $roleData = $redisMaster->role(); - if ( ! $roleData || $roleData[0] != 'master') { - Zend_Cache::throwException('Unable to determine master redis server.'); + if (! $roleData || $roleData[0] != 'master') { + usleep(100000); // Sleep 100ms and try again + $redisMaster = $sentinel->getMasterClient($sentinelMaster); + $this->_applyClientOptions($redisMaster); + $roleData = $redisMaster->role(); + if (! $roleData || $roleData[0] != 'master') { + Zend_Cache::throwException('Unable to determine master redis server.'); + } } } - } - $this->_redis = $redisMaster; - break 2; - } catch (\Exception $e) { - unset($sentinelClient); - $exception = $e; + $this->_redis = $redisMaster; + break 2; + } catch (\Exception $e) { + unset($sentinelClient); + $exception = $e; + } } } - if ( ! $this->_redis) { + if (! $this->_redis) { Zend_Cache::throwException('Unable to connect to a redis sentinel: '.$exception->getMessage(), $exception); } // Optionally use read slaves - will only be used for 'load' operation - if ( ! empty($options['load_from_slaves'])) { + if (! empty($options['load_from_slaves'])) { $slaves = $sentinel->getSlaveClients($sentinelMaster); if ($slaves) { if ($options['load_from_slaves'] == 2) { @@ -236,7 +236,7 @@ public function __construct($options = array()) } if ($slave instanceof Credis_Client && $slave != $this->_redis) { try { - $this->_applyClientOptions($slave, TRUE); + $this->_applyClientOptions($slave, true); $this->_slave = $slave; } catch (Exception $e) { // If there is a problem with first slave then skip 'load_from_slaves' option @@ -249,7 +249,7 @@ public function __construct($options = array()) // Instantiate Credis_Cluster // DEPRECATED - else if ( ! empty($options['cluster'])) { + elseif (! empty($options['cluster'])) { $this->_setupReadWriteCluster($options); } @@ -281,22 +281,22 @@ public function __construct($options = array()) $clientOptions = $this->_clientOptions; // If multiple addresses are given, split and choose a random one - if (strpos($server, ',') !== FALSE) { + if (strpos($server, ',') !== false) { $slaves = preg_split('/\s*,\s*/', $server, -1, PREG_SPLIT_NO_EMPTY); $slaveKey = array_rand($slaves, 1); $server = $slaves[$slaveKey]; - $port = NULL; + $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 - $masterWriteOnly = isset($options['master_write_only']) ? (int) $options['master_write_only'] : FALSE; - if (is_string($server) && $server && ! (!$masterWriteOnly && rand(1,$totalServers) === 1)) { + $masterWriteOnly = isset($options['master_write_only']) ? (int) $options['master_write_only'] : false; + if (is_string($server) && $server && ! (!$masterWriteOnly && rand(1, $totalServers) === 1)) { try { $slave = new Credis_Client($server, $port, $clientOptions->timeout, $clientOptions->persistent); - $this->_applyClientOptions($slave, TRUE, $clientOptions); + $this->_applyClientOptions($slave, true, $clientOptions); $this->_slave = $slave; } catch (Exception $e) { // Slave will not be used @@ -305,72 +305,65 @@ public function __construct($options = array()) } } - if ( isset($options['notMatchingTags']) ) { + if (isset($options['notMatchingTags'])) { $this->_notMatchingTags = (bool) $options['notMatchingTags']; } - if ( isset($options['compress_tags'])) { + if (isset($options['compress_tags'])) { $this->_compressTags = (int) $options['compress_tags']; } - if ( isset($options['compress_data'])) { + if (isset($options['compress_data'])) { $this->_compressData = (int) $options['compress_data']; } - if ( isset($options['lifetimelimit'])) { + if (isset($options['lifetimelimit'])) { $this->_lifetimelimit = (int) min($options['lifetimelimit'], self::MAX_LIFETIME); } - if ( isset($options['compress_threshold'])) { + if (isset($options['compress_threshold'])) { $this->_compressThreshold = (int) $options['compress_threshold']; if ($this->_compressThreshold < 1) { $this->_compressThreshold = 1; } } - if ( isset($options['automatic_cleaning_factor']) ) { + if (isset($options['automatic_cleaning_factor'])) { $this->_options['automatic_cleaning_factor'] = (int) $options['automatic_cleaning_factor']; } else { $this->_options['automatic_cleaning_factor'] = 0; } - if ( isset($options['compression_lib']) ) { + if (isset($options['compression_lib'])) { $this->_compressionLib = (string) $options['compression_lib']; - } - else if ( function_exists('snappy_compress') ) { + } elseif (function_exists('snappy_compress')) { $this->_compressionLib = 'snappy'; - } - else if ( function_exists('lz4_compress')) { + } elseif (function_exists('lz4_compress')) { $version = phpversion("lz4"); - if (version_compare($version, "0.3.0") < 0) - { + if (version_compare($version, "0.3.0") < 0) { $this->_compressTags = $this->_compressTags > 1 ? true : false; $this->_compressData = $this->_compressData > 1 ? true : false; } $this->_compressionLib = 'l4z'; - } - else if ( function_exists('zstd_compress')) { + } elseif (function_exists('zstd_compress')) { $version = phpversion("zstd"); - if (version_compare($version, "0.4.13") < 0) - { + if (version_compare($version, "0.4.13") < 0) { $this->_compressTags = $this->_compressTags > 1 ? true : false; $this->_compressData = $this->_compressData > 1 ? true : false; } $this->_compressionLib = 'zstd'; - } - else if ( function_exists('lzf_compress') ) { + } elseif (function_exists('lzf_compress')) { $this->_compressionLib = 'lzf'; - } - else { + } else { $this->_compressionLib = 'gzip'; } - $this->_compressPrefix = substr($this->_compressionLib,0,2).self::COMPRESS_PREFIX; + $this->_compressPrefix = substr($this->_compressionLib, 0, 2).self::COMPRESS_PREFIX; - if ( isset($options['sunion_chunk_size']) && $options['sunion_chunk_size'] > 0) { + if (isset($options['sunion_chunk_size']) && $options['sunion_chunk_size'] > 0) { $this->_sunionChunkSize = (int) $options['sunion_chunk_size']; } - if ( isset($options['remove_chunk_size']) && $options['remove_chunk_size'] > 0) { + if (isset($options['remove_chunk_size']) && $options['remove_chunk_size'] > 0) { $this->_removeChunkSize = (int) $options['remove_chunk_size']; } @@ -404,7 +397,7 @@ public function __construct($options = array()) * * @param Credis_Client $client */ - protected function _applyClientOptions(Credis_Client $client, $forceSelect = FALSE, $clientOptions = null) + protected function _applyClientOptions(Credis_Client $client, $forceSelect = false, $clientOptions = null) { if ($clientOptions === null) { $clientOptions = $this->_clientOptions; @@ -466,7 +459,7 @@ protected function _setupReadWriteCluster($options) isset($slave['timeout']) ? $slave['timeout'] : 2.5, isset($slave['persistent']) ? $slave['persistent'] : '' ); - $this->_applyClientOptions($this->_redis, TRUE); + $this->_applyClientOptions($this->_redis, true); } } @@ -508,8 +501,8 @@ public function load($id, $doNotTestCacheValidity = false) } } } - if ($data === NULL || $data === FALSE || is_object($data)) { - return FALSE; + if ($data === null || $data === false || is_object($data)) { + return false; } $decoded = $this->_decodeData($data); @@ -538,7 +531,7 @@ 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 ? $mtime : false); } /** @@ -575,10 +568,11 @@ public function getLifetime($specificLifetime) */ public function save($data, $id, $tags = array(), $specificLifetime = false) { - if(!is_array($tags)) + if (!is_array($tags)) { $tags = $tags ? array($tags) : array(); - else + } else { $tags = array_flip(array_flip($tags)); + } $lifetime = $this->_getAutoExpiringLifetime($this->getLifetime($specificLifetime), $id); $lifetime = $lifetime === null ? $lifetime : (int) $lifetime; @@ -595,7 +589,7 @@ public function save($data, $id, $tags = array(), $specificLifetime = false) self::SET_IDS, $id, $this->_encodeData($data, $this->_compressData), - $this->_encodeData(implode(',',$tags), $this->_compressTags), + $this->_encodeData(implode(',', $tags), $this->_compressTags), time(), $lifetime ? 0 : 1, min($lifetime, self::MAX_LIFETIME), @@ -630,17 +624,15 @@ public function save($data, $id, $tags = array(), $specificLifetime = false) // Process removed tags if cache entry already existed if ($res) { $oldTags = explode(',', $this->_decodeData($res)); - if ($remTags = ($oldTags ? array_diff($oldTags, $tags) : FALSE)) - { + if ($remTags = ($oldTags ? array_diff($oldTags, $tags) : false)) { // Update the id list for each tag - foreach($remTags as $tag) - { + foreach ($remTags as $tag) { $this->_redis->sRem(self::PREFIX_TAG_IDS . $tag, $id); } } } - return TRUE; + return true; } // Get list of tags previously assigned @@ -652,50 +644,46 @@ public function save($data, $id, $tags = array(), $specificLifetime = false) // Set the data $result = $this->_redis->hMSet(self::PREFIX_KEY.$id, array( self::FIELD_DATA => $this->_encodeData($data, $this->_compressData), - self::FIELD_TAGS => $this->_encodeData(implode(',',$tags), $this->_compressTags), + self::FIELD_TAGS => $this->_encodeData(implode(',', $tags), $this->_compressTags), self::FIELD_MTIME => time(), self::FIELD_INF => is_null($lifetime) ? 1 : 0, )); - if( ! $result) { + if (! $result) { throw new CredisException("Could not set cache key $id"); } // Set expiration if specified if ($lifetime !== false && !is_null($lifetime)) { - $this->_redis->expire(self::PREFIX_KEY.$id, min($lifetime, self::MAX_LIFETIME)); + $this->_redis->expire(self::PREFIX_KEY.$id, min($lifetime, self::MAX_LIFETIME)); } // Process added tags - if ($tags) - { + if ($tags) { // Update the list with all the tags - $this->_redis->sAdd( self::SET_TAGS, $tags); + $this->_redis->sAdd(self::SET_TAGS, $tags); // Update the id list for each tag - foreach($tags as $tag) - { + foreach ($tags as $tag) { $this->_redis->sAdd(self::PREFIX_TAG_IDS . $tag, $id); } } // Process removed tags - if ($remTags = ($oldTags ? array_diff($oldTags, $tags) : FALSE)) - { + if ($remTags = ($oldTags ? array_diff($oldTags, $tags) : false)) { // Update the id list for each tag - foreach($remTags as $tag) - { + foreach ($remTags as $tag) { $this->_redis->sRem(self::PREFIX_TAG_IDS . $tag, $id); } } // Update the list with all the ids - if($this->_notMatchingTags) { + if ($this->_notMatchingTags) { $this->_redis->sAdd(self::SET_IDS, $id); } $this->_redis->exec(); - return TRUE; + return true; } /** @@ -715,12 +703,12 @@ public function remove($id) $this->_redis->unlink(self::PREFIX_KEY.$id); // Remove id from list of all ids - if($this->_notMatchingTags) { - $this->_redis->sRem( self::SET_IDS, $id ); + if ($this->_notMatchingTags) { + $this->_redis->sRem(self::SET_IDS, $id); } // Update the id list for each tag - foreach($tags as $tag) { + foreach ($tags as $tag) { $this->_redis->sRem(self::PREFIX_TAG_IDS . $tag, $id); } @@ -735,8 +723,7 @@ public function remove($id) protected function _removeByNotMatchingTags($tags) { $ids = $this->getIdsNotMatchingTags($tags); - if($ids) - { + if ($ids) { $ids = array_chunk($ids, $this->_removeChunkSize); foreach ($ids as $idsChunk) { $this->_redis->pipeline()->multi(); @@ -760,8 +747,7 @@ protected function _removeByNotMatchingTags($tags) protected function _removeByMatchingTags($tags) { $ids = $this->getIdsMatchingTags($tags); - if($ids) - { + if ($ids) { $ids = array_chunk($ids, $this->_removeChunkSize); foreach ($ids as $idsChunk) { $this->_redis->pipeline()->multi(); @@ -770,8 +756,8 @@ protected function _removeByMatchingTags($tags) $this->_redis->unlink($this->_preprocessIds($idsChunk)); // Remove ids from list of all ids - if($this->_notMatchingTags) { - $this->_redis->sRem( self::SET_IDS, $idsChunk); + if ($this->_notMatchingTags) { + $this->_redis->sRem(self::SET_IDS, $idsChunk); } $this->_redis->exec(); @@ -788,7 +774,7 @@ protected function _removeByMatchingAnyTags($tags) $tags = array_chunk($tags, $this->_sunionChunkSize); foreach ($tags as $chunk) { $args = array(self::PREFIX_TAG_IDS, self::PREFIX_KEY, self::SET_TAGS, self::SET_IDS, ($this->_notMatchingTags ? 1 : 0), (int) $this->_luaMaxCStack); - if ( ! $this->_redis->evalSha(self::LUA_CLEAN_SH1, $chunk, $args)) { + if (! $this->_redis->evalSha(self::LUA_CLEAN_SH1, $chunk, $args)) { $script = "for i = 1, #KEYS, ARGV[6] do " . "local prefixedTags = {} " . @@ -816,8 +802,7 @@ protected function _removeByMatchingAnyTags($tags) $this->_redis->pipeline()->multi(); - if($ids) - { + if ($ids) { $ids = array_chunk($ids, $this->_removeChunkSize); foreach ($ids as $index => $idsChunk) { // Remove data @@ -837,10 +822,10 @@ protected function _removeByMatchingAnyTags($tags) } // Remove tag id lists - $this->_redis->unlink( $this->_preprocessTagIds($tags)); + $this->_redis->unlink($this->_preprocessTagIds($tags)); // Remove tags from list of tags - $this->_redis->sRem( self::SET_TAGS, $tags); + $this->_redis->sRem(self::SET_TAGS, $tags); $this->_redis->exec(); } @@ -861,8 +846,8 @@ protected function _collectGarbage() foreach ($allTags as $tag) { $tagsBatch[] = $tag; $counter++; - if (count($tagsBatch) == 10 || $counter == $tagsCount ) { - if ( ! $this->_redis->evalSha(self::LUA_GC_SH1, $tagsBatch, $sArgs)) { + if (count($tagsBatch) == 10 || $counter == $tagsCount) { + if (! $this->_redis->evalSha(self::LUA_GC_SH1, $tagsBatch, $sArgs)) { $script = "local tagKeys = {} ". "local expired = {} ". @@ -914,36 +899,36 @@ protected function _collectGarbage() $exists = array(); $tags = (array) $this->_redis->sMembers(self::SET_TAGS); - foreach($tags as $tag) - { + foreach ($tags as $tag) { // Get list of expired ids for each tag $tagMembers = $this->_redis->sMembers(self::PREFIX_TAG_IDS . $tag); $numTagMembers = count($tagMembers); $expired = array(); $numExpired = $numNotExpired = 0; - if($numTagMembers) { + if ($numTagMembers) { while ($id = array_pop($tagMembers)) { - if( ! isset($exists[$id])) { + if (! isset($exists[$id])) { $exists[$id] = $this->_redis->exists(self::PREFIX_KEY.$id); } if ($exists[$id]) { $numNotExpired++; - } - else { + } else { $numExpired++; $expired[] = $id; // Remove incrementally to reduce memory usage if (count($expired) % 100 == 0 && $numNotExpired > 0) { - $this->_redis->sRem( self::PREFIX_TAG_IDS . $tag, $expired); - if($this->_notMatchingTags) { // Clean up expired ids from ids set - $this->_redis->sRem( self::SET_IDS, $expired); + $this->_redis->sRem(self::PREFIX_TAG_IDS . $tag, $expired); + if ($this->_notMatchingTags) { // Clean up expired ids from ids set + $this->_redis->sRem(self::SET_IDS, $expired); } $expired = array(); } } } - if( ! count($expired)) continue; + if (! count($expired)) { + continue; + } } // Remove empty tags or completely expired tags @@ -952,17 +937,17 @@ protected function _collectGarbage() $this->_redis->sRem(self::SET_TAGS, $tag); } // Clean up expired ids from tag ids set - else if (count($expired)) { - $this->_redis->sRem( self::PREFIX_TAG_IDS . $tag, $expired); - if($this->_notMatchingTags) { // Clean up expired ids from ids set - $this->_redis->sRem( self::SET_IDS, $expired); + elseif (count($expired)) { + $this->_redis->sRem(self::PREFIX_TAG_IDS . $tag, $expired); + if ($this->_notMatchingTags) { // Clean up expired ids from ids set + $this->_redis->sRem(self::SET_IDS, $expired); } } unset($expired); } // Clean up global list of ids for ids with no tag - if($this->_notMatchingTags) { + if ($this->_notMatchingTags) { // TODO } } @@ -984,7 +969,7 @@ protected function _collectGarbage() */ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) { - if( $tags && ! is_array($tags)) { + if ($tags && ! is_array($tags)) { $tags = array($tags); } @@ -994,13 +979,12 @@ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) } if ($mode == Zend_Cache::CLEANING_MODE_OLD) { $this->_collectGarbage(); - return TRUE; + return true; } - if ( ! count($tags)) { - return TRUE; + if (! count($tags)) { + return true; } - switch ($mode) - { + switch ($mode) { case Zend_Cache::CLEANING_MODE_MATCHING_TAG: $this->_removeByMatchingTags($tags); @@ -1022,7 +1006,7 @@ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) } catch (CredisException $e) { Zend_Cache::throwException('Error cleaning cache by mode '.$mode.': '.$e->getMessage(), $e); } - return TRUE; + return true; } /** @@ -1032,7 +1016,7 @@ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array()) */ public function isAutomaticCleaningAvailable() { - return TRUE; + return true; } /** @@ -1098,12 +1082,12 @@ protected function _matchesAutoExpiringPattern($id) */ public function getIds() { - if($this->_notMatchingTags) { + if ($this->_notMatchingTags) { return (array) $this->_redis->sMembers(self::SET_IDS); } else { $keys = $this->_redis->keys(self::PREFIX_KEY . '*'); $prefixLen = strlen(self::PREFIX_KEY); - foreach($keys as $index => $key) { + foreach ($keys as $index => $key) { $keys[$index] = substr($key, $prefixLen); } return $keys; @@ -1131,7 +1115,7 @@ public function getTags() public function getIdsMatchingTags($tags = array()) { if ($tags) { - return (array) $this->_redis->sInter( $this->_preprocessTagIds($tags) ); + return (array) $this->_redis->sInter($this->_preprocessTagIds($tags)); } return array(); } @@ -1146,13 +1130,13 @@ public function getIdsMatchingTags($tags = array()) */ public function getIdsNotMatchingTags($tags = array()) { - if( ! $this->_notMatchingTags) { + if (! $this->_notMatchingTags) { Zend_Cache::throwException("notMatchingTags is currently disabled."); } if ($tags) { - return (array) $this->_redis->sDiff( self::SET_IDS, $this->_preprocessTagIds($tags) ); + return (array) $this->_redis->sDiff(self::SET_IDS, $this->_preprocessTagIds($tags)); } - return (array) $this->_redis->sMembers( self::SET_IDS ); + return (array) $this->_redis->sMembers(self::SET_IDS); } /** @@ -1169,7 +1153,7 @@ public function getIdsMatchingAnyTags($tags = array()) if ($tags) { $chunks = array_chunk($tags, $this->_sunionChunkSize); foreach ($chunks as $chunk) { - $result = array_merge($result, (array) $this->_redis->sUnion( $this->_preprocessTagIds($chunk))); + $result = array_merge($result, (array) $this->_redis->sUnion($this->_preprocessTagIds($chunk))); } if (count($chunks) > 1) { $result = array_unique($result); // since we are chunking requests, we must de-duplicate member names @@ -1196,15 +1180,15 @@ public function getInfo() */ public function getFillingPercentage() { - $maxMem = $this->_redis->config('GET','maxmemory'); + $maxMem = $this->_redis->config('GET', 'maxmemory'); 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), + 0, + PHP_ROUND_HALF_UP ); } @@ -1221,8 +1205,9 @@ public function getHitMissPercentage() $misses = $info['keyspace_misses']; $total = $misses+$hits; $percentage = 0; - if ($total > 0) + if ($total > 0) { $percentage = round($hits*100/$total, 0); + } return $percentage; } @@ -1242,11 +1227,11 @@ public function getMetadatas($id) list($tags, $mtime, $inf) = array_values( $this->_redis->hMGet(self::PREFIX_KEY.$id, array(self::FIELD_TAGS, self::FIELD_MTIME, self::FIELD_INF)) ); - if( ! $mtime) { - return FALSE; + if (! $mtime) { + return false; } $tags = explode(',', $this->_decodeData($tags)); - $expire = $inf === '1' ? FALSE : time() + $this->_redis->ttl(self::PREFIX_KEY.$id); + $expire = $inf === '1' ? false : time() + $this->_redis->ttl(self::PREFIX_KEY.$id); return array( 'expire' => $expire, @@ -1308,14 +1293,19 @@ protected function _encodeData($data, $level) { if ($this->_compressionLib && $level !== 0 && strlen($data) >= $this->_compressThreshold) { switch($this->_compressionLib) { - case 'snappy': $data = snappy_compress($data); break; - case 'lzf': $data = lzf_compress($data); break; - case 'l4z': $data = lz4_compress($data, $level); break; - case 'zstd': $data = zstd_compress($data, $level); break; - case 'gzip': $data = gzcompress($data, $level); break; + case 'snappy': $data = snappy_compress($data); + break; + case 'lzf': $data = lzf_compress($data); + break; + case 'l4z': $data = lz4_compress($data, $level); + break; + case 'zstd': $data = zstd_compress($data, $level); + break; + case 'gzip': $data = gzcompress($data, $level); + break; default: throw new CredisException("Unrecognized 'compression_lib'."); } - if( ! $data) { + if (! $data) { throw new CredisException("Could not compress cache data."); } return $this->_compressPrefix.$data; @@ -1330,13 +1320,13 @@ protected function _encodeData($data, $level) protected function _decodeData($data) { try { - if (substr($data,2,3) == self::COMPRESS_PREFIX) { - switch(substr($data,0,2)) { - case 'sn': return snappy_uncompress(substr($data,5)); - case 'lz': return lzf_decompress(substr($data,5)); - case 'l4': return lz4_uncompress(substr($data,5)); - case 'zs': return zstd_uncompress(substr($data,5)); - case 'gz': case 'zc': return gzuncompress(substr($data,5)); + if (substr($data, 2, 3) == self::COMPRESS_PREFIX) { + switch(substr($data, 0, 2)) { + case 'sn': return snappy_uncompress(substr($data, 5)); + case 'lz': return lzf_decompress(substr($data, 5)); + case 'l4': return lz4_uncompress(substr($data, 5)); + case 'zs': return zstd_uncompress(substr($data, 5)); + case 'gz': case 'zc': return gzuncompress(substr($data, 5)); } } } catch(Exception $e) { @@ -1413,5 +1403,4 @@ public function ___checkScriptsExist() } return $scripts; } - } diff --git a/composer.json b/composer.json index ae8e649..420f114 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "colinmollenhour/credis": "^1.14" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.4", "phpunit/phpunit": "^9", "zf1s/zend-cache": "~1.15" }, @@ -22,6 +23,7 @@ ] }, "scripts": { - "test": "vendor/bin/phpunit tests" + "test": "vendor/bin/phpunit tests", + "php-cs-fixer": "php-cs-fixer --rules=@PSR2" } } diff --git a/stats.php b/stats.php index 56c1408..1a829b0 100644 --- a/stats.php +++ b/stats.php @@ -4,13 +4,16 @@ $db = 0; $limit = 20; array_shift($argv); -while($arg = array_shift($argv)) { - switch($arg) { - case '--db': $db = intval(array_shift($argv)); break; - case '--server': $server = array_shift($argv); break; - case '--limit': $limit = array_shift($argv); break; - default: die("Unrecognized argument '$arg'.\nUsage: path/to/stats.php [--server tcp://127.0.0.1:6378] [--db 0] [--limit 20]\n"); - } +while ($arg = array_shift($argv)) { + switch($arg) { + case '--db': $db = intval(array_shift($argv)); + break; + case '--server': $server = array_shift($argv); + break; + case '--limit': $limit = array_shift($argv); + break; + default: die("Unrecognized argument '$arg'.\nUsage: path/to/stats.php [--server tcp://127.0.0.1:6378] [--db 0] [--limit 20]\n"); + } } require __DIR__.'/lib/Credis/Client.php'; @@ -23,59 +26,67 @@ $client->select($db); $tagStats = array(); -foreach($client->sMembers(Cm_Cache_Backend_Redis::SET_TAGS) as $tag) { - if (preg_match('/^\w{3}_MAGE$/', $tag)) continue; - $ids = $client->sMembers(Cm_Cache_Backend_Redis::PREFIX_TAG_IDS . $tag); - $tagSizes = array(); - $missing = 0; - foreach ($ids as $id) { - $data = $client->hGet(Cm_Cache_Backend_Redis::PREFIX_KEY.$id, Cm_Cache_Backend_Redis::FIELD_DATA); - $size = strlen($data); - if ($size) $tagSizes[] = $size; - else $missing++; - } - if ($tagSizes) { - $tagStats[$tag] = array( - 'count' => count($tagSizes), - 'min' => min($tagSizes), - 'max' => max($tagSizes), - 'avg size' => array_sum($tagSizes) / count($tagSizes), - 'total size' => array_sum($tagSizes), - 'missing' => $missing, - ); - } +foreach ($client->sMembers(Cm_Cache_Backend_Redis::SET_TAGS) as $tag) { + if (preg_match('/^\w{3}_MAGE$/', $tag)) { + continue; + } + $ids = $client->sMembers(Cm_Cache_Backend_Redis::PREFIX_TAG_IDS . $tag); + $tagSizes = array(); + $missing = 0; + foreach ($ids as $id) { + $data = $client->hGet(Cm_Cache_Backend_Redis::PREFIX_KEY.$id, Cm_Cache_Backend_Redis::FIELD_DATA); + $size = strlen($data); + if ($size) { + $tagSizes[] = $size; + } else { + $missing++; + } + } + if ($tagSizes) { + $tagStats[$tag] = array( + 'count' => count($tagSizes), + 'min' => min($tagSizes), + 'max' => max($tagSizes), + 'avg size' => array_sum($tagSizes) / count($tagSizes), + 'total size' => array_sum($tagSizes), + 'missing' => $missing, + ); + } } function _format_bytes($a_bytes) { - if ($a_bytes < 1024) { - return $a_bytes .' B'; - } elseif ($a_bytes < 1048576) { - return round($a_bytes / 1024, 4) .' KB'; - } else { - return round($a_bytes / 1048576, 4) . ' MB'; - } + if ($a_bytes < 1024) { + return $a_bytes .' B'; + } elseif ($a_bytes < 1048576) { + return round($a_bytes / 1024, 4) .' KB'; + } else { + return round($a_bytes / 1048576, 4) . ' MB'; + } } -function printStats($data, $key, $limit) { - echo "Top $limit tags by ".ucwords($key)."\n"; - echo "------------------------------------------------------------------------------------\n"; - $sort = array(); - foreach ($data as $tag => $stats) { - $sort[$tag] = $stats[$key]; - } - array_multisort($sort, SORT_DESC, $data); - $i = 0; - $fmt = "%-40s| %-8s| %-15s| %-15s\n"; - printf($fmt, 'Tag', 'Count', 'Avg Size', 'Total Size'); - foreach ($data as $tag => $stats) { - $tag = substr($tag, 4); - if (++$i > $limit) break; - $avg = _format_bytes($stats['avg size']); - $total = _format_bytes($stats['total size']); - printf($fmt, $tag, $stats['count'], $avg, $total); - } - echo "\n"; +function printStats($data, $key, $limit) +{ + echo "Top $limit tags by ".ucwords($key)."\n"; + echo "------------------------------------------------------------------------------------\n"; + $sort = array(); + foreach ($data as $tag => $stats) { + $sort[$tag] = $stats[$key]; + } + array_multisort($sort, SORT_DESC, $data); + $i = 0; + $fmt = "%-40s| %-8s| %-15s| %-15s\n"; + printf($fmt, 'Tag', 'Count', 'Avg Size', 'Total Size'); + foreach ($data as $tag => $stats) { + $tag = substr($tag, 4); + if (++$i > $limit) { + break; + } + $avg = _format_bytes($stats['avg size']); + $total = _format_bytes($stats['total size']); + printf($fmt, $tag, $stats['count'], $avg, $total); + } + echo "\n"; } // Top 20 by total size diff --git a/tests/CommonBackendTest.php b/tests/CommonBackendTest.php index 50d9025..f11ed88 100644 --- a/tests/CommonBackendTest.php +++ b/tests/CommonBackendTest.php @@ -1,8 +1,8 @@ assertTrue($this->_instance->test('bar2') > 999999); $this->assertFalse($this->_instance->test('bar3')); } - } - - diff --git a/tests/CommonExtendedBackendTest.php b/tests/CommonExtendedBackendTest.php index 4eeb0e3..0822a25 100644 --- a/tests/CommonExtendedBackendTest.php +++ b/tests/CommonExtendedBackendTest.php @@ -2,8 +2,8 @@ require_once 'vendor/autoload.php'; require_once 'CommonBackendTest.php'; -abstract class CommonExtendedBackendTest extends CommonBackendTest { - +abstract class CommonExtendedBackendTest extends CommonBackendTest +{ private $_capabilities; public function __construct($name = null, array $data = array(), $dataName = '') @@ -178,7 +178,4 @@ public function testGetCapabilities(): void $this->assertTrue(isset($res['infinite_lifetime'])); $this->assertTrue(isset($res['get_list'])); } - } - - diff --git a/tests/RedisBackendAutoExpiryTest.php b/tests/RedisBackendAutoExpiryTest.php index 8b8d60e..36ee54f 100644 --- a/tests/RedisBackendAutoExpiryTest.php +++ b/tests/RedisBackendAutoExpiryTest.php @@ -36,8 +36,8 @@ * @copyright Copyright (c) 2012 Colin Mollenhour (http://colin.mollenhour.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class RedisBackendAutoExpiryTest extends RedisBackendTest { - +class RedisBackendAutoExpiryTest extends RedisBackendTest +{ protected $autoExpireLifetime = 3600; protected $autoExpireRefreshOnLoad = 1; diff --git a/tests/RedisBackendStandaloneTest.php b/tests/RedisBackendStandaloneTest.php index 56ec839..ae58292 100644 --- a/tests/RedisBackendStandaloneTest.php +++ b/tests/RedisBackendStandaloneTest.php @@ -35,8 +35,7 @@ * @copyright Copyright (c) 2012 Colin Mollenhour (http://colin.mollenhour.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class RedisBackendStandaloneTest extends RedisBackendTest { - - protected $forceStandalone = TRUE; - +class RedisBackendStandaloneTest extends RedisBackendTest +{ + protected $forceStandalone = true; } diff --git a/tests/RedisBackendTest.php b/tests/RedisBackendTest.php index b0deb64..82aa341 100644 --- a/tests/RedisBackendTest.php +++ b/tests/RedisBackendTest.php @@ -35,11 +35,11 @@ * @copyright Copyright (c) 2012 Colin Mollenhour (http://colin.mollenhour.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class RedisBackendTest extends CommonExtendedBackendTest { - +class RedisBackendTest extends CommonExtendedBackendTest +{ const LUA_MAX_C_STACK = 1000; - protected $forceStandalone = FALSE; + protected $forceStandalone = false; protected $autoExpireLifetime = 0; @@ -56,11 +56,11 @@ public function setUp($notag = false): void 'server' => getenv('REDIS_SERVER') ?: 'localhost', 'port' => getenv('REDIS_PORT') ?: '6379', 'database' => '1', - 'notMatchingTags' => TRUE, + 'notMatchingTags' => true, 'force_standalone' => $this->forceStandalone, 'compress_threshold' => 100, 'compression_lib' => 'gzip', - 'use_lua' => TRUE, + 'use_lua' => true, 'lua_max_c_stack' => self::LUA_MAX_C_STACK, 'auto_expire_lifetime' => $this->autoExpireLifetime, 'auto_expire_refresh_on_load' => $this->autoExpireRefreshOnLoad, @@ -91,8 +91,8 @@ public function testCompression(): void public function testExpiredCleanup(): void { $this->assertTrue($this->_instance->clean()); - $this->assertTrue($this->_instance->save('BLAH','foo', array('TAG1', 'TAG2'), 1)); - $this->assertTrue($this->_instance->save('BLAH','bar', array('TAG1', 'TAG3'), 1)); + $this->assertTrue($this->_instance->save('BLAH', 'foo', array('TAG1', 'TAG2'), 1)); + $this->assertTrue($this->_instance->save('BLAH', 'bar', array('TAG1', 'TAG3'), 1)); $ids = $this->_instance->getIdsMatchingAnyTags(array('TAG1','TAG2','TAG3')); sort($ids); $this->assertEquals(array('bar','foo'), $ids);