From 841d59ef81b2eb9018e43fd9e8ae5b1adce3dc31 Mon Sep 17 00:00:00 2001 From: Colin Mollenhour Date: Thu, 29 Dec 2022 14:46:03 -0500 Subject: [PATCH] Handle LOADING exception during read. (#171) Handle LOADING state when reading from slave by reading from master and when reading from master by retrying after 1 second wait. --- Cm/Cache/Backend/Redis.php | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Cm/Cache/Backend/Redis.php b/Cm/Cache/Backend/Redis.php index 5e39b70..b620775 100644 --- a/Cm/Cache/Backend/Redis.php +++ b/Cm/Cache/Backend/Redis.php @@ -480,16 +480,35 @@ protected function _setupReadWriteCluster($options) public function load($id, $doNotTestCacheValidity = false) { if ($this->_slave) { - $data = $this->_slave->hGet(self::PREFIX_KEY.$id, self::FIELD_DATA); + try { + $data = $this->_slave->hGet(self::PREFIX_KEY.$id, self::FIELD_DATA); - // Prevent compounded effect of cache flood on asynchronously replicating master/slave setup - if ($this->_retryReadsOnMaster && $data === false) { - $data = $this->_redis->hGet(self::PREFIX_KEY.$id, self::FIELD_DATA); + // Prevent compounded effect of cache flood on asynchronously replicating master/slave setup + if ($this->_retryReadsOnMaster && $data === false) { + $data = $this->_redis->hGet(self::PREFIX_KEY.$id, self::FIELD_DATA); + } + } catch (CredisException $e) { + // Always retry reads on master when dataset is loading on slave + if ($e->getMessage() === 'LOADING Redis is loading the dataset in memory') { + $data = $this->_redis->hGet(self::PREFIX_KEY.$id, self::FIELD_DATA); + } else { + throw $e; + } } } else { - $data = $this->_redis->hGet(self::PREFIX_KEY.$id, self::FIELD_DATA); + try { + $data = $this->_redis->hGet(self::PREFIX_KEY.$id, self::FIELD_DATA); + } catch (CredisException $e) { + // Retry once after 1 second when dataset is loading + if ($e->getMessage() === 'LOADING Redis is loading the dataset in memory') { + sleep(1); + $data = $this->_redis->hGet(self::PREFIX_KEY.$id, self::FIELD_DATA); + } else { + throw $e; + } + } } - if ($data === NULL || is_object($data)) { + if ($data === NULL || $data === FALSE || is_object($data)) { return FALSE; }